mpeg4dec: add MPEG-4 support
authorRob Clark <rob@ti.com>
Thu, 25 Nov 2010 19:49:23 +0000 (13:49 -0600)
committerRob Clark <rob@ti.com>
Thu, 25 Nov 2010 23:11:25 +0000 (17:11 -0600)
README
src/Makefile.am
src/gstducati.c
src/gstducatih264dec.c
src/gstducatimpeg4dec.c [new file with mode: 0644]
src/gstducatimpeg4dec.h [new file with mode: 0644]
src/gstducatividdec.c
src/gstducatividdec.h

diff --git a/README b/README
index 696ecb92f81496a3bdd093dac8ace6595770ee6c..38157594365617fcc7490f89fc7654659ef011c8 100644 (file)
--- a/README
+++ b/README
@@ -14,8 +14,7 @@ was an interesting project for me to try on my free time.
 
 TODO
 ----
-+ flush (for seek/eos)
-+ mpeg4, vc1, vp6, vp7
++ vc1, vp6, vp7, realvideo
 + fallbacks for sink elements not providing TILER buffers to decode into
 + search the code for XXX or TODO ;-)
 
index 2ab0022e556e2406f6788c14b36d15c23ece5330..793d921402c1bf2afd56c22df5bdb27983838c63 100644 (file)
@@ -2,12 +2,14 @@ plugin_LTLIBRARIES = libgstducati.la
 
 # headers we need but don't want installed
 noinst_HEADERS = \
+       gstducatimpeg4dec.h \
        gstducatih264dec.h \
        gstducatividdec.h \
        gstducati.h
 
 # sources used to compile this plug-in
 libgstducati_la_SOURCES = \
+       gstducatimpeg4dec.c \
        gstducatih264dec.c \
        gstducatividdec.c \
        gstducati.c \
index 66d139b640b5130664a2151ef76eba63bc6161f4..bbe9a5c5fde9f2408a44bcce449cbe4d1f625699 100644 (file)
@@ -24,6 +24,7 @@
 #include <gst/gst.h>
 
 #include "gstducatih264dec.h"
+#include "gstducatimpeg4dec.h"
 
 GST_DEBUG_CATEGORY (gst_ducati_debug);
 
