From 5804e37e47845def2331bb35c666d3c4e35082fd Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Wed, 11 Aug 2010 01:52:35 +0300 Subject: [PATCH 2/7] 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. --- xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 36 ++++++++++++++++++++---- xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h | 2 + 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp index b2864ff..2c3e54a 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp @@ -804,6 +804,8 @@ void CVDPAU::FiniVDPAUOutput() free(m_videoSurfaces[i]); } m_videoSurfaces.clear(); + while (!m_DVDVideoPics.empty()) + m_DVDVideoPics.pop(); } @@ -1151,9 +1153,26 @@ 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) + 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_VDPAU_BOB || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF @@ -1168,7 +1187,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; @@ -1186,6 +1205,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) if(avctx->hurry_up) { ClearUsedForRender(&past[1]); + m_DVDVideoPics.pop(); return VC_BUFFER; } @@ -1210,7 +1230,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 { @@ -1228,7 +1248,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; } } @@ -1273,7 +1293,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 = 0; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h index c50229b..407559f 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 #include +#include #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 m_DVDVideoPics; static inline void ClearUsedForRender(vdpau_render_state **st) { -- 1.7.2