]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugin-ducati.git/blob - src/gstducatirvdec.c
f1b650e19691bf2ba01d4a5f9d9d42a55f60e254
[glsdk/gst-plugin-ducati.git] / src / gstducatirvdec.c
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)
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;
118 static GstBuffer *
119 gst_ducati_rvdec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf)
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;
220 /* GObject vmethod implementations */
222 static void
223 gst_ducati_rvdec_base_init (gpointer gclass)
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));
237 static void
238 gst_ducati_rvdec_class_init (GstDucatiRVDecClass * klass)
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);
252 static void
253 gst_ducati_rvdec_init (GstDucatiRVDec * self,
254     GstDucatiRVDecClass * gclass)