@@ -32,8 +33,8 @@ plugin_init (GstPlugin * plugin)
 {
   GST_DEBUG_CATEGORY_INIT (gst_ducati_debug, "ducati", 0, "ducati");
 
-  return gst_element_register (plugin, "ducatih264dec", GST_RANK_PRIMARY,
-      GST_TYPE_DUCATIH264DEC);
+  return gst_element_register (plugin, "ducatih264dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIH264DEC) &&
+      gst_element_register (plugin, "ducatimpeg4dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIMPEG4DEC);
 }
 
 void *
index 324826c1eb3251417a771c7572fb3ebb5df0f593..d62148ab88d9d6ca364b9f84d63097d1aeadba5d 100644 (file)
@@ -101,7 +101,7 @@ gst_ducati_h264dec_base_init (gpointer gclass)
   gst_element_class_set_details_simple (element_class,
       "DucatiH264Dec",
       "Codec/Decoder/Video",
-      "Decodes video in H.264/AVC format with ducati",
+      "Decodes video in H.264/bytestream format with ducati",
       "Rob Clark <rob@ti.com>");
 
   gst_element_class_add_pad_template (element_class,
diff --git a/src/gstducatimpeg4dec.c b/src/gstducatimpeg4dec.c
new file mode 100644 (file)
index 0000000..acb3acd
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * GStreamer
+ * Copyright (c) 2010, Texas Instruments Incorporated
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/**
+ * SECTION:element-ducatimpeg4dec
+ *
+ * FIXME:Describe ducatimpeg4dec here.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v -m fakesrc ! ducatimpeg4dec ! fakesink silent=TRUE
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+
+#include "gstducatimpeg4dec.h"
+
+
+#define PADX  32
+#define PADY  32
+
+
+GST_BOILERPLATE (GstDucatiMpeg4Dec, gst_ducati_mpeg4dec, GstDucatiVidDec,
+    GST_TYPE_DUCATIVIDDEC);
+
+#define MPEG4DEC_SINKCAPS_COMMON \
+    "width = (int)[ 16, 2048 ], " \
+    "height = (int)[ 16, 2048 ], " \
+    "framerate = (fraction)[ 0, max ]"
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (
+        "video/mpeg, "
+          "mpegversion = (int)4, "
+          "systemstream = (boolean)false, "
+          MPEG4DEC_SINKCAPS_COMMON ";"
+        "video/x-divx, "
+          "divxversion = (int)[4, 5], "  /* TODO check this */
+          MPEG4DEC_SINKCAPS_COMMON ";"
+        "video/x-xvid, "
+          MPEG4DEC_SINKCAPS_COMMON ";"
+        "video/x-3ivx, "
+          MPEG4DEC_SINKCAPS_COMMON ";"
+        )
+    );
+
+/* GstDucatiVideDec vmethod implementations */
+
+static void
+gst_ducati_mpeg4dec_update_buffer_size (GstDucatiVidDec * self)
+{
+  gint w = self->width;
+  gint h = self->height;
+
+  /* calculate output buffer parameters: */
+  self->padded_width = (w + PADX + 0x7f) & ~0x7f;
+  self->padded_height = h + PADY;
+  self->min_buffers = 8;
+}
+
+static gboolean
+gst_ducati_mpeg4dec_allocate_params (GstDucatiVidDec * self, gint params_sz,
+    gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz)
+{
+  gboolean ret = parent_class->allocate_params (self,
+      sizeof (IMPEG4VDEC_Params), sizeof (IMPEG4VDEC_DynamicParams),
+      sizeof (IMPEG4VDEC_Status), sizeof (IMPEG4VDEC_InArgs),
+      sizeof (IMPEG4VDEC_OutArgs));
+
+  if (ret) {
+    IMPEG4VDEC_Params *params = (IMPEG4VDEC_Params *) self->params;
+    self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1;
+    self->dynParams->lateAcquireArg = -1;
+    params->outloopDeBlocking = TRUE;
+    params->sorensonSparkStream = FALSE;
+    params->ErrorConcealmentON = FALSE;
+  }
+
+  return ret;
+}
+
+/* GObject vmethod implementations */
+
+static void
+gst_ducati_mpeg4dec_base_init (gpointer gclass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
+
+  gst_element_class_set_details_simple (element_class,
+      "DucatiMpeg4Dec",
+      "Codec/Decoder/Video",
+      "Decodes video in MPEG-4 format with ducati",
+      "Rob Clark <rob@ti.com>");
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_factory));
+}
+
+static void
+gst_ducati_mpeg4dec_class_init (GstDucatiMpeg4DecClass * klass)
+{
+  GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
+  bclass->codec_name = "ivahd_mpeg4dec";
+  bclass->update_buffer_size =
+      GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_update_buffer_size);
+  bclass->allocate_params =
+      GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_allocate_params);
+}
+
+static void
+gst_ducati_mpeg4dec_init (GstDucatiMpeg4Dec * self,
+    GstDucatiMpeg4DecClass * gclass)
+{
+}
diff --git a/src/gstducatimpeg4dec.h b/src/gstducatimpeg4dec.h
new file mode 100644 (file)
index 0000000..47039cf
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * GStreamer
+ * Copyright (c) 2010, Texas Instruments Incorporated
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GST_DUCATIMPEG4DEC_H__
+#define __GST_DUCATIMPEG4DEC_H__
+
+#include <gst/gst.h>
+
+#include "gstducatividdec.h"
+
+#include <ti/sdo/codecs/mpeg4dec/impeg4vdec.h>
+
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_DUCATIMPEG4DEC              (gst_ducati_mpeg4dec_get_type())
+#define GST_DUCATIMPEG4DEC(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DUCATIMPEG4DEC, GstDucatiMpeg4Dec))
+#define GST_DUCATIMPEG4DEC_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DUCATIMPEG4DEC, GstDucatiMpeg4DecClass))
+#define GST_IS_DUCATIMPEG4DEC(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DUCATIMPEG4DEC))
+#define GST_IS_DUCATIMPEG4DEC_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DUCATIMPEG4DEC))
+
+typedef struct _GstDucatiMpeg4Dec      GstDucatiMpeg4Dec;
+typedef struct _GstDucatiMpeg4DecClass GstDucatiMpeg4DecClass;
+
+struct _GstDucatiMpeg4Dec
+{
+  GstDucatiVidDec parent;
+};
+
+struct _GstDucatiMpeg4DecClass
+{
+  GstDucatiVidDecClass parent_class;
+};
+
+GType gst_ducati_mpeg4dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_DUCATIMPEG4DEC_H__ */
index 28821d8310eb6fbb4bfc4ee1bd1d0f6e673e86b8..953d94a0284868fbe55be9b3f18bd0851b847217 100644 (file)
@@ -330,23 +330,19 @@ gst_ducati_viddec_allocate_params (GstDucatiVidDec * self, gint params_sz,
   }
   self->params->size = params_sz;
   self->params->maxFrameRate = 30000;
