ffmpeg: use bufferpool instead of pad_alloc

This commit is contained in:
Wim Taymans 2011-04-29 18:35:55 +02:00
parent 6d4cdb2877
commit 195f2afea6
4 changed files with 88 additions and 54 deletions

View file

@ -68,6 +68,7 @@ struct _GstFFMpegDec
AVCodecContext *context;
AVFrame *picture;
gboolean opened;
GstBufferPool *pool;
union
{
struct
@ -136,9 +137,6 @@ struct _GstFFMpegDec
/* reverse playback queue */
GList *queued;
/* Can downstream allocate 16bytes aligned data. */
gboolean can_allocate_aligned;
};
typedef struct _GstFFMpegDecClass GstFFMpegDecClass;
@ -433,9 +431,6 @@ gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec)
ffmpegdec->format.video.fps_n = -1;
ffmpegdec->format.video.old_fps_n = -1;
gst_segment_init (&ffmpegdec->segment, GST_FORMAT_TIME);
/* We initially assume downstream can allocate 16 bytes aligned buffers */
ffmpegdec->can_allocate_aligned = TRUE;
}
static void
@ -443,15 +438,14 @@ gst_ffmpegdec_finalize (GObject * object)
{
GstFFMpegDec *ffmpegdec = (GstFFMpegDec *) object;
if (ffmpegdec->context != NULL) {
if (ffmpegdec->context != NULL)
av_free (ffmpegdec->context);
ffmpegdec->context = NULL;
}
if (ffmpegdec->picture != NULL) {
if (ffmpegdec->picture != NULL)
av_free (ffmpegdec->picture);
ffmpegdec->picture = NULL;
}
if (ffmpegdec->pool)
gst_object_unref (ffmpegdec->pool);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -913,12 +907,10 @@ alloc_output_buffer (GstFFMpegDec * ffmpegdec, GstBuffer ** outbuf,
fsize = gst_ffmpeg_avpicture_get_size (ffmpegdec->context->pix_fmt,
width, height);
if (!ffmpegdec->context->palctrl && ffmpegdec->can_allocate_aligned) {
if (!ffmpegdec->context->palctrl) {
GST_LOG_OBJECT (ffmpegdec, "calling pad_alloc");
/* no pallete, we can use the buffer size to alloc */
ret = gst_pad_alloc_buffer_and_set_caps (ffmpegdec->srcpad,
GST_BUFFER_OFFSET_NONE, fsize,
GST_PAD_CAPS (ffmpegdec->srcpad), outbuf);
ret = gst_buffer_pool_acquire_buffer (ffmpegdec->pool, outbuf, NULL);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto alloc_failed;
} else {
@ -1031,15 +1023,6 @@ gst_ffmpegdec_get_buffer (AVCodecContext * context, AVFrame * picture)
/* FIXME, unmap me later */
data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
if (((uintptr_t) data) % 16) {
/* If buffer isn't 128-bit aligned, create a memaligned one ourselves */
gst_buffer_unmap (buf, data, size);
gst_buffer_unref (buf);
GST_DEBUG_OBJECT (ffmpegdec,
"Downstream can't allocate aligned buffers.");
ffmpegdec->can_allocate_aligned = FALSE;
return avcodec_default_get_buffer (context, picture);
}
/* copy the right pointers and strides in the picture object */
gst_ffmpeg_avpicture_fill ((AVPicture *) picture,
@ -1188,6 +1171,48 @@ no_par:
}
}
static gboolean
gst_ffmpegdec_bufferpool (GstFFMpegDec * ffmpegdec, GstCaps * caps)
{
GstQuery *query;
GstBufferPool *pool = NULL;
guint alignment, prefix, size;
GstStructure *config;
/* find a pool for the negotiated caps now */
query = gst_query_new_allocation (caps, TRUE);
if (gst_pad_peer_query (ffmpegdec->srcpad, query)) {
/* we got configuration from our peer, parse them */
gst_query_parse_allocation_params (query, &alignment, &prefix, &size,
&pool);
} else {
alignment = 16;
prefix = 0;
size = gst_ffmpeg_avpicture_get_size (ffmpegdec->context->pix_fmt,
ffmpegdec->context->width, ffmpegdec->context->height);
}
if (pool == NULL) {
/* we did not get a pool, make one ourselves then */
pool = gst_buffer_pool_new ();
}
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set (config, caps, size, 0, 0, prefix, 0,
MAX (alignment, 16));
gst_buffer_pool_set_config (pool, config);
if (ffmpegdec->pool)
gst_object_unref (ffmpegdec->pool);
ffmpegdec->pool = pool;
/* and activate */
gst_buffer_pool_set_active (pool, TRUE);
return TRUE;
}
static gboolean
gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec, gboolean force)
{
@ -1297,6 +1322,10 @@ gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec, gboolean force)
if (!gst_pad_set_caps (ffmpegdec->srcpad, caps))
goto caps_failed;
/* now figure out a bufferpool */
if (!gst_ffmpegdec_bufferpool (ffmpegdec, caps))
goto no_bufferpool;
gst_caps_unref (caps);
return TRUE;
@ -1329,6 +1358,15 @@ caps_failed:
oclass->in_plugin->name));
gst_caps_unref (caps);
return FALSE;
}
no_bufferpool:
{
GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL),
("Could not create bufferpool for fmpeg decoder (%s)",
oclass->in_plugin->name));
gst_caps_unref (caps);
return FALSE;
}
}
@ -2782,7 +2820,11 @@ gst_ffmpegdec_change_state (GstElement * element, GstStateChange transition)
g_free (ffmpegdec->padded);
ffmpegdec->padded = NULL;
ffmpegdec->padded_size = 0;
ffmpegdec->can_allocate_aligned = TRUE;
if (ffmpegdec->pool) {
gst_buffer_pool_set_active (ffmpegdec->pool, FALSE);
gst_object_unref (ffmpegdec->pool);
}
ffmpegdec->pool = NULL;
break;
default:
break;

