implement signal-lost, implement generation of adts silence frames / gap events on...
[gst-plugin-dreamsource.git] / src / gstdreamaudiosource.c
1 /*
2  * GStreamer dreamaudiosource
3  * Copyright 2014-2015 Andreas Frisch <fraxinas@opendreambox.org>
4  *
5  * This program is licensed under the Creative Commons
6  * Attribution-NonCommercial-ShareAlike 3.0 Unported
7  * License. To view a copy of this license, visit
8  * http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
9  * Creative Commons,559 Nathan Abbott Way,Stanford,California 94305,USA.
10  *
11  * Alternatively, this program may be distributed and executed on
12  * hardware which is licensed by Dream Property GmbH.
13  *
14  * This program is NOT free software. It is open source, you are allowed
15  * to modify it (if you keep the license), but it may not be commercially
16  * distributed other than under the conditions noted above.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <gst/gst.h>
24 #include "gstdreamaudiosource.h"
25
26 GST_DEBUG_CATEGORY_STATIC (dreamaudiosource_debug);
27 #define GST_CAT_DEFAULT dreamaudiosource_debug
28
29 GType gst_dreamaudiosource_input_mode_get_type (void)
30 {
31         static volatile gsize input_mode_type = 0;
32         static const GEnumValue input_mode[] = {
33                 {GST_DREAMAUDIOSOURCE_INPUT_MODE_LIVE, "GST_DREAMAUDIOSOURCE_INPUT_MODE_LIVE", "live"},
34                 {GST_DREAMAUDIOSOURCE_INPUT_MODE_HDMI_IN, "GST_DREAMAUDIOSOURCE_INPUT_MODE_HDMI_IN", "hdmi_in"},
35                 {GST_DREAMAUDIOSOURCE_INPUT_MODE_BACKGROUND, "GST_DREAMAUDIOSOURCE_INPUT_MODE_BACKGROUND", "background"},
36                 {0, NULL, NULL},
37         };
38
39         if (g_once_init_enter (&input_mode_type)) {
40                 GType tmp = g_enum_register_static ("GstDreamAudioSourceInputMode", input_mode);
41                 g_once_init_leave (&input_mode_type, tmp);
42         }
43         return (GType) input_mode_type;
44 }
45
46 enum
47 {
48         SIGNAL_GET_DTS_OFFSET,
49         SIGNAL_LOST,
50         LAST_SIGNAL
51 };
52 enum
53 {
54         ARG_0,
55         ARG_BITRATE,
56         ARG_INPUT_MODE
57 };
58
59 static guint gst_dreamaudiosource_signals[LAST_SIGNAL] = { 0 };
60
61 #define DEFAULT_BITRATE     128
62 #define DEFAULT_SAMPLERATE  48000
63 #define DEFAULT_INPUT_MODE  GST_DREAMAUDIOSOURCE_INPUT_MODE_LIVE
64 #define DEFAULT_BUFFER_SIZE 26
65
66 static GstStaticPadTemplate srctemplate =
67     GST_STATIC_PAD_TEMPLATE ("src",
68         GST_PAD_SRC,
69         GST_PAD_ALWAYS,
70         GST_STATIC_CAPS ("audio/mpeg, "
71         "mpegversion = 4,"
72         "stream-format = (string) adts,"
73         "rate = 48000")
74     );
75
76 #define gst_dreamaudiosource_parent_class parent_class
77 G_DEFINE_TYPE (GstDreamAudioSource, gst_dreamaudiosource, GST_TYPE_PUSH_SRC);
78
79 static GstCaps *gst_dreamaudiosource_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
80 static gboolean gst_dreamaudiosource_unlock (GstBaseSrc * bsrc);
81 static gboolean gst_dreamaudiosource_unlock_stop (GstBaseSrc * bsrc);
82 static gboolean gst_dreamaudiosource_query (GstBaseSrc * bsrc, GstQuery * query);
83
84 static void gst_dreamaudiosource_dispose (GObject * gobject);
85 static GstFlowReturn gst_dreamaudiosource_create (GstPushSrc * psrc, GstBuffer ** outbuf);
86
87 static void gst_dreamaudiosource_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
88 static void gst_dreamaudiosource_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
89
90 static GstStateChangeReturn gst_dreamaudiosource_change_state (GstElement * element, GstStateChange transition);
91 static gint64 gst_dreamaudiosource_get_dts_offset (GstDreamAudioSource *self);
92
93 static gboolean gst_dreamaudiosource_encoder_init (GstDreamAudioSource * self);
94 static void gst_dreamaudiosource_encoder_release (GstDreamAudioSource * self);
95
96 static void gst_dreamaudiosource_read_thread_func (GstDreamAudioSource * self);
97
98 #ifdef PROVIDE_CLOCK
99 static GstClock *gst_dreamaudiosource_provide_clock (GstElement * elem);
100 // static GstClockTime gst_dreamaudiosource_get_encoder_time_ (GstClock * clock, GstBaseSrc * bsrc);
101 #endif
102
103 static void _gst_dreamaudiosource_emit_signal_lost (GstDreamAudioSource * self);
104
105 static void
106 gst_dreamaudiosource_class_init (GstDreamAudioSourceClass * klass)
107 {
108         GObjectClass *gobject_class;
109         GstElementClass *gstelement_class;
110         GstBaseSrcClass *gstbasesrc_class;
111         GstPushSrcClass *gstpush_src_class;
112
113         gobject_class = (GObjectClass *) klass;
114         gstelement_class = (GstElementClass *) klass;
115         gstbasesrc_class = (GstBaseSrcClass *) klass;
116         gstpush_src_class = (GstPushSrcClass *) klass;
117
118         gobject_class->set_property = gst_dreamaudiosource_set_property;
119         gobject_class->get_property = gst_dreamaudiosource_get_property;
120         gobject_class->dispose = gst_dreamaudiosource_dispose;
121
122         gst_element_class_add_pad_template (gstelement_class,
123                                             gst_static_pad_template_get (&srctemplate));
124
125         gst_element_class_set_static_metadata (gstelement_class,
126             "Dream Audio source", "Source/Audio",
127             "Provide an audio elementary stream from Dreambox encoder device",
128             "Andreas Frisch <fraxinas@opendreambox.org>");
129
130         gstelement_class->change_state = gst_dreamaudiosource_change_state;
131
132         gstbasesrc_class->get_caps = gst_dreamaudiosource_getcaps;
133         gstbasesrc_class->unlock = gst_dreamaudiosource_unlock;
134         gstbasesrc_class->unlock_stop = gst_dreamaudiosource_unlock_stop;
135         gstbasesrc_class->query = gst_dreamaudiosource_query;
136
137         gstpush_src_class->create = gst_dreamaudiosource_create;
138
139 #ifdef PROVIDE_CLOCK
140         gstelement_class->provide_clock = GST_DEBUG_FUNCPTR (gst_dreamaudiosource_provide_clock);
141 //      g_type_class_ref (GST_TYPE_SYSTEM_CLOCK);
142 #endif
143
144         g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
145           g_param_spec_int ("bitrate", "Bitrate (kb/s)",
146             "Bitrate in kbit/sec", 16, 320, DEFAULT_BITRATE,
147             G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
148
149         g_object_class_install_property (gobject_class, ARG_INPUT_MODE,
150           g_param_spec_enum ("input-mode", "Input Mode",
151             "Select the input source of the audio stream",
152             GST_TYPE_DREAMAUDIOSOURCE_INPUT_MODE, DEFAULT_INPUT_MODE,
153             G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
154
155         gst_dreamaudiosource_signals[SIGNAL_GET_DTS_OFFSET] =
156                 g_signal_new ("get-dts-offset",
157                 G_TYPE_FROM_CLASS (klass),
158                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
159                 G_STRUCT_OFFSET (GstDreamAudioSourceClass, get_dts_offset),
160                 NULL, NULL, gst_dreamsource_marshal_INT64__VOID, G_TYPE_INT64, 0);
161
162         gst_dreamaudiosource_signals[SIGNAL_LOST] =
163                 g_signal_new("signal-lost", G_TYPE_FROM_CLASS(klass),
164                         G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GstDreamAudioSourceClass, signal_lost),
165                         NULL, NULL, g_cclosure_marshal_VOID__VOID,
166                         G_TYPE_NONE, 0);
167
168         klass->get_dts_offset = gst_dreamaudiosource_get_dts_offset;
169 }
170
171 static gint64
172 gst_dreamaudiosource_get_dts_offset (GstDreamAudioSource *self)
173 {
174         GST_DEBUG_OBJECT (self, "gst_dreamaudiosource_get_dts_offset %" GST_TIME_FORMAT"", GST_TIME_ARGS (self->dts_offset) );
175         return self->dts_offset;
176 }
177
178 static void _gst_dreamaudiosource_emit_signal_lost (GstDreamAudioSource *self)
179 {
180         if (!GST_IS_DREAMAUDIOSOURCE (self))
181                 return;
182         GST_INFO_OBJECT (self, "emit signal-lost");
183         g_signal_emit (self, gst_dreamaudiosource_signals[SIGNAL_LOST], 0);
184 }
185
186 static void gst_dreamaudiosource_set_bitrate (GstDreamAudioSource * self, uint32_t bitrate)
187 {
188         g_mutex_lock (&self->mutex);
189         uint32_t abr = bitrate*1000;
190         if (!self->encoder || !self->encoder->fd)
191         {
192                 self->audio_info.bitrate = bitrate;
193                 g_mutex_unlock (&self->mutex);
194                 return;
195         }
196
197         int ret = ioctl(self->encoder->fd, AENC_SET_BITRATE, &abr);
198         if (ret != 0)
199         {
200                 GST_WARNING_OBJECT (self, "can't set audio bitrate to %i bytes/s!", abr);
201                 g_mutex_unlock (&self->mutex);
202                 return;
203         }
204         GST_INFO_OBJECT (self, "set audio bitrate to %i kBytes/s", bitrate);
205         self->audio_info.bitrate = bitrate;
206         g_mutex_unlock (&self->mutex);
207 }
208
209 void gst_dreamaudiosource_set_input_mode (GstDreamAudioSource *self, GstDreamAudioSourceInputMode mode)
210 {
211         g_return_if_fail (GST_IS_DREAMAUDIOSOURCE (self));
212         GEnumValue *val = g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (GST_TYPE_DREAMAUDIOSOURCE_INPUT_MODE)), mode);
213         if (!val)
214         {
215                 GST_ERROR_OBJECT (self, "no such input_mode %i!", mode);
216                 goto out;
217         }
218         const gchar *value_nick = val->value_nick;
219
220         g_mutex_lock (&self->mutex);
221         if (!self->encoder || !self->encoder->fd)
222         {
223                 self->input_mode = mode;
224                 goto out;
225         }
226         int int_mode = mode;
227         int ret = ioctl(self->encoder->fd, AENC_SET_SOURCE, &int_mode);
228         if (ret != 0)
229         {
230                 GST_WARNING_OBJECT (self, "can't set input mode to %s (%i) error: %s", value_nick, mode, strerror(errno));
231                 goto out;
232         }
233         GST_INFO_OBJECT (self, "successfully set input mode to %s (%i)", value_nick, mode);
234         self->input_mode = mode;
235 out:
236         g_mutex_unlock (&self->mutex);
237         return;
238 }
239
240 GstDreamAudioSourceInputMode gst_dreamaudiosource_get_input_mode (GstDreamAudioSource *self)
241 {
242         GstDreamAudioSourceInputMode result;
243         g_return_val_if_fail (GST_IS_DREAMAUDIOSOURCE (self), -1);
244         GST_OBJECT_LOCK (self);
245         result =self->input_mode;
246         GST_OBJECT_UNLOCK (self);
247         return result;
248 }
249
250 gboolean
251 gst_dreamaudiosource_plugin_init (GstPlugin *plugin)
252 {
253         GST_DEBUG_CATEGORY_INIT (dreamaudiosource_debug, "dreamaudiosource", 0, "dreamaudiosource");
254         return gst_element_register (plugin, "dreamaudiosource", GST_RANK_PRIMARY, GST_TYPE_DREAMAUDIOSOURCE);
255 }
256
257 static void
258 gst_dreamaudiosource_init (GstDreamAudioSource * self)
259 {
260         self->encoder = NULL;
261         self->descriptors_available = 0;
262         self->input_mode = DEFAULT_INPUT_MODE;
263
264         self->buffer_size = DEFAULT_BUFFER_SIZE;
265         g_queue_init (&self->current_frames);
266         self->readthread = NULL;
267
268         g_mutex_init (&self->mutex);
269         g_cond_init (&self->cond);
270         READ_SOCKET (self) = -1;
271         WRITE_SOCKET (self) = -1;
272
273         gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
274         gst_base_src_set_live (GST_BASE_SRC (self), TRUE);
275
276         self->encoder = NULL;
277         self->encoder_clock = NULL;
278         self->last_ts = GST_CLOCK_TIME_NONE;
279
280 #ifdef dump
281         self->dumpfd = open("/media/hdd/movie/dreamaudiosource.dump", O_WRONLY | O_CREAT | O_TRUNC);
282         GST_DEBUG_OBJECT (self, "dumpfd = %i (%s)", self->dumpfd, (self->dumpfd > 0) ? "OK" : strerror(errno));
283 #endif
284 }
285
286 static gboolean gst_dreamaudiosource_encoder_init (GstDreamAudioSource * self)
287 {
288         GST_LOG_OBJECT (self, "initializating encoder...");
289         self->encoder = malloc(sizeof(EncoderInfo));
290
291         if (!self->encoder) {
292                 GST_ERROR_OBJECT (self,"out of space");
293                 return FALSE;
294         }
295
296         char fn_buf[32];
297         sprintf(fn_buf, "/dev/aenc%d", 0);
298         self->encoder->fd = open(fn_buf, O_RDWR | O_SYNC);
299         if (self->encoder->fd <= 0) {
300                 GST_ERROR_OBJECT (self,"cannot open device %s (%s)", fn_buf, strerror(errno));
301                 free(self->encoder);
302                 self->encoder = NULL;
303                 return FALSE;
304         }
305
306         self->encoder->buffer = malloc(ABUFSIZE);
307         if (!self->encoder->buffer) {
308                 GST_ERROR_OBJECT(self,"cannot alloc buffer");
309                 return FALSE;
310         }
311
312         self->encoder->cdb = (unsigned char *)mmap (0, AMMAPSIZE, PROT_READ, MAP_PRIVATE, self->encoder->fd, 0);
313
314         if (!self->encoder->cdb || self->encoder->cdb == MAP_FAILED) {
315                 GST_ERROR_OBJECT(self, "cannot alloc buffer: %s (%i)", strerror(errno), errno);
316                 self->encoder->cdb = NULL;
317                 return FALSE;
318         }
319
320         int control_sock[2];
321         if (socketpair (PF_UNIX, SOCK_STREAM, 0, control_sock) < 0)
322         {
323                 GST_ERROR_OBJECT(self, "cannot create control sockets: %s (%i)", strerror(errno), errno);
324                 return FALSE;
325         }
326         READ_SOCKET (self) = control_sock[0];
327         WRITE_SOCKET (self) = control_sock[1];
328         fcntl (READ_SOCKET (self), F_SETFL, O_NONBLOCK);
329         fcntl (WRITE_SOCKET (self), F_SETFL, O_NONBLOCK);
330
331         self->memtrack_list = NULL;
332         self->encoder->used_range_min = UINT32_MAX;
333         self->encoder->used_range_max = 0;
334
335         self->audio_info.samplerate = DEFAULT_SAMPLERATE;
336         gst_dreamaudiosource_set_bitrate (self, self->audio_info.bitrate);
337         gst_dreamaudiosource_set_input_mode (self, self->input_mode);
338
339 #ifdef PROVIDE_CLOCK
340         self->encoder_clock = gst_dreamsource_clock_new ("GstDreamAudioSourceClock", self->encoder->fd);
341         GST_DEBUG_OBJECT (self, "self->encoder_clock = %" GST_PTR_FORMAT, self->encoder_clock);
342         GST_OBJECT_FLAG_SET (self, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
343 #endif
344
345         GST_LOG_OBJECT (self, "encoder %s successfully initialized", fn_buf);
346         return TRUE;
347 }
348
349 static void gst_dreamaudiosource_encoder_release (GstDreamAudioSource * self)
350 {
351         GST_LOG_OBJECT (self, "releasing encoder...");
352         if (self->encoder) {
353                 if (self->encoder->buffer)
354                         free(self->encoder->buffer);
355                 if (self->encoder->cdb)
356                         munmap(self->encoder->cdb, AMMAPSIZE);
357                 if (self->encoder->fd)
358                         close(self->encoder->fd);
359                 free(self->encoder);
360         }
361         self->encoder = NULL;
362         close (READ_SOCKET (self));
363         close (WRITE_SOCKET (self));
364         READ_SOCKET (self) = -1;
365         WRITE_SOCKET (self) = -1;
366         if (self->encoder_clock) {
367                 gst_object_unref (self->encoder_clock);
368                 self->encoder_clock = NULL;
369         }
370 }
371
372 static void
373 gst_dreamaudiosource_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
374 {
375         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (object);
376
377         switch (prop_id) {
378                 case ARG_BITRATE:
379                         gst_dreamaudiosource_set_bitrate(self, g_value_get_int (value));
380                         break;
381                 case ARG_INPUT_MODE:
382                              gst_dreamaudiosource_set_input_mode (self, g_value_get_enum (value));
383                         break;
384                 default:
385                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
386                         break;
387         }
388 }
389
390 static void
391 gst_dreamaudiosource_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
392 {
393         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (object);
394
395         switch (prop_id) {
396                 case ARG_BITRATE:
397                         g_value_set_int (value, self->audio_info.bitrate);
398                         break;
399                 case ARG_INPUT_MODE:
400                         g_value_set_enum (value, gst_dreamaudiosource_get_input_mode (self));
401                         break;
402                 default:
403                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
404                         break;
405         }
406 }
407
408 static GstCaps *
409 gst_dreamaudiosource_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
410 {
411         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (bsrc);
412         GstPadTemplate *pad_template;
413         GstCaps *caps;
414
415         pad_template = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS(self), "src");
416         g_return_val_if_fail (pad_template != NULL, NULL);
417
418         if (self->encoder == NULL) {
419                 GST_DEBUG_OBJECT (self, "encoder not opened -> use template caps");
420                 caps = gst_pad_template_get_caps (pad_template);
421         }
422         else
423         {
424                 caps = gst_caps_make_writable(gst_pad_template_get_caps (pad_template));
425         }
426
427         GST_DEBUG_OBJECT (self, "return caps %" GST_PTR_FORMAT, caps);
428         return caps;
429 }
430
431 static gboolean gst_dreamaudiosource_query (GstBaseSrc * bsrc, GstQuery * query)
432 {
433         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (bsrc);
434         gboolean ret = TRUE;
435         switch (GST_QUERY_TYPE (query)) {
436                 case GST_QUERY_LATENCY:{
437                         if (self->audio_info.samplerate) {
438                                 GstClockTime min, max;
439
440                                 g_mutex_lock (&self->mutex);
441                                 min = gst_util_uint64_scale_ceil (GST_SECOND, 1000, self->audio_info.samplerate);
442                                 g_mutex_unlock (&self->mutex);
443
444                                 max = self->buffer_size * min;
445
446                                 gst_query_set_latency (query, TRUE, min, max);
447                                 GST_DEBUG_OBJECT (bsrc, "set LATENCY QUERY %" GST_PTR_FORMAT, query);
448                                 ret = TRUE;
449                         } else {
450                                 ret = FALSE;
451                         }
452                         break;
453                 }
454                 default:
455                         ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
456                         break;
457         }
458         return ret;
459 }
460
461 static gboolean gst_dreamaudiosource_unlock (GstBaseSrc * bsrc)
462 {
463         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (bsrc);
464         GST_DEBUG_OBJECT (self, "stop creating buffers");
465         g_mutex_lock (&self->mutex);
466         self->flushing = TRUE;
467         GST_DEBUG_OBJECT (self, "set flushing TRUE");
468         g_cond_signal (&self->cond);
469         g_mutex_unlock (&self->mutex);
470         return TRUE;
471 }
472
473 static gboolean gst_dreamaudiosource_unlock_stop (GstBaseSrc * bsrc)
474 {
475         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (bsrc);
476         GST_DEBUG_OBJECT (self, "stop flushing...");
477         g_mutex_lock (&self->mutex);
478         self->flushing = FALSE;
479         g_queue_foreach (&self->current_frames, (GFunc) gst_buffer_unref, NULL);
480         g_queue_clear (&self->current_frames);
481         g_mutex_unlock (&self->mutex);
482         return TRUE;
483 }
484
485 static void gst_dreamaudiosource_free_buffer (struct _buffer_memorytracker * memtrack)
486 {
487         GstDreamAudioSource * self = memtrack->self;
488         GST_OBJECT_LOCK(self);
489         GST_TRACE_OBJECT (self, "freeing %" GST_PTR_FORMAT " uiOffset=%i uiLength=%i used_range_min=%i", memtrack->buffer, memtrack->uiOffset, memtrack->uiLength, self->encoder->used_range_min);
490         GList *list = g_list_first (self->memtrack_list);
491         guint abs_minimum = UINT32_MAX;
492         guint abs_maximum = 0;
493         struct _buffer_memorytracker * mt;
494         int count = 0;
495         self->memtrack_list = g_list_remove(list, memtrack);
496         free(memtrack);
497         if (self->encoder)
498         {
499                 list = g_list_first (self->memtrack_list);
500                 while (list) {
501                         mt = list->data;
502                         if (abs_minimum > 0 && mt->uiOffset < abs_minimum)
503                                 abs_minimum = mt->uiOffset;
504                         if (mt->uiOffset+mt->uiLength > abs_maximum)
505                                 abs_maximum = mt->uiOffset+mt->uiLength;
506                         count++;
507                         list = g_list_next (list);
508                 }
509                 GST_TRACE_OBJECT (self, "new abs_minimum=%i, abs_maximum=%i", abs_minimum, abs_maximum);
510                 self->encoder->used_range_min = abs_minimum;
511                 self->encoder->used_range_max = abs_maximum;
512         }
513         GST_OBJECT_UNLOCK(self);
514 }
515
516 static void gst_dreamaudiosource_read_thread_func (GstDreamAudioSource * self)
517 {
518         EncoderInfo *enc = self->encoder;
519         GstDreamSourceReadthreadState state = READTHREADSTATE_NONE;
520         GstBuffer *readbuf = NULL;
521
522         if (!enc) {
523                 GST_WARNING_OBJECT (self, "encoder device not opened!");
524                 return;
525         }
526
527         GST_DEBUG_OBJECT (self, "enter read thread");
528
529         GstMessage *message;
530         GValue val = { 0 };
531
532         message = gst_message_new_stream_status (GST_OBJECT_CAST (self), GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (GST_OBJECT_PARENT(self)));
533         g_value_init (&val, GST_TYPE_G_THREAD);
534         g_value_set_boxed (&val, self->readthread);
535         gst_message_set_stream_status_object (message, &val);
536         g_value_unset (&val);
537         GST_DEBUG_OBJECT (self, "posting ENTER stream status");
538         gst_element_post_message (GST_ELEMENT_CAST (self), message);
539         GstClockTime clock_time, base_time;
540         gboolean discont = TRUE;
541         int timeout;
542
543         while (TRUE) {
544                 {
545                         if (state == READTHREADSTATE_STOP)
546                                 goto stop_running;
547
548                         struct pollfd rfd[2];
549                         int nfds;
550
551                         rfd[0].fd = READ_SOCKET (self);
552                         rfd[0].events = POLLIN | POLLERR | POLLHUP | POLLPRI;
553                         rfd[1].revents = 0;
554                         rfd[1].events = POLLIN;
555                         nfds = 1;
556                         timeout = 0;
557
558                         if (state <= READTRREADSTATE_PAUSED)
559                                 timeout = 200;
560                         else if (state == READTRREADSTATE_RUNNING && self->descriptors_available == 0)
561                         {
562                                 rfd[1].fd = enc->fd;
563                                 self->descriptors_count = 0;
564                                 timeout = 200;
565                                 nfds = 2;
566                         }
567
568                         int ret = poll(rfd, nfds, timeout);
569
570                         if (G_UNLIKELY (ret == -1))
571                         {
572                                 GST_ERROR_OBJECT (self, "SELECT ERROR!");
573                                 goto stop_running;
574                         }
575                         else if ( ret == 0 && self->descriptors_available == 0 )
576                         {
577                                 g_mutex_lock (&self->mutex);
578                                 gst_clock_get_internal_time(self->encoder_clock);
579                                 if (self->flushing)
580                                 {
581                                         GST_DEBUG_OBJECT (self, "FLUSHING!");
582                                         g_cond_signal (&self->cond);
583                                         g_mutex_unlock (&self->mutex);
584                                         continue;
585                                 }
586                                 g_mutex_unlock (&self->mutex);
587                                 GST_DEBUG_OBJECT (self, "SELECT TIMEOUT");
588                                 //!!! TODO generate valid dummy payload
589                                 discont = TRUE;
590                                 if (self->dts_offset != GST_CLOCK_TIME_NONE)
591                                         readbuf = gst_buffer_new();
592                         }
593                         else if ( rfd[0].revents )
594                         {
595                                 char command;
596                                 READ_COMMAND (self, command, ret);
597                                 switch (command) {
598                                         case CONTROL_STOP:
599                                                 GST_DEBUG_OBJECT (self, "CONTROL_STOP!");
600                                                 state = READTHREADSTATE_STOP;
601                                                 break;
602                                         case CONTROL_PAUSE:
603                                                 GST_DEBUG_OBJECT (self, "CONTROL_PAUSE!");
604                                                 state = READTRREADSTATE_PAUSED;
605                                                 break;
606                                         case CONTROL_RUN:
607                                                 GST_DEBUG_OBJECT (self, "CONTROL_RUN");
608                                                 state = READTRREADSTATE_RUNNING;
609                                                 break;
610                                         default:
611                                                 GST_ERROR_OBJECT (self, "illegal control socket command %c received!", command);
612                                 }
613                                 continue;
614                         }
615                         else if ( G_LIKELY(rfd[1].revents & POLLIN) )
616                         {
617                                 clock_time = gst_clock_get_internal_time (self->encoder_clock);
618                                 base_time = gst_element_get_base_time(GST_ELEMENT(self));
619                                 int rlen = read(enc->fd, enc->buffer, ABUFSIZE);
620                                 if (rlen <= 0 || rlen % ABDSIZE ) {
621                                         if ( errno == 512 )
622                                                 goto stop_running;
623                                         GST_WARNING_OBJECT (self, "read error %s (%i)", strerror(errno), errno);
624                                         goto stop_running;
625                                 }
626                                 self->descriptors_available = rlen / ABDSIZE;
627                                 GST_LOG_OBJECT (self, "encoder buffer was empty, %d descriptors available", self->descriptors_available);
628                         }
629                 }
630
631                 while (self->descriptors_count < self->descriptors_available)
632                 {
633                         GstClockTime encoder_pts = GST_CLOCK_TIME_NONE;
634                         GstClockTime result_pts = GST_CLOCK_TIME_NONE;
635
636                         off_t offset = self->descriptors_count * ABDSIZE;
637                         AudioBufferDescriptor *desc = (AudioBufferDescriptor*)(&enc->buffer[offset]);
638
639                         uint32_t f = desc->stCommon.uiFlags;
640
641                         if (G_UNLIKELY (f & CDB_FLAG_METADATA))
642                         {
643                                 GST_LOG_OBJECT (self, "CDB_FLAG_METADATA... skip outdated packet");
644                                 self->descriptors_count = self->descriptors_available;
645                                 continue;
646                         }
647
648                         GST_LOG_OBJECT (self, "descriptors_count=%d, descriptors_available=%d\tuiOffset=%d, uiLength=%d", self->descriptors_count, self->descriptors_available, desc->stCommon.uiOffset, desc->stCommon.uiLength);
649
650                         if (self->encoder->used_range_min == UINT32_MAX)
651                                 self->encoder->used_range_min = desc->stCommon.uiOffset;
652
653                         if (self->encoder->used_range_max == 0)
654                                 self->encoder->used_range_max = desc->stCommon.uiOffset+desc->stCommon.uiLength;
655
656 //                      if (desc->stCommon.uiOffset < self->encoder->used_range_max && desc->stCommon.uiOffset+desc->stCommon.uiLength > self->encoder->used_range_min)
657 //                      {
658 //                              GST_WARNING_OBJECT (self, "encoder overwrites buffer memory that is still in use! uiOffset=%i uiLength=%i used_range_min=%i used_range_max=%i", desc->stCommon.uiOffset, desc->stCommon.uiLength, self->encoder->used_range_min, self->encoder->used_range_max);
659 //                              self->descriptors_count++;
660 //                              readbuf = gst_buffer_new();
661 //                              continue;
662 //                      }
663
664                         // uiDTS since kernel driver booted
665                         if (f & CDB_FLAG_PTS_VALID)
666                         {
667                                 encoder_pts = MPEGTIME_TO_GSTTIME(desc->stCommon.uiPTS);
668                                 GST_LOG_OBJECT (self, "f & CDB_FLAG_PTS_VALID && encoder's uiPTS=%" GST_TIME_FORMAT"", GST_TIME_ARGS(encoder_pts));
669
670                                 g_mutex_lock (&self->mutex);
671                                 if (G_UNLIKELY (self->dts_offset == GST_CLOCK_TIME_NONE))
672                                 {
673 #if 0 // set to 0 to always wait for audio to become valid, don't rely on video pts
674                                         if (self->dreamvideosrc)
675                                         {
676                                                 guint64 videosource_dts_offset;
677                                                 g_signal_emit_by_name(self->dreamvideosrc, "get-dts-offset", &videosource_dts_offset);
678                                                 if (videosource_dts_offset != GST_CLOCK_TIME_NONE)
679                                                 {
680                                                         GST_DEBUG_OBJECT (self, "use DREAMVIDEOSOURCE's dts_offset=%" GST_TIME_FORMAT "", GST_TIME_ARGS (videosource_dts_offset) );
681                                                         self->dts_offset = videosource_dts_offset;
682                                                 }
683                                         }
684 #endif
685                                         if (self->dts_offset == GST_CLOCK_TIME_NONE)
686                                         {
687                                                 self->dts_offset = encoder_pts;
688                                                 GST_DEBUG_OBJECT (self, "use mpeg stream pts as dts_offset=%" GST_TIME_FORMAT" (%lld)", GST_TIME_ARGS (self->dts_offset), desc->stCommon.uiPTS);
689                                         }
690                                 }
691                                 g_mutex_unlock (&self->mutex);
692                         }
693
694                         if (G_UNLIKELY (self->dts_offset == GST_CLOCK_TIME_NONE))
695                         {
696                                 GST_DEBUG_OBJECT (self, "dts_offset is still unknown, skipping frame...");
697                                 self->descriptors_count++;
698                                 break;
699                         }
700
701                         if (encoder_pts != GST_CLOCK_TIME_NONE)
702                         {
703                                 GstClockTime pts_clock_time = encoder_pts - self->dts_offset;
704                                 GstClockTime internal, external;
705                                 GstClockTime rate_n, rate_d;
706                                 GstClockTimeDiff diff;
707
708                                 gst_clock_get_calibration (self->encoder_clock, &internal, &external, &rate_n, &rate_d);
709
710                                 if (internal > pts_clock_time) {
711                                         diff = internal - pts_clock_time;
712                                         diff = gst_util_uint64_scale (diff, rate_n, rate_d);
713                                         pts_clock_time = external - diff;
714                                 } else {
715                                         diff = pts_clock_time - internal;
716                                         diff = gst_util_uint64_scale (diff, rate_n, rate_d);
717                                         pts_clock_time = external + diff;
718                                 }
719
720                                 if ( pts_clock_time >= base_time )
721                                         result_pts = pts_clock_time - base_time;
722                                 else
723                                         GST_DEBUG_OBJECT (self, "pts_clock_time < base_time, skipping frame...");
724
725 #define extra_timestamp_debug
726 #ifdef extra_timestamp_debug
727                                 GstClockTime my_int_time = gst_clock_get_internal_time(self->encoder_clock);
728                                 GstClockTime pipeline_int_time = GST_CLOCK_TIME_NONE;
729                                 GstClock *elemclk = gst_element_get_clock (GST_ELEMENT (self));
730                                 if (elemclk)
731                                 {
732                                         pipeline_int_time = gst_clock_get_internal_time(elemclk);
733                                         gst_object_unref (elemclk);
734                                 }
735
736                                 GST_LOG_OBJECT (self, "post-calibration\n"
737                                 "  %" GST_TIME_FORMAT " =base_time       %" GST_TIME_FORMAT " =clock_time\n"
738                                 "  %" GST_TIME_FORMAT " =encoder_pts     %" GST_TIME_FORMAT " =pts_clock_time     %" GST_TIME_FORMAT " =result_pts\n"
739                                 "  %" GST_TIME_FORMAT " =internal        %" GST_TIME_FORMAT " =external           %" GST_TIME_FORMAT " =diff                %" PRId64 "/%" PRId64 " =rate\n"
740                                 "  %" GST_TIME_FORMAT " =my_int_time     %" GST_TIME_FORMAT " =pipeline_int_time"
741                                 ,
742                                 GST_TIME_ARGS (base_time), GST_TIME_ARGS (clock_time),
743                                 GST_TIME_ARGS (encoder_pts), GST_TIME_ARGS (pts_clock_time), GST_TIME_ARGS (result_pts),
744                                 GST_TIME_ARGS (internal), GST_TIME_ARGS (external), GST_TIME_ARGS (diff), rate_n, rate_d,
745                                 GST_TIME_ARGS (my_int_time), GST_TIME_ARGS (pipeline_int_time)
746                                 );
747 #endif
748                         }
749
750                         struct _buffer_memorytracker * memtrack = malloc(sizeof(struct _buffer_memorytracker));
751                         if (G_UNLIKELY (!memtrack))
752                         {
753                                 GST_ERROR_OBJECT (self, "can't allocate buffer_memorytracker");
754                                 goto stop_running;
755                         }
756
757                         if (readbuf)
758                         {
759                                 GST_INFO_OBJECT (self, "LAST BUFFER WAS INCOMPLETE... appending");
760                                 GstBuffer *append_buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, enc->cdb, AMMAPSIZE, desc->stCommon.uiOffset, desc->stCommon.uiLength, memtrack, (GDestroyNotify) gst_dreamaudiosource_free_buffer);
761                                 readbuf = gst_buffer_append (readbuf, append_buffer);
762                         }
763                         else
764                         {
765                                 GST_OBJECT_LOCK (self);
766                                 readbuf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, enc->cdb, AMMAPSIZE, desc->stCommon.uiOffset, desc->stCommon.uiLength, memtrack, (GDestroyNotify) gst_dreamaudiosource_free_buffer);
767                                 if (desc->stCommon.uiLength == 0)
768                                 {
769                                         GST_WARNING_OBJECT (self, "ZERO SIZE BUFFER");
770                                         _gst_dreamaudiosource_emit_signal_lost (self);
771                                 }
772                                 memtrack->self = self;
773                                 memtrack->buffer = readbuf;
774                                 memtrack->uiOffset = desc->stCommon.uiOffset;
775                                 memtrack->uiLength = desc->stCommon.uiLength;
776                                 self->memtrack_list = g_list_append(self->memtrack_list, memtrack);
777                                 GST_OBJECT_UNLOCK (self);
778                         }
779                         if (result_pts != GST_CLOCK_TIME_NONE)
780                         {
781                                 GST_BUFFER_PTS(readbuf) = result_pts;
782                                 GST_BUFFER_DTS(readbuf) = result_pts;
783                         }
784 #ifdef dump
785                         int wret = write(self->dumpfd, (unsigned char*)(enc->cdb + desc->stCommon.uiOffset), desc->stCommon.uiLength);
786                         GST_LOG_OBJECT (self, "read=%i dumped=%i gst_buffer_get_size=%" G_GSIZE_FORMAT " ", desc->stCommon.uiLength, wret, gst_buffer_get_size (readbuf) );
787 #endif
788                         self->descriptors_count++;
789                         break;
790                 }
791
792                 if (self->descriptors_count == self->descriptors_available)
793                 {
794                         GST_LOG_OBJECT (self, "self->descriptors_count == self->descriptors_available -> release %i consumed descriptors", self->descriptors_count);
795                         if (state == READTHREADSTATE_STOP)
796                                 GST_DEBUG_OBJECT (self, "readthread stopping, don't write to fd anymore!");
797                         /* release consumed descs */
798                         else if (write(enc->fd, &self->descriptors_count, sizeof(self->descriptors_count)) != sizeof(self->descriptors_count)) {
799                                 GST_WARNING_OBJECT (self, "release consumed descs write error!");
800                                 goto stop_running;
801                         }
802                         self->descriptors_available = 0;
803                 }
804
805                 if (readbuf)
806                 {
807                         g_mutex_lock (&self->mutex);
808                         if (!self->flushing)
809                         {
810                                 if (gst_buffer_get_size (readbuf) == 0)
811                                 {
812                                         GstClockTime duration = timeout * GST_MSECOND;
813 #if 1 // generate silence adts frames
814 #define ADTS_HEADER_LEN       0x07
815 #define AAC_PAYLOAD_LEN       0x06
816 #define ADTS_DUMMY_FRAME_LEN  ADTS_HEADER_LEN + AAC_PAYLOAD_LEN
817                                         gst_buffer_unref(readbuf);
818                                         readbuf = gst_buffer_new_and_alloc (ADTS_DUMMY_FRAME_LEN);
819                                         GST_BUFFER_PTS (readbuf) = self->last_ts;
820                                         GST_BUFFER_DTS (readbuf) = self->last_ts;
821                                         GST_BUFFER_DURATION (readbuf) = duration;
822                                         GstMapInfo map;
823                                         gst_buffer_map (readbuf, &map, GST_MAP_WRITE);
824                                         guint8 *adts_header = map.data;
825                                         adts_header[0] = 0xff;
826                                         adts_header[1] = 0xf1;
827                                         adts_header[2] = 0x4c;
828                                         adts_header[3] = 0xb0;
829                                         adts_header[4] = 0x01;
830                                         adts_header[5] = 0xA0;
831                                         adts_header[6] = 0x00;
832                                         guint8 *payload = map.data+ADTS_HEADER_LEN;
833                                         payload[0] = 0x21;
834                                         payload[1] = 0x10;
835                                         payload[2] = 0x04;
836                                         payload[3] = 0x60;
837                                         payload[4] = 0x8c;
838                                         payload[5] = 0x1c;
839                                         gst_buffer_unmap (readbuf, &map);
840                                         GST_DEBUG_OBJECT (self, "Generated silence ADTS frame %" GST_PTR_FORMAT "" , readbuf);
841 #else // produce gap events (mpegtsmux doesn't handle gap yet)
842                                         GstEvent *event = NULL;
843                                         event = gst_event_new_gap (self->last_ts, duration);
844                                         GST_DEBUG_OBJECT (self, "Sending %" GST_PTR_FORMAT" (from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT ")" , event, GST_TIME_ARGS (self->last_ts), GST_TIME_ARGS (self->last_ts+duration));
845                                         gst_pad_push_event (GST_BASE_SRC_PAD (self), event);
846 #endif
847                                         self->last_ts += duration;
848                                 }
849                                 else
850                                         self->last_ts = GST_BUFFER_PTS(readbuf);
851                                 while (g_queue_get_length (&self->current_frames) >= self->buffer_size)
852                                 {
853                                         GstBuffer * oldbuf = g_queue_pop_head (&self->current_frames);
854                                         GST_WARNING_OBJECT (self, "dropping %" GST_PTR_FORMAT " because of queue overflow! buffers count=%i", oldbuf, g_queue_get_length (&self->current_frames));
855                                         gst_buffer_unref(oldbuf);
856                                         GST_BUFFER_FLAG_SET ((GstBuffer *) g_queue_peek_head (&self->current_frames), GST_BUFFER_FLAG_DISCONT);
857                                 }
858                                 if (discont)
859                                 {
860                                         GST_BUFFER_FLAG_SET (readbuf, GST_BUFFER_FLAG_DISCONT);
861                                         discont = FALSE;
862                                 }
863                                 g_queue_push_tail (&self->current_frames, readbuf);
864                                 GST_INFO_OBJECT (self, "read %" GST_PTR_FORMAT " to queue... buffers count=%i", readbuf, g_queue_get_length (&self->current_frames));
865                         }
866                         else
867                         {
868                                 if (self->flushing)
869                                 {
870                                         GST_INFO_OBJECT (self, "dropping %" GST_PTR_FORMAT " because we're flushing", readbuf);
871                                         gst_buffer_unref(readbuf);
872                                 }
873                                 else
874                                 {
875
876                                 }
877                                 gst_buffer_unref(readbuf);
878                         }
879                         g_cond_signal (&self->cond);
880                         g_mutex_unlock (&self->mutex);
881                         readbuf = NULL;
882                 }
883         }
884
885         g_assert_not_reached ();
886         return;
887
888         stop_running:
889         {
890                 g_mutex_unlock (&self->mutex);
891                 g_cond_signal (&self->cond);
892                 GST_DEBUG ("stop running, exit thread");
893                 message = gst_message_new_stream_status (GST_OBJECT_CAST (self), GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (GST_OBJECT_PARENT(self)));
894                 g_value_init (&val, GST_TYPE_G_THREAD);
895                 g_value_set_boxed (&val, self->readthread);
896                 gst_message_set_stream_status_object (message, &val);
897                 g_value_unset (&val);
898                 GST_DEBUG_OBJECT (self, "posting LEAVE stream status");
899                 gst_element_post_message (GST_ELEMENT_CAST (self), message);
900                 return;
901         }
902 }
903
904 static GstFlowReturn
905 gst_dreamaudiosource_create (GstPushSrc * psrc, GstBuffer ** outbuf)
906 {
907         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (psrc);
908
909         GST_LOG_OBJECT (self, "new buffer requested. queue has %i buffers", g_queue_get_length (&self->current_frames));
910
911         g_mutex_lock (&self->mutex);
912         while (g_queue_is_empty (&self->current_frames) && !self->flushing)
913         {
914                 GST_DEBUG_OBJECT (self, "waiting for buffer from encoder");
915                 g_cond_wait (&self->cond, &self->mutex);
916         }
917
918         *outbuf = g_queue_pop_head (&self->current_frames);
919         g_mutex_unlock (&self->mutex);
920
921         if (*outbuf)
922         {
923                 GST_INFO_OBJECT (self, "pushing %" GST_PTR_FORMAT ". queue has %i buffers", *outbuf, g_queue_get_length (&self->current_frames));
924                 return GST_FLOW_OK;
925         }
926         GST_INFO_OBJECT (self, "FLUSHING");
927         return GST_FLOW_FLUSHING;
928 }
929
930 static GstStateChangeReturn gst_dreamaudiosource_change_state (GstElement * element, GstStateChange transition)
931 {
932         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (element);
933         GstStateChangeReturn sret = GST_STATE_CHANGE_SUCCESS;
934         int ret;
935
936         switch (transition) {
937                 case GST_STATE_CHANGE_NULL_TO_READY:
938                 {
939                         if (!gst_dreamaudiosource_encoder_init (self))
940                         {
941                                 GError *err = g_error_new (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ, "Can't initialize encoder device");
942                                 GstMessage *msg = gst_message_new_error (GST_OBJECT (self), err, NULL);
943                                 gst_element_post_message (element, msg);
944                                 g_error_free (err);
945                                 return GST_STATE_CHANGE_FAILURE;
946                         }
947                         GST_DEBUG_OBJECT (self, "GST_STATE_CHANGE_NULL_TO_READY");
948                         break;
949                 }
950                 case GST_STATE_CHANGE_READY_TO_PAUSED:
951                         GST_LOG_OBJECT (self, "GST_STATE_CHANGE_READY_TO_PAUSED");
952                         self->dreamvideosrc = gst_bin_get_by_name_recurse_up(GST_BIN(GST_ELEMENT_PARENT(self)), "dreamvideosource0");
953                         if (self->dreamvideosrc)
954                         {
955                                 gint videobitrate = 0;
956                                 g_object_get (G_OBJECT (self->dreamvideosrc), "bitrate", &videobitrate, NULL);
957                                 gfloat x = videobitrate/100.0;
958                                 GST_DEBUG_OBJECT (self, "bitrate/100.0 = %f", x);
959                                 self->buffer_size = (gint)((-0.0026)*x*x) + (gint)(1.0756*x) + DEFAULT_BUFFER_SIZE; // empirically approximated polynom
960                                 GST_INFO_OBJECT (self, "%" GST_PTR_FORMAT "'s bitrate=%i -> set internal buffer_size to %i", self->dreamvideosrc, videobitrate, self->buffer_size);
961                         }
962                         self->dts_offset = GST_CLOCK_TIME_NONE;
963 #ifdef PROVIDE_CLOCK
964                         gst_element_post_message (element, gst_message_new_clock_provide (GST_OBJECT_CAST (element), self->encoder_clock, TRUE));
965 #endif
966                         self->flushing = TRUE;
967                         self->readthread = g_thread_try_new ("dreamaudiosrc-read", (GThreadFunc) gst_dreamaudiosource_read_thread_func, self, NULL);
968                         GST_DEBUG_OBJECT (self, "started readthread @%p", self->readthread);
969                         break;
970                 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
971                         g_mutex_lock (&self->mutex);
972                         GST_LOG_OBJECT (self, "GST_STATE_CHANGE_PAUSED_TO_PLAYING");
973                         GstClock *pipeline_clock = gst_element_get_clock (GST_ELEMENT (self));
974                         if (pipeline_clock)
975                         {
976                                 if (pipeline_clock != self->encoder_clock)
977                                 {
978                                         gst_clock_set_master (self->encoder_clock, pipeline_clock);
979                                         GST_DEBUG_OBJECT (self, "slaved %" GST_PTR_FORMAT "to pipeline_clock %" GST_PTR_FORMAT "", self->encoder_clock, pipeline_clock);
980                                 }
981                                 else
982                                         GST_DEBUG_OBJECT (self, "encoder_clock is master clock");
983                         }
984                                 else
985                                         GST_WARNING_OBJECT (self, "no pipeline clock!");
986                         ret = ioctl(self->encoder->fd, AENC_START);
987                         if ( ret != 0 )
988                                 goto fail;
989                         self->descriptors_available = 0;
990                         CLEAR_COMMAND (self);
991                         g_mutex_unlock (&self->mutex);
992                         break;
993                 default:
994                         break;
995         }
996
997         if (GST_ELEMENT_CLASS (parent_class)->change_state)
998                 sret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
999
1000         switch (transition) {
1001                 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1002                         g_mutex_lock (&self->mutex);
1003                         SEND_COMMAND (self, CONTROL_RUN);
1004                         GST_INFO_OBJECT (self, "started encoder!");
1005                         g_mutex_unlock (&self->mutex);
1006                         break;
1007                 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1008                         g_mutex_lock (&self->mutex);
1009                         GST_DEBUG_OBJECT (self, "GST_STATE_CHANGE_PLAYING_TO_PAUSED self->descriptors_count=%i self->descriptors_available=%i", self->descriptors_count, self->descriptors_available);
1010                         SEND_COMMAND (self, CONTROL_PAUSE);
1011                         if (self->descriptors_count < self->descriptors_available)
1012                                 self->descriptors_count = self->descriptors_available;
1013                         if (self->descriptors_count)
1014                                 write(self->encoder->fd, &self->descriptors_count, sizeof(self->descriptors_count));
1015                         ret = ioctl(self->encoder->fd, AENC_STOP);
1016                         if ( ret != 0 )
1017                                 goto fail;
1018 #ifdef PROVIDE_CLOCK
1019                         gst_clock_set_master (self->encoder_clock, NULL);
1020 #endif
1021                         GST_INFO_OBJECT (self, "stopped encoder!");
1022                         g_mutex_unlock (&self->mutex);
1023                         break;
1024                 case GST_STATE_CHANGE_PAUSED_TO_READY:
1025                         GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_PAUSED_TO_READY");
1026 #ifdef PROVIDE_CLOCK
1027                         gst_element_post_message (element, gst_message_new_clock_lost (GST_OBJECT_CAST (element), self->encoder_clock));
1028                         gst_clock_set_calibration (self->encoder_clock, 0, 0, 1, 1);
1029 #endif
1030                         GST_DEBUG_OBJECT (self, "stopping readthread @%p...", self->readthread);
1031                         SEND_COMMAND (self, CONTROL_STOP);
1032                         g_thread_join (self->readthread);
1033                         if (self->dreamvideosrc)
1034                                 gst_object_unref(self->dreamvideosrc);
1035                         self->dreamvideosrc = NULL;
1036                         break;
1037                 case GST_STATE_CHANGE_READY_TO_NULL:
1038                         gst_dreamaudiosource_encoder_release (self);
1039                         GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_READY_TO_NULL");
1040                         break;
1041                 default:
1042                         break;
1043         }
1044
1045         return sret;
1046 fail:
1047         GST_ERROR_OBJECT(self,"can't perform encoder ioctl! error: %s (%i)", strerror(errno), errno);
1048         g_mutex_unlock (&self->mutex);
1049         return GST_STATE_CHANGE_FAILURE;
1050 }
1051
1052 static void
1053 gst_dreamaudiosource_dispose (GObject * gobject)
1054 {
1055         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (gobject);
1056 #ifdef dump
1057         close(self->dumpfd);
1058 #endif
1059         g_list_free(self->memtrack_list);
1060         g_mutex_clear (&self->mutex);
1061         g_cond_clear (&self->cond);
1062         GST_DEBUG_OBJECT (self, "disposed");
1063         G_OBJECT_CLASS (parent_class)->dispose (gobject);
1064 }
1065
1066 #ifdef PROVIDE_CLOCK
1067 static GstClock *gst_dreamaudiosource_provide_clock (GstElement * element)
1068 {
1069         GstDreamAudioSource *self = GST_DREAMAUDIOSOURCE (element);
1070
1071         if (!self->encoder || self->encoder->fd < 0)
1072         {
1073                 GST_DEBUG_OBJECT (self, "encoder device not started, can't provide clock!");
1074                 return NULL;
1075         }
1076
1077         return GST_CLOCK_CAST (gst_object_ref (self->encoder_clock));
1078 }
1079
1080 #endif
1081