ext/ffmpeg/: Fix strides and plane sizes when dealing with odd sized movies.
authorWim Taymans <wim.taymans@gmail.com>
Fri, 5 Nov 2004 18:03:04 +0000 (18:03 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 5 Nov 2004 18:03:04 +0000 (18:03 +0000)
Original commit message from CVS:
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_avpicture_get_size),
(gst_ffmpeg_avpicture_fill), (gst_ffmpeg_img_convert):
* ext/ffmpeg/gstffmpegcodecmap.h:
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_chain):
Fix strides and plane sizes when dealing with odd sized
movies.

ChangeLog
ext/ffmpeg/gstffmpegcodecmap.c
ext/ffmpeg/gstffmpegcodecmap.h
ext/ffmpeg/gstffmpegdec.c

index 3469035..77994c1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2004-11-05  Wim Taymans  <wim@fluendo.com>
+
+       * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_avpicture_get_size),
+       (gst_ffmpeg_avpicture_fill), (gst_ffmpeg_img_convert):
+       * ext/ffmpeg/gstffmpegcodecmap.h:
+       * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_chain):
+       Fix strides and plane sizes when dealing with odd sized
+       movies.
+
 2004-10-29  Sebastien Cote  <sc5@hermes.usherb.ca>
 
        Reviewed by:  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
index 28ef757..14f9d2a 100644 (file)
@@ -2134,7 +2134,20 @@ static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
     },
 };
 
-#define ROUND_UP_4(x) (((x) + 3) & ~3)
+int
+gst_ffmpeg_avpicture_get_size (int pix_fmt, int width, int height)
+{
+  AVPicture dummy_pict;
+
+  return gst_ffmpeg_avpicture_fill (&dummy_pict, NULL, pix_fmt, width, height);
+}
+
+#define GEN_MASK(x) ((1<<(x))-1)
+#define ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
+#define ROUND_UP_2(x) ROUND_UP_X (x, 1)
+#define ROUND_UP_4(x) ROUND_UP_X (x, 2)
+#define ROUND_UP_8(x) ROUND_UP_X (x, 3)
+#define DIV_ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) >> (x))
 
 int
 gst_ffmpeg_avpicture_fill (AVPicture * picture,
@@ -2145,8 +2158,6 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
   PixFmtInfo *pinfo;
 
   pinfo = &pix_fmt_info[pix_fmt];
-  stride = ROUND_UP_4 (width);
-  size = stride * height;
   switch (pix_fmt) {
     case PIX_FMT_YUV420P:
     case PIX_FMT_YUV422P:
@@ -2157,10 +2168,11 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
     case PIX_FMT_YUVJ422P:
     case PIX_FMT_YUVJ444P:
       stride = ROUND_UP_4 (width);
-      size = stride * height;
-      w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
+      h2 = ROUND_UP_X (height, pinfo->y_chroma_shift);
+      size = stride * h2;
+      w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift);
       stride2 = ROUND_UP_4 (w2);
-      h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
+      h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift);
       size2 = stride2 * h2;
       picture->data[0] = ptr;
       picture->data[1] = picture->data[0] + size;
@@ -2233,3 +2245,41 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
 
   return 0;
 }