View file

@ -166,14 +166,12 @@ gst_ffmpegdeinterlace_chain (GstPad * pad, GstBuffer * inbuf)
GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad));
GstBuffer *outbuf = NULL;
GstFlowReturn result;
result =
gst_pad_alloc_buffer (deinterlace->srcpad, GST_BUFFER_OFFSET_NONE,
deinterlace->to_size, GST_PAD_CAPS (deinterlace->srcpad), &outbuf);
if (result == GST_FLOW_OK) {
guint8 *from_data, *to_data;
gsize from_size, to_size;
outbuf = gst_buffer_new_and_alloc (deinterlace->to_size);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (deinterlace->srcpad));
from_data = gst_buffer_map (inbuf, &from_size, NULL, GST_MAP_READ);
gst_ffmpeg_avpicture_fill (&deinterlace->from_frame, from_data,
deinterlace->pixfmt, deinterlace->width, deinterlace->height);
@ -190,7 +188,6 @@ gst_ffmpegdeinterlace_chain (GstPad * pad, GstBuffer * inbuf)
gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
result = gst_pad_push (deinterlace->srcpad, outbuf);
}
gst_buffer_unref (inbuf);

View file

@ -1398,16 +1398,12 @@ gst_ffmpegdemux_loop (GstFFMpegDemux * demux)
else
outsize = pkt.size;
stream->last_flow = gst_pad_alloc_buffer_and_set_caps (srcpad,
GST_CLOCK_TIME_NONE, outsize, GST_PAD_CAPS (srcpad), &outbuf);
outbuf = gst_buffer_new_and_alloc (outsize);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (srcpad));
if ((ret = gst_ffmpegdemux_aggregated_flow (demux)) != GST_FLOW_OK)
goto no_buffer;
/* If the buffer allocation failed, don't try sending it ! */
if (stream->last_flow != GST_FLOW_OK)
goto done;
/* copy the data from packet into the target buffer
* and do conversions for raw video packets */
if (rawvideo) {

View file

@ -165,9 +165,8 @@ gst_ffmpegdata_write (URLContext * h, const unsigned char *buf, int size)
g_return_val_if_fail (h->flags != URL_RDONLY, -EIO);
/* create buffer and push data further */
if (gst_pad_alloc_buffer_and_set_caps (info->pad,
info->offset, size, GST_PAD_CAPS (info->pad), &outbuf) != GST_FLOW_OK)
return 0;
outbuf = gst_buffer_new_and_alloc (size);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (info->pad));
gst_buffer_fill (outbuf, 0, buf, size);