From: Wim Taymans Date: Tue, 11 Sep 2012 11:53:23 +0000 (+0200) Subject: avviddec: add support for codecs that use reget_buffer X-Git-Tag: 1.19.3~499^2~836 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1e5bfa5215dbbeba746b3ed5d541373b6cf44ee1;p=platform%2Fupstream%2Fgstreamer.git avviddec: add support for codecs that use reget_buffer Add support for codec that use reget_buffer. In this mode, it reuses the picture and we need to attach the corresponding input frame to it or else we get the timestamps wrong. --- diff --git a/ext/libav/gstavviddec.c b/ext/libav/gstavviddec.c index 00fd7e4..d14e065 100644 --- a/ext/libav/gstavviddec.c +++ b/ext/libav/gstavviddec.c @@ -151,6 +151,8 @@ static gboolean gst_ffmpegviddec_negotiate (GstFFMpegVidDec * ffmpegdec, /* some sort of bufferpool handling, but different */ static int gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture); +static int gst_ffmpegviddec_reget_buffer (AVCodecContext * context, + AVFrame * picture); static void gst_ffmpegviddec_release_buffer (AVCodecContext * context, AVFrame * picture); @@ -437,6 +439,7 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder, /* set buffer functions */ ffmpegdec->context->get_buffer = gst_ffmpegviddec_get_buffer; + ffmpegdec->context->reget_buffer = gst_ffmpegviddec_reget_buffer; ffmpegdec->context->release_buffer = gst_ffmpegviddec_release_buffer; ffmpegdec->context->draw_horiz_band = NULL; @@ -547,7 +550,7 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture) ffmpegdec = (GstFFMpegVidDec *) context->opaque; - GST_DEBUG_OBJECT (ffmpegdec, "getting buffer"); + GST_DEBUG_OBJECT (ffmpegdec, "getting buffer picture %p", picture); /* apply the last info we have seen to this picture, when we get the * picture back from ffmpeg we can use this to correctly timestamp the output @@ -644,8 +647,60 @@ duplicate_frame: return -1; } no_frame: - GST_WARNING_OBJECT (ffmpegdec, "Couldn't get codec frame !"); - return -1; + { + GST_WARNING_OBJECT (ffmpegdec, "Couldn't get codec frame !"); + return -1; + } +} + +static int +gst_ffmpegviddec_reget_buffer (AVCodecContext * context, AVFrame * picture) +{ + GstVideoCodecFrame *frame; + GstFFMpegVidDecVideoFrame *dframe; + GstFFMpegVidDec *ffmpegdec; + + ffmpegdec = (GstFFMpegVidDec *) context->opaque; + + GST_DEBUG_OBJECT (ffmpegdec, "regetting buffer picture %p", picture); + + picture->reordered_opaque = context->reordered_opaque; + + /* if there is no opaque, we didn't yet attach any frame to it. What usually + * happens is that avcodec_default_reget_buffer will call the getbuffer + * function. */ + dframe = picture->opaque; + if (dframe == NULL) + goto done; + + frame = + gst_video_decoder_get_frame (GST_VIDEO_DECODER (ffmpegdec), + picture->reordered_opaque); + if (G_UNLIKELY (frame == NULL)) + goto no_frame; + + if (G_UNLIKELY (frame->output_buffer != NULL)) + goto duplicate_frame; + + /* replace the frame, this one contains the pts/dts for the correspoding input + * buffer, which we need after decoding. */ + gst_video_codec_frame_unref (dframe->frame); + dframe->frame = frame; + +done: + return avcodec_default_reget_buffer (context, picture); + + /* ERRORS */ +no_frame: + { + GST_WARNING_OBJECT (ffmpegdec, "Couldn't get codec frame !"); + return -1; + } +duplicate_frame: + { + GST_WARNING_OBJECT (ffmpegdec, "already alloc'ed output buffer for frame"); + return -1; + } } /* called when ffmpeg is done with our buffer */