From 37a9cd5ec4811ce81c9f3299c9539a38ba158a60 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Sun, 8 Aug 2010 00:39:22 +0300 Subject: [PATCH 1/6] fixed: ensure that surfaces used for VDPAU video mixer are not overwritten Flag surfaces used by the VDPAU video mixer as such to avoid them being overwritten by new data while still in use. --- xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp | 40 +++++++++++++++++------ xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h | 10 +++++- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp index ee6ac61..f190b29 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp @@ -854,7 +854,7 @@ bool CVDPAU::ConfigVDPAU(AVCodecContext* avctx, int ref_frames) vid_width = avctx->width; vid_height = avctx->height; - past[1] = past[0] = current = future = VDP_INVALID_HANDLE; + past[1] = past[0] = current = future = NULL; CLog::Log(LOGNOTICE, " (VDPAU) screenWidth:%i vidWidth:%i",OutWidth,vid_width); CLog::Log(LOGNOTICE, " (VDPAU) screenHeight:%i vidHeight:%i",OutHeight,vid_height); ReadFormatOf(avctx->pix_fmt, vdp_decoder_profile, vdp_chroma_type); @@ -983,7 +983,7 @@ int CVDPAU::FFGetBuffer(AVCodecContext *avctx, AVFrame *pic) // find unused surface for(unsigned int i = 0; i < vdp->m_videoSurfaces.size(); i++) { - if(!(vdp->m_videoSurfaces[i]->state & FF_VDPAU_STATE_USED_FOR_REFERENCE)) + if(!(vdp->m_videoSurfaces[i]->state & (FF_VDPAU_STATE_USED_FOR_REFERENCE | FF_VDPAU_STATE_USED_FOR_RENDER))) { render = vdp->m_videoSurfaces[i]; render->state = 0; @@ -1145,9 +1145,12 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) if(!render) return VC_ERROR; + render->state |= FF_VDPAU_STATE_USED_FOR_RENDER; + + ClearUsedForRender(&past[0]); past[0] = past[1]; past[1] = current; - current = render->surface; + current = render; if((method == VS_INTERLACEMETHOD_AUTO && pFrame->interlaced_frame) || method == VS_INTERLACEMETHOD_VDPAU_BOB @@ -1180,7 +1183,10 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) { // no new frame given, output second field of old frame if(avctx->hurry_up) + { + ClearUsedForRender(&past[1]); return VC_BUFFER; + } m_mixerstep = 2; if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD) @@ -1199,22 +1205,28 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME) { - past_surfaces[1] = past[0]; - past_surfaces[0] = past[1]; + if (past[0]) + past_surfaces[1] = past[0]->surface; + if (past[1]) + past_surfaces[0] = past[1]->surface; futu_surfaces[0] = VDP_INVALID_HANDLE; } else { if(m_mixerstep == 1) { // first field - past_surfaces[1] = past[1]; - past_surfaces[0] = past[1]; - futu_surfaces[0] = current; + if (past[1]) + { + past_surfaces[1] = past[1]->surface; + past_surfaces[0] = past[1]->surface; + } + futu_surfaces[0] = current->surface; } else { // second field - past_surfaces[1] = past[1]; - past_surfaces[0] = current; + if (past[1]) + past_surfaces[1] = past[1]->surface; + past_surfaces[0] = current->surface; futu_surfaces[0] = VDP_INVALID_HANDLE; } } @@ -1227,7 +1239,7 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) m_mixerfield, 2, past_surfaces, - current, + current->surface, 1, futu_surfaces, NULL, @@ -1242,13 +1254,19 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) if (surfaceNum >= totalAvailableOutputSurfaces) surfaceNum = 0; if(m_mixerfield == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME) + { + ClearUsedForRender(&past[0]); return VC_BUFFER | VC_PICTURE; + } else { if(m_mixerstep == 1) return VC_PICTURE; else + { + ClearUsedForRender(&past[1]); return VC_BUFFER | VC_PICTURE; + } } } diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h index d5d8404..c50229b 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.h @@ -113,13 +113,21 @@ public: pictureAge picAge; bool recover; - VdpVideoSurface past[2], current, future; + vdpau_render_state *past[2], *current, *future; int tmpDeint; float tmpNoiseReduction, tmpSharpness; float tmpBrightness, tmpContrast; int OutWidth, OutHeight; bool upScale; + static inline void ClearUsedForRender(vdpau_render_state **st) + { + if (*st) { + (*st)->state &= ~FF_VDPAU_STATE_USED_FOR_RENDER; + *st = NULL; + } + } + VdpProcamp m_Procamp; VdpCSCMatrix m_CSCMatrix; VdpDevice HasDevice() { return vdp_device != VDP_INVALID_HANDLE; }; -- 1.7.2