From 195f2afea64f33ab870836fc07a0e2756f371e14 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 29 Apr 2011 18:35:55 +0200 Subject: [PATCH] ffmpeg: use bufferpool instead of pad_alloc --- ext/ffmpeg/gstffmpegdec.c | 94 ++++++++++++++++++++++--------- ext/ffmpeg/gstffmpegdeinterlace.c | 35 ++++++------ ext/ffmpeg/gstffmpegdemux.c | 8 +-- ext/ffmpeg/gstffmpegprotocol.c | 5 +- 4 files changed, 88 insertions(+), 54 deletions(-) diff --git a/ext/ffmpeg/gstffmpegdec.c b/ext/ffmpeg/gstffmpegdec.c index e0c7f6f235..a70152bc11 100644 --- a/ext/ffmpeg/gstffmpegdec.c +++ b/ext/ffmpeg/gstffmpegdec.c @@ -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; diff --git a/ext/ffmpeg/gstffmpegdeinterlace.c b/ext/ffmpeg/gstffmpegdeinterlace.c index 422c9758e8..c8d73ebdca 100644 --- a/ext/ffmpeg/gstffmpegdeinterlace.c +++ b/ext/ffmpeg/gstffmpegdeinterlace.c @@ -166,31 +166,28 @@ gst_ffmpegdeinterlace_chain (GstPad * pad, GstBuffer * inbuf) GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad)); GstBuffer *outbuf = NULL; GstFlowReturn result; + guint8 *from_data, *to_data; + gsize from_size, to_size; - 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); + 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); - to_data = gst_buffer_map (outbuf, &to_size, NULL, GST_MAP_WRITE); - gst_ffmpeg_avpicture_fill (&deinterlace->to_frame, to_data, - deinterlace->pixfmt, deinterlace->width, deinterlace->height); + to_data = gst_buffer_map (outbuf, &to_size, NULL, GST_MAP_WRITE); + gst_ffmpeg_avpicture_fill (&deinterlace->to_frame, to_data, + deinterlace->pixfmt, deinterlace->width, deinterlace->height); - avpicture_deinterlace (&deinterlace->to_frame, &deinterlace->from_frame, - deinterlace->pixfmt, deinterlace->width, deinterlace->height); - gst_buffer_unmap (outbuf, to_data, to_size); - gst_buffer_unmap (inbuf, from_data, from_size); + avpicture_deinterlace (&deinterlace->to_frame, &deinterlace->from_frame, + deinterlace->pixfmt, deinterlace->width, deinterlace->height); + gst_buffer_unmap (outbuf, to_data, to_size); + gst_buffer_unmap (inbuf, from_data, from_size); - gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1); + gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1); - result = gst_pad_push (deinterlace->srcpad, outbuf); - } + result = gst_pad_push (deinterlace->srcpad, outbuf); gst_buffer_unref (inbuf); diff --git a/ext/ffmpeg/gstffmpegdemux.c b/ext/ffmpeg/gstffmpegdemux.c index 7d5f93c3b2..3da557d7cf 100644 --- a/ext/ffmpeg/gstffmpegdemux.c +++ b/ext/ffmpeg/gstffmpegdemux.c @@ -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) { diff --git a/ext/ffmpeg/gstffmpegprotocol.c b/ext/ffmpeg/gstffmpegprotocol.c index 28fc3c116c..ec3c308be4 100644 --- a/ext/ffmpeg/gstffmpegprotocol.c +++ b/ext/ffmpeg/gstffmpegprotocol.c @@ -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);