implement signal-lost, implement generation of adts silence frames / gap events on...
[gst-plugin-dreamsource.git] / src / gstdreamvideosource.c
1 /*
2  * GStreamer dreamvideosource
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 "gstdreamvideosource.h"
25
26 GST_DEBUG_CATEGORY_STATIC (dreamvideosource_debug);
27 #define GST_CAT_DEFAULT dreamvideosource_debug
28
29 GType gst_dreamvideosource_input_mode_get_type (void)
30 {
31         static volatile gsize input_mode_type = 0;
32         static const GEnumValue input_mode[] = {
33                 {GST_DREAMVIDEOSOURCE_INPUT_MODE_LIVE, "GST_DREAMVIDEOSOURCE_INPUT_MODE_LIVE", "live"},
34                 {GST_DREAMVIDEOSOURCE_INPUT_MODE_HDMI_IN, "GST_DREAMVIDEOSOURCE_INPUT_MODE_HDMI_IN", "hdmi_in"},
35                 {GST_DREAMVIDEOSOURCE_INPUT_MODE_BACKGROUND, "GST_DREAMVIDEOSOURCE_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 ("GstDreamVideoSourceInputMode", 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         LAST_SIGNAL
50 };
51
52 enum
53 {
54         ARG_0,
55         ARG_CAPS,
56         ARG_BITRATE,
57         ARG_INPUT_MODE
58 };
59
60 static guint gst_dreamvideosource_signals[LAST_SIGNAL] = { 0 };
61
62 #define DEFAULT_BITRATE     2048
63 #define DEFAULT_FRAMERATE   25
64 #define DEFAULT_WIDTH       1280
65 #define DEFAULT_HEIGHT      720
66 #define DEFAULT_INPUT_MODE  GST_DREAMVIDEOSOURCE_INPUT_MODE_LIVE
67 #define DEFAULT_BUFFER_SIZE 50
68
69 static GstStaticPadTemplate srctemplate =
70     GST_STATIC_PAD_TEMPLATE ("src",
71         GST_PAD_SRC,
72         GST_PAD_ALWAYS,
73         GST_STATIC_CAPS ("video/x-h264, "
74         "width = { 720, 1280, 1920 }, "
75         "height = { 576, 720, 1080 }, "
76         "framerate = { 25/1, 30/1, 50/1, 60/1 }, "
77         "display-aspect-ratio = { 5/4, 16/9 }, "
78         "stream-format = (string) byte-stream, "
79         "profile = (string) main")
80     );
81
82 #define gst_dreamvideosource_parent_class parent_class
83 G_DEFINE_TYPE (GstDreamVideoSource, gst_dreamvideosource, GST_TYPE_PUSH_SRC);
84
85 static GstCaps *gst_dreamvideosource_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
86 static gboolean gst_dreamvideosource_setcaps (GstBaseSrc * bsrc, GstCaps * caps);
87 static GstCaps *gst_dreamvideosource_fixate (GstBaseSrc * bsrc, GstCaps * caps);
88 static gboolean gst_dreamvideosource_query (GstBaseSrc * bsrc, GstQuery * query);
89
90 static gboolean gst_dreamvideosource_unlock (GstBaseSrc * bsrc);
91 static gboolean gst_dreamvideosource_unlock_stop (GstBaseSrc * bsrc);
92 static void gst_dreamvideosource_dispose (GObject * gobject);
93 static GstFlowReturn gst_dreamvideosource_create (GstPushSrc * psrc, GstBuffer ** outbuf);
94
95 static void gst_dreamvideosource_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
96 static void gst_dreamvideosource_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
97
98 static GstStateChangeReturn gst_dreamvideosource_change_state (GstElement * element, GstStateChange transition);
99 static gint64 gst_dreamvideosource_get_dts_offset (GstDreamVideoSource *self);
100
101 static gboolean gst_dreamvideosource_encoder_init (GstDreamVideoSource * self);
102 static void gst_dreamvideosource_encoder_release (GstDreamVideoSource * self);
103
104 static void gst_dreamvideosource_read_thread_func (GstDreamVideoSource * self);
105
106 #ifdef PROVIDE_CLOCK
107 static GstClock *gst_dreamvideosource_provide_clock (GstElement * elem);
108 // static GstClockTime gst_dreamvideosource_get_encoder_time_ (GstClock * clock, GstBaseSrc * bsrc);
109 #endif
110
111 static void
112 gst_dreamvideosource_class_init (GstDreamVideoSourceClass * klass)
113 {
114         GObjectClass *gobject_class;
115         GstElementClass *gstelement_class;
116         GstBaseSrcClass *gstbsrc_class;
117         GstPushSrcClass *gstpush_src_class;
118
119         gobject_class = (GObjectClass *) klass;
120         gstelement_class = (GstElementClass *) klass;
121         gstbsrc_class = (GstBaseSrcClass *) klass;
122         gstpush_src_class = (GstPushSrcClass *) klass;
123
124         gobject_class->set_property = gst_dreamvideosource_set_property;
125         gobject_class->get_property = gst_dreamvideosource_get_property;
126         gobject_class->dispose = gst_dreamvideosource_dispose;
127
128         gst_element_class_add_pad_template (gstelement_class,
129                                             gst_static_pad_template_get (&srctemplate));
130
131         gst_element_class_set_static_metadata (gstelement_class,
132             "Dream Video source", "Source/Video",
133             "Provide an h.264 video elementary stream from Dreambox encoder device",
134             "Andreas Frisch <fraxinas@opendreambox.org>");
135
136         gstelement_class->change_state = gst_dreamvideosource_change_state;
137
138         gstbsrc_class->get_caps = gst_dreamvideosource_getcaps;
139         gstbsrc_class->set_caps = gst_dreamvideosource_setcaps;
140         gstbsrc_class->query = gst_dreamvideosource_query;
141         gstbsrc_class->fixate = gst_dreamvideosource_fixate;
142         gstbsrc_class->unlock = gst_dreamvideosource_unlock;
143         gstbsrc_class->unlock_stop = gst_dreamvideosource_unlock_stop;
144
145         gstpush_src_class->create = gst_dreamvideosource_create;
146
147 #ifdef PROVIDE_CLOCK
148         gstelement_class->provide_clock = GST_DEBUG_FUNCPTR (gst_dreamvideosource_provide_clock);
149 //      g_type_class_ref (GST_TYPE_SYSTEM_CLOCK);
150 #endif
151
152         g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
153           g_param_spec_int ("bitrate", "Bitrate (kb/s)",
154             "Bitrate in kbit/sec", 16, 200000, DEFAULT_BITRATE,
155             G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
156
157         g_object_class_install_property (gobject_class, ARG_CAPS,
158           g_param_spec_boxed ("caps", "Caps",
159             "The caps for the source stream", GST_TYPE_CAPS,
160             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
161
162         g_object_class_install_property (gobject_class, ARG_INPUT_MODE,
163           g_param_spec_enum ("input-mode", "Input Mode",
164             "Select the input source of the video stream",
165             GST_TYPE_DREAMVIDEOSOURCE_INPUT_MODE, DEFAULT_INPUT_MODE,
166             G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
167
168         gst_dreamvideosource_signals[SIGNAL_GET_DTS_OFFSET] =
169                 g_signal_new ("get-dts-offset",
170                 G_TYPE_FROM_CLASS (klass),
171                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
172                 G_STRUCT_OFFSET (GstDreamVideoSourceClass, get_dts_offset),
173                 NULL, NULL, gst_dreamsource_marshal_INT64__VOID, G_TYPE_INT64, 0);
174
175         klass->get_dts_offset = gst_dreamvideosource_get_dts_offset;
176 }
177
178 static gint64
179 gst_dreamvideosource_get_dts_offset (GstDreamVideoSource *self)
180 {
181         GST_DEBUG_OBJECT (self, "gst_dreamvideosource_get_dts_offset %" GST_TIME_FORMAT"", GST_TIME_ARGS (self->dts_offset) );
182         return self->dts_offset;
183 }
184
185 static void gst_dreamvideosource_set_bitrate (GstDreamVideoSource * self, uint32_t bitrate)
186 {
187         g_mutex_lock (&self->mutex);
188         uint32_t vbr = bitrate*1000;
189         if (!self->encoder || !self->encoder->fd)
190         {
191                 self->video_info.bitrate = bitrate;
192                 g_mutex_unlock (&self->mutex);
193                 return;
194         }
195
196         int ret = ioctl(self->encoder->fd, VENC_SET_BITRATE, &vbr);
197         if (ret != 0)
198         {
199                 GST_WARNING_OBJECT (self, "can't set video bitrate to %i bytes/s!", vbr);
200                 g_mutex_unlock (&self->mutex);
201                 return;
202         }
203         GST_INFO_OBJECT (self, "set video bitrate to %i kBytes/s", bitrate);
204         self->video_info.bitrate = bitrate;
205         g_mutex_unlock (&self->mutex);
206 }
207
208 static gboolean gst_dreamvideosource_set_format (GstDreamVideoSource * self, VideoFormatInfo * info)
209 {
210         g_mutex_lock (&self->mutex);
211         info->bitrate = self->video_info.bitrate;
212         if (!self->encoder || !self->encoder->fd)
213         {
214                 self->video_info = *info;
215                 g_mutex_unlock (&self->mutex);
216                 return TRUE;
217         }
218
219         if (info->fps_n > 0)
220         {
221                 int venc_fps = 0;
222                 switch (info->fps_n) {
223                         case 25:
224                                 venc_fps = rate_25;
225                                 break;
226                         case 30:
227                                 venc_fps = rate_30;
228                                 break;
229                         case 50:
230                                 venc_fps = rate_50;
231                                 break;
232                         case 60:
233                                 venc_fps = rate_60;
234                                 break;
235                         default:
236                                 GST_ERROR_OBJECT (self, "invalid framerate %d/%d", info->fps_n, info->fps_d);
237                                 goto fail;
238                 }
239                 if (!ioctl(self->encoder->fd, VENC_SET_FRAMERATE, &venc_fps))
240                         GST_INFO_OBJECT (self, "set framerate to %d/%d -> ioctrl(%d, VENC_SET_FRAMERATE, &%d)", info->fps_n, info->fps_d, self->encoder->fd, venc_fps);
241                 else
242                 {
243                         GST_WARNING_OBJECT (self, "can't set framerate to %d/%d -> ioctrl(%d, VENC_SET_FRAMERATE, &%d)", info->fps_n, info->fps_d, self->encoder->fd, venc_fps);
244                         goto fail;
245                 }
246         }
247
248         if (info->width && info->height)
249         {
250                 int venc_size = 0;
251                 if ( info->width == 720 && info->height == 576 )
252                         venc_size = fmt_720x576;
253                 else if ( info->width == 1280 && info->height == 720)
254                         venc_size = fmt_1280x720;
255                 else if ( info->width == 1920 && info->height == 1080)
256                         venc_size = fmt_1920x1080;
257                 else
258                 {
259                         GST_ERROR_OBJECT (self, "invalid resolution %dx%d", info->width, info->height);
260                         goto fail;
261                 }
262                 if (!ioctl(self->encoder->fd, VENC_SET_RESOLUTION, &venc_size))
263                         GST_INFO_OBJECT (self, "set resolution to %dx%d -> ioctrl(%d, VENC_SET_RESOLUTION, &%d)", info->width, info->height, self->encoder->fd, venc_size);
264                 else
265                 {
266                         GST_WARNING_OBJECT (self, "can't set resolution to %dx%d -> ioctrl(%d, VENC_SET_RESOLUTION, &%d)", info->width, info->height, self->encoder->fd, venc_size);
267                         goto fail;
268                 }
269         }
270
271         self->video_info = *info;
272         g_mutex_unlock (&self->mutex);
273         return TRUE;
274
275 fail:
276         g_mutex_unlock (&self->mutex);
277         return FALSE;
278 }
279
280 void gst_dreamvideosource_set_input_mode (GstDreamVideoSource *self, GstDreamVideoSourceInputMode mode)
281 {
282         g_return_if_fail (GST_IS_DREAMVIDEOSOURCE (self));
283         GEnumValue *val = g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (GST_TYPE_DREAMVIDEOSOURCE_INPUT_MODE)), mode);
284         if (!val)
285         {
286                 GST_ERROR_OBJECT (self, "no such input_mode %i!", mode);
287                 return;
288         }
289         const gchar *value_nick = val->value_nick;
290
291         g_mutex_lock (&self->mutex);
292         if (!self->encoder || !self->encoder->fd)
293         {
294                 self->input_mode = mode;
295                 goto out;
296         }
297         int int_mode = mode;
298         int ret = ioctl(self->encoder->fd, VENC_SET_SOURCE, &int_mode);
299         if (ret != 0)
300         {
301                 GST_WARNING_OBJECT (self, "can't set input mode to %s (%i) error: %s", value_nick, mode, strerror(errno));
302                 goto out;
303         }
304         GST_INFO_OBJECT (self, "successfully set input mode to %s (%i)", value_nick, mode);
305         self->input_mode = mode;
306
307 out:
308         g_mutex_unlock (&self->mutex);
309         return;
310 }
311
312 GstDreamVideoSourceInputMode gst_dreamvideosource_get_input_mode (GstDreamVideoSource *self)
313 {
314         GstDreamVideoSourceInputMode result;
315         g_return_val_if_fail (GST_IS_DREAMVIDEOSOURCE (self), -1);
316         g_mutex_lock (&self->mutex);
317         result =self->input_mode;
318         g_mutex_unlock (&self->mutex);
319         return result;
320 }
321
322 gboolean
323 gst_dreamvideosource_plugin_init (GstPlugin *plugin)
324 {
325         GST_DEBUG_CATEGORY_INIT (dreamvideosource_debug, "dreamvideosource", 0, "dreamvideosource");
326         return gst_element_register (plugin, "dreamvideosource", GST_RANK_PRIMARY, GST_TYPE_DREAMVIDEOSOURCE);
327 }
328
329 static void
330 gst_dreamvideosource_init (GstDreamVideoSource * self)
331 {
332         self->current_caps = NULL;
333         self->new_caps = NULL;
334
335         self->dts_valid = FALSE;
336         self->encoder = NULL;
337         self->descriptors_available = 0;
338         self->input_mode = DEFAULT_INPUT_MODE;
339
340         self->buffer_size = DEFAULT_BUFFER_SIZE;
341         g_queue_init (&self->current_frames);
342         self->readthread = NULL;
343
344         g_mutex_init (&self->mutex);
345         g_cond_init (&self->cond);
346         READ_SOCKET (self) = -1;
347         WRITE_SOCKET (self) = -1;
348
349         gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
350         gst_base_src_set_live (GST_BASE_SRC (self), TRUE);
351
352         self->encoder = NULL;
353         self->encoder_clock = NULL;
354
355 #ifdef dump
356         self->dumpfd = open("/media/hdd/movie/dreamvideosource.dump", O_WRONLY | O_CREAT | O_TRUNC);
357         GST_DEBUG_OBJECT (self, "dumpfd = %i (%s)", self->dumpfd, (self->dumpfd > 0) ? "OK" : strerror(errno));
358 #endif
359 }
360
361 static gboolean gst_dreamvideosource_encoder_init (GstDreamVideoSource * self)
362 {
363         GST_LOG_OBJECT (self, "initializating encoder...");
364         self->encoder = malloc (sizeof(EncoderInfo));
365
366         if (!self->encoder) {
367                 GST_ERROR_OBJECT (self,"out of space");
368                 return FALSE;
369         }
370
371         char fn_buf[32];
372         sprintf(fn_buf, "/dev/venc%d", 0);
373         self->encoder->fd = open(fn_buf, O_RDWR | O_SYNC);
374         if (self->encoder->fd <= 0) {
375                 GST_ERROR_OBJECT (self,"cannot open device %s (%s)", fn_buf, strerror(errno));
376                 free(self->encoder);
377                 self->encoder = NULL;
378                 return FALSE;
379         }
380
381         self->encoder->buffer = malloc(VBUFSIZE);
382         if (!self->encoder->buffer) {
383                 GST_ERROR_OBJECT(self,"cannot alloc buffer");
384                 return FALSE;
385         }
386
387         self->encoder->cdb = (unsigned char *)mmap (0, VMMAPSIZE, PROT_READ, MAP_PRIVATE, self->encoder->fd, 0);
388
389         if (!self->encoder->cdb || self->encoder->cdb == MAP_FAILED) {
390                 GST_ERROR_OBJECT(self, "cannot alloc buffer: %s (%i)", strerror(errno), errno);
391                 self->encoder->cdb = NULL;
392                 return FALSE;
393         }
394
395         int control_sock[2];
396         if (socketpair (PF_UNIX, SOCK_STREAM, 0, control_sock) < 0)
397         {
398                 GST_ERROR_OBJECT(self, "cannot create control sockets: %s (%i)", strerror(errno), errno);
399                 return FALSE;
400         }
401         READ_SOCKET (self) = control_sock[0];
402         WRITE_SOCKET (self) = control_sock[1];
403         fcntl (READ_SOCKET (self), F_SETFL, O_NONBLOCK);
404         fcntl (WRITE_SOCKET (self), F_SETFL, O_NONBLOCK);
405
406         gst_dreamvideosource_set_bitrate (self, self->video_info.bitrate);
407         gst_dreamvideosource_set_format (self, &self->video_info);
408         gst_dreamvideosource_set_input_mode (self, self->input_mode);
409
410         GST_LOG_OBJECT (self, "encoder %s successfully initialized", fn_buf);
411         return TRUE;
412 }
413
414 static void gst_dreamvideosource_encoder_release (GstDreamVideoSource * self)
415 {
416         GST_LOG_OBJECT (self, "releasing encoder...");
417         if (self->encoder) {
418                 if (self->encoder->buffer)
419                         free(self->encoder->buffer);
420                 if (self->encoder->cdb)
421                         munmap(self->encoder->cdb, VMMAPSIZE);
422                 if (self->encoder->fd)
423                         close(self->encoder->fd);
424                 free(self->encoder);
425         }
426         self->encoder = NULL;
427         close (READ_SOCKET (self));
428         close (WRITE_SOCKET (self));
429         READ_SOCKET (self) = -1;
430         WRITE_SOCKET (self) = -1;
431         if (self->encoder_clock) {
432                 gst_object_unref (self->encoder_clock);
433                 self->encoder_clock = NULL;
434         }
435 }
436
437 static void
438 gst_dreamvideosource_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
439 {
440         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (object);
441
442         switch (prop_id) {
443                 case ARG_CAPS:
444                 {
445                         if (self->new_caps)
446                                 gst_caps_unref (self->new_caps);
447                         self->new_caps = gst_caps_copy (gst_value_get_caps (value));
448                         gst_pad_mark_reconfigure (GST_BASE_SRC_PAD (GST_BASE_SRC(object)));
449                         break;
450                 }
451                 case ARG_BITRATE:
452                         gst_dreamvideosource_set_bitrate(self, g_value_get_int (value));
453                         break;
454                 case ARG_INPUT_MODE:
455                         gst_dreamvideosource_set_input_mode (self, g_value_get_enum (value));
456                         break;
457                 default:
458                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
459                         break;
460         }
461 }
462
463 static void
464 gst_dreamvideosource_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
465 {
466         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (object);
467
468         switch (prop_id) {
469                 case ARG_CAPS:
470                         g_value_take_boxed (value, gst_dreamvideosource_getcaps (GST_BASE_SRC(object), GST_CAPS_ANY));
471                         break;
472                 case ARG_BITRATE:
473                         g_value_set_int (value, self->video_info.bitrate);
474                         break;
475                 case ARG_INPUT_MODE:
476                         g_value_set_enum (value, gst_dreamvideosource_get_input_mode (self));
477                         break;
478                 default:
479                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
480                         break;
481         }
482 }
483
484 static GstCaps *
485 gst_dreamvideosource_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
486 {
487         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (bsrc);
488         GstCaps *caps;
489
490         g_mutex_lock (&self->mutex);
491         if (self->new_caps)
492         {
493                 GST_DEBUG_OBJECT (self, "gst_dreamvideosource_getcaps has new_caps: %" GST_PTR_FORMAT " / current_caps: %" GST_PTR_FORMAT "", self->new_caps, self->current_caps);
494                 if (self->current_caps)
495                 {
496                         caps = gst_caps_new_empty ();
497                         gst_caps_replace (&caps, self->new_caps);
498                         self->new_caps = NULL;
499                 }
500                 else
501                         caps = gst_caps_copy (self->new_caps);
502         } else if (self->current_caps == NULL) {
503                 GstPadTemplate *pad_template;
504                 pad_template = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS(self), "src");
505                 if (pad_template)
506                         caps = gst_caps_copy (gst_pad_template_get_caps (pad_template));
507                 else
508                         caps = gst_caps_new_empty ();
509
510                 caps = gst_pad_template_get_caps (pad_template);
511         } else
512                 caps = gst_caps_copy(self->current_caps);
513
514         GST_LOG_OBJECT (self, "gst_dreamvideosource_getcaps %" GST_PTR_FORMAT " filter %" GST_PTR_FORMAT, caps, filter);
515
516         if (filter) {
517                 GstCaps *intersection;
518                 intersection = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
519                 gst_caps_unref (caps);
520                 caps = intersection;
521         }
522
523         GST_LOG_OBJECT (self, "return caps %" GST_PTR_FORMAT, caps);
524         g_mutex_unlock (&self->mutex);
525         return caps;
526 }
527
528 static gboolean
529 gst_dreamvideosource_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
530 {
531         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (bsrc);
532         GstCaps *current_caps;
533         const GstStructure *structure;
534         VideoFormatInfo info;
535         gboolean ret;
536         const GValue *framerate;
537
538         g_mutex_lock (&self->mutex);
539         structure = gst_caps_get_structure (caps, 0);
540
541         current_caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (bsrc));
542
543         GST_LOG_OBJECT (self, "gst_dreamvideosource_setcaps parameter %" GST_PTR_FORMAT " self->current_caps=%" GST_PTR_FORMAT " pad's current_caps=%" GST_PTR_FORMAT "  new_caps=%" GST_PTR_FORMAT"", caps, current_caps, self->current_caps, self->new_caps);
544
545         if (current_caps && gst_caps_is_equal (current_caps, caps)) {
546                 GST_LOG_OBJECT (self, "New caps equal to old ones: %" GST_PTR_FORMAT, caps);
547                 ret = TRUE;
548         } else {
549                 GstState state;
550                 gst_element_get_state (GST_ELEMENT(self), &state, NULL, 1*GST_MSECOND);
551                 if (state == GST_STATE_PLAYING)
552                 {
553                         GST_WARNING_OBJECT (self, "can't change caps while in PLAYING state %" GST_PTR_FORMAT, caps);
554                         g_mutex_unlock (&self->mutex);
555                         return TRUE;
556                 }
557                 else if (gst_structure_has_name (structure, "video/x-h264"))
558                 {
559                         memset (&info, 0, sizeof(VideoFormatInfo));
560                         ret = gst_structure_get_int (structure, "width", &info.width);
561                         ret &= gst_structure_get_int (structure, "height", &info.height);
562                         framerate = gst_structure_get_value (structure, "framerate");
563                         if (GST_VALUE_HOLDS_FRACTION(framerate)) {
564                                 info.fps_n = gst_value_get_fraction_numerator (framerate);
565                                 info.fps_d = gst_value_get_fraction_denominator (framerate);
566                         }
567                         GST_DEBUG_OBJECT (self, "set caps %" GST_PTR_FORMAT, caps);
568                         gst_caps_replace (&self->current_caps, caps);
569
570                         g_mutex_unlock (&self->mutex);
571                         if (gst_caps_is_fixed(caps) && gst_dreamvideosource_set_format(self, &info))
572                                 ret = gst_pad_push_event (bsrc->srcpad, gst_event_new_caps (caps));
573                 }
574                 else {
575                         GST_WARNING_OBJECT (self, "unsupported caps: %" GST_PTR_FORMAT, caps);
576                         ret = FALSE;
577                 }
578         }
579         if (current_caps)
580                 gst_caps_unref (current_caps);
581         g_mutex_unlock (&self->mutex);
582         return ret;
583 }
584
585 static GstCaps *
586 gst_dreamvideosource_fixate (GstBaseSrc * bsrc, GstCaps * caps)
587 {
588         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (bsrc);
589         GstStructure *structure;
590
591         caps = gst_caps_make_writable (caps);
592         structure = gst_caps_get_structure (caps, 0);
593
594         if (gst_structure_has_field (structure, "width"))
595                 gst_structure_fixate_field_nearest_int (structure, "width", DEFAULT_WIDTH);
596         if (gst_structure_has_field (structure, "height"))
597                 gst_structure_fixate_field_nearest_int (structure, "height", DEFAULT_HEIGHT);
598         if (gst_structure_has_field (structure, "framerate"))
599                 gst_structure_fixate_field_nearest_fraction (structure, "framerate", DEFAULT_FRAMERATE, 1);
600         if (gst_structure_has_field (structure, "display-aspect-ratio"))
601                 gst_structure_fixate_field_nearest_fraction (structure, "display-aspect-ratio", DEFAULT_WIDTH, DEFAULT_HEIGHT);
602
603         caps = GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps);
604         GST_DEBUG_OBJECT (self, "fixated caps: %" GST_PTR_FORMAT, caps);
605         return caps;
606 }
607
608 static gboolean gst_dreamvideosource_query (GstBaseSrc * bsrc, GstQuery * query)
609 {
610         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (bsrc);
611         gboolean ret = TRUE;
612
613         switch (GST_QUERY_TYPE (query)) {
614                 case GST_QUERY_LATENCY:{
615                         if (self->video_info.fps_n) {
616                                 GstClockTime min, max;
617
618                                 g_mutex_lock (&self->mutex);
619                                 min = gst_util_uint64_scale_ceil (GST_SECOND, self->video_info.fps_d, self->video_info.fps_n);
620                                 g_mutex_unlock (&self->mutex);
621
622                                 max = self->buffer_size * min;
623
624                                 gst_query_set_latency (query, TRUE, min, max);
625                                 GST_DEBUG_OBJECT (bsrc, "set LATENCY QUERY %" GST_PTR_FORMAT, query);
626                                 ret = TRUE;
627                         } else {
628                                 ret = FALSE;
629                         }
630                         break;
631                 }
632                 default:
633                         ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
634                         break;
635         }
636         return ret;
637 }
638
639 static gboolean gst_dreamvideosource_unlock (GstBaseSrc * bsrc)
640 {
641         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (bsrc);
642         GST_DEBUG_OBJECT (self, "stop creating buffers");
643         g_mutex_lock (&self->mutex);
644         self->flushing = TRUE;
645         GST_DEBUG_OBJECT (self, "set flushing TRUE");
646         g_cond_signal (&self->cond);
647         GST_DEBUG_OBJECT (self, "post cond");
648         g_mutex_unlock (&self->mutex);
649         GST_DEBUG_OBJECT (self, "post unlock");
650         return TRUE;
651 }
652
653 static gboolean gst_dreamvideosource_unlock_stop (GstBaseSrc * bsrc)
654 {
655         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (bsrc);
656         GST_DEBUG_OBJECT (self, "stop flushing...");
657         g_mutex_lock (&self->mutex);
658         self->flushing = FALSE;
659         g_queue_foreach (&self->current_frames, (GFunc) gst_buffer_unref, NULL);
660         g_queue_clear (&self->current_frames);
661         g_mutex_unlock (&self->mutex);
662         return TRUE;
663 }
664
665 static void gst_dreamvideosource_read_thread_func (GstDreamVideoSource * self)
666 {
667         EncoderInfo *enc = self->encoder;
668         GstDreamSourceReadthreadState state = READTHREADSTATE_NONE;
669         GstBuffer *readbuf;
670
671         if (!enc) {
672                 GST_WARNING_OBJECT (self, "encoder device not opened!");
673                 return;
674         }
675
676         GST_DEBUG_OBJECT (self, "enter read thread");
677
678         GstMessage *message;
679         GValue val = { 0 };
680
681         message = gst_message_new_stream_status (GST_OBJECT_CAST (self), GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (GST_OBJECT_PARENT(self)));
682         g_value_init (&val, GST_TYPE_G_THREAD);
683         g_value_set_boxed (&val, self->readthread);
684         gst_message_set_stream_status_object (message, &val);
685         g_value_unset (&val);
686         GST_DEBUG_OBJECT (self, "posting ENTER stream status");
687         gst_element_post_message (GST_ELEMENT_CAST (self), message);
688         GstClockTime clock_time, base_time;
689         gboolean discont = TRUE;
690
691         while (TRUE) {
692                 readbuf = NULL;
693                 {
694                         if (state == READTHREADSTATE_STOP)
695                                 goto stop_running;
696
697                         struct pollfd rfd[2];
698                         int timeout, nfds;
699
700                         rfd[0].fd = READ_SOCKET (self);
701                         rfd[0].events = POLLIN | POLLERR | POLLHUP | POLLPRI;
702                         rfd[1].revents = 0;
703                         rfd[1].events = POLLIN;
704                         nfds = 1;
705                         timeout = 0;
706
707                         if (state <= READTRREADSTATE_PAUSED)
708                                 timeout = 200;
709                         else if (state == READTRREADSTATE_RUNNING && self->descriptors_available == 0)
710                         {
711                                 rfd[1].fd = enc->fd;
712                                 self->descriptors_count = 0;
713                                 timeout = 200;
714                                 nfds = 2;
715                         }
716
717                         int ret = poll(rfd, nfds, timeout);
718
719                         if (G_UNLIKELY (ret == -1))
720                         {
721                                 GST_ERROR_OBJECT (self, "SELECT ERROR!");
722                                 goto stop_running;
723                         }
724                         else if ( ret == 0 && self->descriptors_available == 0 )
725                         {
726                                 g_mutex_lock (&self->mutex);
727                                 gst_clock_get_internal_time(self->encoder_clock);
728                                 g_mutex_unlock (&self->mutex);
729                                 GST_DEBUG_OBJECT (self, "SELECT TIMEOUT");
730                                 discont = TRUE;
731 //                              readbuf = gst_buffer_new();
732                         }
733                         else if ( rfd[0].revents )
734                         {
735                                 char command;
736                                 READ_COMMAND (self, command, ret);
737                                 switch (command) {
738                                         case CONTROL_STOP:
739                                                 GST_DEBUG_OBJECT (self, "CONTROL_STOP!");
740                                                 state = READTHREADSTATE_STOP;
741                                                 break;
742                                         case CONTROL_PAUSE:
743                                                 GST_DEBUG_OBJECT (self, "CONTROL_PAUSE!");
744                                                 state = READTRREADSTATE_PAUSED;
745                                                 break;
746                                         case CONTROL_RUN:
747                                                 GST_DEBUG_OBJECT (self, "CONTROL_RUN");
748                                                 state = READTRREADSTATE_RUNNING;
749                                                 break;
750                                         default:
751                                                 GST_ERROR_OBJECT (self, "illegal control socket command %c received!", command);
752                                 }
753                                 continue;
754                         }
755                         else if ( G_LIKELY(rfd[1].revents & POLLIN) )
756                         {
757                                 int rlen = read(enc->fd, enc->buffer, VBUFSIZE);
758                                 if (G_UNLIKELY (!self->encoder_clock))
759                                 {
760                                         GST_DEBUG_OBJECT(self, "no encoder clock yet... continue");
761                                         continue;
762                                 }
763                                 clock_time = gst_clock_get_internal_time (self->encoder_clock);
764                                 base_time = gst_element_get_base_time(GST_ELEMENT(self));
765                                 if (rlen <= 0 || rlen % VBDSIZE ) {
766                                         if ( errno == 512 )
767                                                 goto stop_running;
768                                         GST_WARNING_OBJECT (self, "read error %s (%i)", strerror(errno), errno);
769                                         goto stop_running;
770                                 }
771                                 self->descriptors_available = rlen / VBDSIZE;
772                                 GST_LOG_OBJECT (self, "encoder buffer was empty, %d descriptors available", self->descriptors_available);
773                         }
774                         if (self->flushing)
775                         {
776                                 g_mutex_lock (&self->mutex);
777                                 GST_DEBUG_OBJECT (self, "FLUSHING!");
778                                 g_cond_signal (&self->cond);
779                                 g_mutex_unlock (&self->mutex);
780                                 continue;
781                         }
782                 }
783
784                 while (self->descriptors_count < self->descriptors_available)
785                 {
786                         GstClockTime encoder_dts = GST_CLOCK_TIME_NONE;
787                         GstClockTime encoder_pts = GST_CLOCK_TIME_NONE;
788                         GstClockTime result_dts = GST_CLOCK_TIME_NONE;
789                         GstClockTime result_pts = GST_CLOCK_TIME_NONE;
790                         gint64 dts_pts_offset;
791                         gboolean skip_frame = FALSE;
792
793                         off_t offset = self->descriptors_count * VBDSIZE;
794                         VideoBufferDescriptor *desc = (VideoBufferDescriptor*)(&enc->buffer[offset]);
795
796                         uint32_t f = desc->stCommon.uiFlags;
797
798                         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);
799
800                         if (G_UNLIKELY (f & CDB_FLAG_METADATA))
801                         {
802                                 GST_LOG_OBJECT (self, "CDB_FLAG_METADATA... skip outdated packet");
803                                 self->descriptors_count = self->descriptors_available;
804                                 continue;
805                         }
806
807                         // uiDTS since kernel driver booted
808                         if (f & VBD_FLAG_DTS_VALID && desc->uiDTS)
809                         {
810                                 encoder_dts = MPEGTIME_TO_GSTTIME(desc->uiDTS);
811                                 GST_LOG_OBJECT (self, "f & VBD_FLAG_DTS_VALID && encoder's uiDTS=%" GST_TIME_FORMAT"", GST_TIME_ARGS(encoder_dts));
812
813                                 g_mutex_lock (&self->mutex);
814                                 if (G_UNLIKELY (self->dts_offset == GST_CLOCK_TIME_NONE && self->flushing == FALSE))
815                                 {
816                                         if (self->dreamaudiosrc)
817                                         {
818                                                 guint64 audiosource_dts_offset;
819                                                 g_signal_emit_by_name(self->dreamaudiosrc, "get-dts-offset", &audiosource_dts_offset);
820                                                 if (audiosource_dts_offset != GST_CLOCK_TIME_NONE)
821                                                 {
822                                                         GST_DEBUG_OBJECT (self, "use DREAMAUDIOSOURCE's dts_offset=%" GST_TIME_FORMAT "", GST_TIME_ARGS (audiosource_dts_offset) );
823                                                         self->dts_offset = audiosource_dts_offset;
824                                                 }
825                                         }
826                                         else if (self->dts_offset == GST_CLOCK_TIME_NONE)
827                                         {
828                                                 self->dts_offset = encoder_dts - clock_time;
829                                                 GST_DEBUG_OBJECT (self, "use encoder_dts-clock_time as dts_offset (%" GST_TIME_FORMAT" = %" GST_TIME_FORMAT" - %" GST_TIME_FORMAT")", GST_TIME_ARGS (self->dts_offset), GST_TIME_ARGS (encoder_dts), GST_TIME_ARGS (clock_time));
830                                         }
831                                 }
832                                 if (G_UNLIKELY (self->dts_valid == FALSE && self->dts_offset != GST_CLOCK_TIME_NONE))
833                                         self->dts_valid = TRUE;
834                                 g_mutex_unlock (&self->mutex);
835                         }
836
837                         g_mutex_lock (&self->mutex);
838                         if (G_UNLIKELY (self->dts_valid == FALSE))
839                         {
840                                 GST_DEBUG_OBJECT (self, "dts_valid not set, skipping frame...");
841                                 self->descriptors_count++;
842                                 g_mutex_unlock (&self->mutex);
843                                 break;
844                         }
845                         else
846                                 g_mutex_unlock (&self->mutex);
847
848                         if (G_UNLIKELY (encoder_dts < self->dts_offset))
849                         {
850                                 GST_DEBUG_OBJECT (self, "encoder_dts < dts_offset, skipping frame...");
851                                 skip_frame = TRUE;
852                         }
853 //                      if (self->video_info.fps_d)
854 //                              GST_BUFFER_DURATION(readbuf) = gst_util_uint64_scale (GST_SECOND, self->video_info.fps_d, self->video_info.fps_n);
855
856                         if (!skip_frame && encoder_dts != GST_CLOCK_TIME_NONE)
857                         {
858                                 if (f & CDB_FLAG_PTS_VALID)
859                                         encoder_pts = MPEGTIME_TO_GSTTIME(desc->stCommon.uiPTS);
860                                 else
861                                         encoder_pts = encoder_dts;
862                                 dts_pts_offset = encoder_pts - encoder_dts;
863
864                                 GstClockTime orig_dts_clock_time = encoder_dts - self->dts_offset;
865                                 GstClockTime orig_pts_clock_time = orig_dts_clock_time + dts_pts_offset;
866                                 GstClockTime calib_dts_clock_time = orig_dts_clock_time;
867
868                                 GstClockTime internal, external;
869                                 GstClockTime rate_n, rate_d;
870                                 GstClockTimeDiff diff;
871
872                                 gst_clock_get_calibration (self->encoder_clock, &internal, &external, &rate_n, &rate_d);
873
874                                 if (internal > orig_dts_clock_time) {
875                                         diff = internal - orig_dts_clock_time;
876                                         diff = gst_util_uint64_scale (diff, rate_n, rate_d);
877                                         calib_dts_clock_time = external - diff;
878                                 } else {
879                                         diff = orig_dts_clock_time - internal;
880                                         diff = gst_util_uint64_scale (diff, rate_n, rate_d);
881                                         calib_dts_clock_time = external + diff;
882                                 }
883
884                                 if ( calib_dts_clock_time < base_time )
885                                 {
886                                         GST_DEBUG_OBJECT (self, "calib_dts_clock_time < base_time, skipping frame...");
887                                         skip_frame = TRUE;
888                                 }
889                                 result_dts = calib_dts_clock_time - base_time;
890                                 result_pts = result_dts + dts_pts_offset;
891
892 #define extra_timestamp_debug
893 #ifdef extra_timestamp_debug
894                                 GstClockTime my_int_time = gst_clock_get_internal_time(self->encoder_clock);
895                                 GstClockTime pipeline_int_time = GST_CLOCK_TIME_NONE;
896                                 GstClock *elemclk = gst_element_get_clock (GST_ELEMENT (self));
897                                 if (elemclk)
898                                 {
899                                         pipeline_int_time = gst_clock_get_internal_time(elemclk);
900                                         gst_object_unref (elemclk);
901                                 }
902
903                                 GST_LOG_OBJECT (self, "post-calibration\n"
904                                 "  %" GST_TIME_FORMAT " =base_time       %" GST_TIME_FORMAT " =clock_time            %" PRId64 " =dts_pts_offset\n"
905                                 "  %" GST_TIME_FORMAT " =encoder_dts     %" GST_TIME_FORMAT " =orig_dts_clock_time   %" GST_TIME_FORMAT " =calib_dts_clock_time   %" GST_TIME_FORMAT " =result_dts\n"
906                                 "  %" GST_TIME_FORMAT " =encoder_pts     %" GST_TIME_FORMAT " =orig_pts_clock_time                                            %" GST_TIME_FORMAT " =result_pts\n"
907                                 "  %" GST_TIME_FORMAT " =internal        %" GST_TIME_FORMAT " =external              %" GST_TIME_FORMAT " =diff                   %" PRId64 "/%" PRId64 " =rate\n"
908                                 "  %" GST_TIME_FORMAT " =my_int_time     %" GST_TIME_FORMAT " =pipeline_int_time"
909                                 ,
910                                 GST_TIME_ARGS (base_time), GST_TIME_ARGS (clock_time), dts_pts_offset,
911                                 GST_TIME_ARGS (encoder_dts), GST_TIME_ARGS (orig_dts_clock_time), GST_TIME_ARGS (calib_dts_clock_time), GST_TIME_ARGS (result_dts),
912                                 GST_TIME_ARGS (encoder_pts), GST_TIME_ARGS (orig_pts_clock_time), GST_TIME_ARGS (result_pts),
913                                 GST_TIME_ARGS (internal), GST_TIME_ARGS (external), GST_TIME_ARGS (diff), rate_n, rate_d,
914                                 GST_TIME_ARGS (my_int_time), GST_TIME_ARGS (pipeline_int_time)
915                                 );
916 #endif
917                         }
918
919                         if (!skip_frame)
920                         {
921                                 readbuf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, enc->cdb, VMMAPSIZE, desc->stCommon.uiOffset, desc->stCommon.uiLength, self, NULL);
922                                 if (result_dts != GST_CLOCK_TIME_NONE)
923                                 {
924                                         GST_BUFFER_DTS(readbuf) = result_dts;
925                                         GST_BUFFER_PTS(readbuf) = result_pts;
926                                 }
927                         }
928
929 #ifdef dump
930                         int wret = write(self->dumpfd, (unsigned char*)(enc->cdb + desc->stCommon.uiOffset), desc->stCommon.uiLength);
931                         GST_LOG_OBJECT (self, "read %i dumped %i total %" G_GSIZE_FORMAT " ", desc->stCommon.uiLength, wret, gst_buffer_get_size (*outbuf) );
932 #endif
933                         self->descriptors_count++;
934                         break;
935                 }
936
937                 if (self->descriptors_count == self->descriptors_available)
938                 {
939                         GST_LOG_OBJECT (self, "self->descriptors_count == self->descriptors_available -> release %i consumed descriptors", self->descriptors_count);
940                         if (state == READTHREADSTATE_STOP)
941                                 GST_DEBUG_OBJECT (self, "readthread stopping, don't write to fd anymore!");
942                         /* release consumed descs */
943                         else if (write(enc->fd, &self->descriptors_count, sizeof(self->descriptors_count)) != sizeof(self->descriptors_count)) {
944                                 GST_WARNING_OBJECT (self, "release consumed descs write error!");
945                                 goto stop_running;
946                         }
947                         self->descriptors_available = 0;
948                 }
949
950                 if (readbuf)
951                 {
952                         g_mutex_lock (&self->mutex);
953                         if (!self->flushing)
954                         {
955                                 while (g_queue_get_length (&self->current_frames) >= self->buffer_size)
956                                 {
957                                         GstBuffer * oldbuf = g_queue_pop_head (&self->current_frames);
958                                         GST_WARNING_OBJECT (self, "dropping %" GST_PTR_FORMAT " because of queue overflow! buffers count=%i", oldbuf, g_queue_get_length (&self->current_frames));
959                                         gst_buffer_unref(oldbuf);
960                                         GST_BUFFER_FLAG_SET ((GstBuffer *) g_queue_peek_head (&self->current_frames), GST_BUFFER_FLAG_DISCONT);
961                                 }
962                                 if (discont)
963                                 {
964                                         GST_BUFFER_FLAG_SET (readbuf, GST_BUFFER_FLAG_DISCONT);
965                                         discont = FALSE;
966                                 }
967                                 g_queue_push_tail (&self->current_frames, readbuf);
968                                 GST_INFO_OBJECT (self, "read %" GST_PTR_FORMAT " to queue... buffers count=%i", readbuf, g_queue_get_length (&self->current_frames));
969                                 g_cond_signal (&self->cond);
970                         }
971                         else
972                                 gst_buffer_unref(readbuf);
973 //                      g_cond_signal (&self->cond);
974                         g_mutex_unlock (&self->mutex);
975                 }
976         }
977
978         g_assert_not_reached ();
979         return;
980
981         stop_running:
982         {
983                 g_mutex_unlock (&self->mutex);
984                 g_cond_signal (&self->cond);
985                 GST_DEBUG ("stop running, exit thread");
986                 message = gst_message_new_stream_status (GST_OBJECT_CAST (self), GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (GST_OBJECT_PARENT(self)));
987                 g_value_init (&val, GST_TYPE_G_THREAD);
988                 g_value_set_boxed (&val, self->readthread);
989                 gst_message_set_stream_status_object (message, &val);
990                 g_value_unset (&val);
991                 GST_DEBUG_OBJECT (self, "posting LEAVE stream status");
992                 gst_element_post_message (GST_ELEMENT_CAST (self), message);
993                 return;
994         }
995 }
996
997 static GstFlowReturn
998 gst_dreamvideosource_create (GstPushSrc * psrc, GstBuffer ** outbuf)
999 {
1000         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (psrc);
1001
1002         GST_LOG_OBJECT (self, "new buffer requested. queue has %i buffers", g_queue_get_length (&self->current_frames));
1003
1004         g_mutex_lock (&self->mutex);
1005         while (g_queue_is_empty (&self->current_frames) && !self->flushing)
1006         {
1007                 GST_INFO_OBJECT (self, "waiting for buffer from encoder");
1008                 g_cond_wait (&self->cond, &self->mutex);
1009         }
1010
1011         *outbuf = g_queue_pop_head (&self->current_frames);
1012         g_mutex_unlock (&self->mutex);
1013
1014         if (*outbuf)
1015         {
1016                 GST_INFO_OBJECT (self, "pushing %" GST_PTR_FORMAT ". queue has %i buffers", *outbuf, g_queue_get_length (&self->current_frames));
1017                 return GST_FLOW_OK;
1018         }
1019         GST_INFO_OBJECT (self, "FLUSHING");
1020         return GST_FLOW_FLUSHING;
1021 }
1022
1023
1024 static GstStateChangeReturn gst_dreamvideosource_change_state (GstElement * element, GstStateChange transition)
1025 {
1026         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (element);
1027         GstStateChangeReturn sret = GST_STATE_CHANGE_SUCCESS;
1028         int ret;
1029
1030         switch (transition) {
1031                 case GST_STATE_CHANGE_NULL_TO_READY:
1032                 {
1033                         if (!gst_dreamvideosource_encoder_init (self))
1034                         {
1035                                 GError *err = g_error_new (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ, "Can't initialize encoder device");
1036                                 GstMessage *msg = gst_message_new_error (GST_OBJECT (self), err, NULL);
1037                                 gst_element_post_message (element, msg);
1038                                 g_error_free (err);
1039                                 return GST_STATE_CHANGE_FAILURE;
1040                         }
1041                         GST_DEBUG_OBJECT (self, "GST_STATE_CHANGE_NULL_TO_READY");
1042                         break;
1043                 }
1044                 case GST_STATE_CHANGE_READY_TO_PAUSED:
1045                         GST_LOG_OBJECT (self, "GST_STATE_CHANGE_READY_TO_PAUSED");
1046                         self->dreamaudiosrc = gst_bin_get_by_name_recurse_up(GST_BIN(GST_ELEMENT_PARENT(self)), "dreamaudiosource0");
1047                 #ifdef PROVIDE_CLOCK
1048                         if (self->dreamaudiosrc)
1049                         {
1050                                 self->encoder_clock = gst_element_provide_clock (self->dreamaudiosrc);
1051                                 GST_DEBUG_OBJECT (self, "using dreamaudiosrc's encoder_clock = %" GST_PTR_FORMAT, self->encoder_clock);
1052                         } else {
1053                                 self->encoder_clock = gst_dreamsource_clock_new ("GstDreamVideoSourceClock", self->encoder->fd);
1054                                 GST_OBJECT_FLAG_SET (self, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
1055                                 GstMessage* msg;
1056                                 msg = gst_message_new_clock_provide (GST_OBJECT_CAST (element), self->encoder_clock, TRUE);
1057                                 GST_DEBUG_OBJECT (self, "new clock: %" GST_PTR_FORMAT " %" GST_PTR_FORMAT " typename=%s", self->encoder_clock, msg, GST_MESSAGE_TYPE_NAME(msg));
1058                                 gst_element_post_message (element, msg);
1059                         }
1060                 #endif
1061                         self->dts_offset = GST_CLOCK_TIME_NONE;
1062                         self->flushing = TRUE;
1063                         self->readthread = g_thread_try_new ("dreamvideosrc-read", (GThreadFunc) gst_dreamvideosource_read_thread_func, self, NULL);
1064                         GST_DEBUG_OBJECT (self, "started readthread @%p", self->readthread );
1065                         break;
1066                 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1067                         g_mutex_lock (&self->mutex);
1068                         GST_LOG_OBJECT (self, "GST_STATE_CHANGE_PAUSED_TO_PLAYING");
1069                         self->dts_valid = FALSE;
1070                         GstClock *pipeline_clock = gst_element_get_clock (GST_ELEMENT (self));
1071                         if (pipeline_clock)
1072                         {
1073                                 if (self->dreamaudiosrc)
1074                                         GST_DEBUG_OBJECT (self, "dreamaudiosource owns the clock and is responsible for slaving it");
1075                                 else if (pipeline_clock != self->encoder_clock)
1076                                 {
1077                                         gst_clock_set_master (self->encoder_clock, pipeline_clock);
1078                                         GST_DEBUG_OBJECT (self, "slaved %" GST_PTR_FORMAT "to pipeline_clock %" GST_PTR_FORMAT "", self->encoder_clock, pipeline_clock);
1079                                 }
1080                                 else
1081                                         GST_DEBUG_OBJECT (self, "encoder_clock is master clock");
1082                         }
1083                                 else
1084                                         GST_WARNING_OBJECT (self, "no pipeline clock!");
1085                         ret = ioctl(self->encoder->fd, VENC_START);
1086                         if ( ret != 0 )
1087                                 goto fail;
1088                         self->descriptors_available = 0;
1089                         CLEAR_COMMAND (self);
1090                         g_mutex_unlock (&self->mutex);
1091                         break;
1092                 default:
1093                         break;
1094         }
1095
1096         if (GST_ELEMENT_CLASS (parent_class)->change_state)
1097                 sret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1098
1099         switch (transition) {
1100                 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1101                         g_mutex_lock (&self->mutex);
1102                         SEND_COMMAND (self, CONTROL_RUN);
1103                         GST_INFO_OBJECT (self, "started encoder!");
1104                         g_mutex_unlock (&self->mutex);
1105                         break;
1106                 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1107                         g_mutex_lock (&self->mutex);
1108                         GST_DEBUG_OBJECT (self, "GST_STATE_CHANGE_PLAYING_TO_PAUSED self->descriptors_count=%i self->descriptors_available=%i", self->descriptors_count, self->descriptors_available);
1109                         SEND_COMMAND (self, CONTROL_PAUSE);
1110                         if (self->descriptors_count < self->descriptors_available)
1111                                 self->descriptors_count = self->descriptors_available;
1112                         if (self->descriptors_count)
1113                                 write(self->encoder->fd, &self->descriptors_count, sizeof(self->descriptors_count));
1114                         ret = ioctl(self->encoder->fd, VENC_STOP);
1115                         if ( ret != 0 )
1116                                 goto fail;
1117 #ifdef PROVIDE_CLOCK
1118                         gst_clock_set_master (self->encoder_clock, NULL);
1119 #endif
1120                         GST_INFO_OBJECT (self, "stopped encoder!");
1121                         g_mutex_unlock (&self->mutex);
1122                         break;
1123                 case GST_STATE_CHANGE_PAUSED_TO_READY:
1124                         GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_PAUSED_TO_READY");
1125 #ifdef PROVIDE_CLOCK
1126                         gst_element_post_message (element, gst_message_new_clock_lost (GST_OBJECT_CAST (element), self->encoder_clock));
1127                         if (!self->dreamaudiosrc)
1128                                 gst_clock_set_calibration (self->encoder_clock, 0, 0, 1, 1);
1129 #endif
1130                         GST_DEBUG_OBJECT (self, "stopping readthread @%p...", self->readthread);
1131                         SEND_COMMAND (self, CONTROL_STOP);
1132                         g_thread_join (self->readthread);
1133                         if (self->dreamaudiosrc)
1134                                 gst_object_unref(self->dreamaudiosrc);
1135                         self->dreamaudiosrc = NULL;
1136                         break;
1137                 case GST_STATE_CHANGE_READY_TO_NULL:
1138                         gst_dreamvideosource_encoder_release (self);
1139                         GST_DEBUG_OBJECT (self,"GST_STATE_CHANGE_READY_TO_NULL");
1140                         break;
1141                 default:
1142                         break;
1143         }
1144
1145         return sret;
1146 fail:
1147         GST_ERROR_OBJECT(self,"can't perform encoder ioctl! error: %s (%i)", strerror(errno), errno);
1148         g_mutex_unlock (&self->mutex);
1149         return GST_STATE_CHANGE_FAILURE;
1150 }
1151
1152 static void
1153 gst_dreamvideosource_dispose (GObject * gobject)
1154 {
1155         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (gobject);
1156 #ifdef PROVIDE_CLOCK
1157         if (self->encoder_clock) {
1158                 gst_object_unref (self->encoder_clock);
1159                 self->encoder_clock = NULL;
1160         }
1161 #endif
1162 #ifdef dump
1163         close(self->dumpfd);
1164 #endif
1165         if (self->current_caps)
1166                 gst_caps_unref(self->current_caps);
1167         if (self->new_caps)
1168                 gst_caps_unref(self->new_caps);
1169         g_mutex_clear (&self->mutex);
1170         g_cond_clear (&self->cond);
1171         GST_DEBUG_OBJECT (self, "disposed");
1172         G_OBJECT_CLASS (parent_class)->dispose (gobject);
1173 }
1174
1175 #ifdef PROVIDE_CLOCK
1176 static GstClock *gst_dreamvideosource_provide_clock (GstElement * element)
1177 {
1178         GstDreamVideoSource *self = GST_DREAMVIDEOSOURCE (element);
1179
1180         if (!self->encoder || self->encoder->fd < 0)
1181         {
1182                 GST_DEBUG_OBJECT (self, "encoder device not started, can't provide clock!");
1183                 return NULL;
1184         }
1185
1186         if (!self->encoder_clock)
1187         {
1188                 GST_DEBUG_OBJECT (self, "this element is not the clock provider!");
1189                 return NULL;
1190         }
1191
1192         return GST_CLOCK_CAST (gst_object_ref (self->encoder_clock));
1193 }
1194 #endif