/*
* 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-ducatimpeg2dec
*
* FIXME:Describe ducatimpeg2dec here.
*
*
* Example launch line
* |[
* gst-launch -v -m fakesrc ! ducatimpeg2dec ! fakesink silent=TRUE
* ]|
*
*/
#ifdef HAVE_CONFIG_H
# include
#endif
#include "gstducatimpeg2dec.h"
GST_BOILERPLATE (GstDucatiMpeg2Dec, gst_ducati_mpeg2dec, GstDucatiVidDec,
GST_TYPE_DUCATIVIDDEC);
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/mpeg, "
"mpegversion = (int)[ 1, 2 ], " // XXX check on MPEG-1..
"systemstream = (boolean)false, "
"parsed = (boolean)true, "
"width = (int)[ 64, 2048 ], "
"height = (int)[ 64, 2048 ], "
"framerate = (fraction)[ 0, max ];")
);
/* GstDucatiVidDec vmethod implementations */
static void
gst_ducati_mpeg2dec_update_buffer_size (GstDucatiVidDec * self)
{
gint w = self->width;
gint h = self->height;
/* calculate output buffer parameters: */
self->padded_width = w;
self->padded_height = h;
self->min_buffers = 8;
}
static gboolean
gst_ducati_mpeg2dec_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 (IVIDDEC3_Params), sizeof (IVIDDEC3_DynamicParams),
sizeof (IVIDDEC3_Status), sizeof (IVIDDEC3_InArgs),
sizeof (IVIDDEC3_OutArgs));
if (ret)
self->params->displayDelay = IVIDDEC3_DECODE_ORDER;
return ret;
}
static GstBuffer *
gst_ducati_mpeg2dec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf)
{
GstDucatiMpeg2Dec *self = GST_DUCATIMPEG2DEC (vdec);
guint sz = GST_BUFFER_SIZE (buf);
guint8 *data = GST_BUFFER_DATA (buf);
/* skip codec_data, which is same as first buffer from mpegvideoparse (and
* appears to be periodically resent) and instead prepend to next frame..
*/
if (vdec->codec_data && (sz == GST_BUFFER_SIZE (vdec->codec_data)) &&
!memcmp (data, GST_BUFFER_DATA (vdec->codec_data), sz)) {
GST_DEBUG_OBJECT (self, "skipping codec_data buffer");
self->prepend_codec_data = TRUE;
} else {
if (self->prepend_codec_data) {
GST_DEBUG_OBJECT (self, "prepending codec_data buffer");
push_input (vdec, GST_BUFFER_DATA (vdec->codec_data),
GST_BUFFER_SIZE (vdec->codec_data));
self->prepend_codec_data = FALSE;
}
push_input (vdec, data, sz);
}
gst_buffer_unref (buf);
return NULL;
}
static gboolean
gst_ducati_mpeg2dec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps)
{
GstStructure *structure;
const gchar *profile;
GST_DEBUG_OBJECT (self, "set_sink_caps: %" GST_PTR_FORMAT, caps);
if (!GST_CALL_PARENT_WITH_DEFAULT (GST_DUCATIVIDDEC_CLASS, set_sink_caps,
(self, caps), TRUE))
return FALSE;
/* Simple profile does not have B frames */
structure = gst_caps_get_structure (caps, 0);
profile = gst_structure_get_string (structure, "profile");
if (!profile || strcmp (profile, "simple")) {
/* TODO: can a better bound be found from stream headers ? */
self->backlog_maxframes = self->backlog_max_maxframes;
}
return TRUE;
}
static GstFlowReturn
gst_ducati_mpeg2dec_push_output (GstDucatiVidDec * self, GstBuffer * buf)
{
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_TIMESTAMP (buf);
return parent_class->push_output (self, buf);
}
/* GObject vmethod implementations */
static void
gst_ducati_mpeg2dec_base_init (gpointer gclass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
gst_element_class_set_details_simple (element_class,
"DucatiMpeg2Dec",
"Codec/Decoder/Video",
"Decodes video in MPEG-2 format with ducati",
"Rob Clark ");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
}
static void
gst_ducati_mpeg2dec_class_init (GstDucatiMpeg2DecClass * klass)
{
GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
bclass->codec_name = "ivahd_mpeg2vdec";
bclass->update_buffer_size =
GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_update_buffer_size);
bclass->allocate_params =
GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_allocate_params);
bclass->push_input = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_push_input);
bclass->set_sink_caps = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_set_sink_caps);
bclass->push_output = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_push_output);
}
static void
gst_ducati_mpeg2dec_init (GstDucatiMpeg2Dec * self,
GstDucatiMpeg2DecClass * gclass)
{
GstDucatiVidDec *vdec = GST_DUCATIVIDDEC (self);
vdec->pageMemType = XDM_MEMTYPE_RAW;
}