mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-04 06:29:31 +00:00
avviddec: release buffers when not direct rendering
New libav will not call the release_buffer callback anymore when avcodec_default_get_buffer() is called from get_buffer. Releasing of the memory in a picture should now be done by registering a callback to the avbuffer objects in the picture. There is some compatibility code to wrap the memory we provide in get_buffer in avbuffer with a callback to release_buffer but that is not done when avcodec_default_get_buffer() is called. Work around this by adding a dummy avbuffer object to the picture that will release the frame. Fixes https://bugzilla.gnome.org/show_bug.cgi?id=721077
This commit is contained in:
parent
1e65aac1a4
commit
81cef109e2
1 changed files with 29 additions and 5 deletions
|
@ -524,6 +524,7 @@ open_failed:
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
GstFFMpegVidDec *ffmpegdec;
|
||||||
GstVideoCodecFrame *frame;
|
GstVideoCodecFrame *frame;
|
||||||
gboolean mapped;
|
gboolean mapped;
|
||||||
GstVideoFrame vframe;
|
GstVideoFrame vframe;
|
||||||
|
@ -531,13 +532,17 @@ typedef struct
|
||||||
} GstFFMpegVidDecVideoFrame;
|
} GstFFMpegVidDecVideoFrame;
|
||||||
|
|
||||||
static GstFFMpegVidDecVideoFrame *
|
static GstFFMpegVidDecVideoFrame *
|
||||||
gst_ffmpegviddec_video_frame_new (GstVideoCodecFrame * frame)
|
gst_ffmpegviddec_video_frame_new (GstFFMpegVidDec * ffmpegdec,
|
||||||
|
GstVideoCodecFrame * frame)
|
||||||
{
|
{
|
||||||
GstFFMpegVidDecVideoFrame *dframe;
|
GstFFMpegVidDecVideoFrame *dframe;
|
||||||
|
|
||||||
dframe = g_slice_new0 (GstFFMpegVidDecVideoFrame);
|
dframe = g_slice_new0 (GstFFMpegVidDecVideoFrame);
|
||||||
|
dframe->ffmpegdec = ffmpegdec;
|
||||||
dframe->frame = frame;
|
dframe->frame = frame;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (ffmpegdec, "new video frame %p", dframe);
|
||||||
|
|
||||||
return dframe;
|
return dframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,6 +550,8 @@ static void
|
||||||
gst_ffmpegviddec_video_frame_free (GstFFMpegVidDec * ffmpegdec,
|
gst_ffmpegviddec_video_frame_free (GstFFMpegVidDec * ffmpegdec,
|
||||||
GstFFMpegVidDecVideoFrame * frame)
|
GstFFMpegVidDecVideoFrame * frame)
|
||||||
{
|
{
|
||||||
|
GST_DEBUG_OBJECT (ffmpegdec, "free video frame %p", frame);
|
||||||
|
|
||||||
if (frame->mapped)
|
if (frame->mapped)
|
||||||
gst_video_frame_unmap (&frame->vframe);
|
gst_video_frame_unmap (&frame->vframe);
|
||||||
gst_video_decoder_release_frame (GST_VIDEO_DECODER (ffmpegdec), frame->frame);
|
gst_video_decoder_release_frame (GST_VIDEO_DECODER (ffmpegdec), frame->frame);
|
||||||
|
@ -552,6 +559,14 @@ gst_ffmpegviddec_video_frame_free (GstFFMpegVidDec * ffmpegdec,
|
||||||
g_slice_free (GstFFMpegVidDecVideoFrame, frame);
|
g_slice_free (GstFFMpegVidDecVideoFrame, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dummy_free_buffer (void *opaque, uint8_t * data)
|
||||||
|
{
|
||||||
|
GstFFMpegVidDecVideoFrame *frame = opaque;
|
||||||
|
|
||||||
|
gst_ffmpegviddec_video_frame_free (frame->ffmpegdec, frame);
|
||||||
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
|
@ -590,7 +605,8 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture)
|
||||||
goto duplicate_frame;
|
goto duplicate_frame;
|
||||||
|
|
||||||
/* GstFFMpegVidDecVideoFrame receives the frame ref */
|
/* GstFFMpegVidDecVideoFrame receives the frame ref */
|
||||||
picture->opaque = dframe = gst_ffmpegviddec_video_frame_new (frame);
|
picture->opaque = dframe =
|
||||||
|
gst_ffmpegviddec_video_frame_new (ffmpegdec, frame);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "storing opaque %p", dframe);
|
GST_DEBUG_OBJECT (ffmpegdec, "storing opaque %p", dframe);
|
||||||
|
|
||||||
|
@ -694,11 +710,19 @@ invalid_frame:
|
||||||
fallback:
|
fallback:
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
gboolean first = TRUE;
|
||||||
int ret = avcodec_default_get_buffer (context, picture);
|
int ret = avcodec_default_get_buffer (context, picture);
|
||||||
|
|
||||||
for (c = 0; c < AV_NUM_DATA_POINTERS; c++)
|
for (c = 0; c < AV_NUM_DATA_POINTERS; c++) {
|
||||||
ffmpegdec->stride[c] = picture->linesize[c];
|
ffmpegdec->stride[c] = picture->linesize[c];
|
||||||
|
|
||||||
|
if (picture->buf[c] == NULL && first) {
|
||||||
|
picture->buf[c] =
|
||||||
|
av_buffer_create (NULL, 0, dummy_free_buffer, dframe, 0);
|
||||||
|
first = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
duplicate_frame:
|
duplicate_frame:
|
||||||
|
@ -1669,8 +1693,8 @@ gst_ffmpegviddec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
|
||||||
avcodec_align_dimensions2 (ffmpegdec->context, &width, &height,
|
avcodec_align_dimensions2 (ffmpegdec->context, &width, &height,
|
||||||
linesize_align);
|
linesize_align);
|
||||||
edge =
|
edge =
|
||||||
ffmpegdec->context->
|
ffmpegdec->
|
||||||
flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width ();
|
context->flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width ();
|
||||||
/* increase the size for the padding */
|
/* increase the size for the padding */
|
||||||
width += edge << 1;
|
width += edge << 1;
|
||||||
height += edge << 1;
|
height += edge << 1;
|
||||||
|
|
Loading…
Reference in a new issue