-  //h264, mpeg4:
-  //note mpeg4 and h263 are same..
   self->params->maxBitRate = 10000000;
+
   //vc1:
   //self->params->maxBitRate = 45000000;
+  //vc6/vc7/rv??
 
   self->params->dataEndianness = XDM_BYTE;
   self->params->forceChromaFormat = XDM_YUV_420SP;
   self->params->operatingMode = IVIDEO_DECODE_ONLY;
 
-  //mpeg4:
-  //self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1;
-
   //vc1:
   //self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1;
 
-
   self->params->displayBufsMode = IVIDDEC3_DISPLAYBUFS_EMBEDDED;
   self->params->inputDataMode = IVIDEO_ENTIREFRAME;
   self->params->outputDataMode = IVIDEO_ENTIREFRAME;
@@ -362,12 +358,6 @@ gst_ducati_viddec_allocate_params (GstDucatiVidDec * self, gint params_sz,
   self->params->metadataType[2] = IVIDEO_METADATAPLANE_NONE;
   self->params->errorInfoMode = IVIDEO_ERRORINFO_OFF;
 
-  //mpeg4:
-  //((IMPEG4VDEC_Params *) self->params)->outloopDeBlocking = 0;
-  //((IMPEG4VDEC_Params *) self->params)->sorensonSparkStream = 0;
-  //((IMPEG4VDEC_Params *) self->params)->ErrorConcealmentON = 1;
-
-
   /* allocate dynParams: */
   self->dynParams = dce_alloc (dynparams_sz);
   if (G_UNLIKELY (!self->dynParams)) {
@@ -379,9 +369,6 @@ gst_ducati_viddec_allocate_params (GstDucatiVidDec * self, gint params_sz,
   self->dynParams->frameSkipMode = IVIDEO_NO_SKIP;
   self->dynParams->newFrameFlag = XDAS_TRUE;
 
-  //mpeg4:
-  //self->dynParams->lateAcquireArg = IRES_HDVICP2_UNKNOWNLATEACQUIREARG;
-
   /* allocate status: */
   self->status = dce_alloc (status_sz);
   if (G_UNLIKELY (!self->status)) {
@@ -406,15 +393,28 @@ gst_ducati_viddec_allocate_params (GstDucatiVidDec * self, gint params_sz,
   self->outArgs->size = outargs_sz;
 }
 
+static inline void
+push_input (GstDucatiVidDec * self, GstBuffer * buf)
+{
+  gint sz = GST_BUFFER_SIZE (buf);
+  GST_DEBUG_OBJECT (self, "push: %d bytes)", sz);
+  memcpy (self->input + self->in_size, GST_BUFFER_DATA (buf), sz);
+  self->in_size += sz;
+}
+
 static GstBuffer *
 gst_ducati_viddec_push_input (GstDucatiVidDec * self, GstBuffer * buf)
 {
+  gint sz;
+
+  if (self->first_in_buffer && self->codec_data) {
+    push_input (self, self->codec_data);
+  }
+
   /* just copy entire buffer */
-  self->inArgs->numBytes = GST_BUFFER_SIZE (buf);
-  self->inBufs->descs[0].bufSize.bytes = self->inArgs->numBytes;
-  GST_DEBUG_OBJECT (self, "push: %d bytes)", self->inArgs->numBytes);
-  memcpy (self->input, GST_BUFFER_DATA (buf), self->inArgs->numBytes);
+  push_input (self, buf);
   gst_buffer_unref (buf);
+
   return NULL;
 }
 
@@ -439,6 +439,7 @@ gst_ducati_viddec_set_caps (GstPad * pad, GstCaps * caps)
     if (gst_structure_get_int (s, "width", &width) &&
         gst_structure_get_int (s, "height", &height) &&
         gst_structure_get_fraction (s, "framerate", &frn, &frd)) {
+      const GValue *codec_data;
       GstCaps *outcaps;
 
       /* ok, these caps seem sane.. grab the required values and construct
@@ -448,6 +449,13 @@ gst_ducati_viddec_set_caps (GstPad * pad, GstCaps * caps)
       self->height = height;
       self->stride = 4096;      /* TODO: don't hardcode */
 
+      codec_data = gst_structure_get_value (s, "codec_data");
+      if (codec_data) {
+        GstBuffer *buffer = gst_value_get_buffer (codec_data);
+        GST_DEBUG_OBJECT (self, "codec_data: %" GST_PTR_FORMAT, buffer);
+        self->codec_data = gst_buffer_ref (buffer);
+      }
+
       /* update output/padded sizes:
        */
       GST_DUCATIVIDDEC_GET_CLASS (self)->update_buffer_size (self);
@@ -553,7 +561,10 @@ gst_ducati_viddec_chain (GstPad * pad, GstBuffer * buf)
     return GST_FLOW_ERROR;
   }
 
+  self->in_size = 0;
   buf = GST_DUCATIVIDDEC_GET_CLASS (self)->push_input (self, buf);
+  self->inArgs->numBytes = self->in_size;
+  self->inBufs->descs[0].bufSize.bytes = self->in_size;
 
   if (buf) {
     // XXX
@@ -659,6 +670,11 @@ gst_ducati_viddec_finalize (GObject * obj)
   codec_delete (self);
   engine_close (self);
 
+  if (self->codec_data) {
+      gst_buffer_unref (self->codec_data);
+      self->codec_data = NULL;
+  }
+
   G_OBJECT_CLASS (parent_class)->finalize (obj);
 }
 
index 8be16d7ce2838a8f14fac71e0da10825b4bbc73a..622383b133e4e3d4d0b3877b29d24d92a14cd128 100644 (file)
@@ -65,12 +65,18 @@ struct _GstDucatiVidDec
   /* input buffer, allocated when codec is created: */
   guint8 *input;
 
+  /* number of bytes pushed to input on current frame: */
+  gint in_size;
+
   /* on first output buffer, we need to send crop info to sink.. and some
    * operations like flushing should be avoided if we haven't sent any
    * input buffers:
    */
   gboolean first_out_buffer, first_in_buffer;
 
+  /* by default, codec_data from sinkpad is prepended to first buffer: */
+  GstBuffer *codec_data;
+
   Engine_Handle           engine;
   VIDDEC3_Handle          codec;
   VIDDEC3_Params         *params;