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