fixed vc1 parser...
[gst-plugin-dvbmediasink.git] / src / gstdvbvideosink.c
1 /* GStreamer DVB Media Sink
2  * Copyright 2006 Felix Domke <tmbinc@elitedvb.net>
3  * based on code by:
4  * Copyright 2005 Thomas Vander Stichele <thomas@apestaart.org>
5  * Copyright 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
6  * 
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  * Alternatively, the contents of this file may be used under the
26  * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
27  * which case the following provisions apply instead of the ones
28  * mentioned above:
29  *
30  * This library is free software; you can redistribute it and/or
31  * modify it under the terms of the GNU Library General Public
32  * License as published by the Free Software Foundation; either
33  * version 2 of the License, or (at your option) any later version.
34  *
35  * This library is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38  * Library General Public License for more details.
39  *
40  * You should have received a copy of the GNU Library General Public
41  * License along with this library; if not, write to the
42  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
43  * Boston, MA 02111-1307, USA.
44  */
45
46 /**
47  * SECTION:element-plugin
48  *
49  * <refsect2>
50  * <title>Example launch line</title>
51  * <para>
52  * <programlisting>
53  * gst-launch -v -m audiotestsrc ! plugin ! fakesink silent=TRUE
54  * </programlisting>
55  * </para>
56  * </refsect2>
57  */
58
59 #ifdef HAVE_CONFIG_H
60 #include <config.h>
61 #endif
62 #include <unistd.h>
63 #include <stdint.h>
64 #include <sys/ioctl.h>
65 #include <sys/socket.h>
66 #include <linux/dvb/video.h>
67 #include <fcntl.h>
68 #include <poll.h>
69 #include <string.h>
70
71 #include <gst/gst.h>
72
73 #include "gstdvbvideosink.h"
74 #include "gstdvbsink-marshal.h"
75
76 #ifndef VIDEO_GET_PTS
77 #define VIDEO_GET_PTS              _IOR('o', 57, gint64)
78 #endif
79
80 struct bitstream
81 {
82         guint8 *data;
83         guint8 last;
84         int avail;
85 };
86
87 static void bitstream_init(struct bitstream *bit, const void *buffer, gboolean wr)
88 {
89         bit->data = (guint8*) buffer;
90         if (wr) {
91                 bit->avail = 0;
92                 bit->last = 0;
93         }
94         else {
95                 bit->avail = 8;
96                 bit->last = *bit->data++;
97         }
98 }
99
100 static unsigned long bitstream_get(struct bitstream *bit, int bits)
101 {
102         unsigned long res=0;
103         while (bits)
104         {
105                 unsigned int d=bits;
106                 if (d > bit->avail)
107                         d=bit->avail;
108                 res<<=d;
109                 res|=(bit->last>>(bit->avail-d))&~(-1<<d);
110                 bit->avail-=d;
111                 bits-=d;
112                 if (!bit->avail) {
113                         bit->last = *bit->data++;
114                         bit->avail = 8;
115                 }
116         }
117         return res;
118 }
119
120 static void bitstream_put(struct bitstream *bit, unsigned long val, int bits)
121 {
122         while (bits)
123         {
124                 bit->last |= ((val & (1 << (bits-1))) ? 1 : 0) << (7 - bit->avail);
125                 if (++bit->avail == 8) {
126                         *bit->data = bit->last;
127                         ++bit->data;
128                         bit->last = 0;
129                         bit->avail = 0;
130                 }
131                 --bits;
132         }
133 }
134
135 static unsigned int Vc1ParseSeqHeader( GstDVBVideoSink *self, struct bitstream *bit );
136 static unsigned int Vc1ParseEntryPointHeader( GstDVBVideoSink *self, struct bitstream *bit );
137 static unsigned char Vc1GetFrameType( GstDVBVideoSink *self, struct bitstream *bit );
138 static unsigned char Vc1GetBFractionVal( GstDVBVideoSink *self, struct bitstream *bit );
139 static unsigned char Vc1GetNrOfFramesFromBFractionVal( unsigned char ucBFVal );
140 static unsigned char Vc1HandleStreamBuffer( GstDVBVideoSink *self, unsigned char *data, unsigned int data_len, int flags );
141
142 #define cVC1NoBufferDataAvailable       0
143 #define cVC1BufferDataAvailable         1
144
145 /* We add a control socket as in fdsrc to make it shutdown quickly when it's blocking on the fd.
146  * Poll is used to determine when the fd is ready for use. When the element state is changed,
147  * it happens from another thread while fdsink is poll'ing on the fd. The state-change thread 
148  * sends a control message, so fdsink wakes up and changes state immediately otherwise
149  * it would stay blocked until it receives some data. */
150
151 /* the poll call is also performed on the control sockets, that way
152  * we can send special commands to unblock the poll call */
153 #define CONTROL_STOP            'S'                     /* stop the poll call */
154 #define CONTROL_SOCKETS(sink)   sink->control_sock
155 #define WRITE_SOCKET(sink)      sink->control_sock[1]
156 #define READ_SOCKET(sink)       sink->control_sock[0]
157
158 #define SEND_COMMAND(sink, command)                     \
159 G_STMT_START {                                          \
160         unsigned char c; c = command;                   \
161         write (WRITE_SOCKET(sink), &c, 1);              \
162 } G_STMT_END
163
164 #define READ_COMMAND(sink, command, res)                \
165 G_STMT_START {                                          \
166         res = read(READ_SOCKET(sink), &command, 1);     \
167 } G_STMT_END
168
169 GST_DEBUG_CATEGORY_STATIC (dvbvideosink_debug);
170 #define GST_CAT_DEFAULT dvbvideosink_debug
171
172 #define COMMON_VIDEO_CAPS \
173   "width = (int) [ 16, 4096 ], " \
174   "height = (int) [ 16, 4096 ], " \
175   "framerate = (fraction) [ 0, MAX ]"
176
177 #define MPEG4V2_LIMITED_CAPS \
178   "width = (int) [ 16, 800 ], " \
179   "height = (int) [ 16, 600 ], " \
180   "framerate = (fraction) [ 0, MAX ]"
181
182 enum
183 {
184         SIGNAL_GET_DECODER_TIME,
185         LAST_SIGNAL
186 };
187
188 static guint gst_dvb_videosink_signals[LAST_SIGNAL] = { 0 };
189
190 static GstStaticPadTemplate sink_factory_bcm7400 =
191 GST_STATIC_PAD_TEMPLATE (
192         "sink",
193         GST_PAD_SINK,
194         GST_PAD_ALWAYS,
195         GST_STATIC_CAPS (
196                 "video/mpeg, "
197                 "mpegversion = (int) { 1, 2, 4 }, "
198                 "systemstream = (boolean) false, "
199                 COMMON_VIDEO_CAPS "; "
200                 "video/x-h264, "
201                 COMMON_VIDEO_CAPS "; "
202                 "video/x-h263, "
203                 COMMON_VIDEO_CAPS "; "
204                 "video/x-msmpeg, "
205                 MPEG4V2_LIMITED_CAPS ", msmpegversion = (int) 43; "
206                 "video/x-divx, "
207                 MPEG4V2_LIMITED_CAPS ", divxversion = (int) [ 3, 6 ]; "
208                 "video/x-xvid, "
209                 MPEG4V2_LIMITED_CAPS "; "
210                 "video/x-3ivx, "
211                 MPEG4V2_LIMITED_CAPS "; "
212                 "video/x-wmv, "
213                 "wmvversion = (int) 3, "
214                 COMMON_VIDEO_CAPS "; ")
215 );
216
217 static GstStaticPadTemplate sink_factory_bcm7405 =
218 GST_STATIC_PAD_TEMPLATE (
219         "sink",
220         GST_PAD_SINK,
221         GST_PAD_ALWAYS,
222         GST_STATIC_CAPS (
223                 "video/mpeg, "
224                 "mpegversion = (int) { 1, 2, 4 }, "
225                 "systemstream = (boolean) false, "
226                 COMMON_VIDEO_CAPS "; "
227                 "video/x-msmpeg, "
228                 COMMON_VIDEO_CAPS ", msmpegversion = (int) 43; "
229                 "video/x-h264, "
230                 COMMON_VIDEO_CAPS "; "
231                 "video/x-h263, "
232                 COMMON_VIDEO_CAPS "; "
233                 "video/x-divx, "
234                 COMMON_VIDEO_CAPS ", divxversion = (int) [ 3, 6 ]; "
235                 "video/x-xvid, "
236                 COMMON_VIDEO_CAPS "; "
237                 "video/x-3ivx, "
238                 COMMON_VIDEO_CAPS "; "
239                 "video/x-wmv, "
240                 "wmvversion = (int) 3, "
241                 COMMON_VIDEO_CAPS "; ")
242 );
243
244 static GstStaticPadTemplate sink_factory_bcm7435 =
245 GST_STATIC_PAD_TEMPLATE (
246         "sink",
247         GST_PAD_SINK,
248         GST_PAD_ALWAYS,
249         GST_STATIC_CAPS (
250                 "video/mpeg, "
251                 "mpegversion = (int) { 1, 2, 4 }, "
252                 "systemstream = (boolean) false, "
253                 COMMON_VIDEO_CAPS "; "
254                 "video/x-msmpeg, "
255                 COMMON_VIDEO_CAPS ", msmpegversion = (int) 43; "
256                 "video/x-h264, "
257                 COMMON_VIDEO_CAPS "; "
258                 "video/x-h263, "
259                 COMMON_VIDEO_CAPS "; "
260                 "video/x-divx, "
261                 COMMON_VIDEO_CAPS ", divxversion = (int) [ 3, 6 ]; "
262                 "video/x-xvid, "
263                 COMMON_VIDEO_CAPS "; "
264                 "video/x-3ivx, "
265                 COMMON_VIDEO_CAPS "; "
266                 "video/x-wmv, "
267                 "wmvversion = (int) 3, "
268                 COMMON_VIDEO_CAPS "; "
269 //              "video/x-flash-video, "
270 //              COMMON_VIDEO_CAPS "; "
271 //              "video/x-vp6, "
272 //              COMMON_VIDEO_CAPS "; "
273 //              "video/x-vp6-flash, "
274 //              COMMON_VIDEO_CAPS "; "
275                 "video/x-vp8, "
276                 COMMON_VIDEO_CAPS "; ")
277 );
278
279 static GstStaticPadTemplate sink_factory_bcm7401 =
280 GST_STATIC_PAD_TEMPLATE (
281         "sink",
282         GST_PAD_SINK,
283         GST_PAD_ALWAYS,
284         GST_STATIC_CAPS (
285                 "video/mpeg, "
286                 "mpegversion = (int) { 1, 2, 4 }, "
287                 "systemstream = (boolean) false, "
288                 COMMON_VIDEO_CAPS "; "
289                 "video/x-h264, "
290                 COMMON_VIDEO_CAPS "; "
291                 "video/x-h263, "
292                 COMMON_VIDEO_CAPS "; ")
293 );
294
295 static GstStaticPadTemplate sink_factory_ati_xilleon =
296 GST_STATIC_PAD_TEMPLATE (
297         "sink",
298         GST_PAD_SINK,
299         GST_PAD_ALWAYS,
300         GST_STATIC_CAPS (
301                 "video/mpeg, "
302                 "mpegversion = (int) { 1, 2 }, "
303                 "systemstream = (boolean) false, "
304                 COMMON_VIDEO_CAPS "; ")
305 );
306
307 #define DEBUG_INIT(bla) \
308         GST_DEBUG_CATEGORY_INIT (dvbvideosink_debug, "dvbvideosink", 0, "dvbvideosink element");
309
310 GST_BOILERPLATE_FULL (GstDVBVideoSink, gst_dvbvideosink, GstBaseSink,
311         GST_TYPE_BASE_SINK, DEBUG_INIT);
312
313 static gboolean gst_dvbvideosink_start (GstBaseSink * sink);
314 static gboolean gst_dvbvideosink_stop (GstBaseSink * sink);
315 static gboolean gst_dvbvideosink_event (GstBaseSink * sink, GstEvent * event);
316 static GstFlowReturn gst_dvbvideosink_render (GstBaseSink * sink, GstBuffer * buffer);
317 static gboolean gst_dvbvideosink_set_caps (GstBaseSink * sink, GstCaps * caps);
318 static gboolean gst_dvbvideosink_unlock (GstBaseSink * basesink);
319 static gboolean gst_dvbvideosink_unlock_stop (GstBaseSink * basesink);
320 static void gst_dvbvideosink_dispose (GObject * object);
321 static GstStateChangeReturn gst_dvbvideosink_change_state (GstElement * element, GstStateChange transition);
322 static gint64 gst_dvbvideosink_get_decoder_time (GstDVBVideoSink *self);
323
324 typedef enum { DM7025, DM800, DM8000, DM500HD, DM800SE, DM7020HD, DM7080, DM820 } hardware_type_t;
325
326 static hardware_type_t hwtype;
327 static GstStaticPadTemplate *hwtemplate;
328
329 static void
330 gst_dvbvideosink_base_init (gpointer klass)
331 {
332         static GstElementDetails element_details = {
333                 "A DVB video sink",
334                 "Generic/DVBVideoSink",
335                 "Output video PES / ES into a DVB video device for hardware playback",
336                 "Felix Domke <tmbinc@elitedvb.net>"
337         };
338         GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
339
340         int fd = open("/proc/stb/info/model", O_RDONLY);
341         if ( fd > 0 )
342         {
343                 gchar string[9] = { 0, };
344                 ssize_t rd = read(fd, string, 8);
345                 if ( rd >= 5 )
346                 {
347                         if ( !strncasecmp(string, "DM7025", 6) ) {
348                                 hwtype = DM7025;
349                                 hwtemplate = &sink_factory_ati_xilleon;
350                                 GST_INFO ("model is DM7025... set ati xilleon caps");
351                         } else if ( !strncasecmp(string, "DM500HD", 7) ) {
352                                 hwtype = DM500HD;
353                                 hwtemplate = &sink_factory_bcm7405;
354                                 GST_INFO ("model is DM500HD... set bcm7405 caps");
355                         } else if ( !strncasecmp(string, "DM800SE", 7) ) {
356                                 hwtype = DM800SE;
357                                 hwtemplate = &sink_factory_bcm7405;
358                                 GST_INFO ("model is DM800SE... set bcm7405 caps");
359                         } else if ( !strncasecmp(string, "DM7020HD", 8) ) {
360                                 hwtype = DM7020HD;
361                                 hwtemplate = &sink_factory_bcm7405;
362                                 GST_INFO ("model is DM7020HD... set bcm7405 caps");
363                         } else if ( !strncasecmp(string, "DM7080", 6) ) {
364                                 hwtype = DM7080;
365                                 hwtemplate = &sink_factory_bcm7435;
366                                 GST_INFO ("model is DM7080... set bcm7435 caps");
367                         } else if ( !strncasecmp(string, "DM820", 5) ) {
368                                 hwtype = DM820;
369                                 hwtemplate = &sink_factory_bcm7435;
370                                 GST_INFO ("model is DM820 set bcm7435 caps");
371                         } else if ( !strncasecmp(string, "DM8000", 6) ) {
372                                 hwtype = DM8000;
373                                 hwtemplate = &sink_factory_bcm7400;
374                                 GST_INFO ("model is DM8000... set bcm7400 caps");
375                         } else if ( !strncasecmp(string, "DM800", 5) ) {
376                                 hwtype = DM800;
377                                 hwtemplate = &sink_factory_bcm7401;
378                                 GST_INFO ("model is DM800 set bcm7401 caps");
379                         }
380                         if (hwtemplate) {
381                                 gst_element_class_add_pad_template (element_class,
382                                         gst_static_pad_template_get (hwtemplate));
383                         }
384
385                 }
386                 close(fd);
387         }
388
389         gst_element_class_set_details (element_class, &element_details);
390 }
391
392 static GstCaps *
393 gst_dvbvideosink_get_caps (GstBaseSink *basesink)
394 {
395 //      GstDVBVideoSink *self = GST_DVBVIDEOSINK (basesink);
396         GstCaps *caps;
397 //      gchar *strcaps;
398
399         caps = gst_static_caps_get(&hwtemplate->static_caps);
400
401 //      strcaps = gst_caps_to_string(caps);
402 //      GST_INFO_OBJECT (self, "dynamic caps for model %d '%s'", hwtype, gst_caps_to_string(caps));
403 //      g_free(strcaps);
404
405         return caps;
406 }
407
408 /* initialize the plugin's class */
409 static void
410 gst_dvbvideosink_class_init (GstDVBVideoSinkClass *klass)
411 {
412         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
413         GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass);
414         GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
415
416         gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_dvbvideosink_dispose);
417
418         gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_dvbvideosink_start);
419         gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_dvbvideosink_stop);
420         gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_dvbvideosink_render);
421         gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_dvbvideosink_event);
422         gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_dvbvideosink_unlock);
423         gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_dvbvideosink_unlock_stop);
424         gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_dvbvideosink_set_caps);
425         gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_dvbvideosink_get_caps);
426
427         element_class->change_state = GST_DEBUG_FUNCPTR (gst_dvbvideosink_change_state);
428
429         gst_dvb_videosink_signals[SIGNAL_GET_DECODER_TIME] =
430                 g_signal_new ("get-decoder-time",
431                 G_TYPE_FROM_CLASS (klass),
432                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
433                 G_STRUCT_OFFSET (GstDVBVideoSinkClass, get_decoder_time),
434                 NULL, NULL, gst_dvbsink_marshal_INT64__VOID, G_TYPE_INT64, 0);
435
436         klass->get_decoder_time = gst_dvbvideosink_get_decoder_time;
437 }
438
439 #define H264_BUFFER_SIZE (64*1024+2048)
440
441 /* initialize the new element
442  * instantiate pads and add them to element
443  * set functions
444  * initialize structure
445  */
446 static void
447 gst_dvbvideosink_init (GstDVBVideoSink *klass, GstDVBVideoSinkClass * gclass)
448 {
449         FILE *f = fopen("/proc/stb/vmpeg/0/fallback_framerate", "r");
450         klass->dec_running = FALSE;
451         klass->must_send_header = 1;
452         klass->h264_buffer = NULL;
453         klass->h264_nal_len_size = 0;
454         klass->codec_data = NULL;
455         klass->codec_type = CT_H264;
456
457         klass->must_pack_bitstream = 0;
458         klass->num_non_keyframes = 0;
459         klass->prev_frame = NULL;
460
461         klass->ucPrevFramePicType = 0;
462         klass->no_write = 0;
463         klass->queue = NULL;
464         klass->fd = -1;
465
466         klass->ucVC1_PULLDOWN = 0;
467         klass->ucVC1_INTERLACE = 0;
468         klass->ucVC1_TFCNTRFLAG = 0;
469         klass->ucVC1_FINTERPFLAG = 0;
470         klass->ucVC1_PSF = 0;
471         klass->ucVC1_HRD_PARAM_FLAG = 0;
472         klass->ucVC1_HRD_NUM_LEAKY_BUCKETS = 0;
473         klass->ucVC1_PANSCAN_FLAG = 0;
474         klass->ucVC1_REFDIST_FLAG = 0;
475
476         if (f) {
477                 fgets(klass->saved_fallback_framerate, 16, f);
478                 fclose(f);
479         }
480
481         gst_base_sink_set_sync(GST_BASE_SINK (klass), FALSE);
482         gst_base_sink_set_async_enabled(GST_BASE_SINK (klass), TRUE);
483 }
484
485 static void gst_dvbvideosink_dispose (GObject * object)
486 {
487         GstDVBVideoSink *self = GST_DVBVIDEOSINK (object);
488         GstState state, pending;
489         GST_DEBUG_OBJECT(self, "dispose");
490
491 // hack for decodebin2 bug.. decodebin2 tries to dispose ..but doesnt set state to NULL when it is READY
492         switch(gst_element_get_state(GST_ELEMENT(object), &state, &pending, GST_CLOCK_TIME_NONE))
493         {
494         case GST_STATE_CHANGE_SUCCESS:
495                 GST_DEBUG_OBJECT(self, "success");
496                 if (state != GST_STATE_NULL) {
497                         GST_DEBUG_OBJECT(self, "state %d in dispose.. set it to NULL (decodebin2 bug?)", state);
498                         if (gst_element_set_state(GST_ELEMENT(object), GST_STATE_NULL) == GST_STATE_CHANGE_ASYNC) {
499                                 GST_DEBUG_OBJECT(self, "set state returned async... wait!");
500                                 gst_element_get_state(GST_ELEMENT(object), &state, &pending, GST_CLOCK_TIME_NONE);
501                         }
502                 }
503                 break;
504         case GST_STATE_CHANGE_ASYNC:
505                 GST_DEBUG_OBJECT(self, "async");
506                 break;
507         case GST_STATE_CHANGE_FAILURE:
508                 GST_DEBUG_OBJECT(self, "failure");
509                 break;
510         case GST_STATE_CHANGE_NO_PREROLL:
511                 GST_DEBUG_OBJECT(self, "no preroll");
512                 break;
513         default:
514                 break;
515         }
516 // hack end
517
518         GST_DEBUG_OBJECT(self, "state in dispose %d, pending %d", state, pending);
519
520         G_OBJECT_CLASS (parent_class)->dispose (object);
521 }
522
523 static gint64 gst_dvbvideosink_get_decoder_time (GstDVBVideoSink *self)
524 {
525         if (self->dec_running && self->fd > -1) {
526                 gint64 cur = 0;
527                 static gint64 last_pos = 0;
528
529                 ioctl(self->fd, VIDEO_GET_PTS, &cur);
530
531                 /* workaround until driver fixed */
532                 if (cur)
533                         last_pos = cur;
534                 else
535                         cur = last_pos;
536
537                 cur *= 11111;
538
539                 return cur;
540         }
541         return GST_CLOCK_TIME_NONE;
542 }
543
544 static gboolean gst_dvbvideosink_unlock (GstBaseSink * basesink)
545 {
546         GstDVBVideoSink *self = GST_DVBVIDEOSINK (basesink);
547         GST_OBJECT_LOCK(self);
548         self->no_write |= 2;
549         GST_OBJECT_UNLOCK(self);
550         SEND_COMMAND (self, CONTROL_STOP);
551         GST_DEBUG_OBJECT (basesink, "unlock");
552         return TRUE;
553 }
554
555 static gboolean gst_dvbvideosink_unlock_stop (GstBaseSink * basesink)
556 {
557         GstDVBVideoSink *self = GST_DVBVIDEOSINK (basesink);
558         GST_OBJECT_LOCK(self);
559         self->no_write &= ~2;
560         GST_OBJECT_UNLOCK(self);
561         GST_DEBUG_OBJECT (basesink, "unlock_stop");
562         return TRUE;
563 }
564
565 void queue_push(queue_entry_t **queue_base, guint8 *data, size_t len)
566 {
567         queue_entry_t *entry = malloc(sizeof(queue_entry_t)+len);
568         queue_entry_t *last = *queue_base;
569         guint8 *d = (guint8*)(entry+1);
570         memcpy(d, data, len);
571         entry->bytes = len;
572         entry->offset = 0;
573         if (!last)
574                 *queue_base = entry;
575         else {
576                 while(last->next)
577                         last = last->next;
578                 last->next = entry;
579         }
580         entry->next = NULL;
581 }
582
583 void queue_pop(queue_entry_t **queue_base)
584 {
585         queue_entry_t *base = *queue_base;
586         *queue_base = base->next;
587         free(base);
588 }
589
590 int queue_front(queue_entry_t **queue_base, guint8 **data, size_t *bytes)
591 {
592         if (!*queue_base) {
593                 *bytes = 0;
594                 *data = 0;
595         }
596         else {
597                 queue_entry_t *entry = *queue_base;
598                 *bytes = entry->bytes - entry->offset;
599                 *data = ((guint8*)(entry+1))+entry->offset;
600         }
601         return *bytes;
602 }
603
604 static gboolean
605 gst_dvbvideosink_event (GstBaseSink * sink, GstEvent * event)
606 {
607         GstDVBVideoSink *self = GST_DVBVIDEOSINK (sink);
608         GST_DEBUG_OBJECT (self, "EVENT %s", gst_event_type_get_name(GST_EVENT_TYPE (event)));
609         int ret=TRUE;
610
611         switch (GST_EVENT_TYPE (event)) {
612         case GST_EVENT_FLUSH_START:
613                 GST_OBJECT_LOCK(self);
614                 self->no_write |= 1;
615                 GST_OBJECT_UNLOCK(self);
616                 SEND_COMMAND (self, CONTROL_STOP);
617                 break;
618         case GST_EVENT_FLUSH_STOP:
619                 ioctl(self->fd, VIDEO_CLEAR_BUFFER);
620                 GST_OBJECT_LOCK(self);
621                 self->must_send_header = 1;
622                 if (hwtype == DM7025)
623                         ++self->must_send_header;  // we must send the sequence header twice on dm7025... 
624                 while (self->queue)
625                         queue_pop(&self->queue);
626                 self->no_write &= ~1;
627                 GST_OBJECT_UNLOCK(self);
628                 break;
629         case GST_EVENT_EOS:
630         {
631                 struct pollfd pfd[2];
632                 int retval;
633
634                 if (self->fd < 0)
635                         break;
636
637                 pfd[0].fd = READ_SOCKET(self);
638                 pfd[0].events = POLLIN;
639                 pfd[1].fd = self->fd;
640                 pfd[1].events = POLLIN;
641
642                 GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
643                 while (1) {
644                         retval = poll(pfd, 2, 250);
645                         if (retval < 0) {
646                                 perror("poll in EVENT_EOS");
647                                 ret=FALSE;
648                                 break;
649                         }
650
651                         if (pfd[0].revents & POLLIN) {
652                                 GST_DEBUG_OBJECT (self, "wait EOS aborted!!\n");
653                                 ret=FALSE;
654                                 break;
655                         }
656
657                         if (pfd[1].revents & POLLIN) {
658                                 GST_DEBUG_OBJECT (self, "got buffer empty from driver!\n");
659                                 break;
660                         }
661
662                         if (sink->flushing) {
663                                 GST_DEBUG_OBJECT (self, "wait EOS flushing!!\n");
664                                 ret=FALSE;
665                                 break;
666                         }
667                 }
668                 GST_PAD_PREROLL_LOCK (sink->sinkpad);
669
670                 break;
671         }
672         case GST_EVENT_NEWSEGMENT:{
673                 GstFormat fmt;
674                 gboolean update;
675                 gdouble rate, applied_rate;
676                 gint64 cur, stop, time;
677                 int skip = 0, repeat = 0;
678                 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, &fmt, &cur, &stop, &time);
679                 GST_DEBUG_OBJECT (self, "GST_EVENT_NEWSEGMENT rate=%f applied_rate=%f\n", rate, applied_rate);
680                 
681                 if (fmt == GST_FORMAT_TIME)
682                 {       
683                         if ( rate > 1 )
684                                 skip = (int) rate;
685                         else if ( rate < 1 )
686                                 repeat = 1.0/rate;
687
688                         ret = ioctl(self->fd, VIDEO_SLOWMOTION, repeat) < 0 ? FALSE : TRUE;
689                         ret = ioctl(self->fd, VIDEO_FAST_FORWARD, skip) < 0 ? FALSE : TRUE;
690 //                      gst_segment_set_newsegment_full (&dec->segment, update, rate, applied_rate, dformat, cur, stop, time);
691                 }
692                 break;
693         }
694
695         default:
696                 break;
697         }
698
699         return ret;
700 }
701
702 #define ASYNC_WRITE(data, len) do { \
703                 switch(AsyncWrite(sink, self, data, len)) { \
704                 case -1: goto poll_error; \
705                 case -3: goto write_error; \
706                 default: break; \
707                 } \
708         } while(0)
709
710 static int AsyncWrite(GstBaseSink * sink, GstDVBVideoSink *self, unsigned char *data, unsigned int len)
711 {
712         unsigned int written=0;
713         struct pollfd pfd[2];
714
715         pfd[0].fd = READ_SOCKET(self);
716         pfd[0].events = POLLIN;
717         pfd[1].fd = self->fd;
718         pfd[1].events = POLLOUT | POLLPRI;
719
720         do {
721 loop_start:
722                 if (self->no_write & 1) {
723                         GST_DEBUG_OBJECT (self, "skip %d bytes", len - written);
724                         break;
725                 }
726                 else if (self->no_write & 6) {
727                         // directly push to queue
728                         GST_OBJECT_LOCK(self);
729                         queue_push(&self->queue, data + written, len - written);
730                         GST_OBJECT_UNLOCK(self);
731                         GST_DEBUG_OBJECT (self, "pushed %d bytes to queue", len - written);
732                         break;
733                 }
734                 else
735                         GST_LOG_OBJECT (self, "going into poll, have %d bytes to write", len - written);
736                 if (poll(pfd, 2, -1) == -1) {
737                         if (errno == EINTR)
738                                 continue;
739                         return -1;
740                 }
741                 if (pfd[0].revents & POLLIN) {
742                         /* read all stop commands */
743                         while (TRUE) {
744                                 gchar command;
745                                 int res;
746                                 READ_COMMAND (self, command, res);
747                                 if (res < 0) {
748                                         GST_DEBUG_OBJECT (self, "no more commands");
749                                         /* no more commands */
750                                         goto loop_start;
751                                 }
752                         }
753                 }
754                 if (pfd[1].revents & POLLPRI) {
755                         GstStructure *s;
756                         GstMessage *msg;
757                         struct video_event evt;
758                         if (ioctl(self->fd, VIDEO_GET_EVENT, &evt) < 0)
759                                 g_warning ("failed to ioctl VIDEO_GET_EVENT!");
760                         else {
761                                 GST_INFO_OBJECT (self, "VIDEO_EVENT %d", evt.type);
762                                 if (evt.type == VIDEO_EVENT_SIZE_CHANGED) {
763                                         s = gst_structure_new ("eventSizeChanged",
764                                                 "aspect_ratio", G_TYPE_INT, evt.u.size.aspect_ratio == 0 ? 2 : 3,
765                                                 "width", G_TYPE_INT, evt.u.size.w,
766                                                 "height", G_TYPE_INT, evt.u.size.h, NULL);
767                                         msg = gst_message_new_element (GST_OBJECT (sink), s);
768                                         gst_element_post_message (GST_ELEMENT (sink), msg);
769                                 } else if (evt.type == VIDEO_EVENT_FRAME_RATE_CHANGED) {
770                                         self->framerate = evt.u.frame_rate;
771                                         GST_INFO_OBJECT(self, "decoder framerate %d", self->framerate);
772                                         s = gst_structure_new ("eventFrameRateChanged",
773                                                 "frame_rate", G_TYPE_INT, evt.u.frame_rate, NULL);
774                                         msg = gst_message_new_element (GST_OBJECT (sink), s);
775                                         gst_element_post_message (GST_ELEMENT (sink), msg);
776                                 } else if (evt.type == 16 /*VIDEO_EVENT_PROGRESSIVE_CHANGED*/) {
777                                         s = gst_structure_new ("eventProgressiveChanged",
778                                                 "progressive", G_TYPE_INT, evt.u.frame_rate, NULL);
779                                         msg = gst_message_new_element (GST_OBJECT (sink), s);
780                                         gst_element_post_message (GST_ELEMENT (sink), msg);
781                                 } else
782                                         g_warning ("unhandled DVBAPI Video Event %d", evt.type);
783                         }
784                 }
785                 if (pfd[1].revents & POLLOUT) {
786                         size_t queue_entry_size;
787                         guint8 *queue_data;
788                         GST_OBJECT_LOCK(self);
789                         if (queue_front(&self->queue, &queue_data, &queue_entry_size)) {
790                                 int wr = write(self->fd, queue_data, queue_entry_size);
791                                 if (wr < 0) {
792                                         switch (errno) {
793                                                 case EINTR:
794                                                 case EAGAIN:
795                                                         break;
796                                                 default:
797                                                         GST_OBJECT_UNLOCK(self);
798                                                         return -3;
799                                         }
800                                 }
801                                 else if (wr == queue_entry_size) {
802                                         queue_pop(&self->queue);
803                                         GST_DEBUG_OBJECT (self, "written %d queue bytes... pop entry", wr);
804                                 }
805                                 else {
806                                         self->queue->offset += wr;
807                                         GST_DEBUG_OBJECT (self, "written %d queue bytes... update offset", wr);
808                                 }
809                                 GST_OBJECT_UNLOCK(self);
810                                 continue;
811                         }
812                         GST_OBJECT_UNLOCK(self);
813                         int wr = write(self->fd, data+written, len - written);
814                         if (wr < 0) {
815                                 switch (errno) {
816                                         case EINTR:
817                                         case EAGAIN:
818                                                 continue;
819                                         default:
820                                                 return -3;
821                                 }
822                         }
823                         written += wr;
824                 }
825         } while (written != len);
826
827         return 0;
828 }
829
830 static GstFlowReturn
831 gst_dvbvideosink_render (GstBaseSink * sink, GstBuffer * buffer)
832 {
833         GstDVBVideoSink *self = GST_DVBVIDEOSINK (sink);
834         unsigned char *data = GST_BUFFER_DATA(buffer);
835         unsigned int data_len = GST_BUFFER_SIZE (buffer);
836         guint8 pes_header[2048];
837         unsigned int pes_header_len=0;
838         unsigned int payload_len=0;
839 //      int i=0;
840
841         gboolean commit_prev_frame_data = FALSE,
842                         cache_prev_frame = FALSE;
843
844 //      for (;i < (data_len > 0xF ? 0xF : data_len); ++i)
845 //              printf("%02x ", data[i]);
846 //      printf("%d bytes\n", data_len);
847 //      printf("timestamp: %08llx\n", (long long)GST_BUFFER_TIMESTAMP(buffer));
848
849         if (self->fd < 0)
850                 return GST_FLOW_OK;
851
852         if (self->must_pack_bitstream == 1) {
853                 cache_prev_frame = TRUE;
854                 unsigned int pos = 0;
855                 while(pos < data_len) {
856                         if (data[pos++])
857                                 continue;
858                         if (data[pos++])
859                                 continue;
860                         while (!data[pos])
861                                 ++pos;
862                         if (data[pos++] != 1)
863                                 continue;
864                         if ((data[pos++] & 0xF0) == 0x20) { // we need time_inc_res
865                                 __attribute__((unused)) gboolean low_delay = FALSE;
866                                 unsigned int ver_id = 1, shape=0, time_inc_res=0, tmp=0;
867                                 struct bitstream bit;
868                                 bitstream_init(&bit, data+pos, 0);
869                                 bitstream_get(&bit, 9);
870                                 if (bitstream_get(&bit, 1)) {
871                                         ver_id = bitstream_get(&bit, 4); // ver_id
872                                         bitstream_get(&bit, 3);
873                                 }
874                                 if ((tmp=bitstream_get(&bit, 4)) == 15) { // Custom Aspect Ration
875                                         bitstream_get(&bit, 8); // skip AR width
876                                         bitstream_get(&bit, 8); // skip AR height
877                                 }
878                                 if (bitstream_get(&bit, 1)) {
879                                         bitstream_get(&bit, 2);
880                                         low_delay = bitstream_get(&bit, 1) ? TRUE : FALSE;
881                                         if (bitstream_get(&bit, 1)) {
882                                                 bitstream_get(&bit, 32);
883                                                 bitstream_get(&bit, 32);
884                                                 bitstream_get(&bit, 15);
885                                         }
886                                 }
887                                 shape = bitstream_get(&bit, 2);
888                                 if (ver_id != 1 && shape == 3 /* Grayscale */)
889                                         bitstream_get(&bit, 4);
890                                 bitstream_get(&bit, 1);
891                                 time_inc_res = bitstream_get(&bit, 16);
892                                 self->time_inc_bits = 0;
893                                 while (time_inc_res) { // count bits
894                                         ++self->time_inc_bits;
895                                         time_inc_res >>= 1;
896                                 }
897 //                              printf("%d time_inc_bits\n", self->time_inc_bits);
898                         }
899                 }
900         }
901
902         if (self->must_pack_bitstream == 1) {
903                 int tmp1, tmp2;
904                 unsigned char c1, c2;
905                 unsigned int pos = 0;
906                 while(pos < data_len) {
907                         if (data[pos++])
908                                 continue;
909                         if (data[pos++])
910                                 continue;
911                         while (!data[pos])
912                                 ++pos;
913                         if (data[pos++] != 1)
914                                 continue;
915                         if (data[pos++] != 0xB2)
916                                 continue;
917                         if (data_len - pos < 13)
918                                 break;
919                         if (sscanf((char*)data+pos, "DivX%d%c%d%cp", &tmp1, &c1, &tmp2, &c2) == 4 && (c1 == 'b' || c1 == 'B') && (c2 == 'p' || c2 == 'P')) {
920                                 GST_INFO_OBJECT (self, "%s seen... already packed!", (char*)data+pos);
921                                 self->must_pack_bitstream = 0;
922                         }
923 //                      if (self->must_pack_bitstream)
924 //                              printf("pack needed\n");
925 //                      else
926 //                              printf("no pack needed\n");
927                 }
928         }
929
930         pes_header[0] = 0;
931         pes_header[1] = 0;
932         pes_header[2] = 1;
933         pes_header[3] = 0xE0;
934
935                 /* do we have a timestamp? */
936         if (GST_BUFFER_TIMESTAMP(buffer) != GST_CLOCK_TIME_NONE) {
937                 unsigned long long pts = GST_BUFFER_TIMESTAMP(buffer) * 9LL / 100000 /* convert ns to 90kHz */;
938
939                 pes_header[6] = 0x80;
940                 pes_header[7] = 0x80;
941                 
942                 pes_header[8] = 5;
943                 
944                 pes_header[9] =  0x21 | ((pts >> 29) & 0xE);
945                 pes_header[10] = pts >> 22;
946                 pes_header[11] = 0x01 | ((pts >> 14) & 0xFE);
947                 pes_header[12] = pts >> 7;
948                 pes_header[13] = 0x01 | ((pts << 1) & 0xFE);
949
950                 pes_header_len = 14;
951
952                 if (self->codec_data) {
953                         switch (self->codec_type) { // we must always resend the codec data before every seq header on dm8k
954                         case CT_VC1:
955                                 if (self->no_header && self->ucPrevFramePicType == 6) {  // I-Frame...
956                                         GST_INFO_OBJECT(self, "send seq header");
957                                         self->must_send_header = 1;
958                                 }
959                                 break;
960                         case CT_MPEG4_PART2:
961                         case CT_DIVX4:
962                                 if (data[0] == 0xb3 || !memcmp(data, "\x00\x00\x01\xb3", 4))
963                                         self->must_send_header = 1;
964                         default:
965                                 break;
966                         }
967                         if (self->must_send_header) {
968                                 if (self->codec_type != CT_MPEG1 && self->codec_type != CT_MPEG2 && (self->codec_type != CT_DIVX4 || data[3] == 0x00)) {
969                                         unsigned char *codec_data = GST_BUFFER_DATA (self->codec_data);
970                                         unsigned int codec_data_len = GST_BUFFER_SIZE (self->codec_data);
971                                         if (self->codec_type == CT_VC1) {
972                                                 codec_data += 1;
973                                                 codec_data_len -= 1;
974                                         }
975                                         if (self->codec_type == CT_DIVX311)
976                                                 ASYNC_WRITE(codec_data, codec_data_len);
977                                         else {
978                                                 memcpy(pes_header+pes_header_len, codec_data, codec_data_len);
979                                                 pes_header_len += codec_data_len;
980                                         }
981                                         self->must_send_header = 0;
982                                 }
983                         }
984                         if (self->codec_type == CT_H264) {  // MKV stuff
985                                 unsigned int pos = 0;
986                                 if (self->h264_nal_len_size == 4) {
987                                         while(TRUE) {
988                                                 unsigned int pack_len = (data[pos] << 24) | (data[pos+1] << 16) | (data[pos+2] << 8) | data[pos+3];
989 //                                              printf("patch %02x %02x %02x %02x\n",
990 //                                                      data[pos],
991 //                                                      data[pos + 1],
992 //                                                      data[pos + 2],
993 //                                                      data[pos + 3]);
994                                                 memcpy(data+pos, "\x00\x00\x00\x01", 4);
995 //                                              printf("pos %d, (%d) >= %d\n", pos, pos+pack_len, data_len);
996                                                 pos += 4;
997                                                 if ((pos + pack_len) >= data_len)
998                                                         break;
999                                                 pos += pack_len;
1000                                         }
1001                                 }
1002                                 else if (self->h264_nal_len_size == 3) {
1003                                         while(TRUE) {
1004                                                 unsigned int pack_len = (data[pos] << 16) | (data[pos+1] << 8) | data[pos+2];
1005 //                                              printf("patch %02x %02x %02x\n",
1006 //                                                      data[pos],
1007 //                                                      data[pos + 1],
1008 //                                                      data[pos + 2]);
1009                                                 memcpy(data+pos, "\x00\x00\x01", 3);
1010 //                                              printf("pos %d, (%d) >= %d\n", pos, pos+pack_len, data_len);
1011                                                 pos += 3;
1012                                                 if ((pos + pack_len) >= data_len)
1013                                                         break;
1014                                                 pos += pack_len;
1015                                         }
1016                                 }
1017                                 else {
1018                                         unsigned char *dest = GST_BUFFER_DATA (self->h264_buffer);
1019                                         unsigned int dest_pos = 0;
1020                                         while(TRUE) {
1021                                                 unsigned int pack_len = self->h264_nal_len_size == 2 ? (data[pos] << 8) | data[pos+1] : data[pos];
1022                                                 if (dest_pos + pack_len <= H264_BUFFER_SIZE) {
1023                                                         memcpy(dest+dest_pos, "\x00\x00\x01", 3);
1024                                                         dest_pos += 3;
1025                                                         pos += self->h264_nal_len_size;
1026                                                         memcpy(dest+dest_pos, data+pos, pack_len);
1027                                                         dest_pos += pack_len;
1028                                                         if ((pos + pack_len) >= data_len)
1029                                                                 break;
1030                                                         pos += pack_len;
1031                                                 }
1032                                                 else {
1033                                                         g_error("BUG!!!!!!!! H264 buffer to small skip video data!!.. please report!\n");
1034                                                         break;
1035                                                 }
1036                                         }
1037                                         data = dest;
1038                                         data_len = dest_pos;
1039                                 }
1040                         }
1041                         else if (self->codec_type == CT_MPEG4_PART2) {
1042                                 if (data[0] || data[1] || data[2] != 1) {
1043                                         memcpy(pes_header+pes_header_len, "\x00\x00\x01", 3);
1044                                         pes_header_len += 3;
1045                                 }
1046                         }
1047                         else if (self->codec_type == CT_VC1 || self->codec_type == CT_VC1_SIMPLE_MAIN) {
1048                                 int skip_header_check;
1049
1050                                 if (data[0] || data[1] || data[2] != 1) {
1051                                         memcpy(pes_header+pes_header_len, "\x00\x00\x01\x0d", 4);
1052                                         pes_header_len += 4;
1053                                         skip_header_check = 1;
1054                                 }
1055                                 else
1056                                         skip_header_check = 0;
1057
1058                                 self->no_header = skip_header_check;
1059
1060                                 if (self->codec_type == CT_VC1) {
1061                                         unsigned char ucRetVal = Vc1HandleStreamBuffer( self, data, data_len, skip_header_check );
1062                                         if ( ucRetVal != cVC1NoBufferDataAvailable ) {
1063                                                 data_len = GST_BUFFER_SIZE(self->prev_frame);
1064                                                 data = GST_BUFFER_DATA(self->prev_frame);
1065                                         }
1066                                         else {
1067                                                 GST_DEBUG_OBJECT(self, "first buffer!");
1068
1069                                                 gst_buffer_ref(buffer);
1070                                                 self->prev_frame = buffer;
1071
1072                                                 return GST_FLOW_OK;
1073                                         }
1074
1075                                         cache_prev_frame = TRUE;
1076                                 }
1077                         }
1078                         else if (self->codec_type == CT_DIVX311) {
1079                                 if (data[0] || data[1] || data[2] != 1 || data[3] != 0xb6) {
1080                                         memcpy(pes_header+pes_header_len, "\x00\x00\x01\xb6", 4);
1081                                         pes_header_len += 4;
1082                                 }
1083                         }
1084                 }
1085                 else if (self->codec_type == CT_VP8 || self->codec_type == CT_VP6 || self->codec_type == CT_SPARK) {
1086                         uint32_t len = data_len + 4 + 6;
1087                         memcpy(pes_header+pes_header_len, "BCMV", 4);
1088                         pes_header_len += 4;
1089                         if (self->codec_type == CT_VP6)
1090                                 ++len;
1091                         pes_header[pes_header_len++] = (len & 0xFF000000) >> 24;
1092                         pes_header[pes_header_len++] = (len & 0x00FF0000) >> 16;
1093                         pes_header[pes_header_len++] = (len & 0x0000FF00) >> 8;
1094                         pes_header[pes_header_len++] = (len & 0x000000FF) >> 0;
1095                         pes_header[pes_header_len++] = 0;
1096                         pes_header[pes_header_len++] = 0;
1097                         if (self->codec_type == CT_VP6)
1098                                 pes_header[pes_header_len++] = 0;
1099                 }
1100         }
1101         else {
1102 //              printf("no timestamp!\n");
1103                 pes_header[6] = 0x80;
1104                 pes_header[7] = 0x00;
1105                 pes_header[8] = 0;
1106                 pes_header_len = 9;
1107         }
1108
1109         if (self->must_pack_bitstream == 1) {
1110                 unsigned int pos = 0;
1111                 gboolean i_frame = FALSE;
1112 //              gboolean s_frame = FALSE;
1113                 while(pos < data_len) {
1114                         if (data[pos++])
1115                                 continue;
1116                         if (data[pos++])
1117                                 continue;
1118                         while (!data[pos])
1119                                 ++pos;
1120                         if (data[pos++] != 1)
1121                                 continue;
1122                         if (data[pos++] != 0xB6)
1123                                 continue;
1124                         switch ((data[pos] & 0xC0) >> 6) {
1125                                 case 0: // I-Frame
1126 //                                      printf("I ");
1127                                         cache_prev_frame = FALSE;
1128                                         i_frame = TRUE;
1129                                 case 1: // P-Frame
1130 //                                      if (!i_frame)
1131 //                                              printf("P ");
1132                                         if (self->prev_frame != buffer) {
1133                                                 struct bitstream bit;
1134                                                 gboolean store_frame=FALSE;
1135                                                 if (self->prev_frame) {
1136                                                         if (!self->num_non_keyframes) {
1137 //                                                              printf("no non keyframes...immediate commit prev frame\n");
1138                                                                 GstFlowReturn ret = gst_dvbvideosink_render(sink, self->prev_frame);
1139                                                                 gst_buffer_unref(self->prev_frame);
1140                                                                 self->prev_frame = NULL;
1141                                                                 if (ret != GST_FLOW_OK)
1142                                                                         return ret;
1143                                                                 store_frame = TRUE;
1144                                                         }
1145                                                         else {
1146 //                                                              int i=-4;
1147                                                                 pes_header[pes_header_len++] = 0;
1148                                                                 pes_header[pes_header_len++] = 0;
1149                                                                 pes_header[pes_header_len++] = 1;
1150                                                                 pes_header[pes_header_len++] = 0xB6;
1151                                                                 bitstream_init(&bit, pes_header+pes_header_len, 1);
1152                                                                 bitstream_put(&bit, 1, 2);
1153                                                                 bitstream_put(&bit, 0, 1);
1154                                                                 bitstream_put(&bit, 1, 1);
1155                                                                 bitstream_put(&bit, self->time_inc, self->time_inc_bits);
1156                                                                 bitstream_put(&bit, 1, 1);
1157                                                                 bitstream_put(&bit, 0, 1);
1158                                                                 bitstream_put(&bit, 0x7F >> bit.avail, 8 - bit.avail);
1159 //                                                              printf(" insert pack frame %d non keyframes, time_inc %d, time_inc_bits %d -",
1160 //                                                                      self->num_non_keyframes, self->time_inc, self->time_inc_bits);
1161 //                                                              for (; i < (bit.data - (pes_header+pes_header_len)); ++i)
1162 //                                                                      printf(" %02x", pes_header[pes_header_len+i]);
1163 //                                                              printf("\nset data_len to 0!\n");
1164                                                                 data_len = 0;
1165                                                                 pes_header_len += bit.data - (pes_header+pes_header_len);
1166                                                                 cache_prev_frame = TRUE;
1167                                                         }
1168                                                 }
1169                                                 else if (!i_frame)
1170                                                         store_frame = TRUE;
1171
1172                                                 self->num_non_keyframes=0;
1173
1174                                                 // extract time_inc
1175                                                 bitstream_init(&bit, data+pos, 0);
1176                                                 bitstream_get(&bit, 2); // skip coding_type
1177                                                 while(bitstream_get(&bit, 1));
1178                                                 bitstream_get(&bit, 1);
1179                                                 self->time_inc = bitstream_get(&bit, self->time_inc_bits);
1180 //                                              printf("\ntime_inc is %d\n", self->time_inc);
1181
1182                                                 if (store_frame) {
1183 //                                                      printf("store frame\n");
1184                                                         self->prev_frame = buffer;
1185                                                         gst_buffer_ref (buffer);
1186                                                         return GST_FLOW_OK;
1187                                                 }
1188                                         }
1189                                         else {
1190                                                 cache_prev_frame = FALSE;
1191 //                                              printf(" I/P Frame without non key frame(s)!!\n");
1192                                         }
1193                                         break;
1194                                 case 3: // S-Frame
1195 //                                      printf("S ");
1196 //                                      s_frame = TRUE;
1197                                 case 2: // B-Frame
1198 //                                      if (!s_frame)
1199 //                                              printf("B ");
1200                                         if (++self->num_non_keyframes == 1 && self->prev_frame) {
1201 //                                              printf("send grouped with prev P!\n");
1202                                                 commit_prev_frame_data = TRUE;
1203                                         }
1204                                         break;
1205                                 case 4: // N-Frame
1206                                 default:
1207                                         g_warning("unhandled divx5/xvid frame type %d\n", (data[pos] & 0xC0) >> 6);
1208                                         break;
1209                         }
1210                 }
1211 //              printf("\n");
1212         }
1213
1214         payload_len = data_len + pes_header_len - 6;
1215
1216         if (self->prev_frame && self->prev_frame != buffer) {
1217                 unsigned long long pts = GST_BUFFER_TIMESTAMP(self->prev_frame) * 9LL / 100000 /* convert ns to 90kHz */;
1218                 GST_DEBUG_OBJECT(self, "use prev timestamp: %08llx", (long long)GST_BUFFER_TIMESTAMP(self->prev_frame));
1219
1220                 pes_header[9] =  0x21 | ((pts >> 29) & 0xE);
1221                 pes_header[10] = pts >> 22;
1222                 pes_header[11] = 0x01 | ((pts >> 14) & 0xFE);
1223                 pes_header[12] = pts >> 7;
1224                 pes_header[13] = 0x01 | ((pts << 1) & 0xFE);
1225         }
1226
1227         if (commit_prev_frame_data)
1228                 payload_len += GST_BUFFER_SIZE (self->prev_frame);
1229
1230         if (self->codec_type == CT_MPEG2 || self->codec_type == CT_MPEG1) {
1231                 if (!self->codec_data && data_len > 3 && !data[0] && !data[1] && data[2] == 1 && data[3] == 0xb3) { // sequence header?
1232                         gboolean ok = TRUE;
1233                         unsigned int pos = 4;
1234                         unsigned int sheader_data_len=0;
1235                         while(pos < data_len && ok) {
1236                                 if ( pos >= data_len )
1237                                         break;
1238                                 pos+=7;
1239                                 if ( pos >=data_len )
1240                                         break;
1241                                 sheader_data_len=12;
1242                                 if ( data[pos] & 2 ) { // intra matrix avail?
1243                                         pos+=64;
1244                                         if ( pos >=data_len )
1245                                                 break;
1246                                         sheader_data_len+=64;
1247                                 }
1248                                 if ( data[pos] & 1 ) { // non intra matrix avail?
1249                                         pos+=64;
1250                                         if ( pos >=data_len )
1251                                                 break;
1252                                         sheader_data_len+=64;
1253                                 }
1254                                 pos+=1;
1255                                 if ( pos+3 >=data_len )
1256                                         break;
1257                                 // extended start code
1258                                 if ( !data[pos] && !data[pos+1] && data[pos+2] == 1 && data[pos+3] == 0xB5 ) {
1259                                         pos+=3;
1260                                         sheader_data_len+=3;
1261                                         do {
1262                                                 pos+=1;
1263                                                 ++sheader_data_len;
1264                                                 if (pos+2 > data_len)
1265                                                         goto leave;
1266                                         }
1267                                         while( data[pos] || data[pos+1] || data[pos+2] != 1 );
1268                                 }
1269                                 if ( pos+3 >=data_len )
1270                                         break;
1271                                 // private data
1272                                 if ( !data[pos] && !data[pos+1] && data[pos+2] && data[pos+3] == 0xB2 ) {
1273                                         pos+=3;
1274                                         sheader_data_len+=3;
1275                                         do {
1276                                                 pos+=1;
1277                                                 ++sheader_data_len;
1278                                                 if (pos+2 > data_len)
1279                                                         goto leave;
1280                                         }
1281                                         while( data[pos] || data[pos+1] || data[pos+2] != 1 );
1282                                 }
1283                                 self->codec_data = gst_buffer_new_and_alloc(sheader_data_len);
1284                                 memcpy(GST_BUFFER_DATA(self->codec_data), data+pos-sheader_data_len, sheader_data_len);
1285                                 self->must_send_header = 0;
1286 leave:
1287                                 ok = FALSE;
1288                         }
1289                 }
1290                 else if (self->codec_data && self->must_send_header) {
1291                         unsigned char *codec_data = GST_BUFFER_DATA (self->codec_data);
1292                         unsigned int codec_data_len = GST_BUFFER_SIZE (self->codec_data);
1293                         int pos = 0;
1294                         while(pos < data_len) {
1295                                 if ( data[pos++] )
1296                                         continue;
1297                                 if ( data[pos++] )
1298                                         continue;
1299                                 while ( !data[pos] )
1300                                         pos++;
1301                                 if ( data[pos++] != 1 )
1302                                         continue;
1303                                 if ( data[pos++] != 0xb8 ) // group start code
1304                                         continue;
1305                                 pos-=4; // before group start
1306                                 payload_len += codec_data_len;
1307                                 if (payload_len <= 0xFFFF) {
1308                                         pes_header[4] = payload_len >> 8;
1309                                         pes_header[5] = payload_len & 0xFF;
1310                                 }
1311                                 else {
1312                                         pes_header[4] = 0;
1313                                         pes_header[5] = 0;
1314                                 }
1315                                 ASYNC_WRITE(pes_header, pes_header_len);
1316                                 ASYNC_WRITE(data, pos);
1317                                 ASYNC_WRITE(codec_data, codec_data_len);
1318                                 ASYNC_WRITE(data+pos, data_len - pos);
1319                                 --self->must_send_header;
1320                                 return GST_FLOW_OK;
1321                         }
1322                 }
1323         }
1324
1325         if (payload_len <= 0xFFFF) {
1326                 pes_header[4] = payload_len >> 8;
1327                 pes_header[5] = payload_len & 0xFF;
1328         }
1329         else {
1330                 pes_header[4] = 0;
1331                 pes_header[5] = 0;
1332         }
1333
1334         ASYNC_WRITE(pes_header, pes_header_len);
1335
1336         if (commit_prev_frame_data) {
1337                 GST_DEBUG_OBJECT(self, "commit prev frame data");
1338                 ASYNC_WRITE(GST_BUFFER_DATA (self->prev_frame), GST_BUFFER_SIZE (self->prev_frame));
1339         }
1340
1341         ASYNC_WRITE(data, data_len);
1342
1343         if (self->prev_frame && self->prev_frame != buffer) {
1344                 GST_DEBUG_OBJECT(self, "unref prev_frame buffer");
1345                 gst_buffer_unref(self->prev_frame);
1346                 self->prev_frame = NULL;
1347         }
1348
1349         if (cache_prev_frame) {
1350                 GST_DEBUG_OBJECT(self, "cache prev frame");
1351                 gst_buffer_ref(buffer);
1352                 self->prev_frame = buffer;
1353         }
1354
1355         return GST_FLOW_OK;
1356 poll_error:
1357         {
1358                 GST_ELEMENT_ERROR (self, RESOURCE, READ, (NULL),
1359                                 ("poll on file descriptor: %s.", g_strerror (errno)));
1360                 GST_WARNING_OBJECT (self, "Error during poll");
1361                 return GST_FLOW_ERROR;
1362         }
1363 write_error:
1364         {
1365                 GST_ELEMENT_ERROR (self, RESOURCE, READ, (NULL),
1366                                 ("write on file descriptor: %s.", g_strerror (errno)));
1367                 GST_WARNING_OBJECT (self, "Error during write");
1368                 return GST_FLOW_ERROR;
1369         }
1370         self->must_send_header = 1;
1371         if (hwtype == DM7025)
1372                 ++self->must_send_header;  // we must send the sequence header twice on dm7025...
1373 }
1374
1375 static gboolean 
1376 gst_dvbvideosink_set_caps (GstBaseSink * basesink, GstCaps * caps)
1377 {
1378         GstDVBVideoSink *self = GST_DVBVIDEOSINK (basesink);
1379         GstStructure *structure = gst_caps_get_structure (caps, 0);
1380         const char *mimetype = gst_structure_get_name (structure);
1381         int streamtype = -1;
1382         self->framerate = -1;
1383         self->no_header = 0;
1384
1385         if (!strcmp (mimetype, "video/mpeg")) {
1386                 gint mpegversion;
1387                 gst_structure_get_int (structure, "mpegversion", &mpegversion);
1388                 switch (mpegversion) {
1389                         case 1:
1390                                 streamtype = 6;
1391                                 self->codec_type = CT_MPEG1;
1392                                 GST_INFO_OBJECT (self, "MIMETYPE video/mpeg1 -> VIDEO_SET_STREAMTYPE, 6");
1393                         break;
1394                         case 2:
1395                                 streamtype = 0;
1396                                 self->codec_type = CT_MPEG2;
1397                                 GST_INFO_OBJECT (self, "MIMETYPE video/mpeg2 -> VIDEO_SET_STREAMTYPE, 0");
1398                         break;
1399                         case 4:
1400                         {
1401                                 const GValue *codec_data = gst_structure_get_value (structure, "codec_data");
1402                                 if (codec_data) {
1403                                         GST_INFO_OBJECT (self, "MPEG4 have codec data");
1404                                         self->codec_data = gst_value_get_buffer (codec_data);
1405                                         self->codec_type = CT_MPEG4_PART2;
1406                                         gst_buffer_ref (self->codec_data);
1407                                 }
1408                                 streamtype = 4;
1409                                 GST_INFO_OBJECT (self, "MIMETYPE video/mpeg4 -> VIDEO_SET_STREAMTYPE, 4");
1410                         }
1411                         break;
1412                         default:
1413                                 GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), ("unhandled mpeg version %i", mpegversion));
1414                         break;
1415                 }
1416         } else if (!strcmp (mimetype, "video/x-3ivx")) {
1417                 const GValue *codec_data = gst_structure_get_value (structure, "codec_data");
1418                 if (codec_data) {
1419                         GST_INFO_OBJECT (self, "have 3ivx codec... handle as CT_MPEG4_PART2");
1420                         self->codec_data = gst_value_get_buffer (codec_data);
1421                         self->codec_type = CT_MPEG4_PART2;
1422                         gst_buffer_ref (self->codec_data);
1423                 }
1424                 streamtype = 4;
1425                 GST_INFO_OBJECT (self, "MIMETYPE video/x-3ivx -> VIDEO_SET_STREAMTYPE, 4");
1426         } else if (!strcmp (mimetype, "video/x-h264")) {
1427                 const GValue *cd_data = gst_structure_get_value (structure, "codec_data");
1428                 streamtype = 1;
1429                 if (cd_data) {
1430                         unsigned char tmp[2048];
1431                         unsigned int tmp_len = 0;
1432                         GstBuffer *codec_data = gst_value_get_buffer (cd_data);
1433                         unsigned char *data = GST_BUFFER_DATA (codec_data);
1434                         unsigned int cd_len = GST_BUFFER_SIZE (codec_data);
1435                         unsigned int cd_pos = 0;
1436                         GST_INFO_OBJECT (self, "H264 have codec data..!");
1437                         if (cd_len > 7 && data[0] == 1) {
1438                                 unsigned short len = (data[6] << 8) | data[7];
1439 //                              printf("2 %d bytes\n", len);
1440                                 if (cd_len >= (len + 8)) {
1441                                         unsigned int i=0;
1442                                         uint8_t profile_num[] = { 66, 77, 88, 100 };
1443                                         uint8_t profile_cmp[2] = { 0x67, 0x00 };
1444                                         const char *profile_str[] = { "baseline", "main", "extended", "high" };
1445 //                                      printf("3\n");
1446                                         memcpy(tmp, "\x00\x00\x00\x01", 4);
1447                                         tmp_len += 4;
1448 //                                      printf("header part1 ");
1449 //                                      for (i = 0; i < len; ++i)
1450 //                                              printf("%02x ", data[8+i]);
1451 //                                      printf("\n");
1452                                         memcpy(tmp+tmp_len, data+8, len);
1453                                         for (i = 0; i < 4; ++i) {
1454                                                 profile_cmp[1] = profile_num[i];
1455                                                 if (!memcmp(tmp+tmp_len, profile_cmp, 2)) {
1456                                                         uint8_t level_org = tmp[tmp_len+3];
1457                                                         if (level_org > 0x29) {
1458                                                                 GST_INFO_OBJECT (self, "H264 %s profile@%d.%d patched down to 4.1!", profile_str[i], level_org / 10 , level_org % 10);
1459                                                                 tmp[tmp_len+3] = 0x29; // level 4.1
1460                                                         }
1461                                                         else
1462                                                                 GST_INFO_OBJECT (self, "H264 %s profile@%d.%d", profile_str[i], level_org / 10 , level_org % 10);
1463                                                         break;
1464                                                 }
1465                                         }
1466                                         tmp_len += len;
1467                                         cd_pos = 8 + len;
1468                                         if (cd_len > (cd_pos + 2)) {
1469                                                 len = (data[cd_pos+1] << 8) | data[cd_pos+2];
1470 //                                              printf("4 %d bytes\n", len);
1471                                                 cd_pos += 3;
1472                                                 if (cd_len >= (cd_pos+len)) {
1473 //                                                      printf("codec data ok!\n");
1474                                                         memcpy(tmp+tmp_len, "\x00\x00\x00\x01", 4);
1475                                                         tmp_len += 4;
1476 //                                                      printf("header part2 %02x %02x %02x %02x ... %d bytes\n", data[cd_pos], data[cd_pos+1], data[cd_pos+2], data[cd_pos+3], len);
1477                                                         memcpy(tmp+tmp_len, data+cd_pos, len);
1478                                                         tmp_len += len;
1479                                                         self->codec_data = gst_buffer_new_and_alloc(tmp_len);
1480                                                         memcpy(GST_BUFFER_DATA(self->codec_data), tmp, tmp_len);
1481                                                         self->h264_nal_len_size = (data[4] & 0x03) + 1;
1482                                                         if (self->h264_nal_len_size < 3)
1483                                                                 self->h264_buffer = gst_buffer_new_and_alloc(H264_BUFFER_SIZE);
1484                                                 }
1485                                                 else
1486                                                         GST_WARNING_OBJECT (self, "codec_data to short(4)");
1487                                         }
1488                                         else
1489                                                 GST_WARNING_OBJECT (self, "codec_data to short(3)");
1490                                 }
1491                                 else
1492                                         GST_WARNING_OBJECT (self, "codec_data to short(2)");
1493                         }
1494                         else if (cd_len <= 7)
1495                                 GST_WARNING_OBJECT (self, "codec_data to short(1)");
1496                         else
1497                                 GST_WARNING_OBJECT (self, "wrong avcC version %d!", data[0]);
1498                 }
1499                 else
1500                         self->h264_nal_len_size = 0;
1501                 GST_INFO_OBJECT (self, "MIMETYPE video/x-h264 VIDEO_SET_STREAMTYPE, 1");
1502         } else if (!strcmp (mimetype, "video/x-h263")) {
1503                 streamtype = 2;
1504                 GST_INFO_OBJECT (self, "MIMETYPE video/x-h263 VIDEO_SET_STREAMTYPE, 2");
1505         } else if (!strcmp (mimetype, "video/x-xvid")) {
1506                 streamtype = 10;
1507                 self->must_pack_bitstream = 1;
1508                 GST_INFO_OBJECT (self, "MIMETYPE video/x-xvid -> VIDEO_SET_STREAMTYPE, 10");
1509         } else if (!strcmp (mimetype, "video/x-divx") || !strcmp (mimetype, "video/x-msmpeg")) {
1510                 gint divxversion = -1;
1511                 if (!gst_structure_get_int (structure, "divxversion", &divxversion) && !gst_structure_get_int (structure, "msmpegversion", &divxversion))
1512                         ;
1513                 switch (divxversion) {
1514                         case 3:
1515                         case 43:
1516                         {
1517                                 #define B_GET_BITS(w,e,b)  (((w)>>(b))&(((unsigned)(-1))>>((sizeof(unsigned))*8-(e+1-b))))
1518                                 #define B_SET_BITS(name,v,e,b)  (((unsigned)(v))<<(b))
1519                                 static const guint8 brcm_divx311_sequence_header[] = {
1520                                         0x00, 0x00, 0x01, 0xE0, 0x00, 0x34, 0x80, 0x80, // PES HEADER
1521                                         0x05, 0x2F, 0xFF, 0xFF, 0xFF, 0xFF, 
1522                                         0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, /* 0 .. 7 */
1523                                         0x08, 0xC8, 0x0D, 0x40, 0x00, 0x53, 0x88, 0x40, /* 8 .. 15 */
1524                                         0x0C, 0x40, 0x01, 0x90, 0x00, 0x97, 0x53, 0x0A, /* 16 .. 24 */
1525                                         0x00, 0x00, 0x00, 0x00,
1526                                         0x30, 0x7F, 0x00, 0x00, 0x01, 0xB2, 0x44, 0x69, /* 0 .. 7 */
1527                                         0x76, 0x58, 0x33, 0x31, 0x31, 0x41, 0x4E, 0x44  /* 8 .. 15 */
1528                                 };
1529                                 self->codec_data = gst_buffer_new_and_alloc(63);
1530                                 guint8 *data = GST_BUFFER_DATA(self->codec_data);
1531                                 gint height, width;
1532                                 gst_structure_get_int (structure, "height", &height);
1533                                 gst_structure_get_int (structure, "width", &width);
1534                                 memcpy(data, brcm_divx311_sequence_header, 63);
1535                                 data += 38;
1536                                 data[0] = B_GET_BITS(width,11,4);
1537                                 data[1] = B_SET_BITS("width [3..0]", B_GET_BITS(width,3,0), 7, 4) |
1538                                         B_SET_BITS("'10'", 0x02, 3, 2) |
1539                                         B_SET_BITS("height [11..10]", B_GET_BITS(height,11,10), 1, 0);
1540                                 data[2] = B_GET_BITS(height,9,2);
1541                                 data[3]= B_SET_BITS("height [1.0]", B_GET_BITS(height,1,0), 7, 6) |
1542                                         B_SET_BITS("'100000'", 0x20, 5, 0);
1543                                 streamtype = 13;
1544                                 self->codec_type = CT_DIVX311;
1545                                 GST_INFO_OBJECT (self, "MIMETYPE video/x-divx vers. 3 -> VIDEO_SET_STREAMTYPE, 13");
1546                         }
1547                         break;
1548                         case 4:
1549                                 streamtype = 14;
1550                                 self->codec_type = CT_DIVX4;
1551                                 self->codec_data = gst_buffer_new_and_alloc(12);
1552                                 guint8 *data = GST_BUFFER_DATA(self->codec_data);
1553                                 memcpy(data, "\x00\x00\x01\xb2\x44\x69\x76\x58\x34\x41\x4e\x44", 12);
1554                                 GST_INFO_OBJECT (self, "MIMETYPE video/x-divx vers. 4 -> VIDEO_SET_STREAMTYPE, 14");
1555                         break;
1556                         case 6:
1557                         case 5:
1558                                 streamtype = 15;
1559                                 self->must_pack_bitstream = 1;
1560                                 GST_INFO_OBJECT (self, "MIMETYPE video/x-divx vers. 5 -> VIDEO_SET_STREAMTYPE, 15");
1561                         break;
1562                         default:
1563                                 GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), ("unhandled divx version %i", divxversion));
1564                         break;
1565                 }
1566         } else if (!strcmp (mimetype, "video/x-wmv")) {
1567                 guint32 fourcc=0;
1568                 const GValue *codec_data = gst_structure_get_value (structure, "codec_data");
1569                 if (gst_structure_get_fourcc (structure, "format", &fourcc) ||
1570                     gst_structure_get_fourcc (structure, "fourcc", &fourcc))
1571                 {
1572                         gint width, height;
1573                         if (GST_MAKE_FOURCC('W', 'V', 'C', '1') == fourcc || GST_MAKE_FOURCC('W', 'M', 'V', 'A') == fourcc)
1574                         {
1575                                 streamtype = 16;  // VC-1
1576                                 self->codec_type = CT_VC1;
1577                                 GST_INFO_OBJECT (self, "MIMETYPE video/x-wmv(WVC1) VIDEO_SET_STREAMTYPE, 16");
1578                         }
1579                         else if (GST_MAKE_FOURCC('W', 'M', 'V', '3') == fourcc)
1580                         {
1581                                 streamtype = 17; // VC1 Simple/Main
1582                                 self->codec_type = CT_VC1_SIMPLE_MAIN;
1583                                 gst_structure_get_int (structure, "height", &height);
1584                                 gst_structure_get_int (structure, "width", &width);
1585                                 GST_INFO_OBJECT (self, "MIMETYPE video/x-wmv(WMV3) VIDEO_SET_STREAMTYPE, 17");
1586                         }
1587                         else
1588                                 GST_ERROR_OBJECT (self, "unsupported wmv codec %c%c%c%c", fourcc & 0xFF, (fourcc >> 8) & 0xFF, (fourcc >> 16) & 0xFF, (fourcc >> 24) & 0xFF);
1589                         if (codec_data) {
1590                                 GST_INFO_OBJECT (self, "WMV have codec data..!");
1591                                 if (streamtype == 17) {
1592                                         GstBuffer *cd_data = gst_value_get_buffer (codec_data);
1593                                         guint8 *data = GST_BUFFER_DATA(cd_data);
1594                                         guint cd_len = GST_BUFFER_SIZE(cd_data);
1595                                         if (cd_len > 4) {
1596                                                 GST_INFO_OBJECT(self, "stripped %d byte VC1-SM codec data.. to 4", cd_len);
1597                                                 cd_len=4;
1598                                         }
1599                                         if (cd_len == 4) {
1600                                                 guint8 brcm_vc1sm_sequence_header[] = {
1601                                                         0x00, 0x00, 0x01, 0x0F,
1602                                                         (width >> 8) & 0xFF, width&0xFF,
1603                                                         (height >> 8) & 0xFF, height&0xFF,
1604                                                         0x00, 0x00, 0x00, 0x00,
1605                                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1606                                                 };
1607                                                 GstBuffer *dest = gst_buffer_new_and_alloc(sizeof(brcm_vc1sm_sequence_header));
1608                                                 memcpy(GST_BUFFER_DATA(dest), brcm_vc1sm_sequence_header, sizeof(brcm_vc1sm_sequence_header));
1609                                                 memcpy(GST_BUFFER_DATA(dest)+8, data, 4);
1610                                                 data[0] >>= 4;
1611                                                 if (data[0] != 4 && data[0] != 0)
1612                                                         GST_ERROR_OBJECT(self, "unsupported vc1-sm video compression format (profile %d)", data[0]);
1613                                                 self->codec_data = dest;
1614                                         }
1615                                         else {
1616                                                 GST_ERROR_OBJECT(self, "VC1-SM codec data has wrong size!!!");
1617                                                 streamtype = -1;
1618                                         }
1619                                 }
1620                                 else {
1621                                         self->codec_data = gst_value_get_buffer (codec_data);
1622                                         gst_buffer_ref (self->codec_data);
1623
1624                                         Vc1HandleStreamBuffer( self, GST_BUFFER_DATA(self->codec_data)+1, GST_BUFFER_SIZE(self->codec_data)-1, 2);
1625                                 }
1626                         }
1627                         else
1628                                 GST_INFO_OBJECT(self, "no WMV codec data!");
1629                 }
1630                 else
1631                         GST_ERROR_OBJECT(self, "no WMV fourcc given!");
1632         } else if (!strcmp (mimetype, "video/x-vp6") || !strcmp (mimetype, "video/x-vp6-flash")) {
1633                 self->codec_type = CT_VP6;
1634                 streamtype = 18;
1635                 GST_INFO_OBJECT (self, "MIMETYPE %s -> VIDEO_SET_STREAMTYPE, 18", mimetype);
1636         } else if (!strcmp (mimetype, "video/x-vp8")) {
1637                 self->codec_type = CT_VP8;
1638                 streamtype = 20;
1639                 GST_INFO_OBJECT (self, "MIMETYPE video/x-vp8 -> VIDEO_SET_STREAMTYPE, 20");
1640         } else if (!strcmp (mimetype, "video/x-flash-video")) {
1641                 self->codec_type = CT_SPARK;
1642                 streamtype = 21;
1643                 GST_INFO_OBJECT (self, "MIMETYPE video/x-flash-video -> VIDEO_SET_STREAMTYPE, 21");
1644         }
1645         if (streamtype != -1) {
1646                 gint numerator, denominator;
1647                 if (self->framerate == -1 && gst_structure_get_fraction (structure, "framerate", &numerator, &denominator)) {
1648                         FILE *f = fopen("/proc/stb/vmpeg/0/fallback_framerate", "w");
1649                         if (f) {
1650                                 int valid_framerates[] = { 23976, 24000, 25000, 29970, 30000, 50000, 59940, 60000 };
1651                                 int framerate = (int)(((double)numerator * 1000) / denominator);
1652                                 int diff = 60000;
1653                                 int best = 0;
1654                                 int i = 0;
1655                                 for (; i < 7; ++i) {
1656                                         int ndiff = abs(framerate - valid_framerates[i]);
1657                                         if (ndiff < diff) {
1658                                                 diff = ndiff;
1659                                                 best = i;
1660                                         }
1661                                 }
1662                                 self->framerate = valid_framerates[best];
1663
1664                                 GST_INFO_OBJECT(self, "framerate %d", self->framerate);
1665
1666                                 fprintf(f, "%d", self->framerate);
1667                                 fclose(f);
1668                         }
1669                 }
1670                 else if (self->framerate == -1)
1671                         GST_INFO_OBJECT(self, "no framerate given!");
1672
1673                 if (gst_structure_get_fraction (structure, "pixel-aspect-ratio", &numerator, &denominator)) {
1674                         if (numerator > 1 || denominator > 1) {
1675                                 FILE *f = fopen("/proc/stb/vmpeg/0/sar_x", "w");
1676                                 if (f) {
1677                                         GST_INFO_OBJECT(self, "set SAR_X to %d", numerator);
1678                                         fprintf(f, "%d", numerator);
1679                                         fclose(f);
1680                                 }
1681                                 f = fopen("/proc/stb/vmpeg/0/sar_y", "w");
1682                                 if (f) {
1683                                         GST_INFO_OBJECT(self, "set SAR_Y to %d", denominator);
1684                                         fprintf(f, "%d", denominator);
1685                                         fclose(f);
1686                                 }
1687                         }
1688                         else
1689                                 GST_INFO_OBJECT(self, "ignore container pixel-aspect-ratio %d/%d", numerator, denominator);
1690                 }
1691
1692                 if (self->dec_running) {
1693                         ioctl(self->fd, VIDEO_STOP, 0);
1694                         self->dec_running = FALSE;
1695                 }
1696                 if (ioctl(self->fd, VIDEO_SET_STREAMTYPE, streamtype) < 0 )
1697                         if ( streamtype != 0 && streamtype != 6 )
1698                                 GST_ELEMENT_ERROR (self, STREAM, CODEC_NOT_FOUND, (NULL), ("hardware decoder can't handle streamtype %i", streamtype));
1699                 ioctl(self->fd, VIDEO_PLAY);
1700                 self->dec_running = TRUE;
1701         } else
1702                 GST_ELEMENT_ERROR (self, STREAM, TYPE_NOT_FOUND, (NULL), ("unimplemented stream type %s", mimetype));
1703
1704         return TRUE;
1705 }
1706
1707 static int
1708 readMpegProc(char *str, int decoder)
1709 {
1710         int val = -1;
1711         char tmp[64];
1712         sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1713         FILE *f = fopen(tmp, "r");
1714         if (f)
1715         {
1716                 fscanf(f, "%x", &val);
1717                 fclose(f);
1718         }
1719         return val;
1720 }
1721
1722 static int
1723 readApiSize(int fd, int *xres, int *yres, int *aspect)
1724 {
1725         video_size_t size;
1726         if (!ioctl(fd, VIDEO_GET_SIZE, &size))
1727         {
1728                 *xres = size.w;
1729                 *yres = size.h;
1730                 *aspect = size.aspect_ratio == 0 ? 2 : 3;  // convert dvb api to etsi
1731                 return 0;
1732         }
1733         return -1;
1734 }
1735
1736 static int
1737 readApiFrameRate(int fd, int *framerate)
1738 {
1739         unsigned int frate;
1740         if (!ioctl(fd, VIDEO_GET_FRAME_RATE, &frate))
1741         {
1742                 *framerate = frate;
1743                 return 0;
1744         }
1745         return -1;
1746 }
1747
1748 static gboolean
1749 gst_dvbvideosink_start (GstBaseSink * basesink)
1750 {
1751         GstDVBVideoSink *self = GST_DVBVIDEOSINK (basesink);
1752         gint control_sock[2];
1753
1754         GST_DEBUG_OBJECT (self, "start");
1755
1756
1757         if (socketpair(PF_UNIX, SOCK_STREAM, 0, control_sock) < 0) {
1758                 perror("socketpair");
1759                 goto socket_pair;
1760         }
1761
1762         READ_SOCKET (self) = control_sock[0];
1763         WRITE_SOCKET (self) = control_sock[1];
1764
1765         fcntl (READ_SOCKET (self), F_SETFL, O_NONBLOCK);
1766         fcntl (WRITE_SOCKET (self), F_SETFL, O_NONBLOCK);
1767
1768         return TRUE;
1769         /* ERRORS */
1770 socket_pair:
1771         {
1772                 GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE, (NULL),
1773                                 GST_ERROR_SYSTEM);
1774                 return FALSE;
1775         }
1776 }
1777
1778 static gboolean
1779 gst_dvbvideosink_stop (GstBaseSink * basesink)
1780 {
1781         GstDVBVideoSink *self = GST_DVBVIDEOSINK (basesink);
1782         FILE *f = fopen("/proc/stb/vmpeg/0/fallback_framerate", "w");
1783         GST_DEBUG_OBJECT (self, "stop");
1784         if (self->fd >= 0)
1785         {
1786                 if (self->dec_running) {
1787                         ioctl(self->fd, VIDEO_STOP);
1788                         self->dec_running = FALSE;
1789                 }
1790                 ioctl(self->fd, VIDEO_SLOWMOTION, 0);
1791                 ioctl(self->fd, VIDEO_FAST_FORWARD, 0);
1792                 ioctl(self->fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
1793                 close(self->fd);
1794         }
1795
1796         if (self->codec_data)
1797                 gst_buffer_unref(self->codec_data);
1798
1799         if (self->h264_buffer)
1800                 gst_buffer_unref(self->h264_buffer);
1801
1802         if (self->prev_frame)
1803                 gst_buffer_unref(self->prev_frame);
1804
1805         while(self->queue)
1806                 queue_pop(&self->queue);
1807
1808         if (f) {
1809                 fputs(self->saved_fallback_framerate, f);
1810                 fclose(f);
1811         }
1812
1813         close (READ_SOCKET (self));
1814         close (WRITE_SOCKET (self));
1815         READ_SOCKET (self) = -1;
1816         WRITE_SOCKET (self) = -1;
1817
1818         return TRUE;
1819 }
1820
1821 static GstStateChangeReturn
1822 gst_dvbvideosink_change_state (GstElement * element, GstStateChange transition)
1823 {
1824         GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1825         GstDVBVideoSink *self = GST_DVBVIDEOSINK (element);
1826
1827         switch (transition) {
1828         case GST_STATE_CHANGE_NULL_TO_READY:
1829                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_NULL_TO_READY");
1830                 break;
1831         case GST_STATE_CHANGE_READY_TO_PAUSED:
1832                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_READY_TO_PAUSED");
1833
1834                 self->fd = open("/dev/dvb/adapter0/video0", O_RDWR|O_NONBLOCK);
1835 //              self->fd = open("/dump.pes", O_RDWR|O_CREAT|O_TRUNC, 0555);
1836
1837                 GST_OBJECT_LOCK(self);
1838                 self->no_write |= 4;
1839                 GST_OBJECT_UNLOCK(self);
1840
1841                 if (self->fd >= 0) {
1842                         GstStructure *s = 0;
1843                         GstMessage *msg = 0;
1844                         int aspect = -1, width = -1, height = -1, framerate = -1,
1845                                 progressive = readMpegProc("progressive", 0);
1846
1847                         if (readApiSize(self->fd, &width, &height, &aspect) == -1) {
1848                                 aspect = readMpegProc("aspect", 0);
1849                                 width = readMpegProc("xres", 0);
1850                                 height = readMpegProc("yres", 0);
1851                         } else
1852                                 aspect = aspect == 0 ? 2 : 3; // dvb api to etsi
1853                         if (readApiFrameRate(self->fd, &framerate) == -1)
1854                                 framerate = readMpegProc("framerate", 0);
1855
1856                         self->framerate = framerate;
1857
1858                         s = gst_structure_new ("eventSizeAvail",
1859                                 "aspect_ratio", G_TYPE_INT, aspect == 0 ? 2 : 3,
1860                                 "width", G_TYPE_INT, width,
1861                                 "height", G_TYPE_INT, height, NULL);
1862                         msg = gst_message_new_element (GST_OBJECT (element), s);
1863                         gst_element_post_message (GST_ELEMENT (element), msg);
1864                         s = gst_structure_new ("eventFrameRateAvail",
1865                                 "frame_rate", G_TYPE_INT, framerate, NULL);
1866                         msg = gst_message_new_element (GST_OBJECT (element), s);
1867                         gst_element_post_message (GST_ELEMENT (element), msg);
1868                         s = gst_structure_new ("eventProgressiveAvail",
1869                                 "progressive", G_TYPE_INT, progressive, NULL);
1870                         msg = gst_message_new_element (GST_OBJECT (element), s);
1871                         gst_element_post_message (GST_ELEMENT (element), msg);
1872                         ioctl(self->fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY);
1873                         ioctl(self->fd, VIDEO_FREEZE);
1874                 }
1875                 break;
1876         case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1877                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_PAUSED_TO_PLAYING");
1878                 ioctl(self->fd, VIDEO_CONTINUE);
1879                 GST_OBJECT_LOCK(self);
1880                 self->no_write &= ~4;
1881                 GST_OBJECT_UNLOCK(self);
1882                 break;
1883         default:
1884                 break;
1885         }
1886
1887         ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1888
1889         switch (transition) {
1890         case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1891                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_PLAYING_TO_PAUSED");
1892                 GST_OBJECT_LOCK(self);
1893                 self->no_write |= 4;
1894                 GST_OBJECT_UNLOCK(self);
1895                 ioctl(self->fd, VIDEO_FREEZE);
1896                 SEND_COMMAND (self, CONTROL_STOP);
1897                 break;
1898         case GST_STATE_CHANGE_PAUSED_TO_READY:
1899                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_PAUSED_TO_READY");
1900                 break;
1901         case GST_STATE_CHANGE_READY_TO_NULL:
1902                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_READY_TO_NULL");
1903                 break;
1904         default:
1905                 break;
1906         }
1907
1908         return ret;
1909 }
1910
1911 /* entry point to initialize the plug-in
1912  * initialize the plug-in itself
1913  * register the element factories and pad templates
1914  * register the features
1915  *
1916  * exchange the string 'plugin' with your elemnt name
1917  */
1918 static gboolean
1919 plugin_init (GstPlugin *plugin)
1920 {
1921         return gst_element_register (plugin, "dvbvideosink",
1922                                                  GST_RANK_PRIMARY,
1923                                                  GST_TYPE_DVBVIDEOSINK);
1924 }
1925
1926 /* this is the structure that gstreamer looks for to register plugins
1927  *
1928  * exchange the strings 'plugin' and 'Template plugin' with you plugin name and
1929  * description
1930  */
1931 GST_PLUGIN_DEFINE (
1932         GST_VERSION_MAJOR,
1933         GST_VERSION_MINOR,
1934         "dvb_video_out",
1935         "DVB Video Output",
1936         plugin_init,
1937         VERSION,
1938         "LGPL",
1939         "GStreamer",
1940         "http://gstreamer.net/"
1941 )
1942
1943 static unsigned int
1944 Vc1ParseSeqHeader( GstDVBVideoSink *self, struct bitstream *bit )
1945 {
1946         unsigned char n;
1947         long uiStartAddr = (long)&(bit->data[0]);
1948         long uiStopAddr = 0;
1949
1950         // skip first 5 bytes (PROFILE,LEVEL,COLORDIFF_FORMAT,FRMRTQ_POSTPROC,BITRTQ_POSTPROC,POSTPROCFLAG,MAX_CODED_WIDTH,MAX_CODED_HEIGHT)
1951         bitstream_get( bit, 32 );
1952         bitstream_get( bit, 8 );
1953         self->ucVC1_PULLDOWN = (unsigned char)bitstream_get( bit, 1 );
1954         self->ucVC1_INTERLACE = (unsigned char)bitstream_get( bit, 1 );
1955         self->ucVC1_TFCNTRFLAG = (unsigned char)bitstream_get( bit, 1 );
1956         self->ucVC1_FINTERPFLAG = (unsigned char)bitstream_get( bit, 1 );
1957         // skip 1 bit (RESERVED)
1958         bitstream_get( bit, 1 );
1959         self->ucVC1_PSF = (unsigned char)bitstream_get( bit, 1 );
1960
1961         if ( bitstream_get( bit, 1 ) == 1 ) {
1962                 // DISPLAY_EXT == 1
1963
1964                 // skip 28 bits (DISP_HORIZ_SIZE,DISP_VERT_SIZE)
1965                 bitstream_get( bit, 28 );
1966
1967                 if ( bitstream_get( bit, 1 ) == 1 ) {
1968                         // ASPECT_RATIO_FLAG == 1
1969                         if ( bitstream_get( bit, 4 ) == 15 )
1970                         {
1971                                 // ASPECT_RATIO == '15'
1972
1973                                 // skip 16 bits (ASPECT_HORIZ_SIZE,ASPECT_VERT_SIZE)
1974                                 bitstream_get( bit, 16 );
1975                         }
1976                 }
1977
1978                 if ( bitstream_get( bit, 1 ) == 1 ) {
1979                         int framerate = -1;
1980                         // FRAMERATE_FLAG == 1
1981                         if ( bitstream_get( bit, 1 ) == 0 ) {
1982                                 // FRAMERATEIND == 0
1983                                 int frameratenr = bitstream_get( bit, 8 );
1984                                 int frameratedr = bitstream_get( bit, 4 );
1985
1986                                 GST_DEBUG_OBJECT(self, "VC1 frameratenr %d, frameratedr %d", frameratenr, frameratedr);
1987
1988                                 switch (frameratenr) {
1989                                         case 1: framerate = 24000; break;
1990                                         case 2: framerate = 25000; break;
1991                                         case 3: framerate = 30000; break;
1992                                         case 4: framerate = 50000; break;
1993                                         case 5: framerate = 60000; break;
1994                                         case 6: framerate = 48000; break;
1995                                         case 7: framerate = 72000; break;
1996                                         default:
1997                                                 GST_INFO_OBJECT(self, "forbidden VC1 frameratenr %d", frameratenr);
1998                                                 break;
1999                                 }
2000                                 if (framerate != -1) {
2001                                         switch (frameratedr) {
2002                                         case 1: break;
2003                                         case 2: framerate *= 1000;
2004                                                 framerate /= 1001;
2005                                                 break;
2006                                         default:
2007                                                 GST_INFO_OBJECT(self, "forbidden VC1 frameratedr %d", frameratedr);
2008                                                 break;
2009                                         }
2010                                 }
2011                         }
2012                         else {
2013                                 // FRAMERATEIND == 1
2014                                 int framerateexp = bitstream_get( bit, 16 );
2015
2016                                 GST_DEBUG_OBJECT(self, "VC1 framerateexp %d", framerateexp);
2017
2018                                 framerate = (framerateexp * 1000) / 32;
2019                         }
2020
2021                         if (framerate != -1) {
2022                                 GST_INFO_OBJECT(self, "VC1 seq header framerate %d", framerate);
2023
2024                                 self->framerate = framerate;
2025                         }
2026                 }
2027
2028                 if ( bitstream_get( bit, 1 ) == 1 ) {
2029                         // COLOR_FORMAT_FLAG ==1
2030
2031                         // skip 24 bits (COLOR_PRIM,TRANSFER_CHAR,MATRIX_COEF)
2032                         bitstream_get( bit, 24 );
2033                 }
2034         }
2035
2036         self->ucVC1_HRD_PARAM_FLAG = (unsigned char)bitstream_get( bit, 1 );
2037
2038         if ( self->ucVC1_HRD_PARAM_FLAG == 1 ) {
2039                 // ucVC1_HRD_PARAM_FLAG == 1
2040                 self->ucVC1_HRD_NUM_LEAKY_BUCKETS = (unsigned char)bitstream_get( bit, 5 );
2041
2042                 // skip 8 bits (BIT_RATE_EXPONENT,BUFFER_SIZE_EXPONENT)
2043                 bitstream_get( bit, 8 );
2044
2045                 for ( n = 1; n <= self->ucVC1_HRD_NUM_LEAKY_BUCKETS; n++ ) {
2046                         // skip 32 bits (HRD_RATE[n],HRD_BUFFER[n])
2047                         bitstream_get( bit, 32 );
2048                 }
2049         }
2050
2051         uiStopAddr = (long)&(bit->data[0]);
2052         return (unsigned int)(uiStopAddr - uiStartAddr + 1);
2053 }
2054
2055 static unsigned int
2056 Vc1ParseEntryPointHeader( GstDVBVideoSink *self, struct bitstream *bit )
2057 {
2058         unsigned char n, ucEXTENDED_MV;
2059         long uiStartAddr = (long)&(bit->data[0]);
2060         long uiStopAddr = 0;
2061
2062         // skip the first two bits (BROKEN_LINK,CLOSED_ENTRY)
2063         bitstream_get( bit, 2 );
2064         self->ucVC1_PANSCAN_FLAG = (unsigned char)bitstream_get( bit, 1 );
2065         self->ucVC1_REFDIST_FLAG = (unsigned char)bitstream_get( bit, 1 );
2066
2067         // skip 2 bits (LOOPFILTER,FASTUVMC)
2068         bitstream_get( bit, 2 );
2069
2070         ucEXTENDED_MV = (unsigned char)bitstream_get( bit, 1 );
2071
2072         // skip 6 bits (DQUANT,VSTRANSFORM,OVERLAP,QUANTIZER)
2073         bitstream_get( bit, 6 );
2074
2075         if ( self->ucVC1_HRD_PARAM_FLAG == 1 ) {
2076                 for ( n = 1; n <= self->ucVC1_HRD_NUM_LEAKY_BUCKETS; n++ ) {
2077                         // skip 8 bits (HRD_FULL[n])
2078                         bitstream_get( bit, 8 );
2079                 }
2080         }
2081
2082         if ( bitstream_get( bit, 1 ) == 1 ) {
2083                 // CODED_SIZE_FLAG == 1
2084
2085                 // skip 24 bits (CODED_WIDTH,CODED_HEIGHT)
2086                 bitstream_get( bit, 24 );
2087         }
2088
2089         if ( ucEXTENDED_MV == 1 ) {
2090                 // skip 1 bit (EXTENDED_DMV)
2091                 bitstream_get( bit, 1 );
2092         }
2093
2094         if ( bitstream_get( bit, 1 ) == 1 ) {
2095                 // RANGE_MAPY_FLAG == 1
2096
2097                 // skip 3 bits (RANGE_MAPY)
2098                 bitstream_get( bit, 3 );
2099         }
2100
2101         if ( bitstream_get( bit, 1 ) == 1 ) {
2102                 // RANGE_MAPUV_FLAG == 1
2103
2104                 // skip 3 bits (RANGE_MAPUV)
2105                 bitstream_get( bit, 3 );
2106         }
2107
2108         uiStopAddr = (long)&(bit->data[0]);
2109
2110         return (unsigned int)(uiStopAddr - uiStartAddr + 1);
2111 }
2112
2113 static unsigned char
2114 Vc1GetFrameType( GstDVBVideoSink *self, struct bitstream *bit )
2115 {
2116         unsigned char ucRetVal = 0;
2117
2118         if ( self->ucVC1_INTERLACE == 1 ) {
2119                 // determine FCM
2120                 if ( bitstream_get( bit, 1 ) == 1 ) {
2121                         // Frame- or Field-Interlace Coding Mode -> we have to skip a further bit
2122                         bitstream_get( bit, 1 );
2123                 }
2124                 else {
2125                         // Progressive Frame Coding Mode -> no need to consume a further bit
2126                 }
2127         }
2128
2129         if ( bitstream_get( bit, 1 ) == 0 ) {
2130                 // P-Frame detected
2131                 ucRetVal = 0;
2132         }
2133         else if ( bitstream_get( bit, 1 ) == 0 ) {
2134                 // B-Frame detected
2135                 ucRetVal = 2;
2136         }
2137         else if ( bitstream_get( bit, 1 ) == 0 ) {
2138                 // I-Frame detected
2139                 ucRetVal = 6;
2140         }
2141         else if ( bitstream_get( bit, 1 ) == 0 ) {
2142                 // BI-Frame detected
2143                 ucRetVal = 14;
2144         }
2145         else {
2146                 // Skipped-Frame detected
2147                 ucRetVal = 15;
2148         }
2149
2150         return ucRetVal;
2151 }
2152
2153 static unsigned char
2154 Vc1GetBFractionVal( GstDVBVideoSink *self, struct bitstream *bit )
2155 {
2156         unsigned char ucRetVal = 0;
2157         unsigned char ucNumberOfPanScanWindows = 0;
2158         unsigned char ucRFF = 0;
2159         unsigned char ucRPTFRM = 0;
2160         unsigned char ucTmpVar = 0;
2161         unsigned char i;
2162
2163         if ( self->ucVC1_TFCNTRFLAG == 1 ) {
2164                 // skip the first 8 bit (TFCNTR)
2165                 bitstream_get( bit, 8 );
2166         }
2167
2168         if ( self->ucVC1_PULLDOWN == 1 ) {
2169                 if ( self->ucVC1_INTERLACE == 0 || self->ucVC1_PSF == 1 ) {
2170                         ucRPTFRM = (unsigned char)bitstream_get( bit, 2 );
2171                 }
2172                 else {
2173                         // skip 1 bit (TFF)
2174                         bitstream_get( bit, 1 );
2175                         ucRFF = (unsigned char)bitstream_get( bit, 1 );
2176                 }
2177         }
2178
2179         if ( self->ucVC1_PANSCAN_FLAG == 1 ) {
2180                 if ( bitstream_get( bit, 2 ) != 0 ) {
2181                         // PS_PRESENT
2182                         if ( self->ucVC1_INTERLACE == 1 && self->ucVC1_PSF == 0 ) {
2183                                 if ( self->ucVC1_PULLDOWN == 1 ) {
2184                                         ucNumberOfPanScanWindows = 2 + ucRFF;
2185                                 }
2186                                 else {
2187                                         ucNumberOfPanScanWindows = 2;
2188                                 }
2189                         }
2190                         else {
2191                                 if ( self->ucVC1_PULLDOWN == 1 ) {
2192                                         ucNumberOfPanScanWindows = 1 + ucRPTFRM;
2193                                 }
2194                                 else {
2195                                         ucNumberOfPanScanWindows = 1;
2196                                 }
2197                         }
2198                         for ( i = 0; i < ucNumberOfPanScanWindows; i++ ) {
2199                                 // skip 8 bytes (PS_HOFFSET,PS_VOFFSET,PS_WIDTH,PS_HEIGHT)
2200                                 bitstream_get( bit, 32 );
2201                                 bitstream_get( bit, 32 );
2202                         }
2203                 }
2204         }
2205
2206         // skip 1 bit (RNDCTRL)
2207         bitstream_get( bit, 1 );
2208
2209         if ( self->ucVC1_INTERLACE == 1 ) {
2210                 // skip 1 bit (UVSAMP)
2211                 bitstream_get( bit, 1 );
2212         }
2213
2214         if ( self->ucVC1_FINTERPFLAG == 1 ) {
2215                 // skip 1 bit (INTERPFRM)
2216                 bitstream_get( bit, 1 );
2217         }
2218
2219         ucTmpVar = (unsigned char)bitstream_get( bit, 3 );
2220         ucRetVal = ucTmpVar;
2221
2222         if ( ucTmpVar > 6 ) {
2223                 ucRetVal <<= 4;
2224                 ucTmpVar = (unsigned char)bitstream_get( bit, 4 );
2225                 ucRetVal |= ucTmpVar;
2226         }
2227
2228         return ucRetVal;
2229 }
2230
2231 static unsigned char
2232 Vc1GetNrOfFramesFromBFractionVal( unsigned char ucBFVal )
2233 {
2234         unsigned char ucRetVal;
2235
2236         switch( ucBFVal ) {
2237                 case 0:
2238                         //printf("(1/2)\n");
2239                         ucRetVal = 1;
2240                         break;
2241                 case 1:
2242                         //printf("(1/3)\n");
2243                         ucRetVal = 2;
2244                         break;
2245                 case 3:
2246                         //printf("(1/4)\n");
2247                         ucRetVal = 3;
2248                         break;
2249                 case 5:
2250                         //printf("(1/5)\n");
2251                         ucRetVal = 4;
2252                         break;
2253                 case 0x72:
2254                         //printf("(1/6)\n");
2255                         ucRetVal = 5;
2256                         break;
2257                 case 0x74:
2258                         //printf("(1/7)\n");
2259                         ucRetVal = 6;
2260                         break;
2261                 case 0x7A:
2262                         //printf("(1/8)\n");
2263                         ucRetVal = 7;
2264                         break;
2265                 default:
2266                         ucRetVal = 0;
2267                         //printf("ucBFVal = %d\n", ucBFVal);
2268                         break;
2269         }
2270
2271         return ucRetVal;
2272 }
2273
2274 static unsigned char
2275 Vc1HandleStreamBuffer( GstDVBVideoSink *self, unsigned char *data, unsigned int data_len, int flags )
2276 {
2277         unsigned char ucPType, ucRetVal = cVC1BufferDataAvailable;
2278         unsigned int i = 0;
2279
2280         if (flags & 1)
2281                 goto parse_frame_header;
2282
2283         while ( ((data[i] == 0) && (data[i+1] == 0) && (data[i+2] == 1)) ) {
2284                 i += 3;
2285
2286                 if ( data[i] == 0x0F ) {
2287                         // Sequence header
2288                         struct bitstream bitstr;
2289                         i++;
2290
2291                         GST_DEBUG_OBJECT(self, "Seq Header at POS %d", i);
2292
2293                         bitstream_init( &bitstr, &data[i], 0 );
2294                         i += Vc1ParseSeqHeader(self, &bitstr);
2295                         //printf("Sequence header\n");
2296                 }
2297                 else if (data[i] == 0x0E ) {
2298                         // Entry Point Header
2299                         struct bitstream bitstr;
2300                         i++;
2301
2302                         GST_DEBUG_OBJECT(self, "Entry Point Header at POS %d", i);
2303
2304                         bitstream_init( &bitstr, &data[i], 0 );
2305                         i += Vc1ParseEntryPointHeader(self, &bitstr);
2306                         //printf("Entry Point header\n");
2307                         if ( flags & 2 ) // parse codec_data only
2308                                 return 0;
2309                 }
2310                 else if ( data[i] == 0x0D )
2311                 {
2312                         // Frame Header
2313                         struct bitstream bitstr;
2314                         unsigned char ucBFractionVal = 0;
2315                         i++;
2316 parse_frame_header:
2317                         GST_DEBUG_OBJECT(self, "Frame Header at POS %d", i);
2318                         bitstream_init( &bitstr, &data[i], 0 );
2319                         ucPType = Vc1GetFrameType( self, &bitstr );
2320
2321                         GST_DEBUG_OBJECT(self, "picturetype = %d", ucPType);
2322
2323                         if ( self->prev_frame == NULL ) {
2324                                 // first frame received
2325                                 ucRetVal = cVC1NoBufferDataAvailable;
2326                         }
2327                         else {
2328                                 if ( ucPType == 2 && (self->ucPrevFramePicType == 0 || self->ucPrevFramePicType == 6 || self->ucPrevFramePicType == 15) )
2329                                 {
2330                                         int num_frames;
2331                                         // last frame was a reference frame (P-,I- or Skipped-Frame) and current frame is a B-Frame
2332                                         // -> correct the timestamp of the previous reference frame
2333                                         ucBFractionVal = Vc1GetBFractionVal( self, &bitstr );
2334
2335                                         num_frames = Vc1GetNrOfFramesFromBFractionVal( ucBFractionVal );
2336
2337                                         GST_DEBUG_OBJECT(self, "num_frames = %d", num_frames);
2338
2339                                         GST_BUFFER_TIMESTAMP(self->prev_frame) += (1000000000000ULL / self->framerate) * num_frames;
2340                                 }
2341                                 else if ( self->ucPrevFramePicType == 2 )
2342                                 {
2343                                         // last frame was a B-Frame -> correct the timestamp by the duration
2344                                         // of the preceding reference frame
2345                                         GST_BUFFER_TIMESTAMP(self->prev_frame) -= 1000000000000ULL / self->framerate;
2346                                 }
2347                         }
2348                         // save the current picture type
2349                         self->ucPrevFramePicType = ucPType;
2350                         break;
2351                 }
2352         }
2353
2354         return ucRetVal;
2355 }