ext/ffmpeg/: Move palette handling over from the decoder to the colorspace conversion...
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sat, 2 Oct 2004 14:10:27 +0000 (14:10 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sat, 2 Oct 2004 14:10:27 +0000 (14:10 +0000)
Original commit message from CVS:
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_pixfmt_to_caps),
(gst_ffmpeg_caps_to_pixfmt):
* ext/ffmpeg/gstffmpegcolorspace.c: (gst_ffmpegcsp_pad_link),
(gst_ffmpegcsp_init), (gst_ffmpegcsp_chain),
(gst_ffmpegcsp_change_state), (gst_ffmpegcsp_register):
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_chain):
Move palette handling over from the decoder to the colorspace
conversion plugin (where you would expect it).

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

index e5b37e6..0f0318a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2004-10-02  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
+
+       * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_pixfmt_to_caps),
+       (gst_ffmpeg_caps_to_pixfmt):
+       * ext/ffmpeg/gstffmpegcolorspace.c: (gst_ffmpegcsp_pad_link),
+       (gst_ffmpegcsp_init), (gst_ffmpegcsp_chain),
+       (gst_ffmpegcsp_change_state), (gst_ffmpegcsp_register):
+       * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_chain):
+         Move palette handling over from the decoder to the colorspace
+         conversion plugin (where you would expect it).
+
 2004-10-01  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
 
        * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),
index efaac09..67987ac 100644 (file)
@@ -783,19 +783,33 @@ gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context)
       g_mask = 0x03e0;
       b_mask = 0x001f;
       break;
+    case PIX_FMT_PAL8:
+      bpp = depth = 8;
+      endianness = G_BYTE_ORDER;
+      break;
     default:
       /* give up ... */
       break;
   }
 
   if (bpp != 0) {
-    caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb",
-        "bpp", G_TYPE_INT, bpp,
-        "depth", G_TYPE_INT, depth,
-        "red_mask", G_TYPE_INT, r_mask,
-        "green_mask", G_TYPE_INT, g_mask,
-        "blue_mask", G_TYPE_INT, b_mask,
-       "endianness", G_TYPE_INT, endianness, NULL);
+    if (r_mask != 0) {
+      caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb",
+          "bpp", G_TYPE_INT, bpp,
+          "depth", G_TYPE_INT, depth,
+          "red_mask", G_TYPE_INT, r_mask,
+          "green_mask", G_TYPE_INT, g_mask,
+          "blue_mask", G_TYPE_INT, b_mask,
+          "endianness", G_TYPE_INT, endianness, NULL);
+    } else {
+      caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb",
+          "bpp", G_TYPE_INT, bpp,
+          "depth", G_TYPE_INT, depth,
+          "endianness", G_TYPE_INT, endianness, NULL);
+      if (context) {
+        gst_ffmpeg_set_palette (caps, context);
+      }
+    }
   } else if (fmt) {
     caps = GST_FF_VID_CAPS_NEW ("video/x-raw-yuv",
         "format", GST_TYPE_FOURCC, fmt, NULL);
@@ -1012,34 +1026,40 @@ gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps,
     gint bpp = 0, rmask = 0, endianness = 0;
 
     if (gst_structure_get_int (structure, "bpp", &bpp) &&
-        gst_structure_get_int (structure, "endianness", &endianness) &&
-        gst_structure_get_int (structure, "red_mask", &rmask)) {
-      switch (bpp) {
-        case 32:
+        gst_structure_get_int (structure, "endianness", &endianness)) {
+      if (gst_structure_get_int (structure, "red_mask", &rmask)) {
+        switch (bpp) {
+          case 32:
 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
-          if (rmask == 0x00ff0000)
+            if (rmask == 0x00ff0000)
 #else
-          if (rmask == 0x0000ff00)
+            if (rmask == 0x0000ff00)
 #endif
-            context->pix_fmt = PIX_FMT_RGBA32;
-          break;
-        case 24:
-          if (rmask == 0x0000FF)
-            context->pix_fmt = PIX_FMT_BGR24;
-          else
-            context->pix_fmt = PIX_FMT_RGB24;
-          break;
-        case 16:
-          if (endianness == G_BYTE_ORDER)
-            context->pix_fmt = PIX_FMT_RGB565;
-          break;
-        case 15:
-          if (endianness == G_BYTE_ORDER)
-            context->pix_fmt = PIX_FMT_RGB555;
-          break;
-        default:
-          /* nothing */
-          break;
+              context->pix_fmt = PIX_FMT_RGBA32;
+            break;
+          case 24:
+            if (rmask == 0x0000FF)
+              context->pix_fmt = PIX_FMT_BGR24;
+            else
+              context->pix_fmt = PIX_FMT_RGB24;
+            break;
+          case 16:
+            if (endianness == G_BYTE_ORDER)
+              context->pix_fmt = PIX_FMT_RGB565;
+            break;
+          case 15:
+            if (endianness == G_BYTE_ORDER)
+              context->pix_fmt = PIX_FMT_RGB555;
+            break;
+          default:
+            /* nothing */
+            break;
+        }
+      } else {
+        if (bpp == 8) {
+          context->pix_fmt = PIX_FMT_PAL8;
+          gst_ffmpeg_get_palette (caps, context);
+        }
       }
     }
   }
index 3f3d2e1..43b17c4 100644 (file)
@@ -56,6 +56,7 @@ struct _GstFFMpegCsp
   gfloat fps;
   enum PixelFormat from_pixfmt, to_pixfmt;
   AVFrame *from_frame, *to_frame;
+  AVPaletteControl *palette;
   GstCaps *sinkcaps;
 };
 
