Merge remote-tracking branch 'oe_21/master' into vuplus-3.0-next
[vuplus_openvuplus_3.0] / meta-openvuplus / recipes-multimedia / gstreamer1.0 / gstreamer1.0-plugin-dvbmediasink / gstreamer10_dvbmediasink_vuplus_wmv.patch
1 diff --git a/gstdvbvideosink.c b/gstdvbvideosink.c
2 index 903432c..dd31dc7 100644
3 --- a/gstdvbvideosink.c
4 +++ b/gstdvbvideosink.c
5 @@ -150,6 +150,16 @@ void bitstream_put(struct bitstream *bit, unsigned long val, int bits)
6  }
7  #endif
8  
9 +static unsigned int Vc1ParseSeqHeader( GstDVBVideoSink *self, struct bitstream *bit );
10 +static unsigned int Vc1ParseEntryPointHeader( GstDVBVideoSink *self, struct bitstream *bit );
11 +static unsigned char Vc1GetFrameType( GstDVBVideoSink *self, struct bitstream *bit );
12 +static unsigned char Vc1GetBFractionVal( GstDVBVideoSink *self, struct bitstream *bit );
13 +static unsigned char Vc1GetNrOfFramesFromBFractionVal( unsigned char ucBFVal );
14 +static unsigned char Vc1HandleStreamBuffer( GstDVBVideoSink *self, unsigned char *data, int flags );
15 +
16 +#define cVC1NoBufferDataAvailable      0
17 +#define cVC1BufferDataAvailable                1
18 +
19  GST_DEBUG_CATEGORY_STATIC (dvbvideosink_debug);
20  #define GST_CAT_DEFAULT dvbvideosink_debug
21  
22 @@ -338,6 +348,7 @@ static void gst_dvbvideosink_init(GstDVBVideoSink *self)
23         self->num_non_keyframes = 0;
24         self->prev_frame = NULL;
25  #endif
26 +
27  #if GST_VERSION_MAJOR >= 1
28         self->use_dts = FALSE;
29  #endif
30 @@ -351,6 +362,17 @@ static void gst_dvbvideosink_init(GstDVBVideoSink *self)
31         self->saved_fallback_framerate[0] = 0;
32         self->rate = 1.0;
33  
34 +       self->ucPrevFramePicType = 0;
35 +       self->ucVC1_PULLDOWN = 0;
36 +       self->ucVC1_INTERLACE = 0;
37 +       self->ucVC1_TFCNTRFLAG = 0;
38 +       self->ucVC1_FINTERPFLAG = 0;
39 +       self->ucVC1_PSF = 0;
40 +       self->ucVC1_HRD_PARAM_FLAG = 0;
41 +       self->ucVC1_HRD_NUM_LEAKY_BUCKETS = 0;
42 +       self->ucVC1_PANSCAN_FLAG = 0;
43 +       self->ucVC1_REFDIST_FLAG = 0;
44 +
45         gst_base_sink_set_sync(GST_BASE_SINK(self), FALSE);
46         gst_base_sink_set_async_enabled(GST_BASE_SINK(self), TRUE);
47  }
48 @@ -875,18 +897,31 @@ static GstFlowReturn gst_dvbvideosink_render(GstBaseSink *sink, GstBuffer *buffe
49  
50                 if (self->codec_data)
51                 {
52 +                       if (self->codec_type == CT_VC1)
53 +                       {
54 +                               if (self->no_header && self->ucPrevFramePicType == 6) {  // I-Frame...
55 +                                       GST_INFO_OBJECT(self, "send seq header");
56 +                                       self->must_send_header = 1;
57 +                               }
58 +                       }
59                         if (self->must_send_header)
60                         {
61                                 if (self->codec_type != CT_MPEG1 && self->codec_type != CT_MPEG2 && (self->codec_type != CT_DIVX4 || data[3] == 0x00))
62                                 {
63 +                                       unsigned char *_codec_data = codec_data;
64 +                                       unsigned int _codec_data_size = codec_data_size;
65 +                                       if (self->codec_type == CT_VC1) {
66 +                                               _codec_data += 1;
67 +                                               _codec_data_size -= 1;
68 +                                       }
69                                         if (self->codec_type == CT_DIVX311)
70                                         {
71                                                 video_write(sink, self, self->codec_data, 0, codec_data_size);
72                                         }
73                                         else
74                                         {
75 -                                               memcpy(pes_header + pes_header_len, codec_data, codec_data_size);
76 -                                               pes_header_len += codec_data_size;
77 +                                               memcpy(pes_header + pes_header_len, _codec_data, _codec_data_size);
78 +                                               pes_header_len += _codec_data_size;
79                                         }
80                                         self->must_send_header = FALSE;
81                                 }
82 @@ -976,6 +1011,47 @@ static GstFlowReturn gst_dvbvideosink_render(GstBaseSink *sink, GstBuffer *buffe
83                                         pes_header_len += 3;
84                                 }
85                         }
86 +#if 1
87 +                       else if (self->codec_type == CT_VC1 || self->codec_type == CT_VC1_SM) 
88 +                       {
89 +                               int skip_header_check;
90 +
91 +                               if (data[0] || data[1] || data[2] != 1) {
92 +                                       memcpy(pes_header+pes_header_len, "\x00\x00\x01\x0d", 4);
93 +                                       pes_header_len += 4;
94 +                                       skip_header_check = 1;
95 +                               }
96 +                               else
97 +                                       skip_header_check = 0;
98 +
99 +                               self->no_header = skip_header_check;
100 +
101 +                               if (self->codec_type == CT_VC1) {
102 +                                       unsigned char ucRetVal = Vc1HandleStreamBuffer( self, data, skip_header_check );
103 +                                       if ( ucRetVal != cVC1NoBufferDataAvailable ) {
104 +#if GST_VERSION_MAJOR < 1
105 +                                               data_len = GST_BUFFER_SIZE(self->prev_frame);
106 +                                               data = GST_BUFFER_DATA(self->prev_frame);
107 +#else
108 +                                               gst_buffer_unmap(buffer, &map);
109 +                                               gst_buffer_map(self->prev_frame, &map, GST_MAP_READ);
110 +                                               data_len = map.size;
111 +                                               data = map.data;
112 +#endif
113 +                                       }
114 +                                       else {
115 +                                               GST_DEBUG_OBJECT(self, "first buffer!");
116 +
117 +                                               gst_buffer_ref(buffer);
118 +                                               self->prev_frame = buffer;
119 +
120 +                                               goto ok;
121 +                                       }
122 +
123 +                                       cache_prev_frame = TRUE;
124 +                               }
125 +                       }
126 +#endif
127                         else if (self->codec_type == CT_DIVX311)
128                         {
129                                 if (memcmp(data, "\x00\x00\x01\xb6", 4))
130 @@ -1204,12 +1280,6 @@ static GstFlowReturn gst_dvbvideosink_render(GstBaseSink *sink, GstBuffer *buffe
131                         }
132                 }
133         }
134 -       else if (self->codec_type == CT_VC1 || self->codec_type == CT_VC1_SM)
135 -       {
136 -               memcpy(pes_header + pes_header_len, "\x00\x00\x01\x0d", 4);
137 -               pes_header_len += 4;
138 -               payload_len += 4;
139 -       }
140  
141         pes_set_payload_size(payload_len, pes_header);
142  
143 @@ -1617,12 +1687,90 @@ static gboolean gst_dvbvideosink_set_caps(GstBaseSink *basesink, GstCaps *caps)
144                         self->codec_type = CT_VC1_SM;
145                         GST_INFO_OBJECT (self, "MIMETYPE video/x-wmv -> STREAMTYPE_VC1_SM");
146                 }
147 +
148 +               if (self->codec_type == CT_VC1)
149 +               {
150 +                       const GValue *codec_data = gst_structure_get_value(structure, "codec_data");
151 +                       if (codec_data)
152 +                       {
153 +
154 +                               self->codec_data = gst_value_get_buffer (codec_data);
155 +                               gst_buffer_ref (self->codec_data);
156 +#if GST_VERSION_MAJOR < 1
157 +                               Vc1HandleStreamBuffer(self, GST_BUFFER_DATA(self->codec_data)+1, 2 );
158 +#else
159 +                               GstMapInfo codec_data_map;
160 +                               gst_buffer_map(self->codec_data, &codec_data_map, GST_MAP_READ);
161 +                               Vc1HandleStreamBuffer(self, codec_data_map.data+1, 2 );
162 +                               gst_buffer_unmap(self->codec_data, &codec_data_map);
163 +#endif
164 +
165 +                       }
166 +               }
167 +               else if (self->codec_type == CT_VC1_SM)
168 +               {
169 +                       const GValue *codec_data = gst_structure_get_value(structure, "codec_data");
170 +
171 +                       if (codec_data)
172 +                       {
173 +                               /* wmv version 3 test */
174 +                               guint8 *codec_data_pointer, *data;
175 +                               gint codec_size, size;
176 +                               gint width, height;
177 +#if GST_VERSION_MAJOR < 1
178 +                               codec_size = GST_BUFFER_SIZE(gst_value_get_buffer(codec_data));
179 +                               codec_data_pointer = GST_BUFFER_DATA(gst_value_get_buffer(codec_data));
180 +#else
181 +                               GstMapInfo codecdatamap;
182 +                               gst_buffer_map(gst_value_get_buffer(codec_data), &codecdatamap, GST_MAP_READ);
183 +                               codec_data_pointer = codecdatamap.data;
184 +                               codec_size = codecdatamap.size;
185 +#endif
186 +                               if (codec_size > 4) codec_size = 4;
187 +                               gst_structure_get_int(structure, "width", &width);
188 +                               gst_structure_get_int(structure, "height", &height);
189 +
190 +                               self->codec_data = gst_buffer_new_and_alloc(19);
191 +#if GST_VERSION_MAJOR < 1
192 +                               data = GST_BUFFER_DATA(self->codec_data);
193 +#else
194 +                               GstMapInfo self_codec_map;
195 +                               gst_buffer_map(self->codec_data, &self_codec_map, GST_MAP_WRITE);
196 +                               data = self_codec_map.data;
197 +                               size = codecdatamap.size;
198 +#endif
199 +                               memset(data, 0, size);
200 +
201 +                               *(data++) = 0x00;
202 +                               *(data++) = 0x00;
203 +                               *(data++) = 0x01;
204 +                               *(data++) = 0x0F;
205 +
206 +                               /* width */
207 +                               *(data++) = (width >> 8) & 0xff;
208 +                               *(data++) = width & 0xff;
209 +                               /* height */
210 +                               *(data++) = (height >> 8) & 0xff;
211 +                               *(data++) = height & 0xff;
212 +
213 +                               if (codec_data && codec_size)
214 +                                       memcpy(data, codec_data_pointer, codec_size);
215 +
216 +                               codec_data_pointer[0] >>= 4;
217 +                               if (codec_data_pointer[0] != 4 && codec_data_pointer[0] != 0)
218 +                                       GST_ERROR_OBJECT(self, "unsupported vc1-sm video compression format (profile %d)", codec_data_pointer[0]);
219 +#if GST_VERSION_MAJOR >= 1
220 +                               gst_buffer_unmap(gst_value_get_buffer(codec_data), &self_codec_map);
221 +                               gst_buffer_unmap(self->codec_data, &codecdatamap);
222 +#endif
223 +                       }
224 +               }
225         }
226  
227         if (self->stream_type != STREAMTYPE_UNKNOWN)
228         {
229                 gint numerator, denominator;
230 -               if (gst_structure_get_fraction (structure, "framerate", &numerator, &denominator))
231 +               if (self->framerate == -1 && gst_structure_get_fraction (structure, "framerate", &numerator, &denominator))
232                 {
233                         FILE *f = fopen("/proc/stb/vmpeg/0/fallback_framerate", "w");
234                         if (f)
235 @@ -1663,76 +1811,7 @@ static gboolean gst_dvbvideosink_set_caps(GstBaseSink *basesink, GstCaps *caps)
236                 }
237                 if (self->fd >= 0) 
238                 {
239 -                       if (self->codec_type == CT_VC1)
240 -                       {
241 -                               const GValue *codec_data = gst_structure_get_value(structure, "codec_data");
242 -                               if (codec_data)
243 -                               {
244 -                                       guint8 *codec_data_pointer;
245 -                                       gint codec_size;
246 -                                       guint8 *data;
247 -                                       video_codec_data_t videocodecdata;
248 -#if GST_VERSION_MAJOR < 1
249 -                                       codec_size = GST_BUFFER_SIZE(gst_value_get_buffer(codec_data));
250 -                                       codec_data_pointer = GST_BUFFER_DATA(gst_value_get_buffer(codec_data));
251 -#else
252 -                                       GstMapInfo codecdatamap;
253 -                                       gst_buffer_map(gst_value_get_buffer(codec_data), &codecdatamap, GST_MAP_READ);
254 -                                       codec_data_pointer = codecdatamap.data;
255 -                                       codec_size = codecdatamap.size;
256 -#endif
257 -                                       videocodecdata.length = 8 + codec_size;
258 -                                       data = videocodecdata.data = (guint8*)g_malloc(videocodecdata.length);
259 -                                       memset(data, 0, videocodecdata.length);
260 -                                       data += 8;
261 -                                       memcpy(data, codec_data_pointer, codec_size);
262 -                                       ioctl(self->fd, VIDEO_SET_CODEC_DATA, &videocodecdata);
263 -                                       g_free(videocodecdata.data);
264 -#if GST_VERSION_MAJOR >= 1
265 -                                       gst_buffer_unmap(gst_value_get_buffer(codec_data), &codecdatamap);
266 -#endif
267 -                               }
268 -                       }
269 -                       else if (self->codec_type == CT_VC1_SM)
270 -                       {
271 -                               const GValue *codec_data = gst_structure_get_value(structure, "codec_data");
272 -                               if (codec_data)
273 -                               {
274 -                                       guint8 *codec_data_pointer;
275 -                                       gint codec_size;
276 -                                       guint8 *data;
277 -                                       video_codec_data_t videocodecdata;
278 -                                       gint width, height;
279 -#if GST_VERSION_MAJOR < 1
280 -                                       codec_size = GST_BUFFER_SIZE(gst_value_get_buffer(codec_data));
281 -                                       codec_data_pointer = GST_BUFFER_DATA(gst_value_get_buffer(codec_data));
282 -#else
283 -                                       GstMapInfo codecdatamap;
284 -                                       gst_buffer_map(gst_value_get_buffer(codec_data), &codecdatamap, GST_MAP_READ);
285 -                                       codec_data_pointer = codecdatamap.data;
286 -                                       codec_size = codecdatamap.size;
287 -#endif
288 -                                       if (codec_size > 4) codec_size = 4;
289 -                                       gst_structure_get_int(structure, "width", &width);
290 -                                       gst_structure_get_int(structure, "height", &height);
291 -                                       videocodecdata.length = 33;
292 -                                       data = videocodecdata.data = (guint8*)g_malloc(videocodecdata.length);
293 -                                       memset(data, 0, videocodecdata.length);
294 -                                       data += 18;
295 -                                       /* width */
296 -                                       *(data++) = (width >> 8) & 0xff;
297 -                                       *(data++) = width & 0xff;
298 -                                       /* height */
299 -                                       *(data++) = (height >> 8) & 0xff;
300 -                                       *(data++) = height & 0xff;
301 -                                       if (codec_data && codec_size) memcpy(data, codec_data_pointer, codec_size);
302 -                                       ioctl(self->fd, VIDEO_SET_CODEC_DATA, &videocodecdata);
303 -                                       g_free(videocodecdata.data);
304 -#if GST_VERSION_MAJOR >= 1
305 -                                       gst_buffer_unmap(gst_value_get_buffer(codec_data), &codecdatamap);
306 -#endif
307 -                               }
308 -                       }
309 +                       
310                         ioctl(self->fd, VIDEO_PLAY);
311                 }
312                 self->playing = TRUE;
313 @@ -1941,3 +2020,434 @@ GST_PLUGIN_DEFINE (
314         "GStreamer",
315         "http://gstreamer.net/"
316  )
317 +
318 +static unsigned int
319 +Vc1ParseSeqHeader( GstDVBVideoSink *self, struct bitstream *bit )
320 +{
321 +       unsigned char n;
322 +       long uiStartAddr = (long)&(bit->data[0]);
323 +       long uiStopAddr = 0;
324 +
325 +       // skip first 5 bytes (PROFILE,LEVEL,COLORDIFF_FORMAT,FRMRTQ_POSTPROC,BITRTQ_POSTPROC,POSTPROCFLAG,MAX_CODED_WIDTH,MAX_CODED_HEIGHT)
326 +       bitstream_get( bit, 32 );
327 +       bitstream_get( bit, 8 );
328 +       self->ucVC1_PULLDOWN = (unsigned char)bitstream_get( bit, 1 );
329 +       self->ucVC1_INTERLACE = (unsigned char)bitstream_get( bit, 1 );
330 +       self->ucVC1_TFCNTRFLAG = (unsigned char)bitstream_get( bit, 1 );
331 +       self->ucVC1_FINTERPFLAG = (unsigned char)bitstream_get( bit, 1 );
332 +       // skip 1 bit (RESERVED)
333 +       bitstream_get( bit, 1 );
334 +       self->ucVC1_PSF = (unsigned char)bitstream_get( bit, 1 );
335 +
336 +       if ( bitstream_get( bit, 1 ) == 1 ) {
337 +               // DISPLAY_EXT == 1
338 +
339 +               // skip 28 bits (DISP_HORIZ_SIZE,DISP_VERT_SIZE)
340 +               bitstream_get( bit, 28 );
341 +
342 +               if ( bitstream_get( bit, 1 ) == 1 ) {
343 +                       // ASPECT_RATIO_FLAG == 1
344 +                       if ( bitstream_get( bit, 4 ) == 15 )
345 +                       {
346 +                               // ASPECT_RATIO == '15'
347 +
348 +                               // skip 16 bits (ASPECT_HORIZ_SIZE,ASPECT_VERT_SIZE)
349 +                               bitstream_get( bit, 16 );
350 +                       }
351 +               }
352 +
353 +               if ( bitstream_get( bit, 1 ) == 1 ) {
354 +                       int framerate = -1;
355 +                       // FRAMERATE_FLAG == 1
356 +                       if ( bitstream_get( bit, 1 ) == 0 ) {
357 +                               // FRAMERATEIND == 0
358 +                               int frameratenr = bitstream_get( bit, 8 );
359 +                               int frameratedr = bitstream_get( bit, 4 );
360 +
361 +                               GST_DEBUG_OBJECT(self, "VC1 frameratenr %d, frameratedr %d", frameratenr, frameratedr);
362 +
363 +                               switch (frameratenr) {
364 +                                       case 1: framerate = 24000; break;
365 +                                       case 2: framerate = 25000; break;
366 +                                       case 3: framerate = 30000; break;
367 +                                       case 4: framerate = 50000; break;
368 +                                       case 5: framerate = 60000; break;
369 +                                       case 6: framerate = 48000; break;
370 +                                       case 7: framerate = 72000; break;
371 +                                       default:
372 +                                               GST_INFO_OBJECT(self, "forbidden VC1 frameratenr %d", frameratenr);
373 +                                               break;
374 +                               }
375 +                               if (framerate != -1) {
376 +                                       switch (frameratedr) {
377 +                                       case 1: break;
378 +                                       case 2: framerate *= 1000;
379 +                                               framerate /= 1001;
380 +                                               break;
381 +                                       default:
382 +                                               GST_INFO_OBJECT(self, "forbidden VC1 frameratedr %d", frameratedr);
383 +                                               break;
384 +                                       }
385 +                               }
386 +                       }
387 +                       else {
388 +                               // FRAMERATEIND == 1
389 +                               int framerateexp = bitstream_get( bit, 16 );
390 +
391 +                               GST_DEBUG_OBJECT(self, "VC1 framerateexp %d", framerateexp);
392 +
393 +                               framerate = (framerateexp * 1000) / 32;
394 +                       }
395 +
396 +                       if (framerate != -1) {
397 +                               GST_INFO_OBJECT(self, "VC1 seq header framerate %d", framerate);
398 +
399 +                               self->framerate = framerate;
400 +                       }
401 +               }
402 +
403 +               if ( bitstream_get( bit, 1 ) == 1 ) {
404 +                       // COLOR_FORMAT_FLAG ==1
405 +
406 +                       // skip 24 bits (COLOR_PRIM,TRANSFER_CHAR,MATRIX_COEF)
407 +                       bitstream_get( bit, 24 );
408 +               }
409 +       }
410 +
411 +       self->ucVC1_HRD_PARAM_FLAG = (unsigned char)bitstream_get( bit, 1 );
412 +
413 +       if ( self->ucVC1_HRD_PARAM_FLAG == 1 ) {
414 +               // ucVC1_HRD_PARAM_FLAG == 1
415 +               self->ucVC1_HRD_NUM_LEAKY_BUCKETS = (unsigned char)bitstream_get( bit, 5 );
416 +
417 +               // skip 8 bits (BIT_RATE_EXPONENT,BUFFER_SIZE_EXPONENT)
418 +               bitstream_get( bit, 8 );
419 +
420 +               for ( n = 1; n <= self->ucVC1_HRD_NUM_LEAKY_BUCKETS; n++ ) {
421 +                       // skip 32 bits (HRD_RATE[n],HRD_BUFFER[n])
422 +                       bitstream_get( bit, 32 );
423 +               }
424 +       }
425 +
426 +       uiStopAddr = (long)&(bit->data[0]);
427 +       return (unsigned int)(uiStopAddr - uiStartAddr + 1);
428 +}
429 +
430 +static unsigned int
431 +Vc1ParseEntryPointHeader( GstDVBVideoSink *self, struct bitstream *bit )
432 +{
433 +       unsigned char n, ucEXTENDED_MV;
434 +       long uiStartAddr = (long)&(bit->data[0]);
435 +       long uiStopAddr = 0;
436 +
437 +       // skip the first two bits (BROKEN_LINK,CLOSED_ENTRY)
438 +       bitstream_get( bit, 2 );
439 +       self->ucVC1_PANSCAN_FLAG = (unsigned char)bitstream_get( bit, 1 );
440 +       self->ucVC1_REFDIST_FLAG = (unsigned char)bitstream_get( bit, 1 );
441 +
442 +       // skip 2 bits (LOOPFILTER,FASTUVMC)
443 +       bitstream_get( bit, 2 );
444 +
445 +       ucEXTENDED_MV = (unsigned char)bitstream_get( bit, 1 );
446 +
447 +       // skip 6 bits (DQUANT,VSTRANSFORM,OVERLAP,QUANTIZER)
448 +       bitstream_get( bit, 6 );
449 +
450 +       if ( self->ucVC1_HRD_PARAM_FLAG == 1 ) {
451 +               for ( n = 1; n <= self->ucVC1_HRD_NUM_LEAKY_BUCKETS; n++ ) {
452 +                       // skip 8 bits (HRD_FULL[n])
453 +                       bitstream_get( bit, 8 );
454 +               }
455 +       }
456 +
457 +       if ( bitstream_get( bit, 1 ) == 1 ) {
458 +               // CODED_SIZE_FLAG == 1
459 +
460 +               // skip 24 bits (CODED_WIDTH,CODED_HEIGHT)
461 +               bitstream_get( bit, 24 );
462 +       }
463 +
464 +       if ( ucEXTENDED_MV == 1 ) {
465 +               // skip 1 bit (EXTENDED_DMV)
466 +               bitstream_get( bit, 1 );
467 +       }
468 +
469 +       if ( bitstream_get( bit, 1 ) == 1 ) {
470 +               // RANGE_MAPY_FLAG == 1
471 +
472 +               // skip 3 bits (RANGE_MAPY)
473 +               bitstream_get( bit, 3 );
474 +       }
475 +
476 +       if ( bitstream_get( bit, 1 ) == 1 ) {
477 +               // RANGE_MAPUV_FLAG == 1
478 +
479 +               // skip 3 bits (RANGE_MAPUV)
480 +               bitstream_get( bit, 3 );
481 +       }
482 +
483 +       uiStopAddr = (long)&(bit->data[0]);
484 +
485 +       return (unsigned int)(uiStopAddr - uiStartAddr + 1);
486 +}
487 +
488 +static unsigned char
489 +Vc1GetFrameType( GstDVBVideoSink *self, struct bitstream *bit )
490 +{
491 +       unsigned char ucRetVal = 0;
492 +
493 +       if ( self->ucVC1_INTERLACE == 1 ) {
494 +               // determine FCM
495 +               if ( bitstream_get( bit, 1 ) == 1 ) {
496 +                       // Frame- or Field-Interlace Coding Mode -> we have to skip a further bit
497 +                       bitstream_get( bit, 1 );
498 +               }
499 +               else {
500 +                       // Progressive Frame Coding Mode -> no need to consume a further bit
501 +               }
502 +       }
503 +
504 +       if ( bitstream_get( bit, 1 ) == 0 ) {
505 +               // P-Frame detected
506 +               ucRetVal = 0;
507 +       }
508 +       else if ( bitstream_get( bit, 1 ) == 0 ) {
509 +               // B-Frame detected
510 +               ucRetVal = 2;
511 +       }
512 +       else if ( bitstream_get( bit, 1 ) == 0 ) {
513 +               // I-Frame detected
514 +               ucRetVal = 6;
515 +       }
516 +       else if ( bitstream_get( bit, 1 ) == 0 ) {
517 +               // BI-Frame detected
518 +               ucRetVal = 14;
519 +       }
520 +       else {
521 +               // Skipped-Frame detected
522 +               ucRetVal = 15;
523 +       }
524 +
525 +       return ucRetVal;
526 +}
527 +
528 +static unsigned char
529 +Vc1GetBFractionVal( GstDVBVideoSink *self, struct bitstream *bit )
530 +{
531 +       unsigned char ucRetVal = 0;
532 +       unsigned char ucNumberOfPanScanWindows = 0;
533 +       unsigned char ucRFF = 0;
534 +       unsigned char ucRPTFRM = 0;
535 +       unsigned char ucTmpVar = 0;
536 +       unsigned char i;
537 +
538 +       if ( self->ucVC1_TFCNTRFLAG == 1 ) {
539 +               // skip the first 8 bit (TFCNTR)
540 +               bitstream_get( bit, 8 );
541 +       }
542 +
543 +       if ( self->ucVC1_PULLDOWN == 1 ) {
544 +               if ( self->ucVC1_INTERLACE == 0 || self->ucVC1_PSF == 1 ) {
545 +                       ucRPTFRM = (unsigned char)bitstream_get( bit, 2 );
546 +               }
547 +               else {
548 +                       // skip 1 bit (TFF)
549 +                       bitstream_get( bit, 1 );
550 +                       ucRFF = (unsigned char)bitstream_get( bit, 1 );
551 +               }
552 +       }
553 +
554 +       if ( self->ucVC1_PANSCAN_FLAG == 1 ) {
555 +               if ( bitstream_get( bit, 2 ) != 0 ) {
556 +                       // PS_PRESENT
557 +                       if ( self->ucVC1_INTERLACE == 1 && self->ucVC1_PSF == 0 ) {
558 +                               if ( self->ucVC1_PULLDOWN == 1 ) {
559 +                                       ucNumberOfPanScanWindows = 2 + ucRFF;
560 +                               }
561 +                               else {
562 +                                       ucNumberOfPanScanWindows = 2;
563 +                               }
564 +                       }
565 +                       else {
566 +                               if ( self->ucVC1_PULLDOWN == 1 ) {
567 +                                       ucNumberOfPanScanWindows = 1 + ucRPTFRM;
568 +                               }
569 +                               else {
570 +                                       ucNumberOfPanScanWindows = 1;
571 +                               }
572 +                       }
573 +                       for ( i = 0; i < ucNumberOfPanScanWindows; i++ ) {
574 +                               // skip 8 bytes (PS_HOFFSET,PS_VOFFSET,PS_WIDTH,PS_HEIGHT)
575 +                               bitstream_get( bit, 32 );
576 +                               bitstream_get( bit, 32 );
577 +                       }
578 +               }
579 +       }
580 +
581 +       // skip 1 bit (RNDCTRL)
582 +       bitstream_get( bit, 1 );
583 +
584 +       if ( self->ucVC1_INTERLACE == 1 ) {
585 +               // skip 1 bit (UVSAMP)
586 +               bitstream_get( bit, 1 );
587 +       }
588 +
589 +       if ( self->ucVC1_FINTERPFLAG == 1 ) {
590 +               // skip 1 bit (INTERPFRM)
591 +               bitstream_get( bit, 1 );
592 +       }
593 +
594 +       ucTmpVar = (unsigned char)bitstream_get( bit, 3 );
595 +       ucRetVal = ucTmpVar;
596 +
597 +       if ( ucTmpVar > 6 ) {
598 +               ucRetVal <<= 4;
599 +               ucTmpVar = (unsigned char)bitstream_get( bit, 4 );
600 +               ucRetVal |= ucTmpVar;
601 +       }
602 +
603 +       return ucRetVal;
604 +}
605 +
606 +static unsigned char
607 +Vc1GetNrOfFramesFromBFractionVal( unsigned char ucBFVal )
608 +{
609 +       unsigned char ucRetVal;
610 +
611 +       switch( ucBFVal ) {
612 +               case 0:
613 +                       //printf("(1/2)\n");
614 +                       ucRetVal = 1;
615 +                       break;
616 +               case 1:
617 +                       //printf("(1/3)\n");
618 +                       ucRetVal = 2;
619 +                       break;
620 +               case 3:
621 +                       //printf("(1/4)\n");
622 +                       ucRetVal = 3;
623 +                       break;
624 +               case 5:
625 +                       //printf("(1/5)\n");
626 +                       ucRetVal = 4;
627 +                       break;
628 +               case 0x72:
629 +                       //printf("(1/6)\n");
630 +                       ucRetVal = 5;
631 +                       break;
632 +               case 0x74:
633 +                       //printf("(1/7)\n");
634 +                       ucRetVal = 6;
635 +                       break;
636 +               case 0x7A:
637 +                       //printf("(1/8)\n");
638 +                       ucRetVal = 7;
639 +                       break;
640 +               default:
641 +                       ucRetVal = 0;
642 +                       //printf("ucBFVal = %d\n", ucBFVal);
643 +                       break;
644 +       }
645 +
646 +       return ucRetVal;
647 +}
648 +
649 +static unsigned char
650 +Vc1HandleStreamBuffer( GstDVBVideoSink *self, unsigned char *data, int flags )
651 +{
652 +       unsigned char ucPType, ucRetVal = cVC1BufferDataAvailable;
653 +       unsigned int i = -1;
654 +
655 +       if (flags & 1)
656 +               goto parse_frame_header;
657 +
658 +       i = 0;
659 +
660 +       if ( ((data[i] == 0) && (data[i+1] == 0) && (data[i+2] == 1)) ) {
661 +
662 +               i += 3;
663 +
664 +               if ( data[i] == 0x0F ) {
665 +                       // Sequence header
666 +                       struct bitstream bitstr;
667 +                       i++;
668 +                       bitstream_init( &bitstr, &data[i], 0 );
669 +                       i += Vc1ParseSeqHeader(self, &bitstr);
670 +                       //printf("Sequence header\n");
671 +
672 +                       if ( data[i] == 0 && data[i+1] == 0 && data[i+2] == 1 && data[i+3] == 0x0E ) {
673 +                               // Entry Point Header
674 +                               struct bitstream bitstr;
675 +                               i += 4;
676 +                               bitstream_init( &bitstr, &data[i], 0 );
677 +                               i += Vc1ParseEntryPointHeader(self, &bitstr);
678 +                               //printf("Entry Point header\n");
679 +
680 +                               if ( flags & 2 ) // parse codec_data only
681 +                                       return 0;
682 +
683 +                               if ( data[i] == 0 && data[i+1] == 0 && data[i+2] == 1 && data[i+3] == 0x0D )
684 +                                       i += 3;
685 +                               else
686 +                                       GST_ERROR_OBJECT(self, "No Frame Header after a VC1 Entry Point header!!!");
687 +                       }
688 +                       else
689 +                               GST_ERROR_OBJECT(self, "No Entry Point Header after a VC1 Sequence header!!!");
690 +               }
691 +
692 +               if ( data[i] == 0x0D )
693 +parse_frame_header:
694 +               {
695 +                       // Frame Header
696 +                       struct bitstream bitstr;
697 +                       unsigned char ucBFractionVal = 0;
698 +
699 +                       i++;
700 +
701 +                       bitstream_init( &bitstr, &data[i], 0 );
702 +                       ucPType = Vc1GetFrameType( self, &bitstr );
703 +
704 +                       GST_DEBUG_OBJECT(self, "picturetype = %d", ucPType);
705 +
706 +                       if ( self->prev_frame == NULL ) {
707 +                               // first frame received
708 +                               ucRetVal = cVC1NoBufferDataAvailable;
709 +                       }
710 +                       else {
711 +                               if ( ucPType == 2 && (self->ucPrevFramePicType == 0 || self->ucPrevFramePicType == 6 || self->ucPrevFramePicType == 15) )
712 +                               {
713 +                                       int num_frames;
714 +                                       // last frame was a reference frame (P-,I- or Skipped-Frame) and current frame is a B-Frame
715 +                                       // -> correct the timestamp of the previous reference frame
716 +                                       ucBFractionVal = Vc1GetBFractionVal( self, &bitstr );
717 +
718 +                                       num_frames = Vc1GetNrOfFramesFromBFractionVal( ucBFractionVal );
719 +
720 +                                       GST_DEBUG_OBJECT(self, "num_frames = %d", num_frames);
721 +#if GST_VERSION_MAJOR < 1
722 +                                       GST_BUFFER_TIMESTAMP(self->prev_frame) += (1000000000000ULL / self->framerate) * num_frames;
723 +#else
724 +                                       GST_BUFFER_PTS(self->prev_frame) += (1000000000000ULL / self->framerate) * num_frames;
725 +#endif
726 +                               }
727 +                               else if ( self->ucPrevFramePicType == 2 )
728 +                               {
729 +                                       // last frame was a B-Frame -> correct the timestamp by the duration
730 +                                       // of the preceding reference frame
731 +#if GST_VERSION_MAJOR < 1
732 +                                       GST_BUFFER_TIMESTAMP(self->prev_frame) -= 1000000000000ULL / self->framerate;
733 +#else
734 +                                       GST_BUFFER_PTS(self->prev_frame) -= 1000000000000ULL / self->framerate;
735 +#endif
736 +                               }
737 +                       }
738 +                       // save the current picture type
739 +                       self->ucPrevFramePicType = ucPType;
740 +               }
741 +       }
742 +       else
743 +               GST_ERROR_OBJECT(self, "startcodes in VC1 buffer not correctly aligned!");
744 +
745 +       return ucRetVal;
746 +}
747 +
748 diff --git a/gstdvbvideosink.h b/gstdvbvideosink.h
749 index 8cf1dc2..14429a8 100644
750 --- a/gstdvbvideosink.h
751 +++ b/gstdvbvideosink.h
752 @@ -71,9 +71,9 @@ typedef enum {
753         STREAMTYPE_MPEG2 = 0,
754         STREAMTYPE_MPEG4_H264 = 1,
755         STREAMTYPE_H263 = 2,
756 -       STREAMTYPE_VC1 = 3,
757 +       STREAMTYPE_VC1 = 16,
758         STREAMTYPE_MPEG4_Part2 = 4,
759 -       STREAMTYPE_VC1_SM = 5,
760 +       STREAMTYPE_VC1_SM = 17,
761         STREAMTYPE_MPEG1 = 6,
762         STREAMTYPE_XVID = 10,
763         STREAMTYPE_DIVX311 = 13,
764 @@ -116,6 +116,27 @@ struct _GstDVBVideoSink
765         gboolean must_send_header;
766  
767         queue_entry_t *queue;
768 +
769 +       // VC1 stuff....
770 +
771 +       int no_header;
772 +
773 +       int framerate;  // current framerate
774 +
775 +       unsigned char ucPrevFramePicType;
776 +
777 +       // Sequence header variables
778 +       unsigned char ucVC1_PULLDOWN;
779 +       unsigned char ucVC1_INTERLACE;
780 +       unsigned char ucVC1_TFCNTRFLAG ;
781 +       unsigned char ucVC1_FINTERPFLAG;
782 +       unsigned char ucVC1_PSF;
783 +       unsigned char ucVC1_HRD_PARAM_FLAG;
784 +       unsigned char ucVC1_HRD_NUM_LEAKY_BUCKETS;
785 +
786 +       // Entry Point header variables
787 +       unsigned char ucVC1_PANSCAN_FLAG;
788 +       unsigned char ucVC1_REFDIST_FLAG;
789  };
790  
791  struct _GstDVBVideoSinkClass