avviddec: Enforce allocate new AVFrame per input frame

... if ffmpeg would reuse the allocated AVBuffer. Reused AVFrame by
the ffmpeg seems to break our decoding flow since the reused AVFrame
holds the initial opaque data (GstVideoCodecFrame in this case), so
we couldn't trace the our in/out frames.
To enforce get_buffer() call per output frame, hold another reference
to the AVBuffer in order to mark the AVBuffer as not writable.

Fixes: https://gitlab.freedesktop.org/gstreamer/gst-libav/issues/62
This commit is contained in:
Seungha Yang 2019-10-24 00:25:28 +09:00
parent ca478e7546
commit 80c8c05457

View file

@ -773,6 +773,12 @@ gst_ffmpegviddec_can_direct_render (GstFFMpegVidDec * ffmpegdec)
AV_CODEC_CAP_DR1); AV_CODEC_CAP_DR1);
} }
static void
gst_ffmpegviddec_avbuffer_unref (AVBufferRef * avbuffer)
{
av_buffer_unref (&avbuffer);
}
/* called when ffmpeg wants us to allocate a buffer to write the decoded frame /* called when ffmpeg wants us to allocate a buffer to write the decoded frame
* into. We try to give it memory from our pool */ * into. We try to give it memory from our pool */
static int static int
@ -866,6 +872,16 @@ gst_ffmpegviddec_get_buffer2 (AVCodecContext * context, AVFrame * picture,
} }
picture->buf[0] = av_buffer_create (NULL, 0, dummy_free_buffer, dframe, 0); picture->buf[0] = av_buffer_create (NULL, 0, dummy_free_buffer, dframe, 0);
if ((flags & AV_GET_BUFFER_FLAG_REF) == AV_GET_BUFFER_FLAG_REF) {
/* decoder might reuse this AVFrame and it would result to no more
* get_buffer() call if the AVFrame's AVBuffer is writable
* (meaning that the refcount of AVBuffer == 1).
* To enforce get_buffer() for the every output frame, hold another ref here
*/
gst_video_codec_frame_set_user_data (frame,
av_buffer_ref (picture->buf[0]),
(GDestroyNotify) gst_ffmpegviddec_avbuffer_unref);
}
GST_LOG_OBJECT (ffmpegdec, "returned frame %p", dframe->buffer); GST_LOG_OBJECT (ffmpegdec, "returned frame %p", dframe->buffer);