diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/gstducati.c | 7 | ||||
-rw-r--r-- | src/gstducatih264dec.c | 2 | ||||
-rw-r--r-- | src/gstducatimpeg4dec.c | 2 | ||||
-rw-r--r-- | src/gstducativc1dec.c | 218 | ||||
-rw-r--r-- | src/gstducativc1dec.h | 57 | ||||
-rw-r--r-- | src/gstducatividdec.c | 72 | ||||
-rw-r--r-- | src/gstducatividdec.h | 20 |
8 files changed, 339 insertions, 41 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 793d921..bd44995 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,7 @@ plugin_LTLIBRARIES = libgstducati.la # headers we need but don't want installed noinst_HEADERS = \ + gstducativc1dec.h \ gstducatimpeg4dec.h \ gstducatih264dec.h \ gstducatividdec.h \ @@ -9,6 +10,7 @@ noinst_HEADERS = \ # sources used to compile this plug-in libgstducati_la_SOURCES = \ + gstducativc1dec.c \ gstducatimpeg4dec.c \ gstducatih264dec.c \ gstducatividdec.c \ diff --git a/src/gstducati.c b/src/gstducati.c index bbe9a5c..7ed7e69 100644 --- a/src/gstducati.c +++ b/src/gstducati.c @@ -25,6 +25,7 @@ #include "gstducatih264dec.h" #include "gstducatimpeg4dec.h" +#include "gstducativc1dec.h" GST_DEBUG_CATEGORY (gst_ducati_debug); @@ -33,8 +34,12 @@ plugin_init (GstPlugin * plugin) { GST_DEBUG_CATEGORY_INIT (gst_ducati_debug, "ducati", 0, "ducati"); + /* TODO .. find some way to reasonably detect if the corresponding + * codecs are actually available.. + */ return gst_element_register (plugin, "ducatih264dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIH264DEC) && - gst_element_register (plugin, "ducatimpeg4dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIMPEG4DEC); + gst_element_register (plugin, "ducatimpeg4dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIMPEG4DEC) && + gst_element_register (plugin, "ducativc1dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIVC1DEC); } void * diff --git a/src/gstducatih264dec.c b/src/gstducatih264dec.c index d62148a..af7ddc2 100644 --- a/src/gstducatih264dec.c +++ b/src/gstducatih264dec.c @@ -58,7 +58,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", "framerate = (fraction)[ 0, max ];") ); -/* GstDucatiVideDec vmethod implementations */ +/* GstDucatiVidDec vmethod implementations */ static void gst_ducati_h264dec_update_buffer_size (GstDucatiVidDec * self) diff --git a/src/gstducatimpeg4dec.c b/src/gstducatimpeg4dec.c index acb3acd..4c79044 100644 --- a/src/gstducatimpeg4dec.c +++ b/src/gstducatimpeg4dec.c @@ -70,7 +70,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", ) ); -/* GstDucatiVideDec vmethod implementations */ +/* GstDucatiVidDec vmethod implementations */ static void gst_ducati_mpeg4dec_update_buffer_size (GstDucatiVidDec * self) diff --git a/src/gstducativc1dec.c b/src/gstducativc1dec.c new file mode 100644 index 0000000..ace7baf --- /dev/null +++ b/src/gstducativc1dec.c @@ -0,0 +1,218 @@ +/* + * 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-ducativc1dec + * + * FIXME:Describe ducativc1dec here. + * + * <refsect2> + * <title>Example launch line</title> + * |[ + * gst-launch -v -m fakesrc ! ducativc1dec ! fakesink silent=TRUE + * ]| + * </refsect2> + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gst/gst.h> +#include <gst/video/video.h> + +#include "gstducativc1dec.h" + + +#define PADX 32 +#define PADY 40 + + +GST_BOILERPLATE (GstDucatiVC1Dec, gst_ducati_vc1dec, GstDucatiVidDec, + GST_TYPE_DUCATIVIDDEC); + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-wmv, " + "wmvversion = (int)[ 2, 3 ], " + "format = (fourcc){ WVC1, WMV3, WMV2, WMV1 }, " + "width = (int)[ 16, 2048 ], " + "height = (int)[ 16, 2048 ], " + "framerate = (fraction)[ 0, max ];") + ); + +/* GstDucatiVidDec vmethod implementations */ + +static gboolean +gst_ducati_vc1dec_parse_caps (GstDucatiVidDec * vdec, GstStructure * s) +{ + GstDucatiVC1Dec *self = GST_DUCATIVC1DEC (vdec); + + if (parent_class->parse_caps (vdec, s)) { + guint32 format; + gboolean ret = gst_structure_get_fourcc (s, "format", &format); + if (ret) { + switch (format) { + case GST_MAKE_FOURCC ('W', 'V', 'C', '1'): + self->level = 4; + break; + case GST_MAKE_FOURCC ('W', 'M', 'V', '3'): + self->level = 3; + break; + case GST_MAKE_FOURCC ('W', 'M', 'V', '2'): + self->level = 2; + break; + case GST_MAKE_FOURCC ('W', 'M', 'V', '1'): + self->level = 1; + break; + default: + ret = FALSE; + break; + } + } + return ret; + } + + return FALSE; +} + +static void +gst_ducati_vc1dec_update_buffer_size (GstDucatiVidDec * self) +{ + gint w = self->width; + gint h = self->height; + + /* calculate output buffer parameters: */ + self->padded_width = (w + (2 * PADX) + 0x7f) & ~0x7f; + self->padded_height = (((h / 2 + 0xf) & ~0xf) * 2) + 2 * PADY; + self->min_buffers = 8; +} + +static gboolean +gst_ducati_vc1dec_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 (IVC1VDEC_Params), sizeof (IVC1VDEC_DynamicParams), + sizeof (IVC1VDEC_Status), sizeof (IVC1VDEC_InArgs), + sizeof (IVC1VDEC_OutArgs)); + + if (ret) { + IVC1VDEC_Params *params = (IVC1VDEC_Params *) self->params; + self->params->maxBitRate = 45000000; + self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1; + params->FrameLayerDataPresentFlag = FALSE; + } + + return ret; +} + +static GstBuffer * +gst_ducati_vc1dec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf) +{ + GstDucatiVC1Dec *self = GST_DUCATIVC1DEC (vdec); + + if (G_UNLIKELY (vdec->first_in_buffer) && vdec->codec_data) { + if (self->level == 4) { + /* for VC-1 Advanced Profile, strip off first byte, and + * send rest of codec_data unmodified; + */ + push_input (vdec, GST_BUFFER_DATA (vdec->codec_data) + 1, + GST_BUFFER_SIZE (vdec->codec_data) - 1); + } else { + guint32 val; + + /* for VC-1 Simple and Main Profile, build the Table 265 Sequence + * Layer Data Structure header (refer to VC-1 spec, Annex L): + */ + + val = 0xc5ffffff; /* we don't know the number of frames */ + push_input (vdec, (guint8 *) & val, 4); + + /* STRUCT_C (preceded by length).. see Table 263, 264 */ + val = GST_BUFFER_SIZE (vdec->codec_data); + push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, GST_BUFFER_DATA (vdec->codec_data), val); + + /* STRUCT_A.. see Table 260 and Annex J.2 */ + push_input (vdec, (guint8 *) & vdec->height, 4); + push_input (vdec, (guint8 *) & vdec->width, 4); + + val = 0x0000000c; + push_input (vdec, (guint8 *) & val, 4); + + /* STRUCT_B.. see Table 261, 262 */ + val = 0x00000000; /* not sure how to populate, but codec ignores anyways */ + push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (guint8 *) & val, 4); + } + } + + /* VC-1 Advanced profile needs start-code prepended: */ + if (self->level == 4) { + static guint8 sc[] = { 0x00, 0x00, 0x01, 0x0d }; /* start code */ + push_input (vdec, sc, sizeof (sc)); + } + + push_input (vdec, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_buffer_unref (buf); + + return NULL; +} + + +/* GObject vmethod implementations */ + +static void +gst_ducati_vc1dec_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple (element_class, + "DucatiVC1Dec", + "Codec/Decoder/Video", + "Decodes video in WMV/VC-1 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_vc1dec_class_init (GstDucatiVC1DecClass * klass) +{ + GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass); + bclass->codec_name = "ivahd_vc1vdec"; + bclass->parse_caps = + GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_parse_caps); + bclass->update_buffer_size = + GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_update_buffer_size); + bclass->allocate_params = + GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_allocate_params); + bclass->push_input = + GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_push_input); +} + +static void +gst_ducati_vc1dec_init (GstDucatiVC1Dec * self, + GstDucatiVC1DecClass * gclass) +{ +} diff --git a/src/gstducativc1dec.h b/src/gstducativc1dec.h new file mode 100644 index 0000000..1031cdf --- /dev/null +++ b/src/gstducativc1dec.h @@ -0,0 +1,57 @@ +/* + * 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_DUCATIVC1DEC_H__ +#define __GST_DUCATIVC1DEC_H__ + +#include <gst/gst.h> + +#include "gstducatividdec.h" + +#include <ti/sdo/codecs/vc1vdec/ivc1vdec.h> + + +G_BEGIN_DECLS + +#define GST_TYPE_DUCATIVC1DEC (gst_ducati_vc1dec_get_type()) +#define GST_DUCATIVC1DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DUCATIVC1DEC, GstDucatiVC1Dec)) +#define GST_DUCATIVC1DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DUCATIVC1DEC, GstDucatiVC1DecClass)) +#define GST_IS_DUCATIVC1DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DUCATIVC1DEC)) +#define GST_IS_DUCATIVC1DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DUCATIVC1DEC)) + +typedef struct _GstDucatiVC1Dec GstDucatiVC1Dec; +typedef struct _GstDucatiVC1DecClass GstDucatiVC1DecClass; + +struct _GstDucatiVC1Dec +{ + GstDucatiVidDec parent; + + gint level; +}; + +struct _GstDucatiVC1DecClass +{ + GstDucatiVidDecClass parent_class; +}; + +GType gst_ducati_vc1dec_get_type (void); + +G_END_DECLS + +#endif /* __GST_DUCATIVC1DEC_H__ */ diff --git a/src/gstducatividdec.c b/src/gstducatividdec.c index 953d94a..53bc94c 100644 --- a/src/gstducatividdec.c +++ b/src/gstducatividdec.c @@ -319,6 +319,28 @@ codec_flush (GstDucatiVidDec * self, gboolean eos) /* GstDucatiVidDec vmethod default implementations */ static gboolean +gst_ducati_viddec_parse_caps (GstDucatiVidDec * self, GstStructure * s) +{ + const GValue *codec_data; + + if (gst_structure_get_int (s, "width", &self->width) && + gst_structure_get_int (s, "height", &self->height)) { + + const GValue *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); + } + + return TRUE; + } + + return FALSE; +} + +static gboolean gst_ducati_viddec_allocate_params (GstDucatiVidDec * self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz) { @@ -332,17 +354,12 @@ gst_ducati_viddec_allocate_params (GstDucatiVidDec * self, gint params_sz, self->params->maxFrameRate = 30000; 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; - //vc1: - //self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1; - self->params->displayBufsMode = IVIDDEC3_DISPLAYBUFS_EMBEDDED; self->params->inputDataMode = IVIDEO_ENTIREFRAME; self->params->outputDataMode = IVIDEO_ENTIREFRAME; @@ -393,26 +410,16 @@ 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); + if (G_UNLIKELY (self->first_in_buffer) && self->codec_data) { + push_input (self, GST_BUFFER_DATA (self->codec_data), + GST_BUFFER_SIZE (self->codec_data)); } /* just copy entire buffer */ - push_input (self, buf); + push_input (self, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); gst_buffer_unref (buf); return NULL; @@ -425,6 +432,7 @@ gst_ducati_viddec_set_caps (GstPad * pad, GstCaps * caps) { gboolean ret = TRUE; GstDucatiVidDec *self = GST_DUCATIVIDDEC (gst_pad_get_parent (pad)); + GstDucatiVidDecClass *klass = GST_DUCATIVIDDEC_GET_CLASS (self); GstStructure *s; g_return_val_if_fail (caps, FALSE); @@ -433,32 +441,19 @@ gst_ducati_viddec_set_caps (GstPad * pad, GstCaps * caps) s = gst_caps_get_structure (caps, 0); if (pad == self->sinkpad) { - gint width, height, frn, frd; + gint frn = 0, frd = 1; GST_INFO_OBJECT (self, "setcaps (sink): %" GST_PTR_FORMAT, 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; + if (klass->parse_caps (self, s)) { GstCaps *outcaps; - /* ok, these caps seem sane.. grab the required values and construct - * appropriate output caps - */ - self->width = width; - self->height = height; - self->stride = 4096; /* TODO: don't hardcode */ + gst_structure_get_fraction (s, "framerate", &frn, &frd); - 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); - } + self->stride = 4096; /* TODO: don't hardcode */ /* update output/padded sizes: */ - GST_DUCATIVIDDEC_GET_CLASS (self)->update_buffer_size (self); + klass->update_buffer_size (self); self->outsize = GST_ROUND_UP_2 (self->stride * self->padded_height * 3) / 2; @@ -539,7 +534,6 @@ gst_ducati_viddec_chain (GstPad * pad, GstBuffer * buf) /* TODO: if we had our own buffer class, we could allocate our own * output buffer from TILER... */ - GST_WARNING_OBJECT (self, "ret=%d", ret); GST_WARNING_OBJECT (self, "TODO: allocate output TILER buffer"); return ret; } @@ -696,6 +690,8 @@ gst_ducati_viddec_class_init (GstDucatiVidDecClass * klass) gobject_class->finalize = gst_ducati_viddec_finalize; gstelement_class->change_state = gst_ducati_viddec_change_state; + klass->parse_caps = + GST_DEBUG_FUNCPTR (gst_ducati_viddec_parse_caps); klass->allocate_params = GST_DEBUG_FUNCPTR (gst_ducati_viddec_allocate_params); klass->push_input = diff --git a/src/gstducatividdec.h b/src/gstducatividdec.h index 622383b..9be1d91 100644 --- a/src/gstducatividdec.h +++ b/src/gstducatividdec.h @@ -95,11 +95,21 @@ struct _GstDucatiVidDecClass const gchar *codec_name; /** + * Parse codec specific fields the given caps structure. The base- + * class implementation of this method handles standard stuff like + * width/height/framerate/codec_data. + */ + gboolean (*parse_caps) (GstDucatiVidDec * self, GstStructure * s); + + /** * Called when the input buffer size changes, to recalculate codec required * output buffer size and minimum count */ void (*update_buffer_size) (GstDucatiVidDec * self); + /** + * Called to allocate/initialize params/dynParams/status/inArgs/outArgs + */ gboolean (*allocate_params) (GstDucatiVidDec * self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz); @@ -112,6 +122,16 @@ struct _GstDucatiVidDecClass GType gst_ducati_viddec_get_type (void); +/* helper methods for derived classes: */ + +static inline void +push_input (GstDucatiVidDec * self, guint8 *in, gint sz) +{ + GST_DEBUG_OBJECT (self, "push: %d bytes)", sz); + memcpy (self->input + self->in_size, in, sz); + self->in_size += sz; +} + G_END_DECLS #endif /* __GST_DUCATIVIDDEC_H__ */ |