+
+/**
+ * Convert image 'src' to 'dst'.
+ *
+ * We use this code to copy two pictures between the same
+ * colorspaces, so this function is not realy used to do
+ * colorspace conversion.
+ * The ffmpeg code has a bug in it where odd sized frames were
+ * not copied completely. We adjust the input parameters for
+ * the original ffmpeg img_convert function here so that it
+ * still does the right thing.
+ */
+int
+gst_ffmpeg_img_convert (AVPicture * dst, int dst_pix_fmt,
+    const AVPicture * src, int src_pix_fmt, int src_width, int src_height)
+{
+  int i;
+  PixFmtInfo *pf = &pix_fmt_info[src_pix_fmt];
+
+  pf = &pix_fmt_info[src_pix_fmt];
+  switch (pf->pixel_type) {
+    case FF_PIXEL_PACKED:
+      /* nothing wrong here */
+      break;
+    case FF_PIXEL_PLANAR:
+      /* patch up, so that img_copy copies all of the pixels */
+      src_width = ROUND_UP_X (src_width, pf->x_chroma_shift);
+      src_height = ROUND_UP_X (src_height, pf->y_chroma_shift);
+      break;
+    case FF_PIXEL_PALETTE:
+      /* nothing wrong here */
+      break;
+  }
+  return img_convert (dst, dst_pix_fmt, src, src_pix_fmt, src_width, src_height);
+}
+
+
+
index 47ca2c6..1cb94fa 100644 (file)
@@ -96,6 +96,12 @@ G_CONST_RETURN gchar *
 gst_ffmpeg_get_codecid_longname (enum CodecID codec_id);
 
 /*
+ *Get the size of an picture
+ */
+int
+gst_ffmpeg_avpicture_get_size (int pix_fmt, int width, int height);
+
+/*
  * Fill in pointers in an AVPicture, aligned by 4 (required by X).
  */
 
@@ -107,6 +113,15 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
                           int         height);
 
 /*
+ * convert an image, we only use this for copying the image, ie,
+ * convert between the same colorspaces.
+ */
+int
+gst_ffmpeg_img_convert (AVPicture * dst, int dst_pix_fmt,
+    const AVPicture * src, int src_pix_fmt, int src_width, int src_height);
+
+
+/*
  * FFMPEG debugging function; maybe move to a different file.
  */
 
index db4d084..739e23c 100644 (file)
@@ -358,6 +358,9 @@ gst_ffmpegdec_release_buffer (AVCodecContext * context, AVFrame * picture)
 }
 #endif
 
+#define ROUND_UP_2(x) (((x) + 1) & ~1)
+#define ROUND_UP_4(x) (((x) + 3) & ~3)
+
 static void
 gst_ffmpegdec_chain (GstPad * pad, GstData * _data)
 {
@@ -406,23 +409,28 @@ gst_ffmpegdec_chain (GstPad * pad, GstData * _data)
             ffmpegdec->picture, &have_data, data, size);
 
         if (len >= 0 && have_data) {
-#define ROUND_UP_4(x) (((x) + 3) & ~3)
           /* libavcodec constantly crashes on stupid buffer allocation
            * errors inside. This drives me crazy, so we let it allocate
            * it's own buffers and copy to our own buffer afterwards... */
           AVPicture pic;
-          gint size = avpicture_get_size (ffmpegdec->context->pix_fmt,
-              ROUND_UP_4 (ffmpegdec->context->width),
-              ROUND_UP_4 (ffmpegdec->context->height));
+          gint size = gst_ffmpeg_avpicture_get_size (ffmpegdec->context->pix_fmt,
+              ffmpegdec->context->width, ffmpegdec->context->height);
 
           outbuf = gst_buffer_new_and_alloc (size);
+         /* original ffmpeg code does not handle odd sizes correctly. This patched
+          * up version does */
           gst_ffmpeg_avpicture_fill (&pic, GST_BUFFER_DATA (outbuf),
               ffmpegdec->context->pix_fmt,
               ffmpegdec->context->width, ffmpegdec->context->height);
-          img_convert (&pic, ffmpegdec->context->pix_fmt,
+
+         /* the original convert function did not do the right thing, this
+          * is a patched up version that adjust widht/height so that the
+          * ffmpeg one works correctly. */
+          gst_ffmpeg_img_convert (&pic, ffmpegdec->context->pix_fmt,
               (AVPicture *) ffmpegdec->picture,
               ffmpegdec->context->pix_fmt,
-              ffmpegdec->context->width, ffmpegdec->context->height);
+              ffmpegdec->context->width, 
+             ffmpegdec->context->height);
 
           /* note that ffmpeg sometimes gets the FPS wrong */
           if (GST_CLOCK_TIME_IS_VALID (expected_ts) &&