@@ -227,6 +228,11 @@ gst_ffmpegcsp_pad_link (GstPad * pad, const GstCaps * caps)
     space->to_pixfmt = ctx->pix_fmt;
   } else {
     space->from_pixfmt = ctx->pix_fmt;
+
+    /* palette */
+    if (space->palette)
+      av_free (space->palette);
+    space->palette = ctx->palctrl;
   }
   av_free (ctx);
   if (space->from_frame)
@@ -311,6 +317,7 @@ gst_ffmpegcsp_init (GstFFMpegCsp * space)
 
   space->from_pixfmt = space->to_pixfmt = PIX_FMT_NB;
   space->from_frame = space->to_frame = NULL;
+  space->palette = NULL;
 }
 
 static void
@@ -344,25 +351,54 @@ gst_ffmpegcsp_chain (GstPad * pad, GstData * data)
   if (space->from_pixfmt == space->to_pixfmt) {
     outbuf = inbuf;
   } else {
-    /* use bufferpool here */
+    enum PixelFormat from_pixfmt =
+        (space->from_pixfmt == PIX_FMT_PAL8) ?
+        PIX_FMT_RGBA32 : space->from_pixfmt;
     guint size = avpicture_get_size (space->to_pixfmt,
-        space->width,
-        space->height);
+        space->width, space->height);
+    GstBuffer *inbuf2;
+
+    if (from_pixfmt != space->from_pixfmt) {
+      /* manual conversion from palette to RGBA32 */
+      gint x, y, pix, wd = space->width;
+      guint8 *dest;
+      guint32 conv;
+      AVPaletteControl *pal = space->palette;
+
+      inbuf2 = gst_buffer_new_and_alloc (4 *
+          space->width * space->height);
+      dest = GST_BUFFER_DATA (inbuf2);
+
+      for (y = 0; y < space->height; y++) {
+        for (x = 0; x < space->width; x++) {
+          pix = GST_BUFFER_DATA (inbuf)[y * wd + x];
+          conv = pal->palette[pix];
+          dest[(y * wd + x) * 4]     = ((guint8 *) &conv)[0];
+          dest[(y * wd + x) * 4 + 1] = ((guint8 *) &conv)[1];
+          dest[(y * wd + x) * 4 + 2] = ((guint8 *) &conv)[2];
+          dest[(y * wd + x) * 4 + 3] = ((guint8 *) &conv)[3];
+        }
+      }
+    } else {
+      inbuf2 = inbuf;
+    }
 
     outbuf = gst_pad_alloc_buffer (space->srcpad, GST_BUFFER_OFFSET_NONE, size);
 
     /* convert */
