[prev in list] [next in list] [prev in thread] [next in thread]
List: gstreamer-cvs
Subject: [0.11] gst-ffmpeg: ffdec: refactor picture fill code
From: wtay () kemper ! freedesktop ! org (Wim Taymans)
Date: 2011-07-29 15:32:55
Message-ID: 20110729153255.08B7AD8003 () kemper ! freedesktop ! org
[Download RAW message or body]
Module: gst-ffmpeg
Branch: 0.11
Commit: 1dc718b195ae096822bc887d3f6aa0f8c061ad66
URL: http://cgit.freedesktop.org/gstreamer/gst-ffmpeg/commit/?id=1dc718b195ae096822bc887d3f6aa0f8c061ad66
Author: Wim Taymans <wim.taymans@collabora.co.uk>
Date: Fri Jul 29 13:40:30 2011 +0200
ffdec: refactor picture fill code
Make a method to hold the code to convert a GstVideoFrame to an AVFrame so that
we can reuse it in the non-direct rendering case.
---
ext/ffmpeg/gstffmpegdec.c | 143 +++++++++++++++++++++++++--------------------
1 files changed, 80 insertions(+), 63 deletions(-)
diff --git a/ext/ffmpeg/gstffmpegdec.c b/ext/ffmpeg/gstffmpegdec.c
index fe72d79..784c366 100644
--- a/ext/ffmpeg/gstffmpegdec.c
+++ b/ext/ffmpeg/gstffmpegdec.c
@@ -889,6 +889,44 @@ open_failed:
}
}
+static void
+gst_ffmpegdec_fill_picture (GstFFMpegDec * ffmpegdec, GstVideoFrame * frame,
+ AVFrame * picture)
+{
+ guint i;
+ AVCodecContext *context = ffmpegdec->context;
+
+ /* setup data pointers and strides */
+ for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (frame); i++) {
+ picture->data[i] = GST_VIDEO_FRAME_PLANE_DATA (frame, i);
+ picture->linesize[i] = GST_VIDEO_FRAME_PLANE_STRIDE (frame, i);
+
+ GST_LOG_OBJECT (ffmpegdec, "plane %d: data %p, linesize %d", i,
+ picture->data[i], picture->linesize[i]);
+ }
+
+ /* adjust for the borders */
+ if (!(context->flags & CODEC_FLAG_EMU_EDGE)) {
+ gint edge = avcodec_get_edge_width ();
+ const GstVideoFormatInfo *vinfo = frame->info.finfo;
+
+ /* FIXME, not quite correct, NV12 would apply the vedge twice on the second
+ * plane */
+ for (i = 0; i < GST_VIDEO_FRAME_N_COMPONENTS (frame); i++) {
+ gint vedge, hedge, plane;
+
+ hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, edge);
+ vedge = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, i, edge);
+ plane = GST_VIDEO_FORMAT_INFO_PLANE (vinfo, i);
+
+ GST_LOG_OBJECT (ffmpegdec, "comp %d, plane %d: hedge %d, vedge %d", i,
+ plane, hedge, vedge);
+
+ picture->data[plane] += (vedge * picture->linesize[plane]) + hedge;
+ }
+ }
+}
+
/* called when ffmpeg wants us to allocate a buffer to write the decoded frame
* into. We try to give it memory from our pool */
static int
@@ -897,8 +935,7 @@ gst_ffmpegdec_get_buffer (AVCodecContext * context, AVFrame * \
picture) GstBuffer *buf = NULL;
GstFFMpegDec *ffmpegdec;
GstFlowReturn ret;
- GstVideoFrame *frame;
- guint i;
+ GstVideoFrame frame;
ffmpegdec = (GstFFMpegDec *) context->opaque;
@@ -924,48 +961,20 @@ gst_ffmpegdec_get_buffer (AVCodecContext * context, AVFrame * \
picture) if (G_UNLIKELY (ret != GST_FLOW_OK))
goto alloc_failed;
- frame = g_slice_new (GstVideoFrame);
- if (!gst_video_frame_map (frame, &ffmpegdec->pool_info, buf,
+ if (!gst_video_frame_map (&frame, &ffmpegdec->pool_info, buf,
GST_MAP_READWRITE))
goto invalid_frame;
- /* setup data pointers and strides */
- for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (frame); i++) {
- picture->data[i] = GST_VIDEO_FRAME_PLANE_DATA (frame, i);
- picture->linesize[i] = GST_VIDEO_FRAME_PLANE_STRIDE (frame, i);
-
- GST_LOG_OBJECT (ffmpegdec, "plane %d: data %p, linesize %d", i,
- picture->data[i], picture->linesize[i]);
- }
-
- /* adjust for the borders */
- if (!(context->flags & CODEC_FLAG_EMU_EDGE)) {
- gint edge = avcodec_get_edge_width ();
- const GstVideoFormatInfo *vinfo = frame->info.finfo;
-
- /* FIXME, not quite correct, NV12 would apply the vedge twice on the second
- * plane */
- for (i = 0; i < GST_VIDEO_FRAME_N_COMPONENTS (frame); i++) {
- gint vedge, hedge, plane;
-
- hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, edge);
- vedge = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, i, edge);
- plane = GST_VIDEO_FORMAT_INFO_PLANE (vinfo, i);
-
- GST_LOG_OBJECT (ffmpegdec, "comp %d, plane %d: hedge %d, vedge %d", i,
- plane, hedge, vedge);
-
- picture->data[plane] += (vedge * picture->linesize[plane]) + hedge;
- }
- }
+ gst_ffmpegdec_fill_picture (ffmpegdec, &frame, picture);
/* tell ffmpeg we own this buffer, tranfer the ref we have on the buffer to
* the opaque data. */
picture->type = FF_BUFFER_TYPE_USER;
picture->age = 256 * 256 * 256 * 64;
- picture->opaque = frame;
+ picture->opaque = g_slice_dup (GstVideoFrame, &frame);
- GST_LOG_OBJECT (ffmpegdec, "returned buffer %p in frame %p", buf, frame);
+ GST_LOG_OBJECT (ffmpegdec, "returned buffer %p in frame %p", buf,
+ picture->opaque);
return 0;
@@ -991,7 +1000,6 @@ 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 (buf);
- g_slice_free (GstVideoFrame, frame);
goto fallback;
}
fallback:
@@ -1626,63 +1634,72 @@ static GstFlowReturn
get_output_buffer (GstFFMpegDec * ffmpegdec, GstBuffer ** outbuf)
{
GstFlowReturn ret;
- GstVideoFrame *frame;
-
- ret = GST_FLOW_OK;
- *outbuf = NULL;
if (ffmpegdec->picture->opaque != NULL) {
+ GstVideoFrame *frame;
+
/* we allocated a picture already for ffmpeg to decode into, let's pick it
* up and use it now. */
frame = ffmpegdec->picture->opaque;
*outbuf = frame->buffer;
- GST_LOG_OBJECT (ffmpegdec, "using opaque buffer %p", *outbuf);
+ GST_LOG_OBJECT (ffmpegdec, "using opaque buffer %p on frame %p", *outbuf,
+ frame);
gst_buffer_ref (*outbuf);
} else {
- AVPicture pic, *outpic;
+ GstVideoFrame frame;
+ AVPicture *src, *dest;
+ AVFrame pic;
gint width, height;
- guint8 *data;
- gsize size;
+ GstBuffer *buf;
GST_LOG_OBJECT (ffmpegdec, "get output buffer");
- width = ffmpegdec->out_info.width;
- height = ffmpegdec->out_info.height;
-
- GST_LOG_OBJECT (ffmpegdec, "width %d/height %d", width, height);
+ if (G_UNLIKELY (!gst_ffmpegdec_video_negotiate (ffmpegdec, FALSE)))
+ goto negotiate_failed;
- ret = gst_buffer_pool_acquire_buffer (ffmpegdec->pool, outbuf, NULL);
+ ret = gst_buffer_pool_acquire_buffer (ffmpegdec->pool, &buf, NULL);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto alloc_failed;
- /* original ffmpeg code does not handle odd sizes correctly.
- * This patched up version does */
- data = gst_buffer_map (*outbuf, &size, NULL, GST_MAP_WRITE);
+ if (!gst_video_frame_map (&frame, &ffmpegdec->pool_info, buf,
+ GST_MAP_READWRITE))
+ goto invalid_frame;
- gst_ffmpeg_avpicture_fill (&pic, data,
- ffmpegdec->context->pix_fmt, width, height);
+ gst_ffmpegdec_fill_picture (ffmpegdec, &frame, &pic);
- outpic = (AVPicture *) ffmpegdec->picture;
+ width = ffmpegdec->out_info.width;
+ height = ffmpegdec->out_info.height;
- GST_LOG_OBJECT (ffmpegdec, "linsize %d %d %d", outpic->linesize[0],
- outpic->linesize[1], outpic->linesize[2]);
- GST_LOG_OBJECT (ffmpegdec, "data %u %u %u", 0,
- (guint) (outpic->data[1] - outpic->data[0]),
- (guint) (outpic->data[2] - outpic->data[0]));
+ src = (AVPicture *) ffmpegdec->picture;
+ dest = (AVPicture *) & pic;
- av_picture_copy (&pic, outpic, ffmpegdec->context->pix_fmt, width, height);
- gst_buffer_unmap (*outbuf, data, size);
+ GST_LOG_OBJECT (ffmpegdec, "copy width %d/height %d", width, height);
+ av_picture_copy (dest, src, ffmpegdec->context->pix_fmt, width, height);
+
+ gst_video_frame_unmap (&frame);
+
+ *outbuf = buf;
}
ffmpegdec->picture->reordered_opaque = -1;
- return ret;
+ return GST_FLOW_OK;
/* special cases */
+negotiate_failed:
+ {
+ GST_DEBUG_OBJECT (ffmpegdec, "negotiation failed");
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
alloc_failed:
{
GST_DEBUG_OBJECT (ffmpegdec, "buffer alloc failed");
return ret;
}
+invalid_frame:
+ {
+ GST_DEBUG_OBJECT (ffmpegdec, "could not map frame");
+ return GST_FLOW_ERROR;
+ }
}
static void
_______________________________________________
gstreamer-commits mailing list
gstreamer-commits@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/gstreamer-commits
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic