1 /*
2 * GStreamer
3 * Copyright (c) 2010, Texas Instruments Incorporated
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation
8 * version 2.1 of the License.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
20 /**
21 * SECTION:element-ducatimpeg2dec
22 *
23 * FIXME:Describe ducatimpeg2dec here.
24 *
25 * <refsect2>
26 * <title>Example launch line</title>
27 * |[
28 * gst-launch -v -m fakesrc ! ducatimpeg2dec ! fakesink silent=TRUE
29 * ]|
30 * </refsect2>
31 */
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
37 #include "gstducatimpeg2dec.h"
39 GST_BOILERPLATE (GstDucatiMpeg2Dec, gst_ducati_mpeg2dec, GstDucatiVidDec,
40 GST_TYPE_DUCATIVIDDEC);
42 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
43 GST_PAD_SINK,
44 GST_PAD_ALWAYS,
45 GST_STATIC_CAPS ("video/mpeg, " "mpegversion = (int)[ 1, 2 ], " // XXX check on MPEG-1..
46 "systemstream = (boolean)false, "
47 "parsed = (boolean)true, "
48 "width = (int)[ 64, 2048 ], "
49 "height = (int)[ 64, 2048 ], " "framerate = (fraction)[ 0, max ];")
50 );
52 /* GstDucatiVidDec vmethod implementations */
54 static void
55 gst_ducati_mpeg2dec_update_buffer_size (GstDucatiVidDec * self)
56 {
57 gint w = self->width;
58 gint h = self->height;
60 /* calculate output buffer parameters: */
61 self->padded_width = w;
62 self->padded_height = h;
63 self->min_buffers = 8;
64 }
66 static gboolean
67 gst_ducati_mpeg2dec_allocate_params (GstDucatiVidDec * self, gint params_sz,
68 gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz)
69 {
70 gboolean ret = parent_class->allocate_params (self,
71 sizeof (IVIDDEC3_Params), sizeof (IVIDDEC3_DynamicParams),
72 sizeof (IVIDDEC3_Status), sizeof (IVIDDEC3_InArgs),
73 sizeof (IVIDDEC3_OutArgs));
75 if (ret)
76 self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_AUTO;
78 return ret;
79 }
81 static GstBuffer *
82 gst_ducati_mpeg2dec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf)
83 {
84 GstDucatiMpeg2Dec *self = GST_DUCATIMPEG2DEC (vdec);
85 guint sz = GST_BUFFER_SIZE (buf);
86 guint8 *data = GST_BUFFER_DATA (buf);
88 /* skip codec_data, which is same as first buffer from mpegvideoparse (and
89 * appears to be periodically resent) and instead prepend to next frame..
90 */
91 if (vdec->codec_data && (sz == GST_BUFFER_SIZE (vdec->codec_data)) &&
92 !memcmp (data, GST_BUFFER_DATA (vdec->codec_data), sz)) {
93 GST_DEBUG_OBJECT (self, "skipping codec_data buffer");
94 self->prepend_codec_data = TRUE;
95 } else {
96 if (self->prepend_codec_data) {
97 GST_DEBUG_OBJECT (self, "prepending codec_data buffer");
98 push_input (vdec, GST_BUFFER_DATA (vdec->codec_data),
99 GST_BUFFER_SIZE (vdec->codec_data));
100 self->prepend_codec_data = FALSE;
101 }
102 push_input (vdec, data, sz);
103 }
105 gst_buffer_unref (buf);
107 return NULL;
108 }
110 static gboolean
111 gst_ducati_mpeg2dec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps)
112 {
113 GstStructure *structure;
114 const gchar *profile;
116 GST_DEBUG_OBJECT (self, "set_sink_caps: %" GST_PTR_FORMAT, caps);
118 if (!GST_CALL_PARENT_WITH_DEFAULT (GST_DUCATIVIDDEC_CLASS, set_sink_caps,
119 (self, caps), TRUE))
120 return FALSE;
122 /* I have at least one case where incoming timestamps are ordered,
123 but frames are not, so we'd need to find out how to get correct
124 ordering from the internals of the frames. For now, let the hw
125 codec do the reordering to avoid more aggravation (and the 1.0
126 port will let the codec do it anyway). */
127 #if 0
128 /* Simple profile does not have B frames */
129 structure = gst_caps_get_structure (caps, 0);
130 profile = gst_structure_get_string (structure, "profile");
131 if (!profile || strcmp (profile, "simple")) {
132 /* TODO: can a better bound be found from stream headers ? */
133 self->backlog_maxframes = self->backlog_max_maxframes;
134 }
135 #endif
137 return TRUE;
138 }
140 static GstFlowReturn
141 gst_ducati_mpeg2dec_push_output (GstDucatiVidDec * self, GstBuffer * buf)
142 {
143 GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_TIMESTAMP (buf);
144 return parent_class->push_output (self, buf);
145 }
147 /* GObject vmethod implementations */
149 static void
150 gst_ducati_mpeg2dec_base_init (gpointer gclass)
151 {
152 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
154 gst_element_class_set_details_simple (element_class,
155 "DucatiMpeg2Dec",
156 "Codec/Decoder/Video",
157 "Decodes video in MPEG-2 format with ducati", "Rob Clark <rob@ti.com>");
159 gst_element_class_add_pad_template (element_class,
160 gst_static_pad_template_get (&sink_factory));
161 }
163 static void
164 gst_ducati_mpeg2dec_class_init (GstDucatiMpeg2DecClass * klass)
165 {
166 GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
167 bclass->codec_name = "ivahd_mpeg2vdec";
168 bclass->update_buffer_size =
169 GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_update_buffer_size);
170 bclass->allocate_params =
171 GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_allocate_params);
172 bclass->push_input = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_push_input);
173 bclass->set_sink_caps = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_set_sink_caps);
174 bclass->push_output = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_push_output);
175 }
177 static void
178 gst_ducati_mpeg2dec_init (GstDucatiMpeg2Dec * self,
179 GstDucatiMpeg2DecClass * gclass)
180 {
181 GstDucatiVidDec *vdec = GST_DUCATIVIDDEC (self);
182 vdec->pageMemType = XDM_MEMTYPE_RAW;
183 }