-    avpicture_fill ((AVPicture *) space->from_frame, GST_BUFFER_DATA (inbuf),
-        space->from_pixfmt, space->width, space->height);
+    avpicture_fill ((AVPicture *) space->from_frame, GST_BUFFER_DATA (inbuf2),
+        from_pixfmt, space->width, space->height);
     avpicture_fill ((AVPicture *) space->to_frame, GST_BUFFER_DATA (outbuf),
         space->to_pixfmt, space->width, space->height);
     img_convert ((AVPicture *) space->to_frame, space->to_pixfmt,
-        (AVPicture *) space->from_frame, space->from_pixfmt,
+        (AVPicture *) space->from_frame, from_pixfmt,
         space->width, space->height);
 
     GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf);
     GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf);
 
+    if (inbuf != inbuf2)
+      gst_buffer_unref (inbuf2);
     gst_buffer_unref (inbuf);
   }
 
@@ -382,8 +418,11 @@ gst_ffmpegcsp_change_state (GstElement * element)
         av_free (space->from_frame);
       if (space->to_frame)
         av_free (space->to_frame);
+      if (space->palette)
+        av_free (space->palette);
       space->from_frame = NULL;
       space->to_frame = NULL;
+      space->palette = NULL;
       break;
   }
 
@@ -437,6 +476,8 @@ gst_ffmpegcsp_register (GstPlugin * plugin)
   /* build templates */
   srctempl = gst_pad_template_new ("src",
       GST_PAD_SRC, GST_PAD_ALWAYS, gst_caps_copy (caps));
+
+  /* the sink template will do palette handling as well... */
   sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
 
   return gst_element_register (plugin, "ffcolorspace",
index 8076d58..272f2e3 100644 (file)
@@ -409,40 +409,18 @@ gst_ffmpegdec_chain (GstPad * pad, GstData * _data)
            * errors inside. This drives me crazy, so we let it allocate
            * it's own buffers and copy to our own buffer afterwards... */
           AVPicture pic;
-          enum PixelFormat to_fmt =
-             (ffmpegdec->context->pix_fmt == PIX_FMT_PAL8) ?
-             PIX_FMT_RGBA32 : ffmpegdec->context->pix_fmt;
-          gint size = avpicture_get_size (to_fmt,
+          gint size = avpicture_get_size (ffmpegdec->context->pix_fmt,
               ffmpegdec->context->width,
               ffmpegdec->context->height);
 
           outbuf = gst_buffer_new_and_alloc (size);
-          avpicture_fill (&pic, GST_BUFFER_DATA (outbuf), to_fmt,
+          avpicture_fill (&pic, GST_BUFFER_DATA (outbuf),
+              ffmpegdec->context->pix_fmt,
+              ffmpegdec->context->width, ffmpegdec->context->height);
+          img_convert (&pic, ffmpegdec->context->pix_fmt,
+              (AVPicture *) ffmpegdec->picture,
+              ffmpegdec->context->pix_fmt,
               ffmpegdec->context->width, ffmpegdec->context->height);
-          if (to_fmt == ffmpegdec->context->pix_fmt) {
-            img_convert (&pic, ffmpegdec->context->pix_fmt,
-                (AVPicture *) ffmpegdec->picture,
-                ffmpegdec->context->pix_fmt,
-                ffmpegdec->context->width, ffmpegdec->context->height);
-          } else {
-            /* manual conversion from palette to RGBA32 */
-            gint x, y, pix, ws = ffmpegdec->picture->linesize[0],
-               wd = ffmpegdec->context->width;
-            guint8 *dest = GST_BUFFER_DATA (outbuf);
-            guint32 conv;
-            AVPaletteControl *pal = ffmpegdec->context->palctrl;
-
-            for (y = 0; y < ffmpegdec->context->height; y++) {
-              for (x = 0; x < ffmpegdec->context->width; x++) {
-                pix = ffmpegdec->picture->data[0][y * ws + x];
-                conv = pal->palette[pix];
-                dest[(y * wd + x) * 4]     = ((guint8 *) &conv)[0];
-                dest[(y * wd + x) * 4 + 1] = ((guint8 *) &conv)[1];
-                dest[(y * wd + x) * 4 + 2] = ((guint8 *) &conv)[2];
-                dest[(y * wd + x) * 4 + 3] = ((guint8 *) &conv)[3];
-              }
-            }
-          }
 
           /* note that ffmpeg sometimes gets the FPS wrong */
           if (GST_CLOCK_TIME_IS_VALID (expected_ts)) {