bd1eab38ce17f237d9dfaa43c476dc570b9bf159
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-ducatirvdec
22 *
23 * FIXME:Describe ducatirvdec here.
24 *
25 * <refsect2>
26 * <title>Example launch line</title>
27 * |[
28 * gst-launch -v -m fakesrc ! ducatirvdec ! fakesink silent=TRUE
29 * ]|
30 * </refsect2>
31 */
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
37 #include "gstducatirvdec.h"
40 #define PADX 32
41 #define PADY 32
44 GST_BOILERPLATE (GstDucatiRVDec, gst_ducati_rvdec, GstDucatiVidDec,
45 GST_TYPE_DUCATIVIDDEC);
47 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
48 GST_PAD_SINK,
49 GST_PAD_ALWAYS,
50 GST_STATIC_CAPS ("video/x-pn-realvideo, "
51 "systemstream = (boolean)false, "
52 "rmversion = (int){ 3, 4 }, "
53 "width = (int)[ 16, 2048 ], "
54 "height = (int)[ 16, 2048 ], "
55 "framerate = (fraction)[ 0, max ];")
56 );
58 /* GstDucatiVidDec vmethod implementations */
60 static gboolean
61 gst_ducati_rvdec_parse_caps (GstDucatiVidDec * vdec, GstStructure * s)
62 {
63 GstDucatiRVDec *self = GST_DUCATIRVDEC (vdec);
65 if (parent_class->parse_caps (vdec, s)) {
66 gboolean ret = gst_structure_get_int (s, "rmversion", &self->rmversion);
67 if (ret) {
68 IrealVDEC_Params *params = (IrealVDEC_Params *) vdec->params;
69 GST_DEBUG_OBJECT (self, "rmversion: %d", self->rmversion);
71 if (self->rmversion == 3) {
72 params->stream_type = 1;
73 params->codec_version = 8;
74 } else if (self->rmversion == 4) {
75 params->stream_type = 1;
76 params->codec_version = 9;
77 } else {
78 ret = FALSE;
79 }
80 }
82 return ret;
83 }
85 return FALSE;
86 }
88 static void
89 gst_ducati_rvdec_update_buffer_size (GstDucatiVidDec * self)
90 {
91 /* calculate output buffer parameters: */
92 self->padded_width = ALIGN2 (self->width + (2 * PADX), 7);
93 self->padded_height = self->height + 2 * PADY;
94 self->min_buffers = 8;
95 }
97 static gboolean
98 gst_ducati_rvdec_allocate_params (GstDucatiVidDec * vdec, gint params_sz,
99 gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz)
100 {
101 GstDucatiRVDec *self = GST_DUCATIRVDEC (vdec);
102 gboolean ret = parent_class->allocate_params (vdec,
103 sizeof (IrealVDEC_Params), sizeof (IrealVDEC_DynamicParams),
104 sizeof (IrealVDEC_Status), sizeof (IrealVDEC_InArgs),
105 sizeof (IrealVDEC_OutArgs));
107 if (ret) {
108 /*IrealVDEC_Params *params = (IrealVDEC_Params *) vdec->params;*/
109 vdec->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1;
110 vdec->dynParams->newFrameFlag = FALSE;
111 vdec->dynParams->lateAcquireArg = -1;
112 vdec->params->numInputDataUnits = 1;
113 vdec->params->numOutputDataUnits = 1;
114 }
116 return ret;
117 }
119 static GstBuffer *
120 gst_ducati_rvdec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf)
121 {
122 GstDucatiRVDec *self = GST_DUCATIRVDEC (vdec);
123 guint8 *data;
124 guint8 val[4];
125 gint i, sz, slice_count;
127 /* *** on first buffer, build up the stream header for the codec *** */
128 if (G_UNLIKELY (vdec->first_in_buffer) && vdec->codec_data) {
130 sz = GST_BUFFER_SIZE (vdec->codec_data);
131 data = GST_BUFFER_DATA (vdec->codec_data);
133 /* header size, 4 bytes, big-endian */
134 GST_WRITE_UINT32_BE (val, sz + 26);
135 push_input (vdec, val, 4);
137 /* stream type */
138 if (self->rmversion == 3) {
139 push_input (vdec, (guint8 *)"VIDORV30", 8);
140 } else if (self->rmversion == 4) {
141 push_input (vdec, (guint8 *)"VIDORV40", 8);
142 }
144 /* horiz x vert resolution */
145 GST_WRITE_UINT16_BE (val, vdec->width);
146 push_input (vdec, val, 2);
147 GST_WRITE_UINT16_BE (val, vdec->height);
148 push_input (vdec, val, 2);
150 /* unknown? */
151 GST_WRITE_UINT32_BE (val, 0x000c0000);
152 push_input (vdec, val, 4);
154 /* unknown? may be framerate.. */
155 GST_WRITE_UINT32_BE (val, 0x0000000f);
156 push_input (vdec, val, 4);
158 /* unknown? */
159 GST_WRITE_UINT16_BE (val, 0x0000);
160 push_input (vdec, val, 2);
162 /* and rest of stream header is the codec_data */
163 push_input (vdec, data, sz);
164 }
166 data = GST_BUFFER_DATA (buf);
167 sz = GST_BUFFER_SIZE (buf);
168 slice_count = (*data++) + 1;
170 /* payload size, excluding fixed header and slice header */
171 sz -= 1 + (8 * slice_count);
173 /* *** insert frame header *** */
174 /* payload size */
175 GST_WRITE_UINT32_BE (val, sz);
176 push_input (vdec, val, 4);
178 /* unknown? may be timestamp, hopefully decoder doesn't care */
179 GST_WRITE_UINT32_BE (val, 0x00000001);
180 push_input (vdec, val, 4);
182 /* unknown? may be sequence number, hopefully decoder doesn't care */
183 GST_WRITE_UINT16_BE (val, 0x0000);
184 push_input (vdec, val, 2);
186 /* unknown? may indicate I frame, hopefully decoder doesn't care */
187 if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
188 GST_WRITE_UINT16_BE (val, 0x0000);
189 } else {
190 GST_WRITE_UINT16_BE (val, 0x0002);
191 }
192 push_input (vdec, val, 2);
194 /* unknown? seems to be always zeros */
195 GST_WRITE_UINT32_BE (val, 0x00000000);
196 push_input (vdec, val, 4);
198 /* convert the slice_header to big endian, and note that the codec
199 * expects to get slice_count rather than slice_count-1
200 */
201 GST_WRITE_UINT32_BE (val, slice_count);
202 push_input (vdec, val, 4);
204 for (i = 0; i < slice_count; i++) {
205 GST_WRITE_UINT32_BE (val, 0x00000001);
206 push_input (vdec, val, 4);
208 data += 4;
209 GST_WRITE_UINT32_BE (val, GST_READ_UINT32_LE (data));
210 data += 4;
211 push_input (vdec, val, 4);
212 }
214 /* copy the payload (rest of buffer) */
215 push_input (vdec, data, sz);
216 gst_buffer_unref (buf);
218 return NULL;
219 }
221 /* GObject vmethod implementations */
223 static void
224 gst_ducati_rvdec_base_init (gpointer gclass)
225 {
226 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
228 gst_element_class_set_details_simple (element_class,
229 "DucatiRVDec",
230 "Codec/Decoder/Video",
231 "Decodes video in RealVideo (RV8/9/10) format with ducati",
232 "Rob Clark <rob@ti.com>");
234 gst_element_class_add_pad_template (element_class,
235 gst_static_pad_template_get (&sink_factory));
236 }
238 static void
239 gst_ducati_rvdec_class_init (GstDucatiRVDecClass * klass)
240 {
241 GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
242 bclass->codec_name = "ivahd_realvdec";
243 bclass->parse_caps =
244 GST_DEBUG_FUNCPTR (gst_ducati_rvdec_parse_caps);
245 bclass->update_buffer_size =
246 GST_DEBUG_FUNCPTR (gst_ducati_rvdec_update_buffer_size);
247 bclass->allocate_params =
248 GST_DEBUG_FUNCPTR (gst_ducati_rvdec_allocate_params);
249 bclass->push_input =
250 GST_DEBUG_FUNCPTR (gst_ducati_rvdec_push_input);
251 }
253 static void
254 gst_ducati_rvdec_init (GstDucatiRVDec * self,
255 GstDucatiRVDecClass * gclass)
256 {
257 }