avviddec: Rename variables and fuse function

* gst_ffmpegviddec_frame() is the only caller of gst_ffmpegviddec_video_frame()
  and has the same signature. Just move the checks into a single function and
  use that.
* Make it clear which frames are the input and output ones in
  gst_ffmpegviddec_video_frame() to make issues like the one fixed in the previous
  commit more obvious.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6851>
This commit is contained in:
Edward Hervey 2024-05-14 10:27:36 +02:00 committed by GStreamer Marge Bot
parent f858179d01
commit aab2f59d02

View file

@ -1839,15 +1839,24 @@ not_negotiated:
*/ */
static gboolean static gboolean
gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
GstVideoCodecFrame * frame, GstFlowReturn * ret) GstVideoCodecFrame * input_frame, GstFlowReturn * ret)
{ {
gint res; gint res;
gboolean got_frame = FALSE; gboolean got_frame = FALSE;
gboolean mode_switch; gboolean mode_switch;
GstVideoCodecFrame *out_frame; GstVideoCodecFrame *output_frame;
GstFFMpegVidDecVideoFrame *out_dframe; GstFFMpegVidDecVideoFrame *out_dframe;
GstBufferPool *pool; GstBufferPool *pool;
if (G_UNLIKELY (ffmpegdec->context->codec == NULL))
goto no_codec;
#if LIBAVCODEC_VERSION_MAJOR >= 60
ffmpegdec->context->frame_num++;
#else
ffmpegdec->context->frame_number++;
#endif
*ret = GST_FLOW_OK; *ret = GST_FLOW_OK;
/* in case we skip frames */ /* in case we skip frames */
@ -1855,7 +1864,7 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
/* run QoS code, we don't stop decoding the frame when we are late because /* run QoS code, we don't stop decoding the frame when we are late because
* else we might skip a reference frame */ * else we might skip a reference frame */
gst_ffmpegviddec_do_qos (ffmpegdec, frame, &mode_switch); gst_ffmpegviddec_do_qos (ffmpegdec, input_frame, &mode_switch);
/* FFmpeg might request new buffer from other threads. /* FFmpeg might request new buffer from other threads.
* Release lock here */ * Release lock here */
@ -1882,17 +1891,17 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
/* get the output picture timing info again */ /* get the output picture timing info again */
out_dframe = ffmpegdec->picture->opaque; out_dframe = ffmpegdec->picture->opaque;
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (60, 31, 100) #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (60, 31, 100)
out_frame = output_frame =
gst_video_codec_frame_ref (av_buffer_get_opaque (ffmpegdec-> gst_video_codec_frame_ref (av_buffer_get_opaque (ffmpegdec->
picture->opaque_ref)); picture->opaque_ref));
#else #else
g_assert (out_dframe); g_assert (out_dframe);
out_frame = gst_video_codec_frame_ref (out_dframe->frame); output_frame = gst_video_codec_frame_ref (out_dframe->frame);
#endif #endif
/* also give back a buffer allocated by the frame, if any */ /* also give back a buffer allocated by the frame, if any */
if (out_dframe) { if (out_dframe) {
gst_buffer_replace (&out_frame->output_buffer, out_dframe->buffer); gst_buffer_replace (&output_frame->output_buffer, out_dframe->buffer);
gst_buffer_replace (&out_dframe->buffer, NULL); gst_buffer_replace (&out_dframe->buffer, NULL);
} }
@ -1923,7 +1932,7 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
GST_DEBUG_OBJECT (ffmpegdec, GST_DEBUG_OBJECT (ffmpegdec,
"pts %" G_GUINT64_FORMAT " duration %" G_GUINT64_FORMAT, "pts %" G_GUINT64_FORMAT " duration %" G_GUINT64_FORMAT,
out_frame->pts, out_frame->duration); output_frame->pts, output_frame->duration);
GST_DEBUG_OBJECT (ffmpegdec, "picture: pts %" G_GUINT64_FORMAT, GST_DEBUG_OBJECT (ffmpegdec, "picture: pts %" G_GUINT64_FORMAT,
(guint64) ffmpegdec->picture->pts); (guint64) ffmpegdec->picture->pts);
#if LIBAVUTIL_VERSION_MAJOR < 58 #if LIBAVUTIL_VERSION_MAJOR < 58
@ -1947,21 +1956,22 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
!!(ffmpegdec->picture->flags & AV_FRAME_FLAG_CORRUPT)); !!(ffmpegdec->picture->flags & AV_FRAME_FLAG_CORRUPT));
if (!gst_ffmpegviddec_negotiate (ffmpegdec, ffmpegdec->context, if (!gst_ffmpegviddec_negotiate (ffmpegdec, ffmpegdec->context,
ffmpegdec->picture, GST_BUFFER_FLAGS (out_frame->input_buffer))) ffmpegdec->picture, GST_BUFFER_FLAGS (output_frame->input_buffer)))
goto negotiation_error; goto negotiation_error;
pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (ffmpegdec)); pool = gst_video_decoder_get_buffer_pool (GST_VIDEO_DECODER (ffmpegdec));
if (G_UNLIKELY (out_frame->output_buffer == NULL)) { if (G_UNLIKELY (output_frame->output_buffer == NULL)) {
*ret = get_output_buffer (ffmpegdec, out_frame); *ret = get_output_buffer (ffmpegdec, output_frame);
} else if (G_UNLIKELY (out_frame->output_buffer->pool != pool)) { } else if (G_UNLIKELY (output_frame->output_buffer->pool != pool)) {
GstBuffer *tmp = out_frame->output_buffer; GstBuffer *tmp = output_frame->output_buffer;
out_frame->output_buffer = NULL; output_frame->output_buffer = NULL;
*ret = get_output_buffer (ffmpegdec, out_frame); *ret = get_output_buffer (ffmpegdec, output_frame);
gst_buffer_unref (tmp); gst_buffer_unref (tmp);
} }
#ifndef G_DISABLE_ASSERT #ifndef G_DISABLE_ASSERT
else { else {
GstVideoMeta *vmeta = gst_buffer_get_video_meta (out_frame->output_buffer); GstVideoMeta *vmeta =
gst_buffer_get_video_meta (output_frame->output_buffer);
if (vmeta) { if (vmeta) {
GstVideoInfo *info = &ffmpegdec->output_state->info; GstVideoInfo *info = &ffmpegdec->output_state->info;
g_assert ((gint) vmeta->width == GST_VIDEO_INFO_WIDTH (info)); g_assert ((gint) vmeta->width == GST_VIDEO_INFO_WIDTH (info));
@ -1976,24 +1986,27 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
/* Mark corrupted frames as corrupted */ /* Mark corrupted frames as corrupted */
if (ffmpegdec->picture->flags & AV_FRAME_FLAG_CORRUPT) if (ffmpegdec->picture->flags & AV_FRAME_FLAG_CORRUPT)
GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_BUFFER_FLAG_CORRUPTED); GST_BUFFER_FLAG_SET (output_frame->output_buffer,
GST_BUFFER_FLAG_CORRUPTED);
if (ffmpegdec->pic_interlaced) { if (ffmpegdec->pic_interlaced) {
/* set interlaced flags */ /* set interlaced flags */
if (ffmpegdec->picture->repeat_pict) if (ffmpegdec->picture->repeat_pict)
GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_VIDEO_BUFFER_FLAG_RFF); GST_BUFFER_FLAG_SET (output_frame->output_buffer,
GST_VIDEO_BUFFER_FLAG_RFF);
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100) #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
if (ffmpegdec->picture->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) if (ffmpegdec->picture->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)
#else #else
if (ffmpegdec->picture->top_field_first) if (ffmpegdec->picture->top_field_first)
#endif #endif
GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_VIDEO_BUFFER_FLAG_TFF); GST_BUFFER_FLAG_SET (output_frame->output_buffer,
GST_VIDEO_BUFFER_FLAG_TFF);
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100) #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(60, 31, 100)
if (ffmpegdec->picture->flags & AV_FRAME_FLAG_INTERLACED) if (ffmpegdec->picture->flags & AV_FRAME_FLAG_INTERLACED)
#else #else
if (ffmpegdec->picture->interlaced_frame) if (ffmpegdec->picture->interlaced_frame)
#endif #endif
GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_BUFFER_FLAG_SET (output_frame->output_buffer,
GST_VIDEO_BUFFER_FLAG_INTERLACED); GST_VIDEO_BUFFER_FLAG_INTERLACED);
} }
@ -2007,11 +2020,11 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
GST_MEMDUMP ("A53 CC", side_data->data, side_data->size); GST_MEMDUMP ("A53 CC", side_data->data, side_data->size);
/* do not add closed caption meta if it already exists */ /* do not add closed caption meta if it already exists */
if (!gst_buffer_get_meta (out_frame->input_buffer, if (!gst_buffer_get_meta (output_frame->input_buffer,
GST_VIDEO_CAPTION_META_API_TYPE)) { GST_VIDEO_CAPTION_META_API_TYPE)) {
out_frame->output_buffer = output_frame->output_buffer =
gst_buffer_make_writable (out_frame->output_buffer); gst_buffer_make_writable (output_frame->output_buffer);
gst_buffer_add_video_caption_meta (out_frame->output_buffer, gst_buffer_add_video_caption_meta (output_frame->output_buffer,
GST_VIDEO_CAPTION_TYPE_CEA708_RAW, side_data->data, GST_VIDEO_CAPTION_TYPE_CEA708_RAW, side_data->data,
side_data->size); side_data->size);
} else { } else {
@ -2037,7 +2050,7 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
while (l) { while (l) {
GstVideoCodecFrame *tmp = l->data; GstVideoCodecFrame *tmp = l->data;
if (tmp == out_frame) if (tmp == output_frame)
old = FALSE; old = FALSE;
if (old && GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY (tmp)) { if (old && GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY (tmp)) {
@ -2060,28 +2073,30 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
av_frame_unref (ffmpegdec->picture); av_frame_unref (ffmpegdec->picture);
if (frame) if (input_frame)
GST_VIDEO_CODEC_FRAME_FLAG_UNSET (frame, GST_VIDEO_CODEC_FRAME_FLAG_UNSET (input_frame,
GST_FFMPEG_VIDEO_CODEC_FRAME_FLAG_ALLOCATED); GST_FFMPEG_VIDEO_CODEC_FRAME_FLAG_ALLOCATED);
if (gst_video_decoder_get_subframe_mode (GST_VIDEO_DECODER (ffmpegdec))) if (gst_video_decoder_get_subframe_mode (GST_VIDEO_DECODER (ffmpegdec)))
gst_video_decoder_have_last_subframe (GST_VIDEO_DECODER (ffmpegdec), gst_video_decoder_have_last_subframe (GST_VIDEO_DECODER (ffmpegdec),
out_frame); output_frame);
/* FIXME: Ideally we would remap the buffer read-only now before pushing but /* FIXME: Ideally we would remap the buffer read-only now before pushing but
* libav might still have a reference to it! * libav might still have a reference to it!
*/ */
if (GST_BUFFER_FLAG_IS_SET (out_frame->input_buffer, if (GST_BUFFER_FLAG_IS_SET (output_frame->input_buffer,
GST_VIDEO_BUFFER_FLAG_ONEFIELD)) { GST_VIDEO_BUFFER_FLAG_ONEFIELD)) {
GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_BUFFER_FLAG_SET (output_frame->output_buffer,
GST_VIDEO_BUFFER_FLAG_ONEFIELD); GST_VIDEO_BUFFER_FLAG_ONEFIELD);
if (GST_BUFFER_FLAG_IS_SET (out_frame->input_buffer, if (GST_BUFFER_FLAG_IS_SET (output_frame->input_buffer,
GST_VIDEO_BUFFER_FLAG_TFF)) { GST_VIDEO_BUFFER_FLAG_TFF)) {
GST_BUFFER_FLAG_SET (out_frame->output_buffer, GST_VIDEO_BUFFER_FLAG_TFF); GST_BUFFER_FLAG_SET (output_frame->output_buffer,
GST_VIDEO_BUFFER_FLAG_TFF);
} }
} }
*ret = *ret =
gst_video_decoder_finish_frame (GST_VIDEO_DECODER (ffmpegdec), out_frame); gst_video_decoder_finish_frame (GST_VIDEO_DECODER (ffmpegdec),
output_frame);
beach: beach:
GST_DEBUG_OBJECT (ffmpegdec, "return flow %s, got frame: %d", GST_DEBUG_OBJECT (ffmpegdec, "return flow %s, got frame: %d",
@ -2092,15 +2107,15 @@ beach:
no_output: no_output:
{ {
GST_DEBUG_OBJECT (ffmpegdec, "no output buffer"); GST_DEBUG_OBJECT (ffmpegdec, "no output buffer");
GST_VIDEO_CODEC_FRAME_FLAG_UNSET (frame, GST_VIDEO_CODEC_FRAME_FLAG_UNSET (input_frame,
GST_FFMPEG_VIDEO_CODEC_FRAME_FLAG_ALLOCATED); GST_FFMPEG_VIDEO_CODEC_FRAME_FLAG_ALLOCATED);
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (ffmpegdec), out_frame); gst_video_decoder_drop_frame (GST_VIDEO_DECODER (ffmpegdec), output_frame);
goto beach; goto beach;
} }
negotiation_error: negotiation_error:
{ {
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (ffmpegdec), out_frame); gst_video_decoder_drop_frame (GST_VIDEO_DECODER (ffmpegdec), output_frame);
if (GST_PAD_IS_FLUSHING (GST_VIDEO_DECODER_SRC_PAD (ffmpegdec))) { if (GST_PAD_IS_FLUSHING (GST_VIDEO_DECODER_SRC_PAD (ffmpegdec))) {
*ret = GST_FLOW_FLUSHING; *ret = GST_FLOW_FLUSHING;
goto beach; goto beach;
@ -2109,39 +2124,16 @@ negotiation_error:
*ret = GST_FLOW_NOT_NEGOTIATED; *ret = GST_FLOW_NOT_NEGOTIATED;
goto beach; goto beach;
} }
}
/* Returns: Whether a frame was decoded */
static gboolean
gst_ffmpegviddec_frame (GstFFMpegVidDec * ffmpegdec, GstVideoCodecFrame * frame,
GstFlowReturn * ret)
{
gboolean got_frame = FALSE;
if (G_UNLIKELY (ffmpegdec->context->codec == NULL))
goto no_codec;
*ret = GST_FLOW_OK;
#if LIBAVCODEC_VERSION_MAJOR >= 60
ffmpegdec->context->frame_num++;
#else
ffmpegdec->context->frame_number++;
#endif
got_frame = gst_ffmpegviddec_video_frame (ffmpegdec, frame, ret);
return got_frame;
/* ERRORS */
no_codec: no_codec:
{ {
GST_ERROR_OBJECT (ffmpegdec, "no codec context"); GST_ERROR_OBJECT (ffmpegdec, "no codec context");
*ret = GST_FLOW_NOT_NEGOTIATED; *ret = GST_FLOW_NOT_NEGOTIATED;
return -1; goto beach;
} }
} }
static GstFlowReturn static GstFlowReturn
gst_ffmpegviddec_drain (GstVideoDecoder * decoder) gst_ffmpegviddec_drain (GstVideoDecoder * decoder)
{ {
@ -2160,7 +2152,7 @@ gst_ffmpegviddec_drain (GstVideoDecoder * decoder)
GST_VIDEO_DECODER_STREAM_LOCK (ffmpegdec); GST_VIDEO_DECODER_STREAM_LOCK (ffmpegdec);
do { do {
got_frame = gst_ffmpegviddec_frame (ffmpegdec, NULL, &ret); got_frame = gst_ffmpegviddec_video_frame (ffmpegdec, NULL, &ret);
} while (got_frame && ret == GST_FLOW_OK); } while (got_frame && ret == GST_FLOW_OK);
GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec); GST_VIDEO_DECODER_STREAM_UNLOCK (ffmpegdec);
@ -2285,7 +2277,7 @@ gst_ffmpegviddec_handle_frame (GstVideoDecoder * decoder,
do { do {
/* decode a frame of audio/video now */ /* decode a frame of audio/video now */
got_frame = gst_ffmpegviddec_frame (ffmpegdec, frame, &ret); got_frame = gst_ffmpegviddec_video_frame (ffmpegdec, frame, &ret);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {
GST_LOG_OBJECT (ffmpegdec, "breaking because of flow ret %s", GST_LOG_OBJECT (ffmpegdec, "breaking because of flow ret %s",