Deinterlacing with VDPAU, TVTime
#16
Here is an attempt to stop the memory leak. Runs smoothly for me:
Code:
--- DVDFactoryCodec.cpp (revision 29122)
+++ DVDFactoryCodec.cpp (working copy)
@@ -184,7 +184,7 @@
       CDVDCodecOptions dvdOptions;

#ifdef HAVE_LIBVDPAU
-      if (hint.height >= 720)
+//      if (hint.height >= 720)
       {
         CLog::Log(LOGNOTICE,"Trying VDPAU-MPEG from FFMPEG");
         if( (pCodec = OpenCodec(new CDVDVideoCodecFFmpeg(), hint, dvdOptions)) ) return pCodec;
Code:
--- VDPAU.cpp    (revision 29122)
+++ VDPAU.cpp    (working copy)
@@ -950,6 +950,8 @@
   CVDPAU*               vdp        = (CVDPAU*)ctx->GetHardware();
   struct pictureAge*    pA         = &vdp->picAge;

+  static int VSurfaceRelease = 0;
+
   // while we are waiting to recover we can't do anything
   if(vdp->recover)
   {
@@ -959,16 +961,14 @@

   vdpau_render_state * render = NULL;

-  // find unused surface
-  for(unsigned int i = 0; i < vdp->m_videoSurfaces.size(); i++)
+  if (vdp->m_videoSurfaces.size() >= 50)    // Maximum number of surfaces have been created
   {
-    if(!(vdp->m_videoSurfaces[i]->state & FF_VDPAU_STATE_USED_FOR_REFERENCE))
-    {
-      render = vdp->m_videoSurfaces[i];
-      render->state = 0;
-      break;
-    }
+    render = vdp->m_videoSurfaces[VSurfaceRelease];        // Re-use oldest surface
+    render->state = 0;
+    if (VSurfaceRelease < (vdp->m_videoSurfaces.size()-1)) VSurfaceRelease++; // Next surface to be released
+    else VSurfaceRelease = 0;
   }
+  else    VSurfaceRelease = 0;    // reset release pointer

   VdpStatus vdp_st = VDP_STATUS_ERROR;
   if (render == NULL)
@@ -1016,7 +1016,7 @@
   }
   pic->type= FF_BUFFER_TYPE_USER;

-  render->state |= FF_VDPAU_STATE_USED_FOR_REFERENCE;
+//  render->state |= FF_VDPAU_STATE_USED_FOR_REFERENCE;
   pic->reordered_opaque= avctx->reordered_opaque;
   return 0;
}
@@ -1034,7 +1034,7 @@
     return;
   }

-  render->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE;
+//  render->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE;
   for(i=0; i<4; i++)
     pic->data[i]= NULL;
}
@@ -1126,7 +1126,8 @@

     past[0] = past[1];
     past[1] = current;
-    current = render->surface;
+    current = future;
+    future = render->surface;

     if((method == VS_INTERLACEMETHOD_AUTO && pFrame->interlaced_frame)
     ||  method == VS_INTERLACEMETHOD_VDPAU_BOB
@@ -1173,41 +1174,56 @@
     return VC_BUFFER;
   }

-  VdpVideoSurface past_surfaces[2] = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
-  VdpVideoSurface futu_surfaces[1] = { VDP_INVALID_HANDLE };
+  VdpVideoSurface past_surfaces[4] = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE, VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
+  VdpVideoSurface futu_surfaces[2] = { VDP_INVALID_HANDLE, VDP_INVALID_HANDLE };
+  uint32_t pastCount = 4;
+  uint32_t futuCount = 2;

   if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME)
   {
     past_surfaces[1] = past[0];
     past_surfaces[0] = past[1];
-    futu_surfaces[0] = VDP_INVALID_HANDLE;
+    //       current = current
+    futu_surfaces[0] = future;
+    pastCount = 2;
+    futuCount = 1;
+    CLog::Log(LOGNOTICE, "CVDPAU::Decode - Video surfaces %d [%d] %d %d ", futu_surfaces[0],current,past_surfaces[0],past_surfaces[1]);
   }
   else
   {
     if(m_mixerstep == 1)
     { // first field
+      past_surfaces[3] = past[0];
+      past_surfaces[2] = past[0];
       past_surfaces[1] = past[1];
       past_surfaces[0] = past[1];
       futu_surfaces[0] = current;
+      //       current = current
+      futu_surfaces[1] = future;
     }
     else
     { // second field
+      past_surfaces[3] = past[0];
+      past_surfaces[2] = past[1];
       past_surfaces[1] = past[1];
       past_surfaces[0] = current;
-      futu_surfaces[0] = VDP_INVALID_HANDLE;
+      //       current = current
+      futu_surfaces[0] = future;
+      futu_surfaces[1] = future;
     }
+    CLog::Log(LOGNOTICE, "CVDPAU::Decode - Video surfaces %d %d [%d] %d %d %d %d ", futu_surfaces[1],futu_surfaces[0],current,past_surfaces[0],past_surfaces[1],past_surfaces[2],past_surfaces[3]);
   }

   vdp_st = vdp_presentation_queue_block_until_surface_idle(vdp_flip_queue,outputSurface,&time);

