try to fix EOS event handling
[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 <stdint.h>
65 #include <string.h>
66 #include <sys/ioctl.h>
67 #include <sys/socket.h>
68 #include <linux/dvb/audio.h>
69 #include <linux/dvb/video.h>
70 #include <fcntl.h>
71 #include <poll.h>
72
73 #include <gst/gst.h>
74
75 #include "gstdvbaudiosink.h"
76 #include "gstdvbsink-marshal.h"
77
78 /* We add a control socket as in fdsrc to make it shutdown quickly when it's blocking on the fd.
79  * Poll is used to determine when the fd is ready for use. When the element state is changed,
80  * it happens from another thread while fdsink is poll'ing on the fd. The state-change thread 
81  * sends a control message, so fdsink wakes up and changes state immediately otherwise
82  * it would stay blocked until it receives some data. */
83
84 /* the poll call is also performed on the control sockets, that way
85  * we can send special commands to unblock the poll call */
86 #define CONTROL_STOP            'S'                     /* stop the poll call */
87 #define CONTROL_SOCKETS(sink)   sink->control_sock
88 #define WRITE_SOCKET(sink)      sink->control_sock[1]
89 #define READ_SOCKET(sink)       sink->control_sock[0]
90
91 #define SEND_COMMAND(sink, command)                     \
92 G_STMT_START {                                          \
93         unsigned char c; c = command;                   \
94         write (WRITE_SOCKET(sink), &c, 1);              \
95 } G_STMT_END
96
97 #define READ_COMMAND(sink, command, res)                \
98 G_STMT_START {                                          \
99         res = read(READ_SOCKET(sink), &command, 1);     \
100 } G_STMT_END
101
102 #ifndef AUDIO_GET_PTS
103 #define AUDIO_GET_PTS           _IOR('o', 19, gint64)
104 #endif
105
106 GST_DEBUG_CATEGORY_STATIC (dvbaudiosink_debug);
107 #define GST_CAT_DEFAULT dvbaudiosink_debug
108
109 enum
110 {
111         SIGNAL_GET_DECODER_TIME,
112         LAST_SIGNAL
113 };
114
115 static guint gst_dvbaudiosink_signals[LAST_SIGNAL] = { 0 };
116
117 static guint AdtsSamplingRates[] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0 };
118
119 static GstStaticPadTemplate sink_factory_ati_xilleon =
120 GST_STATIC_PAD_TEMPLATE (
121         "sink",
122         GST_PAD_SINK,
123         GST_PAD_ALWAYS,
124         GST_STATIC_CAPS ("audio/mpeg, "
125                 "mpegversion = (int) 1, "
126                 "layer = (int) [ 1, 2 ], "
127                 "framed = (boolean) true; "
128                 "audio/x-ac3, "
129                 "framed = (boolean) true; "
130                 "audio/x-private1-ac3, "
131                 "framed = (boolean) true")
132 );
133
134 static GstStaticPadTemplate sink_factory_broadcom_dts =
135 GST_STATIC_PAD_TEMPLATE (
136         "sink",
137         GST_PAD_SINK,
138         GST_PAD_ALWAYS,
139         GST_STATIC_CAPS ("audio/mpeg, "
140                 "framed = (boolean) true; "
141                 "audio/x-ac3, "
142                 "framed = (boolean) true; "
143                 "audio/x-private1-ac3, "
144                 "framed = (boolean) true; "
145                 "audio/x-dts, "
146                 "framed = (boolean) true; "
147                 "audio/x-private1-dts, "
148                 "framed = (boolean) true; "
149                 "audio/x-private1-lpcm, "
150                 "framed = (boolean) true")
151 );
152
153 static GstStaticPadTemplate sink_factory_broadcom =
154 GST_STATIC_PAD_TEMPLATE (
155         "sink",
156         GST_PAD_SINK,
157         GST_PAD_ALWAYS,
158         GST_STATIC_CAPS ("audio/mpeg, "
159                 "framed = (boolean) true; "
160                 "audio/x-ac3, "
161                 "framed = (boolean) true; "
162                 "audio/x-private1-ac3, "
163                 "framed = (boolean) true")
164 );
165
166 #define DEBUG_INIT(bla) \
167         GST_DEBUG_CATEGORY_INIT (dvbaudiosink_debug, "dvbaudiosink", 0, "dvbaudiosink element");
168
169 GST_BOILERPLATE_FULL (GstDVBAudioSink, gst_dvbaudiosink, GstBaseSink, GST_TYPE_BASE_SINK, DEBUG_INIT);
170
171 static gboolean gst_dvbaudiosink_start (GstBaseSink * sink);
172 static gboolean gst_dvbaudiosink_stop (GstBaseSink * sink);
173 static gboolean gst_dvbaudiosink_event (GstBaseSink * sink, GstEvent * event);
174 static GstFlowReturn gst_dvbaudiosink_render (GstBaseSink * sink, GstBuffer * buffer);
175 static gboolean gst_dvbaudiosink_unlock (GstBaseSink * basesink);
176 static gboolean gst_dvbaudiosink_unlock_stop (GstBaseSink * basesink);
177 static gboolean gst_dvbaudiosink_set_caps (GstBaseSink * sink, GstCaps * caps);
178 static void gst_dvbaudiosink_dispose (GObject * object);
179 static GstStateChangeReturn gst_dvbaudiosink_change_state (GstElement * element, GstStateChange transition);
180 static gint64 gst_dvbaudiosink_get_decoder_time (GstDVBAudioSink *self);
181
182 typedef enum { DM7025, DM800, DM8000, DM500HD, DM800SE } hardware_type_t;
183
184 static hardware_type_t hwtype;
185
186 static void
187 gst_dvbaudiosink_base_init (gpointer klass)
188 {
189         static GstElementDetails element_details = {
190                 "A DVB audio sink",
191                 "Generic/DVBAudioSink",
192                 "Outputs a MPEG2 PES / ES into a DVB audio device for hardware playback",
193                 "Felix Domke <tmbinc@elitedvb.net>"
194         };
195         GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
196
197         int fd = open("/proc/stb/info/model", O_RDONLY);
198         if ( fd > 0 )
199         {
200                 gchar string[8] = { 0, };
201                 ssize_t rd = read(fd, string, 7);
202                 if ( rd >= 5 )
203                 {
204                         string[rd] = 0;
205                         if ( !strncasecmp(string, "DM7025", 6) ) {
206                                 hwtype = DM7025;
207                                 GST_INFO ("model is DM7025 set ati xilleon caps");
208                         }
209                         else if ( !strncasecmp(string, "DM8000", 6) ) {
210                                 hwtype = DM8000;
211                                 GST_INFO ("model is DM8000 set broadcom dts caps");
212                                 gst_element_class_add_pad_template (element_class,
213                                         gst_static_pad_template_get (&sink_factory_broadcom_dts));
214                         }
215                         else if ( !strncasecmp(string, "DM800SE", 7) ) {
216                                 hwtype = DM800SE;
217                                 GST_INFO ("model is DM800SE set broadcom dts caps", string);
218                                 gst_element_class_add_pad_template (element_class,
219                                         gst_static_pad_template_get (&sink_factory_broadcom_dts));
220                         }
221                         else if ( !strncasecmp(string, "DM800", 5) ) {
222                                 hwtype = DM800;
223                                 GST_INFO ("model is DM800 set broadcom caps", string);
224                                 gst_element_class_add_pad_template (element_class,
225                                         gst_static_pad_template_get (&sink_factory_broadcom));
226                         }
227                         else if ( !strncasecmp(string, "DM500HD", 7) ) {
228                                 hwtype = DM500HD;
229                                 GST_INFO ("model is DM500HD set broadcom dts caps", string);
230                                 gst_element_class_add_pad_template (element_class,
231                                         gst_static_pad_template_get (&sink_factory_broadcom_dts));
232                         }
233                 }
234                 close(fd);
235         }
236
237         if (hwtype == DM7025) {
238                 gst_element_class_add_pad_template (element_class,
239                         gst_static_pad_template_get (&sink_factory_ati_xilleon));
240         }
241
242         gst_element_class_set_details (element_class, &element_details);
243 }
244
245 static int
246 gst_dvbaudiosink_async_write(GstDVBAudioSink *self, unsigned char *data, unsigned int len);
247
248 /* initialize the plugin's class */
249 static void
250 gst_dvbaudiosink_class_init (GstDVBAudioSinkClass *klass)
251 {
252         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
253         GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass);
254         GstElementClass *gelement_class = GST_ELEMENT_CLASS (klass);
255
256         gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_dispose);
257
258         gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_start);
259         gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_stop);
260         gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_render);
261         gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_event);
262         gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_unlock);
263         gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_unlock_stop);
264         gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_set_caps);
265
266         gelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvbaudiosink_change_state);
267
268         gst_dvbaudiosink_signals[SIGNAL_GET_DECODER_TIME] =
269                 g_signal_new ("get-decoder-time",
270                 G_TYPE_FROM_CLASS (klass),
271                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
272                 G_STRUCT_OFFSET (GstDVBAudioSinkClass, get_decoder_time),
273                 NULL, NULL, gst_dvbsink_marshal_INT64__VOID, G_TYPE_INT64, 0);
274
275         klass->get_decoder_time = gst_dvbaudiosink_get_decoder_time;
276         klass->async_write = gst_dvbaudiosink_async_write;
277 }
278
279 /* initialize the new element
280  * instantiate pads and add them to element
281  * set functions
282  * initialize structure
283  */
284 static void
285 gst_dvbaudiosink_init (GstDVBAudioSink *klass, GstDVBAudioSinkClass * gclass)
286 {
287         klass->bypass = -1;
288
289         klass->timestamp = 0;
290         klass->aac_adts_header_valid = FALSE;
291
292         klass->no_write = 0;
293         klass->queue = NULL;
294         klass->fd = -1;
295
296         gst_base_sink_set_sync (GST_BASE_SINK(klass), FALSE);
297         gst_base_sink_set_async_enabled (GST_BASE_SINK(klass), TRUE);
298 }
299
300 static void
301 gst_dvbaudiosink_dispose (GObject * object)
302 {
303         GstDVBAudioSink *self = GST_DVBAUDIOSINK (object);
304         GstState state, pending;
305         GST_DEBUG_OBJECT (self, "dispose");
306
307 // hack for gstreamer decodebin2 bug... it tries to dispose .. but doesnt set the state to NULL when it is READY
308         switch(gst_element_get_state(GST_ELEMENT(object), &state, &pending, GST_CLOCK_TIME_NONE))
309         {
310         case GST_STATE_CHANGE_SUCCESS:
311                 GST_DEBUG_OBJECT(self, "success");
312                 if (state != GST_STATE_NULL) {
313                         GST_DEBUG_OBJECT(self, "state %d in dispose.. set it to NULL (decodebin2 bug?)", state);
314                         if (gst_element_set_state(GST_ELEMENT(object), GST_STATE_NULL) == GST_STATE_CHANGE_ASYNC) {
315                                 GST_DEBUG_OBJECT(self, "set state returned async... wait!");
316                                 gst_element_get_state(GST_ELEMENT(object), &state, &pending, GST_CLOCK_TIME_NONE);
317                         }
318                 }
319                 break;
320         case GST_STATE_CHANGE_ASYNC:
321                 GST_DEBUG_OBJECT(self, "async");
322                 break;
323         case GST_STATE_CHANGE_FAILURE:
324                 GST_DEBUG_OBJECT(self, "failure");
325                 break;
326         case GST_STATE_CHANGE_NO_PREROLL:
327                 GST_DEBUG_OBJECT(self, "no preroll");
328                 break;
329         default:
330                 break;
331         }
332 // hack end
333
334         GST_DEBUG_OBJECT(self, "state in dispose %d, pending %d", state, pending);
335
336         G_OBJECT_CLASS (parent_class)->dispose (object);
337 }
338
339 static gint64
340 gst_dvbaudiosink_get_decoder_time (GstDVBAudioSink *self)
341 {
342         if (self->bypass != -1) {
343                 gint64 cur = 0;
344                 static gint64 last_pos = 0;
345
346                 ioctl(self->fd, AUDIO_GET_PTS, &cur);
347
348                 /* workaround until driver fixed */
349                 if (cur)
350                         last_pos = cur;
351                 else
352                         cur = last_pos;
353
354                 cur *= 11111;
355
356                 return cur;
357         }
358         return GST_CLOCK_TIME_NONE;
359 }
360
361 static gboolean
362 gst_dvbaudiosink_unlock (GstBaseSink * basesink)
363 {
364         GstDVBAudioSink *self = GST_DVBAUDIOSINK (basesink);
365         GST_OBJECT_LOCK(self);
366         self->no_write |= 2;
367         GST_OBJECT_UNLOCK(self);
368         SEND_COMMAND (self, CONTROL_STOP);
369         GST_DEBUG_OBJECT (basesink, "unlock");
370         return TRUE;
371 }
372
373 static gboolean
374 gst_dvbaudiosink_unlock_stop (GstBaseSink * basesink)
375 {
376         GstDVBAudioSink *self = GST_DVBAUDIOSINK (basesink);
377         GST_OBJECT_LOCK(self);
378         self->no_write &= ~2;
379         GST_OBJECT_UNLOCK(self);
380         GST_DEBUG_OBJECT (basesink, "unlock_stop");
381         return TRUE;
382 }
383
384 static gboolean
385 gst_dvbaudiosink_set_caps (GstBaseSink * basesink, GstCaps * caps)
386 {
387         GstDVBAudioSink *self = GST_DVBAUDIOSINK (basesink);
388         GstStructure *structure = gst_caps_get_structure (caps, 0);
389         const char *type = gst_structure_get_name (structure);
390         int bypass = -1;
391
392         self->skip = 0;
393
394         if (!strcmp(type, "audio/mpeg")) {
395                 gint mpegversion;
396                 gst_structure_get_int (structure, "mpegversion", &mpegversion);
397                 switch (mpegversion) {
398                         case 1:
399                         {
400                                 gint layer;
401                                 gst_structure_get_int (structure, "layer", &layer);
402                                 if ( layer == 3 )
403                                         bypass = 0xA;
404                                 else
405                                         bypass = 1;
406                                 GST_INFO_OBJECT (self, "MIMETYPE %s version %d layer %d",type,mpegversion,layer);
407                                 break;
408                         }
409                         case 2:
410                         case 4:
411                         {
412                                 const gchar *stream_type = gst_structure_get_string (structure, "stream-type");
413                                 if (!stream_type)
414                                         stream_type = gst_structure_get_string (structure, "stream-format");
415                                 if (stream_type && !strcmp(stream_type, "adts"))
416                                         GST_INFO_OBJECT (self, "MIMETYPE %s version %d (AAC-ADTS)", type, mpegversion);
417                                 else {
418                                         const GValue *codec_data = gst_structure_get_value (structure, "codec_data");
419                                         GST_INFO_OBJECT (self, "MIMETYPE %s version %d (AAC-RAW)", type, mpegversion);
420                                         if (codec_data) {
421                                                 guint8 *h = GST_BUFFER_DATA(gst_value_get_buffer (codec_data));
422                                                 guint8 obj_type = ((h[0] & 0xC) >> 2) + 1;
423                                                 guint8 rate_idx = ((h[0] & 0x3) << 1) | ((h[1] & 0x80) >> 7);
424                                                 guint8 channels = (h[1] & 0x78) >> 3;
425                                                 GST_INFO_OBJECT (self, "have codec data -> obj_type = %d, rate_idx = %d, channels = %d\n",
426                                                         obj_type, rate_idx, channels);
427                                                 /* Sync point over a full byte */
428                                                 self->aac_adts_header[0] = 0xFF;
429                                                 /* Sync point continued over first 4 bits + static 4 bits
430                                                  * (ID, layer, protection)*/
431                                                 self->aac_adts_header[1] = 0xF1;
432                                                 if (mpegversion == 2)
433                                                         self->aac_adts_header[1] |= 8;
434                                                 /* Object type over first 2 bits */
435                                                 self->aac_adts_header[2] = obj_type << 6;
436                                                 /* rate index over next 4 bits */
437                                                 self->aac_adts_header[2] |= rate_idx << 2;
438                                                 /* channels over last 2 bits */
439                                                 self->aac_adts_header[2] |= (channels & 0x4) >> 2;
440                                                 /* channels continued over next 2 bits + 4 bits at zero */
441                                                 self->aac_adts_header[3] = (channels & 0x3) << 6;
442                                                 self->aac_adts_header_valid = TRUE;
443                                         }
444                                         else {
445                                                 gint rate, channels, rate_idx=0, obj_type=1; // hardcoded yet.. hopefully this works every time ;)
446                                                 GST_INFO_OBJECT (self, "no codec data");
447                                                 if (gst_structure_get_int (structure, "rate", &rate) && gst_structure_get_int (structure, "channels", &channels)) {
448                                                         do {
449                                                                 if (AdtsSamplingRates[rate_idx] == rate)
450                                                                         break;
451                                                                 ++rate_idx;
452                                                         } while (AdtsSamplingRates[rate_idx]);
453                                                         if (AdtsSamplingRates[rate_idx]) {
454                                                                 GST_INFO_OBJECT (self, "mpegversion %d, channels %d, rate %d, rate_idx %d\n", mpegversion, channels, rate, rate_idx);
455                                                                 /* Sync point over a full byte */
456                                                                 self->aac_adts_header[0] = 0xFF;
457                                                                 /* Sync point continued over first 4 bits + static 4 bits
458                                                                  * (ID, layer, protection)*/
459                                                                 self->aac_adts_header[1] = 0xF1;
460                                                                 if (mpegversion == 2)
461                                                                         self->aac_adts_header[1] |= 8;
462                                                                 /* Object type over first 2 bits */
463                                                                 self->aac_adts_header[2] = obj_type << 6;
464                                                                 /* rate index over next 4 bits */
465                                                                 self->aac_adts_header[2] |= rate_idx << 2;
466                                                                 /* channels over last 2 bits */
467                                                                 self->aac_adts_header[2] |= (channels & 0x4) >> 2;
468                                                                 /* channels continued over next 2 bits + 4 bits at zero */
469                                                                 self->aac_adts_header[3] = (channels & 0x3) << 6;
470                                                                 self->aac_adts_header_valid = TRUE;
471                                                         }
472                                                 }
473                                         }
474                                 }
475                                 bypass = 0x0b; // always use AAC+ ADTS yet..
476                                 break;
477                         }
478                         default:
479                                 GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), ("unhandled mpeg version %i", mpegversion));
480                                 break;
481                 }
482         }
483         else if (!strcmp(type, "audio/x-ac3") || !strcmp(type, "audio/ac3"))
484         {
485                 GST_INFO_OBJECT (self, "MIMETYPE %s",type);
486                 bypass = 0;
487         }
488         else if (!strcmp(type, "audio/x-private1-dts"))
489         {
490                 GST_INFO_OBJECT (self, "MIMETYPE %s (DVD Audio - 2 byte skipping)",type);
491                 bypass = 2;
492                 self->skip = 2;
493         }
494         else if (!strcmp(type, "audio/x-private1-ac3"))
495         {
496                 GST_INFO_OBJECT (self, "MIMETYPE %s (DVD Audio - 2 byte skipping)",type);
497                 bypass = 0;
498                 self->skip = 2;
499         }
500         else if (!strcmp(type, "audio/x-private1-lpcm"))
501         {
502                 GST_INFO_OBJECT (self, "MIMETYPE %s (DVD Audio)",type);
503                 bypass = 6;
504         }
505         else if (!strcmp(type, "audio/x-dts") || !strcmp(type, "audio/dts"))
506         {
507                 GST_INFO_OBJECT (self, "MIMETYPE %s",type);
508                 bypass = 2;
509         } else
510         {
511                 GST_ELEMENT_ERROR (self, STREAM, TYPE_NOT_FOUND, (NULL), ("unimplemented stream type %s", type));
512                 return FALSE;
513         }
514
515         GST_INFO_OBJECT(self, "setting dvb mode 0x%02x\n", bypass);
516
517         if (ioctl(self->fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
518         {
519                 if (bypass == 2) {
520                         GST_ELEMENT_ERROR (self, STREAM, TYPE_NOT_FOUND, (NULL), ("hardware decoder can't be set to bypass mode type %s", type));
521                         return FALSE;
522                 }
523                 GST_ELEMENT_WARNING (self, STREAM, DECODE, (NULL), ("hardware decoder can't be set to bypass mode %i.", bypass));
524 //              return FALSE;
525         }
526         self->bypass = bypass;
527         return TRUE;
528 }
529
530 static void
531 queue_push(queue_entry_t **queue_base, guint8 *data, size_t len)
532 {
533         queue_entry_t *entry = malloc(sizeof(queue_entry_t)+len);
534         queue_entry_t *last = *queue_base;
535         guint8 *d = (guint8*)(entry+1);
536         memcpy(d, data, len);
537         entry->bytes = len;
538         entry->offset = 0;
539         if (!last)
540                 *queue_base = entry;
541         else {
542                 while(last->next)
543                         last = last->next;
544                 last->next = entry;
545         }
546         entry->next = NULL;
547 }
548
549 static void
550 queue_pop(queue_entry_t **queue_base)
551 {
552         queue_entry_t *base = *queue_base;
553         *queue_base = base->next;
554         free(base);
555 }
556
557 static int
558 queue_front(queue_entry_t **queue_base, guint8 **data, size_t *bytes)
559 {
560         if (!*queue_base) {
561                 *bytes = 0;
562                 *data = 0;
563         }
564         else {
565                 queue_entry_t *entry = *queue_base;
566                 *bytes = entry->bytes - entry->offset;
567                 *data = ((guint8*)(entry+1))+entry->offset;
568         }
569         return *bytes;
570 }
571
572 static gboolean
573 gst_dvbaudiosink_event (GstBaseSink * sink, GstEvent * event)
574 {
575         GstDVBAudioSink *self = GST_DVBAUDIOSINK (sink);
576         GST_DEBUG_OBJECT (self, "EVENT %s", gst_event_type_get_name(GST_EVENT_TYPE (event)));
577         int ret=TRUE;
578
579         switch (GST_EVENT_TYPE (event)) {
580         case GST_EVENT_FLUSH_START:
581                 GST_OBJECT_LOCK(self);
582                 self->no_write |= 1;
583                 GST_OBJECT_UNLOCK(self);
584                 SEND_COMMAND (self, CONTROL_STOP);
585                 break;
586         case GST_EVENT_FLUSH_STOP:
587                 ioctl(self->fd, AUDIO_CLEAR_BUFFER);
588                 GST_OBJECT_LOCK(self);
589                 self->no_write &= ~1;
590                 while(self->queue)
591                         queue_pop(&self->queue);
592                 self->timestamp = 0;
593                 GST_OBJECT_UNLOCK(self);
594                 break;
595         case GST_EVENT_EOS:
596         {
597                 struct pollfd pfd[2];
598                 int retval;
599
600                 pfd[0].fd = READ_SOCKET(self);
601                 pfd[0].events = POLLIN;
602                 pfd[1].fd = self->fd;
603                 pfd[1].events = POLLIN;
604
605                 GST_PAD_PREROLL_UNLOCK (sink->sinkpad);
606                 while (1) {
607                         retval = poll(pfd, 2, 250);
608                         if (retval < 0) {
609                                 perror("poll in EVENT_EOS");
610                                 ret=FALSE;
611                                 break;
612                         }
613
614                         if (pfd[0].revents & POLLIN) {
615                                 GST_DEBUG_OBJECT (self, "wait EOS aborted!!\n");
616                                 ret=FALSE;
617                                 break;
618                         }
619
620                         if (pfd[1].revents & POLLIN) {
621                                 GST_DEBUG_OBJECT (self, "got buffer empty from driver!\n");
622                                 break;
623                         }
624
625                         if (sink->flushing) {
626                                 GST_DEBUG_OBJECT (self, "wait EOS flushing!!\n");
627                                 ret=FALSE;
628                                 break;
629                         }
630                 }
631                 GST_PAD_PREROLL_LOCK (sink->sinkpad);
632
633                 break;
634         }
635         case GST_EVENT_NEWSEGMENT:{
636                 GstFormat fmt;
637                 gboolean update;
638                 gdouble rate, applied_rate;
639                 gint64 cur, stop, time;
640                 int skip = 0, repeat = 0, ret;
641                 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, &fmt, &cur, &stop, &time);
642                 GST_DEBUG_OBJECT (self, "GST_EVENT_NEWSEGMENT rate=%f applied_rate=%f\n", rate, applied_rate);
643
644                 int video_fd = open("/dev/dvb/adapter0/video0", O_RDWR);
645                 if (fmt == GST_FORMAT_TIME)
646                 {
647                         if ( rate > 1 )
648                                 skip = (int) rate;
649                         else if ( rate < 1 )
650                                 repeat = 1.0/rate;
651                         ret = ioctl(video_fd, VIDEO_SLOWMOTION, repeat);
652                         ret = ioctl(video_fd, VIDEO_FAST_FORWARD, skip);
653 //                      gst_segment_set_newsegment_full (&dec->segment, update, rate, applied_rate, dformat, cur, stop, time);
654                 }
655                 close(video_fd);
656                 break;
657         }
658
659         default:
660                 break;
661         }
662
663         return ret;
664 }
665
666 #define ASYNC_WRITE(data, len) do { \
667                 switch(gst_dvbaudiosink_async_write(self, data, len)) { \
668                 case -1: goto poll_error; \
669                 case -3: goto write_error; \
670                 default: break; \
671                 } \
672         } while(0)
673
674 static int
675 gst_dvbaudiosink_async_write(GstDVBAudioSink *self, unsigned char *data, unsigned int len)
676 {
677         unsigned int written=0;
678         struct pollfd pfd[2];
679
680         pfd[0].fd = READ_SOCKET(self);
681         pfd[0].events = POLLIN;
682         pfd[1].fd = self->fd;
683         pfd[1].events = POLLOUT;
684
685         do {
686 loop_start:
687                 if (self->no_write & 1) {
688                         GST_DEBUG_OBJECT (self, "skip %d bytes", len - written);
689                         break;
690                 }
691                 else if (self->no_write & 6) {
692                         // directly push to queue
693                         GST_OBJECT_LOCK(self);
694                         queue_push(&self->queue, data + written, len - written);
695                         GST_OBJECT_UNLOCK(self);
696                         GST_DEBUG_OBJECT (self, "pushed %d bytes to queue", len - written);
697                         break;
698                 }
699                 else
700                         GST_LOG_OBJECT (self, "going into poll, have %d bytes to write", len - written);
701                 if (poll(pfd, 2, -1) == -1) {
702                         if (errno == EINTR)
703                                 continue;
704                         return -1;
705                 }
706                 if (pfd[0].revents & POLLIN) {
707                         /* read all stop commands */
708                         while (TRUE) {
709                                 gchar command;
710                                 int res;
711                                 READ_COMMAND (self, command, res);
712                                 if (res < 0) {
713                                         GST_DEBUG_OBJECT (self, "no more commands");
714                                         /* no more commands */
715                                         goto loop_start;
716                                 }
717                         }
718                 }
719                 if (pfd[1].revents & POLLOUT) {
720                         size_t queue_entry_size;
721                         guint8 *queue_data;
722                         GST_OBJECT_LOCK(self);
723                         if (queue_front(&self->queue, &queue_data, &queue_entry_size)) {
724                                 int wr = write(self->fd, queue_data, queue_entry_size);
725                                 if (wr < 0) {
726                                         switch (errno) {
727                                                 case EINTR:
728                                                 case EAGAIN:
729                                                         break;
730                                                 default:
731                                                         GST_OBJECT_UNLOCK(self);
732                                                         return -3;
733                                         }
734                                 }
735                                 else if (wr == queue_entry_size) {
736                                         queue_pop(&self->queue);
737                                         GST_DEBUG_OBJECT (self, "written %d queue bytes... pop entry", wr);
738                                 }
739                                 else {
740                                         self->queue->offset += wr;
741                                         GST_DEBUG_OBJECT (self, "written %d queue bytes... update offset", wr);
742                                 }
743                                 GST_OBJECT_UNLOCK(self);
744                                 continue;
745                         }
746                         GST_OBJECT_UNLOCK(self);
747                         int wr = write(self->fd, data+written, len - written);
748                         if (wr < 0) {
749                                 switch (errno) {
750                                         case EINTR:
751                                         case EAGAIN:
752                                                 continue;
753                                         default:
754                                                 return -3;
755                                 }
756                         }
757                         written += wr;
758                 }
759         } while (written != len);
760
761         return 0;
762 }
763
764 static GstFlowReturn
765 gst_dvbaudiosink_render (GstBaseSink * sink, GstBuffer * buffer)
766 {
767         GstDVBAudioSink *self = GST_DVBAUDIOSINK (sink);
768         unsigned char pes_header[64];
769         unsigned int size = GST_BUFFER_SIZE (buffer) - self->skip;
770         unsigned char *data = GST_BUFFER_DATA (buffer) + self->skip;
771         long long timestamp = GST_BUFFER_TIMESTAMP(buffer);
772         long long duration = GST_BUFFER_DURATION(buffer);
773
774         size_t pes_header_size;
775 //      int i=0;
776
777         /* LPCM workaround.. we also need the first two byte of the lpcm header.. (substreamid and num of frames) 
778            i dont know why the mpegpsdemux strips out this two bytes... */
779         if (self->bypass == 6 && (data[0] < 0xA0 || data[0] > 0xAF)) {
780                 if (data[-2] >= 0xA0 && data[-2] <= 0xAF) {
781                         data -= 2;
782                         size += 2;
783                 }
784         }
785
786         if (duration != -1 && timestamp != -1) {
787                 if (self->timestamp == 0)
788                         self->timestamp = timestamp;
789                 else
790                         timestamp = self->timestamp;
791                 self->timestamp += duration;
792         }
793         else
794                 self->timestamp = 0;
795
796 //      for (;i < (size > 0x1F ? 0x1F : size); ++i)
797 //              printf("%02x ", data[i]);
798 //      printf("%d bytes\n", size);
799 //      printf("timestamp: %016lld, buffer timestamp: %016lld, duration %lld, diff %lld\n", timestamp, GST_BUFFER_TIMESTAMP(buffer), duration,
800 //              (timestamp > GST_BUFFER_TIMESTAMP(buffer) ? timestamp - GST_BUFFER_TIMESTAMP(buffer) : GST_BUFFER_TIMESTAMP(buffer) - timestamp) / 1000000);
801
802         if ( self->bypass == -1 ) {
803                 GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), ("hardware decoder not setup (no caps in pipeline?)"));
804                 return GST_FLOW_ERROR;
805         }
806
807         if (self->fd < 0)
808                 return GST_FLOW_OK;
809
810         pes_header[0] = 0;
811         pes_header[1] = 0;
812         pes_header[2] = 1;
813         pes_header[3] = 0xC0;
814
815         if (self->bypass == 2) {  // dts
816                 int pos=0;
817                 while((pos+3) < size) {
818                         if (!strcmp((char*)(data+pos), "\x64\x58\x20\x25")) {  // is DTS-HD ?
819                                 size = pos;
820                                 break;
821                         }
822                         ++pos;
823                 }
824         }
825
826         if (self->aac_adts_header_valid)
827                 size += 7;
828
829                 /* do we have a timestamp? */
830         if (timestamp != GST_CLOCK_TIME_NONE) {
831                 unsigned long long pts = timestamp * 9LL / 100000 /* convert ns to 90kHz */;
832
833                 pes_header[6] = 0x80;
834
835                 pes_header[9]  = 0x21 | ((pts >> 29) & 0xE);
836                 pes_header[10] = pts >> 22;
837                 pes_header[11] = 0x01 | ((pts >> 14) & 0xFE);
838                 pes_header[12] = pts >> 7;
839                 pes_header[13] = 0x01 | ((pts << 1) & 0xFE);
840
841                 if (hwtype == DM7025) {  // DM7025 needs DTS in PES header
842                         int64_t dts = pts; // what to use as DTS-PTS offset?
843                         pes_header[4] = (size + 13) >> 8;
844                         pes_header[5] = (size + 13) & 0xFF;
845                         pes_header[7] = 0xC0;
846                         pes_header[8] = 10;
847                         pes_header[9] |= 0x10;
848
849                         pes_header[14] = 0x11 | ((dts >> 29) & 0xE);
850                         pes_header[15] = dts >> 22;
851                         pes_header[16] = 0x01 | ((dts >> 14) & 0xFE);
852                         pes_header[17] = dts >> 7;
853                         pes_header[18] = 0x01 | ((dts << 1) & 0xFE);
854                         pes_header_size = 19;
855                 }
856                 else {
857                         pes_header[4] = (size + 8) >> 8;
858                         pes_header[5] = (size + 8) & 0xFF;
859                         pes_header[7] = 0x80;
860                         pes_header[8] = 5;
861                         pes_header_size = 14;
862                 }
863         }
864         else {
865                 pes_header[4] = (size + 3) >> 8;
866                 pes_header[5] = (size + 3) & 0xFF;
867                 pes_header[6] = 0x80;
868                 pes_header[7] = 0x00;
869                 pes_header[8] = 0;
870                 pes_header_size = 9;
871         }
872
873         if (self->aac_adts_header_valid) {
874                 self->aac_adts_header[3] &= 0xC0;
875                 /* frame size over last 2 bits */
876                 self->aac_adts_header[3] |= (size & 0x1800) >> 11;
877                 /* frame size continued over full byte */
878                 self->aac_adts_header[4] = (size & 0x1FF8) >> 3;
879                 /* frame size continued first 3 bits */
880                 self->aac_adts_header[5] = (size & 7) << 5;
881                 /* buffer fullness (0x7FF for VBR) over 5 last bits */
882                 self->aac_adts_header[5] |= 0x1F;
883                 /* buffer fullness (0x7FF for VBR) continued over 6 first bits + 2 zeros for
884                  * number of raw data blocks */
885                 self->aac_adts_header[6] = 0xFC;
886                 memcpy(pes_header + pes_header_size, self->aac_adts_header, 7);
887                 pes_header_size += 7;
888                 size -= 7;
889         }
890
891         ASYNC_WRITE(pes_header, pes_header_size);
892         ASYNC_WRITE(data, size);
893
894         return GST_FLOW_OK;
895 poll_error:
896         {
897                 GST_ELEMENT_ERROR (self, RESOURCE, READ, (NULL),
898                                 ("poll on file descriptor: %s.", g_strerror (errno)));
899                 GST_WARNING_OBJECT (self, "Error during poll");
900                 return GST_FLOW_ERROR;
901         }
902 write_error:
903         {
904                 GST_ELEMENT_ERROR (self, RESOURCE, READ, (NULL),
905                                 ("write on file descriptor: %s.", g_strerror (errno)));
906                 GST_WARNING_OBJECT (self, "Error during write");
907                 return GST_FLOW_ERROR;
908         }
909 }
910
911 static gboolean
912 gst_dvbaudiosink_start (GstBaseSink * basesink)
913 {
914         GstDVBAudioSink *self = GST_DVBAUDIOSINK (basesink);
915         gint control_sock[2];
916
917         GST_DEBUG_OBJECT (self, "start");
918
919         if (socketpair(PF_UNIX, SOCK_STREAM, 0, control_sock) < 0) {
920                 perror("socketpair");
921                 goto socket_pair;
922         }
923
924         READ_SOCKET (self) = control_sock[0];
925         WRITE_SOCKET (self) = control_sock[1];
926
927         fcntl (READ_SOCKET (self), F_SETFL, O_NONBLOCK);
928         fcntl (WRITE_SOCKET (self), F_SETFL, O_NONBLOCK);
929
930         return TRUE;
931         /* ERRORS */
932 socket_pair:
933         {
934                 GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ_WRITE, (NULL),
935                                 GST_ERROR_SYSTEM);
936                 return FALSE;
937         }
938 }
939
940 static gboolean
941 gst_dvbaudiosink_stop (GstBaseSink * basesink)
942 {
943         GstDVBAudioSink *self = GST_DVBAUDIOSINK (basesink);
944
945         GST_DEBUG_OBJECT (self, "stop");
946
947         if (self->fd >= 0)
948         {
949                 int video_fd = open("/dev/dvb/adapter0/video0", O_RDWR);
950
951                 ioctl(self->fd, AUDIO_STOP);
952                 ioctl(self->fd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX);
953
954                 if ( video_fd > 0 )
955                 {
956                         ioctl(video_fd, VIDEO_SLOWMOTION, 0);
957                         ioctl(video_fd, VIDEO_FAST_FORWARD, 0);
958                         close (video_fd);
959                 }
960                 close(self->fd);
961         }
962
963         while(self->queue)
964                 queue_pop(&self->queue);
965
966         close (READ_SOCKET (self));
967         close (WRITE_SOCKET (self));
968         READ_SOCKET (self) = -1;
969         WRITE_SOCKET (self) = -1;
970
971         return TRUE;
972 }
973
974 static GstStateChangeReturn
975 gst_dvbaudiosink_change_state (GstElement * element, GstStateChange transition)
976 {
977         GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
978         GstDVBAudioSink *self = GST_DVBAUDIOSINK (element);
979
980         switch (transition) {
981         case GST_STATE_CHANGE_NULL_TO_READY:
982                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_NULL_TO_READY");
983                 break;
984         case GST_STATE_CHANGE_READY_TO_PAUSED:
985                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_READY_TO_PAUSED");
986                 GST_OBJECT_LOCK(self);
987                 self->no_write |= 4;
988                 GST_OBJECT_UNLOCK(self);
989
990                 self->fd = open("/dev/dvb/adapter0/audio0", O_RDWR|O_NONBLOCK);
991 //              self->fd = open("/dump.pes", O_RDWR|O_CREAT, 0555);
992
993                 if (self->fd) {
994                         ioctl(self->fd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY);
995                         ioctl(self->fd, AUDIO_PLAY);
996                 }
997
998                 ioctl(self->fd, AUDIO_PAUSE);
999                 break;
1000         case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1001                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_PAUSED_TO_PLAYING");
1002                 ioctl(self->fd, AUDIO_CONTINUE);
1003                 GST_OBJECT_LOCK(self);
1004                 self->no_write &= ~4;
1005                 GST_OBJECT_UNLOCK(self);
1006                 break;
1007         default:
1008                 break;
1009         }
1010
1011         ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1012
1013         switch (transition) {
1014         case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1015                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_PLAYING_TO_PAUSED");
1016                 GST_OBJECT_LOCK(self);
1017                 self->no_write |= 4;
1018                 GST_OBJECT_UNLOCK(self);
1019                 ioctl(self->fd, AUDIO_PAUSE);
1020                 SEND_COMMAND (self, CONTROL_STOP);
1021                 break;
1022         case GST_STATE_CHANGE_PAUSED_TO_READY:
1023                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_PAUSED_TO_READY");
1024                 break;
1025         case GST_STATE_CHANGE_READY_TO_NULL:
1026                 GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_READY_TO_NULL");
1027                 break;
1028         default:
1029                 break;
1030         }
1031
1032         return ret;
1033 }
1034
1035 /* entry point to initialize the plug-in
1036  * initialize the plug-in itself
1037  * register the element factories and pad templates
1038  * register the features
1039  *
1040  * exchange the string 'plugin' with your elemnt name
1041  */
1042 static gboolean
1043 plugin_init (GstPlugin *plugin)
1044 {
1045         return gst_element_register (plugin, "dvbaudiosink",
1046                                                  GST_RANK_PRIMARY,
1047                                                  GST_TYPE_DVBAUDIOSINK);
1048 }
1049
1050 /* this is the structure that gstreamer looks for to register plugins
1051  *
1052  * exchange the strings 'plugin' and 'Template plugin' with you plugin name and
1053  * description
1054  */
1055 GST_PLUGIN_DEFINE (
1056         GST_VERSION_MAJOR,
1057         GST_VERSION_MINOR,
1058         "dvb_audio_out",
1059         "DVB Audio Output",
1060         plugin_init,
1061         VERSION,
1062         "LGPL",
1063         "GStreamer",
1064         "http://gstreamer.net/"
1065 )