Sophie

Sophie

distrib > Mandriva > 2010.1 > i586 > media > contrib-updates-src > by-pkgid > f722e3fddb6bcd9335a8848a4b05a73c > files > 9

xbmc-10.1-1.pvr.2mdv2010.2.src.rpm

From bb7658a2c400a7d55fe99db177fdcced3c028601 Mon Sep 17 00:00:00 2001
From: anssih <anssih@568bbfeb-2a22-0410-94d2-cc84cf5bfa90>
Date: Fri, 3 Sep 2010 19:34:22 +0000
Subject: [PATCH 2/8] fixed: VDPAU temporal deinterlacer was not provided enough fields

According to NVIDIA documentation, the advanced deinterlacers need 2
previous fields and 1 future field for every call to video mixer.
We didn't provide those, causing VDPAU to fallback to bob deinterlacer.

Make VDPAU always render the previously decoded frame, so that the
newly decoded frame can be used as a future field.

git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@33509 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
(cherry picked from commit 295d725c9c7c288cf4c5cab13ff66eccb9fd8f79)
---
 xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp |   39 +++++++++++++++++++----
 xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h   |    2 +
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
index 04b9e6b..e6ac689 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp
@@ -816,6 +816,8 @@ void CVDPAU::FiniVDPAUOutput()
     free(m_videoSurfaces[i]);
   }
   m_videoSurfaces.clear();
+  while (!m_DVDVideoPics.empty())
+    m_DVDVideoPics.pop();
 }
 
 
@@ -1163,10 +1165,28 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
     ClearUsedForRender(&past[0]);
     past[0] = past[1];
     past[1] = current;
-    current = render;
+    current = future;
+    future = render;
 
-    if((method == VS_INTERLACEMETHOD_AUTO && pFrame->interlaced_frame)
-    || (method == VS_INTERLACEMETHOD_AUTO_ION && pFrame->interlaced_frame)
+    DVDVideoPicture DVDPic;
+    ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&DVDPic);
+    m_DVDVideoPics.push(DVDPic);
+
+    int pics = m_DVDVideoPics.size();
+    if (pics < 2)
+        return VC_BUFFER;
+    else if (pics > 2)
+    {
+      // this should not normally happen
+      CLog::Log(LOGERROR, "CVDPAU::Decode - invalid number of pictures in queue");
+      while (pics-- != 2)
+        m_DVDVideoPics.pop();
+    }
+
+    if((method == VS_INTERLACEMETHOD_AUTO &&
+                  m_DVDVideoPics.front().iFlags & DVP_FLAG_INTERLACED)
+    || (method == VS_INTERLACEMETHOD_AUTO_ION &&
+                  m_DVDVideoPics.front().iFlags & DVP_FLAG_INTERLACED)
     ||  method == VS_INTERLACEMETHOD_VDPAU_BOB
     ||  method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
     ||  method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
@@ -1182,7 +1202,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
       else
         m_mixerstep = 1;
 
-      if(pFrame->top_field_first)
+      if(m_DVDVideoPics.front().iFlags & DVP_FLAG_TOP_FIELD_FIRST)
         m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
       else
         m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
@@ -1200,6 +1220,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
     if(avctx->hurry_up)
     {
       ClearUsedForRender(&past[1]);
+      m_DVDVideoPics.pop();
       return VC_BUFFER;
     }
 
@@ -1224,7 +1245,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
       past_surfaces[1] = past[0]->surface;
     if (past[1])
       past_surfaces[0] = past[1]->surface;
-    futu_surfaces[0] = VDP_INVALID_HANDLE;
+    futu_surfaces[0] = future->surface;
   }
   else
   {
@@ -1242,7 +1263,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
       if (past[1])
         past_surfaces[1] = past[1]->surface;
       past_surfaces[0] = current->surface;
-      futu_surfaces[0] = VDP_INVALID_HANDLE;
+      futu_surfaces[0] = future->surface;
     }
   }
 
@@ -1287,7 +1308,11 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame)
 
 bool CVDPAU::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
 {
-  ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(picture);
+  *picture = m_DVDVideoPics.front();
+  // if this is the first field of an interlaced frame, we'll need
+  // this same picture for the second field later
+  if (m_mixerstep != 1)
+    m_DVDVideoPics.pop();
 
   picture->format = DVDVideoPicture::FMT_VDPAU;
   picture->iFlags &= DVP_FLAG_DROPPED;
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
index 15b2f6c..18ebb10 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h
@@ -30,6 +30,7 @@
 #define GLX_GLXEXT_PROTOTYPES
 #include <GL/gl.h>
 #include <GL/glx.h>
+#include <queue>
 #include "utils/CriticalSection.h"
 #include "settings/VideoSettings.h"
 namespace Surface { class CSurface; }
@@ -119,6 +120,7 @@ public:
   float      tmpBrightness, tmpContrast;
   int        OutWidth, OutHeight;
   bool       upScale;
+  std::queue<DVDVideoPicture> m_DVDVideoPics;
 
   static inline void ClearUsedForRender(vdpau_render_state **st)
   {
-- 
1.7.3