mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
avviddec: improve buffer handling and semantics
... so as to focus on providing *a* buffer rather than one (too) tied to a frame, in particular allowing multiple allocations related to a frame. Fixes https://bugzilla.gnome.org/show_bug.cgi?id=697806
This commit is contained in:
parent
1aa253cd3b
commit
47d5c2b6d6
1 changed files with 22 additions and 6 deletions
|
@ -527,6 +527,7 @@ typedef struct
|
|||
GstVideoCodecFrame *frame;
|
||||
gboolean mapped;
|
||||
GstVideoFrame vframe;
|
||||
GstBuffer *buffer;
|
||||
} GstFFMpegVidDecVideoFrame;
|
||||
|
||||
static GstFFMpegVidDecVideoFrame *
|
||||
|
@ -547,6 +548,7 @@ gst_ffmpegviddec_video_frame_free (GstFFMpegVidDec * ffmpegdec,
|
|||
if (frame->mapped)
|
||||
gst_video_frame_unmap (&frame->vframe);
|
||||
gst_video_decoder_release_frame (GST_VIDEO_DECODER (ffmpegdec), frame->frame);
|
||||
gst_buffer_replace (&frame->buffer, NULL);
|
||||
g_slice_free (GstFFMpegVidDecVideoFrame, frame);
|
||||
}
|
||||
|
||||
|
@ -570,6 +572,8 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture)
|
|||
* picture back from ffmpeg we can use this to correctly timestamp the output
|
||||
* buffer */
|
||||
picture->reordered_opaque = context->reordered_opaque;
|
||||
GST_DEBUG_OBJECT (ffmpegdec, "opaque value SN %d",
|
||||
(gint32) picture->reordered_opaque);
|
||||
|
||||
frame =
|
||||
gst_video_decoder_get_frame (GST_VIDEO_DECODER (ffmpegdec),
|
||||
|
@ -605,9 +609,16 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture)
|
|||
if (ret != GST_FLOW_OK)
|
||||
goto alloc_failed;
|
||||
|
||||
/* piggy-backed alloc'ed on the frame,
|
||||
* and there was much rejoicing and we are grateful.
|
||||
* Now take away buffer from frame, we will give it back later when decoded.
|
||||
* This allows multiple request for a buffer per frame; unusual but possible. */
|
||||
gst_buffer_replace (&dframe->buffer, frame->output_buffer);
|
||||
gst_buffer_replace (&frame->output_buffer, NULL);
|
||||
|
||||
/* Fill avpicture */
|
||||
info = &ffmpegdec->output_state->info;
|
||||
if (!gst_video_frame_map (&dframe->vframe, info, dframe->frame->output_buffer,
|
||||
if (!gst_video_frame_map (&dframe->vframe, info, dframe->buffer,
|
||||
GST_MAP_READWRITE))
|
||||
goto invalid_frame;
|
||||
dframe->mapped = TRUE;
|
||||
|
@ -635,7 +646,7 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture)
|
|||
}
|
||||
gst_video_frame_unmap (&dframe->vframe);
|
||||
dframe->mapped = FALSE;
|
||||
gst_buffer_replace (&frame->output_buffer, NULL);
|
||||
gst_buffer_replace (&dframe->buffer, NULL);
|
||||
ffmpegdec->current_dr = FALSE;
|
||||
|
||||
goto no_dr;
|
||||
|
@ -652,7 +663,7 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture)
|
|||
* the opaque data. */
|
||||
picture->type = FF_BUFFER_TYPE_USER;
|
||||
|
||||
GST_LOG_OBJECT (ffmpegdec, "returned frame %p", frame->output_buffer);
|
||||
GST_LOG_OBJECT (ffmpegdec, "returned frame %p", dframe->buffer);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -677,8 +688,7 @@ invalid_frame:
|
|||
{
|
||||
/* alloc default buffer when we can't get one from downstream */
|
||||
GST_LOG_OBJECT (ffmpegdec, "failed to map frame, fallback alloc");
|
||||
gst_buffer_unref (frame->output_buffer);
|
||||
frame->output_buffer = NULL;
|
||||
gst_buffer_replace (&dframe->buffer, NULL);
|
||||
goto fallback;
|
||||
}
|
||||
fallback:
|
||||
|
@ -704,6 +714,8 @@ no_frame:
|
|||
}
|
||||
}
|
||||
|
||||
/* this should havesame effect as _get_buffer wrt opaque metadata,
|
||||
* but preserving current content, if any */
|
||||
static int
|
||||
gst_ffmpegviddec_reget_buffer (AVCodecContext * context, AVFrame * picture)
|
||||
{
|
||||
|
@ -764,7 +776,7 @@ gst_ffmpegviddec_release_buffer (AVCodecContext * context, AVFrame * picture)
|
|||
|
||||
ffmpegdec = (GstFFMpegVidDec *) context->opaque;
|
||||
frame = (GstFFMpegVidDecVideoFrame *) picture->opaque;
|
||||
GST_DEBUG_OBJECT (ffmpegdec, "release frame %d",
|
||||
GST_DEBUG_OBJECT (ffmpegdec, "release frame SN %d",
|
||||
frame->frame->system_frame_number);
|
||||
|
||||
/* check if it was our buffer */
|
||||
|
@ -1214,6 +1226,10 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec,
|
|||
out_dframe = ffmpegdec->picture->opaque;
|
||||
out_frame = gst_video_codec_frame_ref (out_dframe->frame);
|
||||
|
||||
/* also give back a buffer allocated by the frame, if any */
|
||||
gst_buffer_replace (&out_frame->output_buffer, out_dframe->buffer);
|
||||
gst_buffer_replace (&out_dframe->buffer, NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (ffmpegdec,
|
||||
"pts %" G_GUINT64_FORMAT " duration %" G_GUINT64_FORMAT,
|
||||
out_frame->pts, out_frame->duration);
|
||||
|
|
Loading…
Reference in a new issue