[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