1 |
From bb7658a2c400a7d55fe99db177fdcced3c028601 Mon Sep 17 00:00:00 2001 |
2 |
From: anssih <anssih@568bbfeb-2a22-0410-94d2-cc84cf5bfa90> |
3 |
Date: Fri, 3 Sep 2010 19:34:22 +0000 |
4 |
Subject: [PATCH 2/8] fixed: VDPAU temporal deinterlacer was not provided enough fields |
5 |
|
6 |
According to NVIDIA documentation, the advanced deinterlacers need 2 |
7 |
previous fields and 1 future field for every call to video mixer. |
8 |
We didn't provide those, causing VDPAU to fallback to bob deinterlacer. |
9 |
|
10 |
Make VDPAU always render the previously decoded frame, so that the |
11 |
newly decoded frame can be used as a future field. |
12 |
|
13 |
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@33509 568bbfeb-2a22-0410-94d2-cc84cf5bfa90 |
14 |
(cherry picked from commit 295d725c9c7c288cf4c5cab13ff66eccb9fd8f79) |
15 |
--- |
16 |
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 39 +++++++++++++++++++---- |
17 |
xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h | 2 + |
18 |
2 files changed, 34 insertions(+), 7 deletions(-) |
19 |
|
20 |
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp |
21 |
index 04b9e6b..e6ac689 100644 |
22 |
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp |
23 |
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp |
24 |
@@ -816,6 +816,8 @@ void CVDPAU::FiniVDPAUOutput() |
25 |
free(m_videoSurfaces[i]); |
26 |
} |
27 |
m_videoSurfaces.clear(); |
28 |
+ while (!m_DVDVideoPics.empty()) |
29 |
+ m_DVDVideoPics.pop(); |
30 |
} |
31 |
|
32 |
|
33 |
@@ -1163,10 +1165,28 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) |
34 |
ClearUsedForRender(&past[0]); |
35 |
past[0] = past[1]; |
36 |
past[1] = current; |
37 |
- current = render; |
38 |
+ current = future; |
39 |
+ future = render; |
40 |
|
41 |
- if((method == VS_INTERLACEMETHOD_AUTO && pFrame->interlaced_frame) |
42 |
- || (method == VS_INTERLACEMETHOD_AUTO_ION && pFrame->interlaced_frame) |
43 |
+ DVDVideoPicture DVDPic; |
44 |
+ ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(&DVDPic); |
45 |
+ m_DVDVideoPics.push(DVDPic); |
46 |
+ |
47 |
+ int pics = m_DVDVideoPics.size(); |
48 |
+ if (pics < 2) |
49 |
+ return VC_BUFFER; |
50 |
+ else if (pics > 2) |
51 |
+ { |
52 |
+ // this should not normally happen |
53 |
+ CLog::Log(LOGERROR, "CVDPAU::Decode - invalid number of pictures in queue"); |
54 |
+ while (pics-- != 2) |
55 |
+ m_DVDVideoPics.pop(); |
56 |
+ } |
57 |
+ |
58 |
+ if((method == VS_INTERLACEMETHOD_AUTO && |
59 |
+ m_DVDVideoPics.front().iFlags & DVP_FLAG_INTERLACED) |
60 |
+ || (method == VS_INTERLACEMETHOD_AUTO_ION && |
61 |
+ m_DVDVideoPics.front().iFlags & DVP_FLAG_INTERLACED) |
62 |
|| method == VS_INTERLACEMETHOD_VDPAU_BOB |
63 |
|| method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL |
64 |
|| method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF |
65 |
@@ -1182,7 +1202,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) |
66 |
else |
67 |
m_mixerstep = 1; |
68 |
|
69 |
- if(pFrame->top_field_first) |
70 |
+ if(m_DVDVideoPics.front().iFlags & DVP_FLAG_TOP_FIELD_FIRST) |
71 |
m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; |
72 |
else |
73 |
m_mixerfield = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD; |
74 |
@@ -1200,6 +1220,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) |
75 |
if(avctx->hurry_up) |
76 |
{ |
77 |
ClearUsedForRender(&past[1]); |
78 |
+ m_DVDVideoPics.pop(); |
79 |
return VC_BUFFER; |
80 |
} |
81 |
|
82 |
@@ -1224,7 +1245,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) |
83 |
past_surfaces[1] = past[0]->surface; |
84 |
if (past[1]) |
85 |
past_surfaces[0] = past[1]->surface; |
86 |
- futu_surfaces[0] = VDP_INVALID_HANDLE; |
87 |
+ futu_surfaces[0] = future->surface; |
88 |
} |
89 |
else |
90 |
{ |
91 |
@@ -1242,7 +1263,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) |
92 |
if (past[1]) |
93 |
past_surfaces[1] = past[1]->surface; |
94 |
past_surfaces[0] = current->surface; |
95 |
- futu_surfaces[0] = VDP_INVALID_HANDLE; |
96 |
+ futu_surfaces[0] = future->surface; |
97 |
} |
98 |
} |
99 |
|
100 |
@@ -1287,7 +1308,11 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) |
101 |
|
102 |
bool CVDPAU::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture) |
103 |
{ |
104 |
- ((CDVDVideoCodecFFmpeg*)avctx->opaque)->GetPictureCommon(picture); |
105 |
+ *picture = m_DVDVideoPics.front(); |
106 |
+ // if this is the first field of an interlaced frame, we'll need |
107 |
+ // this same picture for the second field later |
108 |
+ if (m_mixerstep != 1) |
109 |
+ m_DVDVideoPics.pop(); |
110 |
|
111 |
picture->format = DVDVideoPicture::FMT_VDPAU; |
112 |
picture->iFlags &= DVP_FLAG_DROPPED; |
113 |
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h |
114 |
index 15b2f6c..18ebb10 100644 |
115 |
--- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h |
116 |
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h |
117 |
@@ -30,6 +30,7 @@ |
118 |
#define GLX_GLXEXT_PROTOTYPES |
119 |
#include <GL/gl.h> |
120 |
#include <GL/glx.h> |
121 |
+#include <queue> |
122 |
#include "utils/CriticalSection.h" |
123 |
#include "settings/VideoSettings.h" |
124 |
namespace Surface { class CSurface; } |
125 |
@@ -119,6 +120,7 @@ public: |
126 |
float tmpBrightness, tmpContrast; |
127 |
int OutWidth, OutHeight; |
128 |
bool upScale; |
129 |
+ std::queue<DVDVideoPicture> m_DVDVideoPics; |
130 |
|
131 |
static inline void ClearUsedForRender(vdpau_render_state **st) |
132 |
{ |
133 |
-- |
134 |
1.7.3 |
135 |
|