-  vdp_st = vdp_video_mixer_render(videoMixer,
+  if (current != VDP_INVALID_HANDLE) vdp_st = vdp_video_mixer_render(videoMixer,
                                   VDP_INVALID_HANDLE,
-                                  0,
+                                  0,
                                   m_mixerfield,
-                                  2,
+                                  pastCount,
                                   past_surfaces,
                                   current,
-                                  1,
+                                  futuCount,
                                   futu_surfaces,
                                   NULL,
                                   outputSurface,
(edit)
Don't forget to comment out the LOGNOTICE lines when you no longer need them.
Stu-e
Reply
#17
works for me (sd and hd). by the way: with sd material behaviour was as you said (recovery every ~10 secs.), hd material let the oomkiller do its work...

thanks for doing this!
Reply
#18
I have submitted a patch request to fix retaining old frames for advanced deinterlace context and provide the nVidia recommended minimum of 2 past frames and 1 future frame to the video mixer for context. Having reassessed advanced deinterlace quality, temporal is at least on par if not better than yadif and greedyH for 576i video. Spatial-temporal looks bad with 576i which is puzzling. For 1080i I can't tell the difference between temporal and spatial-temporal.

http://trac.xbmc.org/ticket/9069

Considering old video surfaces were being overwritten prematurely would this mean reference frames for the decoder were being overwritten to? That would surely cause video corruption?

Please note I have not included the patch to enable VDPAU mpeg2 decode (and deinterlace).

Stu-e
Reply
#19
Apologies but my opinion of vdpau advanced deinterlace features has changed. The way temporal-spatial is selected in XBMC is different compared to other vdpau applications. To select temporal-spatial as it is used in Mplayer for example, select the 'Auto' mode. This in fact selects both temporal and temporal-spatial features and does indeed produce very good deinterlaced video.

When temporal-spatial is selected this enables only the temporal-spatial feature which on its own appears to produce video no different from bob.

Unfortunately XBMC currently will not permit selection of any advanced deinterlace feature combined with inverse telecine.

Here's another ticket:
http://trac.xbmc.org/ticket/9072

Stu-e
Reply
#20
vdpau will always fallback to bob if an unsupported mode is used. so maybe your (and probably mine) doesn't support temporal spatial.

Running ivtc with any deinterlacers is just silly. ivtc should always recover a progressive frame.
Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.


Image
Reply
#21
I have tested my nVidia GT220 with qvdpautest:
http://hftom.free.fr/qvdpautest-0.5.tar.gz
It shows it can support temporal-spatial with IVTC.
When running Mplayer with temporal-spatial I get identical results to XBMC 'Auto'. But looking at the Mplayer code (libvo/vo_vdpau.c) it appears to select only VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL so I'm really confused now.
(edit) Actually it does select both. See function create_vdp_mixer

My understanding is IVTC should run in conjunction with deinterlace. It's purpose is to detect pulldown and stop deinterlacing. Then depending on the type of pulldown recreate progressive frames and output them at the rate at which the video mixer renderer function is called at.
http://http.download.nvidia.com/XFree86/...index.html
Quote from vdpau api:
"To implement de-interlacing/inverse-telecine on progressive material, simply treat the stream of decoded frames as a stream of decoded fields, apply any telecine flags (see the next section), and then apply de-interlacing to those fields..."

Stu-e
Reply
#22
Also see here:
http://us.download.nvidia.com/XFree86/Li...dix-h.html
It specifically states one of the advanced deinterlace features must be requested and enabled for IVTC to have any effect.

Stu-e
Reply
#23
Hello all,

this is my first post to this forum an I would like to thank all those guys here for their excellent work. I built me a HTPC on Linux. After having tried serveral players I think I will stick with XBMC. Watching TV is one my major use cases (I use pvr-testing2 branch) and de-interlacing of 576i and 1080i content is very important. I am wondering if there is currently any work on improvements on this topic. I have done some experiments by myself which I would like to share. I would post the modified VDPAU.cpp and VDPAU.h. as well but I don't know how?

- Implementation of a buffer class in order to prevent video surfaces in the mixer queue from getting overwritten
- Provide mixer with at least two past and a future frame (Stu-e)
- Run mixer on its own thread with a frame in a buffer. I have an overclocked mGPU (GeForce 9300). This way it can cope with 1080i50 content using one of the advanced de-interlacing methods.
- Blacked some top and bottom lines of interlaced content. The flickering in particular with SD content was very annoying.

//Rainer
Reply
#24
FernetMenta Wrote:Hello all,

this is my first post to this forum an I would like to thank all those guys here for their excellent work. I built me a HTPC on Linux. After having tried serveral players I think I will stick with XBMC. Watching TV is one my major use cases (I use pvr-testing2 branch) and de-interlacing of 576i and 1080i content is very important. I am wondering if there is currently any work on improvements on this topic. I have done some experiments by myself which I would like to share. I would post the modified VDPAU.cpp and VDPAU.h. as well but I don't know how?

- Implementation of a buffer class in order to prevent video surfaces in the mixer queue from getting overwritten
- Provide mixer with at least two past and a future frame (Stu-e)
- Run mixer on its own thread with a frame in a buffer. I have an overclocked mGPU (GeForce 9300). This way it can cope with 1080i50 content using one of the advanced de-interlacing methods.
- Blacked some top and bottom lines of interlaced content. The flickering in particular with SD content was very annoying.

//Rainer

Rainer - open a bug report - see http://trac.xbmc.org/. Attach your files and it'll get reviewed and possibly added.
Reply

Logout Mark Read Team Forum Stats Members Help
Deinterlacing with VDPAU, TVTime1