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 gboolean ret = parent_class->allocate_params (vdec,
102 sizeof (IrealVDEC_Params), sizeof (IrealVDEC_DynamicParams),
103 sizeof (IrealVDEC_Status), sizeof (IrealVDEC_InArgs),
104 sizeof (IrealVDEC_OutArgs));
106 if (ret) {
107 /*IrealVDEC_Params *params = (IrealVDEC_Params *) vdec->params;*/
108 vdec->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1;
109 vdec->dynParams->newFrameFlag = FALSE;
110 vdec->dynParams->lateAcquireArg = -1;
111 vdec->params->numInputDataUnits = 1;
112 vdec->params->numOutputDataUnits = 1;
113 }
115 return ret;
116 }
118 static GstBuffer *
119 gst_ducati_rvdec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf)
120 {
121 GstDucatiRVDec *self = GST_DUCATIRVDEC (vdec);
122 guint8 *data;
123 guint8 val[4];
124 gint i, sz, slice_count;
126 /* *** on first buffer, build up the stream header for the codec *** */
127 if (G_UNLIKELY (vdec->first_in_buffer) && vdec->codec_data) {
129 sz = GST_BUFFER_SIZE (vdec->codec_data);
130 data = GST_BUFFER_DATA (vdec->codec_data);
132 /* header size, 4 bytes, big-endian */
133 GST_WRITE_UINT32_BE (val, sz + 26);
134 push_input (vdec, val, 4);
136 /* stream type */
137 if (self->rmversion == 3) {
138 push_input (vdec, (guint8 *)"VIDORV30", 8);
139 } else if (self->rmversion == 4) {
140 push_input (vdec, (guint8 *)"VIDORV40", 8);
141 }
143 /* horiz x vert resolution */
144 GST_WRITE_UINT16_BE (val, vdec->width);
145 push_input (vdec, val, 2);
146 GST_WRITE_UINT16_BE (val, vdec->height);
147 push_input (vdec, val, 2);
149 /* unknown? */
150 GST_WRITE_UINT32_BE (val, 0x000c0000);
151 push_input (vdec, val, 4);
153 /* unknown? may be framerate.. */
154 GST_WRITE_UINT32_BE (val, 0x0000000f);
155 push_input (vdec, val, 4);
157 /* unknown? */
158 GST_WRITE_UINT16_BE (val, 0x0000);
159 push_input (vdec, val, 2);
161 /* and rest of stream header is the codec_data */
162 push_input (vdec, data, sz);
163 }
165 data = GST_BUFFER_DATA (buf);
166 sz = GST_BUFFER_SIZE (buf);
167 slice_count = (*data++) + 1;
169 /* payload size, excluding fixed header and slice header */
170 sz -= 1 + (8 * slice_count);
172 /* *** insert frame header *** */
173 /* payload size */
174 GST_WRITE_UINT32_BE (val, sz);
175 push_input (vdec, val, 4);
177 /* unknown? may be timestamp, hopefully decoder doesn't care */
178 GST_WRITE_UINT32_BE (val, 0x00000001);
179 push_input (vdec, val, 4);
181 /* unknown? may be sequence number, hopefully decoder doesn't care */
182 GST_WRITE_UINT16_BE (val, 0x0000);
183 push_input (vdec, val, 2);
185 /* unknown? may indicate I frame, hopefully decoder doesn't care */
186 if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
187 GST_WRITE_UINT16_BE (val, 0x0000);
188 } else {
189 GST_WRITE_UINT16_BE (val, 0x0002);
190 }
191 push_input (vdec, val, 2);
193 /* unknown? seems to be always zeros */
194 GST_WRITE_UINT32_BE (val, 0x00000000);
195 push_input (vdec, val, 4);
197 /* convert the slice_header to big endian, and note that the codec
198 * expects to get slice_count rather than slice_count-1
199 */
200 GST_WRITE_UINT32_BE (val, slice_count);
201 push_input (vdec, val, 4);
203 for (i = 0; i < slice_count; i++) {
204 GST_WRITE_UINT32_BE (val, 0x00000001);
205 push_input (vdec, val, 4);
207 data += 4;
208 GST_WRITE_UINT32_BE (val, GST_READ_UINT32_LE (data));
209 data += 4;
210 push_input (vdec, val, 4);
211 }
213 /* copy the payload (rest of buffer) */
214 push_input (vdec, data, sz);
215 gst_buffer_unref (buf);
217 return NULL;
218 }
220 /* GObject vmethod implementations */
222 static void
223 gst_ducati_rvdec_base_init (gpointer gclass)
224 {
225 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
227 gst_element_class_set_details_simple (element_class,
228 "DucatiRVDec",
229 "Codec/Decoder/Video",
230 "Decodes video in RealVideo (RV8/9/10) format with ducati",
231 "Rob Clark <rob@ti.com>");
233 gst_element_class_add_pad_template (element_class,
234 gst_static_pad_template_get (&sink_factory));
235 }
237 static void
238 gst_ducati_rvdec_class_init (GstDucatiRVDecClass * klass)
239 {
240 GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass);
241 bclass->codec_name = "ivahd_realvdec";
242 bclass->parse_caps =
243 GST_DEBUG_FUNCPTR (gst_ducati_rvdec_parse_caps);
244 bclass->update_buffer_size =
245 GST_DEBUG_FUNCPTR (gst_ducati_rvdec_update_buffer_size);
246 bclass->allocate_params =
247 GST_DEBUG_FUNCPTR (gst_ducati_rvdec_allocate_params);
248 bclass->push_input =
249 GST_DEBUG_FUNCPTR (gst_ducati_rvdec_push_input);
250 }
252 static void
253 gst_ducati_rvdec_init (GstDucatiRVDec * self,
254 GstDucatiRVDecClass * gclass)
255 {
256 }