prevent infinite loop on hacky EOS detection (fixes playlist getting stuck at the...
[gst-plugin-dvbmediasink.git] / src / gstdvbaudiosink.c
1 /*
2  * GStreamer DVB Media Sink
3  * Copyright 2006 Felix Domke <tmbinc@elitedvb.net>
4  * based on code by:
5  * Copyright 2005 Thomas Vander Stichele <thomas@apestaart.org>
6  * Copyright 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
7  * 
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  *
26  * Alternatively, the contents of this file may be used under the
27  * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
28  * which case the following provisions apply instead of the ones
29  * mentioned above:
30  *
31  * This library is free software; you can redistribute it and/or
32  * modify it under the terms of the GNU Library General Public
33  * License as published by the Free Software Foundation; either
34  * version 2 of the License, or (at your option) any later version.
35  *
36  * This library is distributed in the hope that it will be useful,
37  * but WITHOUT ANY WARRANTY; without even the implied warranty of
38  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39  * Library General Public License for more details.
40  *
41  * You should have received a copy of the GNU Library General Public
42  * License along with this library; if not, write to the
43  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
44  * Boston, MA 02111-1307, USA.
45  */
46
47 /**
48  * SECTION:element-plugin
49  *
50  * <refsect2>
51  * <title>Example launch line</title>
52  * <para>
53  * <programlisting>
54  * gst-launch -v -m audiotestsrc ! plugin ! fakesink silent=TRUE
55  * </programlisting>
56  * </para>
57  * </refsect2>
58  */
59
60 #ifdef HAVE_CONFIG_H
61 #include <config.h>
62 #endif
63 #include <unistd.h>
64 #include <string.h>
65 #include <sys/ioctl.h>
66 #include <sys/socket.h>
67 #include <linux/dvb/audio.h>
68 #include <linux/dvb/video.h>
69 #include <fcntl.h>
70 #include <poll.h>
71
72 #include <gst/gst.h>
73
74 /* We add a control socket as in fdsrc to make it shutdown quickly when it's blocking on the fd.
75  * Poll is used to determine when the fd is ready for use. When the element state is changed,
76  * it happens from another thread while fdsink is select'ing on the fd. The state-change thread 
77  * sends a control message, so fdsink wakes up and changes state immediately otherwise
78  * it would stay blocked until it receives some data. */
79
80 /* the poll call is also performed on the control sockets, that way
81  * we can send special commands to unblock the select call */
82 #define CONTROL_STOP                                            'S'              /* stop the select call */
83 #define CONTROL_SOCKETS(sink)    sink->control_sock
84 #define WRITE_SOCKET(sink)                      sink->control_sock[1]
85 #define READ_SOCKET(sink)                        sink->control_sock[0]
86
87 #define SEND_COMMAND(sink, command)                                     \
88 G_STMT_START {                                                                                                                  \
89         unsigned char c; c = command;                                            \
90         write (WRITE_SOCKET(sink), &c, 1);                               \
91 } G_STMT_END
92
93 #define READ_COMMAND(sink, command, res)                                \
94 G_STMT_START {                                                                                                                           \
95         res = read(READ_SOCKET(sink), &command, 1);      \
96 } G_STMT_END
97
98 #include "gstdvbaudiosink.h"
99
100 #ifndef AUDIO_GET_PTS
101 #define AUDIO_GET_PTS              _IOR('o', 19, gint64)
102 #endif
103
104 GST_DEBUG_CATEGORY_STATIC (dvbaudiosink_debug);
105 #define GST_CAT_DEFAULT dvbaudiosink_debug
106
107 /* Filter signals and args */
108 enum {
109         /* FILL ME */
110         LAST_SIGNAL
111 };
112
113 enum {
114         ARG_0,
115         ARG_SILENT
116 };
117
118 static GstStaticPadTemplate sink_factory =
119 GST_STATIC_PAD_TEMPLATE (
120         "sink",
121         GST_PAD_SINK,
122         GST_PAD_ALWAYS,
123         GST_STATIC_CAPS ("audio/mpeg, "
124                 "mpegversion = (int) { 1, 2, 4 }; "
125                 "audio/x-private1-ac3; "
126                 "audio/x-ac3; "
127                 "audio/x-dts")
128 );
129
130 #define DEBUG_INIT(bla) \
131         GST_DEBUG_CATEGORY_INIT (dvbaudiosink_debug, "dvbaudiosink", 0, "dvbaudiosink element");
132
133 GST_BOILERPLATE_FULL (GstDVBAudioSink, gst_dvbaudiosink, GstBaseSink,
134         GST_TYPE_BASE_SINK, DEBUG_INIT);
135
136 static void     gst_dvbaudiosink_set_property (GObject *object, guint prop_id,
137                                                                                                                                                                                                         const GValue *value,
138                                                                                                                                                                                                         GParamSpec *pspec);
139 static void     gst_dvbaudiosink_get_property (GObject *object, guint prop_id,
140                                                                                                                                                                                                         GValue *value,
141                                                                                                                                                                                                         GParamSpec *pspec);
142
143 static gboolean gst_dvbaudiosink_start (GstBaseSink * sink);
144 static gboolean gst_dvbaudiosink_stop (GstBaseSink * sink);
145 static gboolean gst_dvbaudiosink_event (GstBaseSink * sink, GstEvent * event);
146 static GstFlowReturn gst_dvbaudiosink_render (GstBaseSink * sink,
147         GstBuffer * buffer);
148 static gboolean gst_dvbaudiosink_query (GstElement * element, GstQuery * query);
149 static gboolean gst_dvbaudiosink_unlock (GstBaseSink * basesink);
150 static gboolean gst_dvbaudiosink_unlock_stop (GstBaseSink * basesink);
151 static gboolean gst_dvbaudiosink_set_caps (GstBaseSink * sink, GstCaps * caps);
152
153 gboolean bypass_set = FALSE;
154
155 static void
156 gst_dvbaudiosink_base_init (gpointer klass)
157 {
158         static GstElementDetails element_details = {
159                 "A DVB audio sink",
160                 "Generic/DVBAudioSink",
161                 "Outputs a MPEG2 PES / ES into a DVB audio device for hardware playback",
162                 "Felix Domke <tmbinc@elitedvb.net>"
163         };
164         GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
165
166         gst_element_class_add_pad_template (element_class,
167                 gst_static_pad_template_get (&sink_factory));
168         gst_element_class_set_details (element_class, &element_details);
169 }
170
171 /* initialize the plugin's class */
172 static void
173 gst_dvbaudiosink_class_init (GstDVBAudioSinkClass *klass)
174 {
175         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
176         GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass);
177         
178         gobject_class->set_property = gst_dvbaudiosink_set_property;
179         gobject_class->get_property = gst_dvbaudiosink_get_property;
180         
181         gobject_class = G_OBJECT_CLASS (klass);
182         g_object_class_install_property (gobject_class, ARG_SILENT,
183                 g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
184                                                                                                         FALSE, G_PARAM_READWRITE));
185
186         gstbasesink_class->get_times = NULL;
187         gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_start);
188         gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_stop);
189         gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_render);
190         gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_event);
191         gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_unlock);
192         gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR ( gst_dvbaudiosink_unlock_stop);
193         gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_set_caps);
194         GST_ELEMENT_CLASS (klass)->query = GST_DEBUG_FUNCPTR(gst_dvbaudiosink_query);
195 }
196
197 /* initialize the new element
198  * instantiate pads and add them to element
199  * set functions
200  * initialize structure
201  */
202 static void
203 gst_dvbaudiosink_init (GstDVBAudioSink *klass,
204                 GstDVBAudioSinkClass * gclass)
205 {
206         klass->silent = FALSE;
207         klass->aac_adts_header_valid = FALSE;
208
209         GST_BASE_SINK (klass)->sync = FALSE;
210 }
211
212 static void
213 gst_dvbaudiosink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
214 {
215         GstDVBAudioSink *filter;
216
217         g_return_if_fail (GST_IS_DVBAUDIOSINK (object));
218         filter = GST_DVBAUDIOSINK (object);
219
220         switch (prop_id)
221         {
222         case ARG_SILENT:
223                 filter->silent = g_value_get_boolean (value);
224                 break;
225         default:
226                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
227                 break;
228         }
229 }
230
231 static void
232 gst_dvbaudiosink_get_property (GObject *object, guint prop_id,
233                                                                                                                                         GValue *value, GParamSpec *pspec)
234 {
235         GstDVBAudioSink *filter;
236
237         g_return_if_fail (GST_IS_DVBAUDIOSINK (object));
238         filter = GST_DVBAUDIOSINK (object);
239
240         switch (prop_id) {
241         case ARG_SILENT:
242                 g_value_set_boolean (value, filter->silent);
243                 break;
244         default:
245                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
246                 break;
247         }
248 }
249
250 static gboolean
251 gst_dvbaudiosink_query (GstElement * element, GstQuery * query)
252 {
253         GstDVBAudioSink *self = GST_DVBAUDIOSINK (element);
254
255 //      printf("query %d %d\n", GST_QUERY_TYPE(query), GST_QUERY_POSITION);
256
257         switch (GST_QUERY_TYPE (query)) {
258         case GST_QUERY_POSITION:
259         {
260                 gint64 cur = 0;
261                 static gint64 last_pos = 0;
262                 GstFormat format;
263
264                 gst_query_parse_position (query, &format, NULL);
265
266                 if (format != GST_FORMAT_TIME)
267                         goto query_default;
268
269                 ioctl(self->fd, AUDIO_GET_PTS, &cur);
270 //              printf("gst_dvbaudiosink_query AUDIO_GET_PTS: %08llx\n", cur);
271
272                 /* workaround until driver fixed */
273                 if (cur)
274                         last_pos = cur;
275                 else
276                         cur = last_pos;
277
278                 cur *= 11111;
279
280                 gst_query_set_position (query, format, cur);
281
282                 GST_DEBUG_OBJECT (self, "position format %d", format);
283                 return TRUE;
284         }
285         default:
286 query_default:
287                 return GST_ELEMENT_CLASS (parent_class)->query (element, query);
288         }
289 }
290
291 static gboolean gst_dvbaudiosink_unlock (GstBaseSink * basesink)
292 {
293         GstDVBAudioSink *self = GST_DVBAUDIOSINK (basesink);
294
295         SEND_COMMAND (self, CONTROL_STOP);
296
297         return TRUE;
298 }
299
300 static gboolean gst_dvbaudiosink_unlock_stop (GstBaseSink * sink)
301 {
302         GstDVBAudioSink *self = GST_DVBAUDIOSINK (sink);
303         while (TRUE)
304         {
305                 gchar command;
306                 int res;
307                 
308                 READ_COMMAND (self, command, res);
309                 if (res < 0)
310                 {
311                 GST_LOG_OBJECT (self, "no more commands");
312                 /* no more commands */
313                 break;
314                 }
315         }
316         return TRUE;
317 }
318
319 static gboolean 
320 gst_dvbaudiosink_set_caps (GstBaseSink * basesink, GstCaps * caps)
321 {
322         GstDVBAudioSink *self = GST_DVBAUDIOSINK (basesink);
323         GstStructure *structure = gst_caps_get_structure (caps, 0);
324         const char *type = gst_structure_get_name (structure);
325         int bypass = -1;
326
327         self->skip = 0;
328         if (!strcmp(type, "audio/mpeg")) {
329                 gint mpegversion;
330                 gst_structure_get_int (structure, "mpegversion", &mpegversion);
331                 switch (mpegversion) {
332                         case 1:
333                         {
334                                 gint layer;
335                                 gst_structure_get_int (structure, "layer", &layer);
336                                 if ( layer == 3 )
337                                         bypass = 0xA;
338                                 else
339                                         bypass = 1;
340                                 printf("MIMETYPE %s version %d layer %d\n",type,mpegversion,layer);
341                                 break;
342                         }
343                         case 2:
344                         case 4:
345                         {
346                                 const GValue *codec_data = gst_structure_get_value (structure, "codec_data");
347                                 printf("MIMETYPE %s version %d (AAC)\n", type, mpegversion);
348                                 if (codec_data) {
349                                         guint8 *h = GST_BUFFER_DATA(gst_value_get_buffer (codec_data));
350                                         guint8 obj_type = ((h[0] & 0xC) >> 2) + 1;
351                                         guint8 rate_idx = ((h[0] & 0x3) << 1) | ((h[1] & 0x80) >> 7);
352                                         guint8 channels = (h[1] & 0x78) >> 3;
353 //                                      printf("have codec data -> obj_type = %d, rate_idx = %d, channels = %d\n",
354 //                                              obj_type, rate_idx, channels);
355                                         /* Sync point over a full byte */
356                                         self->aac_adts_header[0] = 0xFF;
357                                         /* Sync point continued over first 4 bits + static 4 bits
358                                          * (ID, layer, protection)*/
359                                         self->aac_adts_header[1] = 0xF1;
360                                         if (mpegversion == 2)
361                                                 self->aac_adts_header[1] |= 8;
362                                         /* Object type over first 2 bits */
363                                         self->aac_adts_header[2] = obj_type << 6;
364                                         /* rate index over next 4 bits */
365                                         self->aac_adts_header[2] |= rate_idx << 2;
366                                         /* channels over last 2 bits */
367                                         self->aac_adts_header[2] |= (channels & 0x4) >> 2;
368                                         /* channels continued over next 2 bits + 4 bits at zero */
369                                         self->aac_adts_header[3] = (channels & 0x3) << 6;
370                                         self->aac_adts_header_valid = TRUE;
371                                 }
372                                 else {
373                                         gint rate, channels, rate_idx=0, obj_type=1; // hardcoded yet.. hopefully this works every time ;)
374                                         gint AdtsSamplingRates[] = {
375                                                 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
376                                                 16000, 12000, 11025, 8000, 7350, 0
377                                         };
378                                         printf("no codec data!\n");
379                                         if (gst_structure_get_int (structure, "rate", &rate) && gst_structure_get_int (structure, "channels", &channels)) {
380                                                 do {
381                                                         if (AdtsSamplingRates[rate_idx] == rate)
382                                                                 break;
383                                                         ++rate_idx;
384                                                 } while (AdtsSamplingRates[rate_idx]);
385                                                 if (AdtsSamplingRates[rate_idx]) {
386                                                         printf("mpegversion %d, channels %d, rate %d, rate_idx %d\n", mpegversion, channels, rate, rate_idx);
387                                                         /* Sync point over a full byte */
388                                                         self->aac_adts_header[0] = 0xFF;
389                                                         /* Sync point continued over first 4 bits + static 4 bits
390                                                          * (ID, layer, protection)*/
391                                                         self->aac_adts_header[1] = 0xF1;
392                                                         if (mpegversion == 2)
393                                                                 self->aac_adts_header[1] |= 8;
394                                                         /* Object type over first 2 bits */
395                                                         self->aac_adts_header[2] = obj_type << 6;
396                                                         /* rate index over next 4 bits */
397                                                         self->aac_adts_header[2] |= rate_idx << 2;
398                                                         /* channels over last 2 bits */
399                                                         self->aac_adts_header[2] |= (channels & 0x4) >> 2;
400                                                         /* channels continued over next 2 bits + 4 bits at zero */
401                                                         self->aac_adts_header[3] = (channels & 0x3) << 6;
402                                                         self->aac_adts_header_valid = TRUE;
403                                                 }
404                                         }
405                                 }
406                                 if (bypass == -1)
407                                         bypass = 0x0b;
408                                 break;
409                         }
410                         default:
411                                 GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), ("unhandled mpeg version %i", mpegversion));
412                                 break;
413                 }
414         }
415         else if (!strcmp(type, "audio/x-ac3") || !strcmp(type, "audio/ac3"))
416         {
417                 printf("MIMETYPE %s\n",type);
418                 bypass = 0;
419         }
420         else if (!strcmp(type, "audio/x-private1-dts"))
421         {
422                 printf("MIMETYPE %s (DVD Audio - 2 byte skipping)\n",type);
423                 bypass = 2;
424                 self->skip = 2;
425         }
426         else if (!strcmp(type, "audio/x-private1-ac3"))
427         {
428                 printf("MIMETYPE %s (DVD Audio - 2 byte skipping)\n",type);
429                 bypass = 0;
430                 self->skip = 2;
431         } 
432         else if (!strcmp(type, "audio/x-dts") || !strcmp(type, "audio/dts"))
433         {
434                 printf("MIMETYPE %s\n",type);
435                 bypass = 2;
436                 GST_ELEMENT_ERROR (self, STREAM, CODEC_NOT_FOUND, (NULL), ("DTS not yet handled by driver"));
437                 return FALSE;
438         } else
439         {
440                 GST_ELEMENT_ERROR (self, STREAM, TYPE_NOT_FOUND, (NULL), ("unimplemented stream type %s", type));
441                 return FALSE;
442         }
443
444         GST_DEBUG_OBJECT(self, "setting dvb mode 0x%02x\n", bypass);
445
446         if (ioctl(self->fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
447         {
448                 GST_ELEMENT_WARNING (self, STREAM, DECODE, (NULL), ("hardware decoder can't be set to bypass mode %i.", bypass));
449 //              return FALSE;
450         }
451         bypass_set = TRUE;
452         return TRUE;
453 }
454
455 static gboolean
456 gst_dvbaudiosink_event (GstBaseSink * sink, GstEvent * event)
457 {
458         GstDVBAudioSink *self = GST_DVBAUDIOSINK (sink);
459         GST_DEBUG_OBJECT (self, "EVENT %s", gst_event_type_get_name(GST_EVENT_TYPE (event)));
460
461         switch (GST_EVENT_TYPE (event)) {
462         case GST_EVENT_FLUSH_START:
463                 ioctl(self->fd, AUDIO_CLEAR_BUFFER);
464                 break;
465         case GST_EVENT_FLUSH_STOP:
466                 ioctl(self->fd, AUDIO_CLEAR_BUFFER);
467                 break;
468         case GST_EVENT_EOS:
469         {
470                 struct pollfd pfd[2];
471                 int retval;
472                 pfd[0].fd = READ_SOCKET(self);
473                 pfd[0].events = POLLIN;
474 #if 0
475                         /* needs driver support */
476                 pfd[1].fd = self->fd;
477                 pfd[1].events = POLLHUP;
478
479                 do {
480                         GST_DEBUG_OBJECT (self, "going into poll to wait for EOS");
481                         retval = poll(pfd, 2, -1);
482                 } while ((retval == -1 && errno == EINTR));
483                 
484                 if (pfd[0].revents & POLLIN) /* flush */
485                         break;
486                 GST_DEBUG_OBJECT (self, "EOS wait ended because of buffer empty. now waiting for PTS %llx", self->pts_eos);
487 #endif
488                 long long lastdiff = 0;
489                 do {
490                         unsigned long long cur;
491                         ioctl(self->fd, AUDIO_GET_PTS, &cur);
492                         
493                         long long diff = self->last_pts_eos - cur;
494                         
495                         GST_DEBUG_OBJECT (self, "at %llx (diff %llx)", cur, diff);
496                         
497                         if ( diff <= 0x1000 || lastdiff == diff )
498                                 break;
499
500                         lastdiff = diff;
501                         retval = poll(pfd, 1, 1000);
502                                 /* check for flush */
503                         if (pfd[0].revents & POLLIN)
504                                 break;
505                 } while (1);
506
507                 break;
508         }
509         case GST_EVENT_NEWSEGMENT:{
510                 GstFormat fmt;
511                 gboolean update;
512                 gdouble rate, applied_rate;
513                 gint64 cur, stop, time;
514                 int skip = 0, repeat = 0, ret;
515                 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, &fmt, &cur, &stop, &time);
516 //              g_print("DVBAUDIOSINK GST_EVENT_NEWSEGMENT rate=%f applied_rate=%f\n", rate, applied_rate);
517                 int video_fd = open("/dev/dvb/adapter0/video0", O_RDWR);
518
519                 if (fmt == GST_FORMAT_TIME)
520                 {
521                         if ( rate > 1 )
522                                 skip = (int) rate;
523                         else if ( rate < 1 )
524                                 repeat = 1.0/rate;
525
526                         ret = ioctl(video_fd, VIDEO_SLOWMOTION, repeat);
527                         ret = ioctl(video_fd, VIDEO_FAST_FORWARD, skip);
528
529 //                      gst_segment_set_newsegment_full (&dec->segment, update, rate, applied_rate, dformat, cur, stop, time);
530
531                 }
532                 close(video_fd);
533                 break;
534         }
535
536         default:
537                 break;
538         }
539         return TRUE;
540 }
541
542 static GstFlowReturn
543 gst_dvbaudiosink_render (GstBaseSink * sink, GstBuffer * buffer)
544 {
545         GstDVBAudioSink *self = GST_DVBAUDIOSINK (sink);
546         unsigned char pes_header[64];
547         int skip = self->skip;
548         unsigned int size = GST_BUFFER_SIZE (buffer) - skip;
549         unsigned char *data = GST_BUFFER_DATA (buffer) + skip;
550         gint retval;
551         size_t pes_header_size;
552         struct pollfd pfd[2];
553
554 //      int i=0;
555 //      for (;i < (size > 0x1F ? 0x1F : size); ++i)
556 //              printf("%02x ", data[i]);
557 //      printf("%d bytes\n", size);
558 //      printf("timestamp: %08llx\n", (long long)GST_BUFFER_TIMESTAMP(buffer));
559
560         if ( !bypass_set )
561         {
562                 GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), ("hardware decoder not setup (no caps in pipeline?)"));
563                 return GST_FLOW_ERROR;
564         }
565
566         pfd[0].fd = READ_SOCKET(self);
567         pfd[0].events = POLLIN;
568         pfd[1].fd = self->fd;
569         pfd[1].events = POLLOUT;
570
571         do {
572                 GST_DEBUG_OBJECT (self, "going into poll, have %d bytes to write",
573                                 size);
574                 retval = poll(pfd, 2, -1);
575         } while ((retval == -1 && errno == EINTR));
576
577         if (retval == -1)
578                 goto poll_error;
579
580         if (pfd[0].revents & POLLIN) {
581                 /* read all stop commands */
582                 while (TRUE) {
583                         gchar command;
584                         int res;
585
586                         READ_COMMAND (self, command, res);
587                         if (res < 0) {
588                                 GST_LOG_OBJECT (self, "no more commands");
589                                 /* no more commands */
590                                 break;
591                         }
592                 }
593                 goto stopped;
594         }
595
596         if (self->fd < 0)
597                 return GST_FLOW_OK;
598
599         pes_header[0] = 0;
600         pes_header[1] = 0;
601         pes_header[2] = 1;
602         pes_header[3] = 0xC0;
603
604         if (self->aac_adts_header_valid)
605                 size += 7;
606
607                 /* do we have a timestamp? */
608         if (GST_BUFFER_TIMESTAMP(buffer) != GST_CLOCK_TIME_NONE)
609         {
610                 unsigned long long pts = GST_BUFFER_TIMESTAMP(buffer) * 9LL / 100000 /* convert ns to 90kHz */;
611
612                 self->last_pts_eos = self->pts_eos;
613                 self->pts_eos = pts;
614
615                 pes_header[4] = (size + 8) >> 8;
616                 pes_header[5] = (size + 8) & 0xFF;
617                 
618                 pes_header[6] = 0x80;
619                 pes_header[7] = 0x80;
620                 
621                 pes_header[8] = 5;
622                 
623                 pes_header[9]  = 0x21 | ((pts >> 29) & 0xE);
624                 pes_header[10] = pts >> 22;
625                 pes_header[11] = 0x01 | ((pts >> 14) & 0xFE);
626                 pes_header[12] = pts >> 7;
627                 pes_header[13] = 0x01 | ((pts << 1) & 0xFE);
628                 pes_header_size = 14;
629         } else
630         {
631                 pes_header[4] = (size + 3) >> 8;
632                 pes_header[5] = (size + 3) & 0xFF;
633                 pes_header[6] = 0x80;
634                 pes_header[7] = 0x00;
635                 pes_header[8] = 0;
636                 pes_header_size = 9;
637         }
638
639         if (self->aac_adts_header_valid) {
640                 self->aac_adts_header[3] &= 0xC0;
641                 /* frame size over last 2 bits */
642                 self->aac_adts_header[3] |= (size & 0x1800) >> 11;
643                 /* frame size continued over full byte */
644                 self->aac_adts_header[4] = (size & 0x1FF8) >> 3;
645                 /* frame size continued first 3 bits */
646                 self->aac_adts_header[5] = (size & 7) << 5;
647                 /* buffer fullness (0x7FF for VBR) over 5 last bits */
648                 self->aac_adts_header[5] |= 0x1F;
649                 /* buffer fullness (0x7FF for VBR) continued over 6 first bits + 2 zeros for
650                  * number of raw data blocks */
651                 self->aac_adts_header[6] = 0xFC;
652                 memcpy(pes_header + pes_header_size, self->aac_adts_header, 7);
653                 pes_header_size += 7;
654         }
655
656         write(self->fd, pes_header, pes_header_size);
657         write(self->fd, data, GST_BUFFER_SIZE (buffer) - skip);
658
659         return GST_FLOW_OK;
660 poll_error:
661         {
662                 GST_ELEMENT_ERROR (self, RESOURCE, READ, (NULL),
663                                 ("poll on file descriptor: %s.", g_strerror (errno)));
664                 GST_DEBUG_OBJECT (self, "Error during poll");
665                 return GST_FLOW_ERROR;
666         }
667 stopped:
668         {
669                 GST_DEBUG_OBJECT (self, "Select stopped");
670                 ioctl(self->fd, AUDIO_CLEAR_BUFFER);
671                 return GST_FLOW_WRONG_STATE;
672         }
673 }
674
675 static gboolean
676 gst_dvbaudiosink_start (GstBaseSink * basesink)
677 {
678         GstDVBAudioSink *self = GST_DVBAUDIOSINK (basesink);
679         self->fd = open("/dev/dvb/adapter0/audio0", O_RDWR);
680 //      self->fd = open("/dump.pes", O_RDWR|O_CREAT, 0555);
681         
682         gint control_sock[2];
683
684         if (socketpair (PF_UNIX, SOCK_STREAM, 0, control_sock) < 0)
685                 goto socket_pair;
686
687         READ_SOCKET (self) = control_sock[0];
688         WRITE_SOCKET (self) = control_sock[1];
689
690         fcntl (READ_SOCKET (self), F_SETFL, O_NONBLOCK);
691         fcntl (WRITE_SOCKET (self), F_SETFL, O_NONBLOCK);
692
693         if (self->fd)
694         {
695                 ioctl(self->fd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY);
696                 ioctl(self->fd, AUDIO_PLAY);
697 //              ioctl(self->fd, AUDIO_SET_BYPASS_MODE, 0);
698         }
699         return TRUE;
700         /* ERRORS */
701 socket_pair:
702         {
703                 GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE, (NULL),
704                                 GST_ERROR_SYSTEM);
705                 return FALSE;
706         }
707 }
708
709 static gboolean
710 gst_dvbaudiosink_stop (GstBaseSink * basesink)
711 {
712         GstDVBAudioSink *self = GST_DVBAUDIOSINK (basesink);
713         if (self->fd >= 0)
714         {
715                 ioctl(self->fd, AUDIO_STOP);
716                 ioctl(self->fd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX);
717
718                 int video_fd = open("/dev/dvb/adapter0/video0", O_RDWR);
719                 if ( video_fd > 0 )
720                 {
721                         ioctl(video_fd, VIDEO_SLOWMOTION, 0);
722                         ioctl(video_fd, VIDEO_FAST_FORWARD, 0);
723                         close (video_fd);
724                 }
725                 close(self->fd);
726         }
727
728         return TRUE;
729 }
730
731 /* entry point to initialize the plug-in
732  * initialize the plug-in itself
733  * register the element factories and pad templates
734  * register the features
735  *
736  * exchange the string 'plugin' with your elemnt name
737  */
738 static gboolean
739 plugin_init (GstPlugin *plugin)
740 {
741         return gst_element_register (plugin, "dvbaudiosink",
742                                                  GST_RANK_PRIMARY,
743                                                  GST_TYPE_DVBAUDIOSINK);
744 }
745
746 /* this is the structure that gstreamer looks for to register plugins
747  *
748  * exchange the strings 'plugin' and 'Template plugin' with you plugin name and
749  * description
750  */
751 GST_PLUGIN_DEFINE (
752         GST_VERSION_MAJOR,
753         GST_VERSION_MINOR,
754         "dvb_audio_out",
755         "DVB Audio Output",
756         plugin_init,
757         VERSION,
758         "LGPL",
759         "GStreamer",
760         "http://gstreamer.net/"
761 )