gst/base/: Implement clock sync in base class.
[platform/upstream/gstreamer.git] / libs / gst / base / gstbasesrc.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *               2000,2005 Wim Taymans <wim@fluendo.com>
4  *
5  * gstbasesrc.c:
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:gstbasesrc
25  * @short_description: Base class for getrange based source elements
26  * @see_also: #GstBaseTransform, #GstBaseSink
27  *
28  * This class is mostly useful for elements that do byte based
29  * access to a random access resource, like files.
30  * If random access is not possible, the live-mode should be set
31  * to TRUE.
32  *
33  * <itemizedlist>
34  *   <listitem><para>one source pad</para></listitem>
35  *   <listitem><para>handles state changes</para></listitem>
36  *   <listitem><para>does flushing</para></listitem>
37  *   <listitem><para>preroll with optional preview</para></listitem>
38  *   <listitem><para>pull/push mode</para></listitem>
39  *   <listitem><para>EOS handling</para></listitem>
40  * </itemizedlist>
41  */
42
43 #include <stdlib.h>
44 #include <string.h>
45
46 #ifdef HAVE_CONFIG_H
47 #  include "config.h"
48 #endif
49
50 #include "gstbasesrc.h"
51 #include "gsttypefindhelper.h"
52 #include <gst/gstmarshal.h>
53 #include <gst/gst-i18n-lib.h>
54
55 #define DEFAULT_BLOCKSIZE       4096
56 #define DEFAULT_NUM_BUFFERS     -1
57
58 GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);
59 #define GST_CAT_DEFAULT gst_base_src_debug
60
61 /* BaseSrc signals and args */
62 enum
63 {
64   /* FILL ME */
65   LAST_SIGNAL
66 };
67
68 enum
69 {
70   PROP_0,
71   PROP_BLOCKSIZE,
72   PROP_NUM_BUFFERS,
73 };
74
75 static GstElementClass *parent_class = NULL;
76
77 static void gst_base_src_base_init (gpointer g_class);
78 static void gst_base_src_class_init (GstBaseSrcClass * klass);
79 static void gst_base_src_init (GstBaseSrc * src, gpointer g_class);
80 static void gst_base_src_finalize (GObject * object);
81
82
83 GType
84 gst_base_src_get_type (void)
85 {
86   static GType base_src_type = 0;
87
88   if (!base_src_type) {
89     static const GTypeInfo base_src_info = {
90       sizeof (GstBaseSrcClass),
91       (GBaseInitFunc) gst_base_src_base_init,
92       NULL,
93       (GClassInitFunc) gst_base_src_class_init,
94       NULL,
95       NULL,
96       sizeof (GstBaseSrc),
97       0,
98       (GInstanceInitFunc) gst_base_src_init,
99     };
100
101     base_src_type = g_type_register_static (GST_TYPE_ELEMENT,
102         "GstBaseSrc", &base_src_info, G_TYPE_FLAG_ABSTRACT);
103   }
104   return base_src_type;
105 }
106 static GstCaps *gst_base_src_getcaps (GstPad * pad);
107 static gboolean gst_base_src_setcaps (GstPad * pad, GstCaps * caps);
108
109 static gboolean gst_base_src_activate_push (GstPad * pad, gboolean active);
110 static gboolean gst_base_src_activate_pull (GstPad * pad, gboolean active);
111 static void gst_base_src_set_property (GObject * object, guint prop_id,
112     const GValue * value, GParamSpec * pspec);
113 static void gst_base_src_get_property (GObject * object, guint prop_id,
114     GValue * value, GParamSpec * pspec);
115 static gboolean gst_base_src_event_handler (GstPad * pad, GstEvent * event);
116 static gboolean gst_base_src_send_event (GstElement * elem, GstEvent * event);
117
118 static gboolean gst_base_src_query (GstPad * pad, GstQuery * query);
119
120 static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc);
121 static gboolean gst_base_src_default_newsegment (GstBaseSrc * src);
122
123 static gboolean gst_base_src_unlock (GstBaseSrc * basesrc);
124 static gboolean gst_base_src_get_size (GstBaseSrc * basesrc, guint64 * size);
125 static gboolean gst_base_src_start (GstBaseSrc * basesrc);
126 static gboolean gst_base_src_stop (GstBaseSrc * basesrc);
127
128 static GstStateChangeReturn gst_base_src_change_state (GstElement * element,
129     GstStateChange transition);
130
131 static void gst_base_src_loop (GstPad * pad);
132 static gboolean gst_base_src_check_get_range (GstPad * pad);
133 static GstFlowReturn gst_base_src_pad_get_range (GstPad * pad, guint64 offset,
134     guint length, GstBuffer ** buf);
135 static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset,
136     guint length, GstBuffer ** buf);
137
138 static void
139 gst_base_src_base_init (gpointer g_class)
140 {
141   GST_DEBUG_CATEGORY_INIT (gst_base_src_debug, "basesrc", 0, "basesrc element");
142 }
143
144 static void
145 gst_base_src_class_init (GstBaseSrcClass * klass)
146 {
147   GObjectClass *gobject_class;
148   GstElementClass *gstelement_class;
149
150   gobject_class = (GObjectClass *) klass;
151   gstelement_class = (GstElementClass *) klass;
152
153   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
154
155   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_src_finalize);
156   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_src_set_property);
157   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_src_get_property);
158
159   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BLOCKSIZE,
160       g_param_spec_ulong ("blocksize", "Block size",
161           "Size in bytes to read per buffer", 1, G_MAXULONG, DEFAULT_BLOCKSIZE,
162           G_PARAM_READWRITE));
163
164   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NUM_BUFFERS,
165       g_param_spec_int ("num-buffers", "num-buffers",
166           "Number of buffers to output before sending EOS", -1, G_MAXINT,
167           DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE));
168
169   gstelement_class->change_state =
170       GST_DEBUG_FUNCPTR (gst_base_src_change_state);
171   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_src_send_event);
172
173   klass->negotiate = gst_base_src_default_negotiate;
174   klass->newsegment = gst_base_src_default_newsegment;
175 }
176
177 static void
178 gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
179 {
180   GstPad *pad;
181   GstPadTemplate *pad_template;
182
183   basesrc->is_live = FALSE;
184   basesrc->live_lock = g_mutex_new ();
185   basesrc->live_cond = g_cond_new ();
186   basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
187   basesrc->num_buffers_left = -1;
188
189   basesrc->can_activate_push = TRUE;
190   basesrc->pad_mode = GST_ACTIVATE_NONE;
191
192   pad_template =
193       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
194   g_return_if_fail (pad_template != NULL);
195
196   GST_DEBUG_OBJECT (basesrc, "creating src pad");
197   pad = gst_pad_new_from_template (pad_template, "src");
198
199   GST_DEBUG_OBJECT (basesrc, "setting functions on src pad");
200   gst_pad_set_activatepush_function (pad,
201       GST_DEBUG_FUNCPTR (gst_base_src_activate_push));
202   gst_pad_set_activatepull_function (pad,
203       GST_DEBUG_FUNCPTR (gst_base_src_activate_pull));
204   gst_pad_set_event_function (pad,
205       GST_DEBUG_FUNCPTR (gst_base_src_event_handler));
206   gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_query));
207   gst_pad_set_checkgetrange_function (pad,
208       GST_DEBUG_FUNCPTR (gst_base_src_check_get_range));
209   gst_pad_set_getrange_function (pad,
210       GST_DEBUG_FUNCPTR (gst_base_src_pad_get_range));
211   gst_pad_set_getcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_getcaps));
212   gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_setcaps));
213
214   /* hold pointer to pad */
215   basesrc->srcpad = pad;
216   GST_DEBUG_OBJECT (basesrc, "adding src pad");
217   gst_element_add_pad (GST_ELEMENT (basesrc), pad);
218
219   basesrc->blocksize = DEFAULT_BLOCKSIZE;
220   basesrc->clock_id = NULL;
221   basesrc->segment_start = 0;
222   basesrc->segment_end = -1;
223
224   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
225
226   GST_DEBUG_OBJECT (basesrc, "init done");
227 }
228
229 static void
230 gst_base_src_finalize (GObject * object)
231 {
232   GstBaseSrc *basesrc;
233
234   basesrc = GST_BASE_SRC (object);
235
236   g_mutex_free (basesrc->live_lock);
237   g_cond_free (basesrc->live_cond);
238
239   G_OBJECT_CLASS (parent_class)->finalize (object);
240 }
241
242 /**
243  * gst_base_src_set_live:
244  * @src: base source instance
245  * @live: new live-mode
246  *
247  * If the element listens to a live source, the @livemode should
248  * be set to %TRUE. This declares that this source can't seek.
249  */
250 void
251 gst_base_src_set_live (GstBaseSrc * src, gboolean live)
252 {
253   GST_LIVE_LOCK (src);
254   src->is_live = live;
255   GST_LIVE_UNLOCK (src);
256 }
257
258 /**
259  * gst_base_src_is_live:
260  * @src: base source instance
261  *
262  * Check if an element is in live mode.
263  *
264  * Returns: %TRUE if element is in live mode.
265  */
266 gboolean
267 gst_base_src_is_live (GstBaseSrc * src)
268 {
269   gboolean result;
270
271   GST_LIVE_LOCK (src);
272   result = src->is_live;
273   GST_LIVE_UNLOCK (src);
274
275   return result;
276 }
277
278 static gboolean
279 gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
280 {
281   GstBaseSrcClass *bclass;
282   GstBaseSrc *bsrc;
283   gboolean res = TRUE;
284
285   bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
286   bclass = GST_BASE_SRC_GET_CLASS (bsrc);
287
288   if (bclass->set_caps)
289     res = bclass->set_caps (bsrc, caps);
290
291   return res;
292 }
293
294 static GstCaps *
295 gst_base_src_getcaps (GstPad * pad)
296 {
297   GstBaseSrcClass *bclass;
298   GstBaseSrc *bsrc;
299   GstCaps *caps = NULL;
300
301   bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
302   bclass = GST_BASE_SRC_GET_CLASS (bsrc);
303   if (bclass->get_caps)
304     caps = bclass->get_caps (bsrc);
305
306   if (caps == NULL) {
307     GstPadTemplate *pad_template;
308
309     pad_template =
310         gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
311     if (pad_template != NULL) {
312       caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
313     }
314   }
315   return caps;
316 }
317
318 static gboolean
319 gst_base_src_query (GstPad * pad, GstQuery * query)
320 {
321   GstBaseSrc *src;
322   gboolean res;
323
324   src = GST_BASE_SRC (gst_pad_get_parent (pad));
325
326   switch (GST_QUERY_TYPE (query)) {
327     case GST_QUERY_POSITION:
328     {
329       GstFormat format;
330
331       gst_query_parse_position (query, &format, NULL);
332       switch (format) {
333         case GST_FORMAT_DEFAULT:
334         case GST_FORMAT_BYTES:
335           gst_query_set_position (query, GST_FORMAT_BYTES, src->offset);
336           res = TRUE;
337           break;
338         case GST_FORMAT_PERCENT:
339         {
340           gboolean b;
341           gint64 i64;
342           guint64 ui64;
343
344           b = gst_base_src_get_size (src, &ui64);
345           if (b && src->offset > ui64)
346             i64 = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, src->offset,
347                 ui64);
348           else
349             i64 = GST_FORMAT_PERCENT_MAX;
350
351           gst_query_set_position (query, GST_FORMAT_PERCENT, i64);
352           res = TRUE;
353           break;
354         }
355         default:
356           res = FALSE;
357           break;
358       }
359       break;
360     }
361     case GST_QUERY_DURATION:
362     {
363       GstFormat format;
364
365       gst_query_parse_duration (query, &format, NULL);
366       switch (format) {
367         case GST_FORMAT_DEFAULT:
368         case GST_FORMAT_BYTES:
369         {
370           gboolean b;
371           gint64 i64;
372           guint64 ui64;
373
374           b = gst_base_src_get_size (src, &ui64);
375           /* better to make get_size take an int64 */
376           i64 = b ? (gint64) ui64 : -1;
377           gst_query_set_duration (query, GST_FORMAT_BYTES, i64);
378           res = TRUE;
379           break;
380         }
381         case GST_FORMAT_PERCENT:
382           gst_query_set_duration (query, GST_FORMAT_PERCENT,
383               GST_FORMAT_PERCENT_MAX);
384           res = TRUE;
385           break;
386         default:
387           res = FALSE;
388           break;
389       }
390       break;
391     }
392
393     case GST_QUERY_SEEKING:
394       gst_query_set_seeking (query, GST_FORMAT_BYTES,
395           src->seekable, 0, src->size);
396       res = TRUE;
397       break;
398
399     case GST_QUERY_SEGMENT:
400     {
401       gint64 start, stop;
402
403       start = src->segment_start;
404       /* no end segment configured, current size then */
405       if ((stop = src->segment_end) == -1)
406         stop = src->size;
407
408       /* FIXME, we can't report our rate as we did not store it, d'oh!.
409        * Also, subclasses might want to support other formats. */
410       gst_query_set_segment (query, 1.0, GST_FORMAT_BYTES, start, stop);
411       res = TRUE;
412       break;
413     }
414
415     case GST_QUERY_FORMATS:
416       gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT,
417           GST_FORMAT_BYTES, GST_FORMAT_PERCENT);
418       res = TRUE;
419       break;
420
421     case GST_QUERY_LATENCY:
422     case GST_QUERY_JITTER:
423     case GST_QUERY_RATE:
424     case GST_QUERY_CONVERT:
425     default:
426       res = gst_pad_query_default (pad, query);
427       break;
428   }
429
430   gst_object_unref (src);
431   return res;
432 }
433
434 static gboolean
435 gst_base_src_default_newsegment (GstBaseSrc * src)
436 {
437   GstEvent *event;
438
439   GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
440       " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
441
442   event = gst_event_new_newsegment (FALSE, 1.0,
443       GST_FORMAT_BYTES, src->segment_start, src->segment_end,
444       src->segment_start);
445
446   return gst_pad_push_event (src->srcpad, event);
447 }
448
449 static gboolean
450 gst_base_src_newsegment (GstBaseSrc * src)
451 {
452   GstBaseSrcClass *bclass;
453   gboolean result = FALSE;
454
455   bclass = GST_BASE_SRC_GET_CLASS (src);
456
457   if (bclass->newsegment)
458     result = bclass->newsegment (src);
459
460   return result;
461 }
462
463 /* based on the event parameters configure the segment_start/stop
464  * times. Called with STREAM_LOCK.
465  */
466 static gboolean
467 gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
468 {
469   gdouble rate;
470   GstFormat format;
471   GstSeekFlags flags;
472   GstSeekType cur_type, stop_type;
473   gint64 cur, stop;
474   gboolean update_stop, update_start;
475
476   gst_event_parse_seek (event, &rate, &format, &flags,
477       &cur_type, &cur, &stop_type, &stop);
478
479   /* parse the loop flag */
480   /* FIXME, need to store other flags and rate too */
481   src->segment_loop = (flags & GST_SEEK_FLAG_SEGMENT) != 0;
482
483   /* assume we'll update both start and stop values */
484   update_start = TRUE;
485   update_stop = TRUE;
486
487   /* perform the seek, segment_start is never invalid */
488   switch (cur_type) {
489     case GST_SEEK_TYPE_NONE:
490       /* no update to segment */
491       cur = src->segment_start;
492       update_start = FALSE;
493       break;
494     case GST_SEEK_TYPE_SET:
495       /* cur holds desired position */
496       break;
497     case GST_SEEK_TYPE_CUR:
498       /* add cur to currently configure segment */
499       cur = src->segment_start + cur;
500       break;
501     case GST_SEEK_TYPE_END:
502       /* add cur to total length */
503       cur = src->size + cur;
504       break;
505   }
506   /* bring in sane range */
507   if (src->size != -1)
508     cur = CLAMP (cur, 0, src->size);
509   else
510     cur = MAX (cur, 0);
511
512   /* segment_end can be -1 if we have not configured a stop. */
513   switch (stop_type) {
514     case GST_SEEK_TYPE_NONE:
515       stop = src->segment_end;
516       update_stop = FALSE;
517       break;
518     case GST_SEEK_TYPE_SET:
519       /* stop folds required value */
520       break;
521     case GST_SEEK_TYPE_CUR:
522       if (src->segment_end != -1)
523         stop = src->segment_end + stop;
524       else
525         stop = -1;
526       break;
527     case GST_SEEK_TYPE_END:
528       if (src->size != -1)
529         stop = src->size + stop;
530       else
531         stop = -1;
532       break;
533   }
534
535   /* if we have a valid stop time, make sure it is clipped */
536   if (stop != -1) {
537     if (src->size != -1)
538       stop = CLAMP (stop, 0, src->size);
539     else
540       stop = MAX (stop, 0);
541   }
542
543   src->segment_start = cur;
544   src->segment_end = stop;
545
546   /* update our offset if it was updated */
547   if (update_start)
548     src->offset = cur;
549
550   GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT
551       " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
552
553   return TRUE;
554 }
555
556 /* this code implements the seeking. It is a good example
557  * handling all cases (modulo the FIXMEs).
558  *
559  * A seek updates the currently configured segment_start
560  * and segment_stop values based on the SEEK_TYPE. If the
561  * segment_start value is updated, a seek to this new position
562  * should be performed.
563  *
564  * The seek can only be executed when we are not currently
565  * streaming any data, to make sure that this is the case, we
566  * acquire the STREAM_LOCK which is taken when we are in the
567  * _loop() function or when a getrange() is called. Normally
568  * we will not receive a seek if we are operating in pull mode
569  * though.
570  *
571  * When we are in the loop() function, we might be in the middle
572  * of pushing a buffer, which might block in a sink. To make sure
573  * that the push gets unblocked we push out a FLUSH_START event.
574  * Our loop function will get a WRONG_STATE return value from
575  * the push and will pause, effectively releasing the STREAM_LOCK.
576  *
577  * For a non-flushing seek, we pause the task, which might eventually
578  * release the STREAM_LOCK. We say eventually because when the sink
579  * blocks on the sample we might wait a very long time until the sink
580  * unblocks the sample. In any case we acquire the STREAM_LOCK and
581  * can continue the seek. A non-flushing seek is normally done in a 
582  * running pipeline to perform seamless playback.
583  *
584  * After updating the segment_start/stop values, we prepare for
585  * streaming again. We push out a FLUSH_STOP to make the peer pad
586  * accept data again and we start our task again.
587  *
588  * A segment seek posts a message on the bus saying that the playback
589  * of the segment started. We store the segment flag internally because
590  * when we reach the segment_stop we have to post a segment_done
591  * instead of EOS when doing a segment seek.
592  */
593 static gboolean
594 gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
595 {
596   gdouble rate;
597   GstFormat format;
598   GstSeekFlags flags;
599   gboolean flush;
600
601   gst_event_parse_seek (event, &rate, &format, &flags, NULL, NULL, NULL, NULL);
602
603   /* FIXME subclasses should be able to provide other formats */
604   /* get seek format */
605   if (format == GST_FORMAT_DEFAULT)
606     format = GST_FORMAT_BYTES;
607   /* we can only seek bytes */
608   if (format != GST_FORMAT_BYTES)
609     goto unsupported_seek;
610
611   flush = flags & GST_SEEK_FLAG_FLUSH;
612
613   /* send flush start */
614   if (flush)
615     gst_pad_push_event (src->srcpad, gst_event_new_flush_start ());
616   else
617     gst_pad_pause_task (src->srcpad);
618
619   /* unblock streaming thread */
620   gst_base_src_unlock (src);
621
622   /* grab streaming lock, this should eventually be possible, either
623    * because the task is paused or out streaming thread stopped 
624    * because our peer is flushing. */
625   GST_STREAM_LOCK (src->srcpad);
626
627   /* now configure the segment */
628   gst_base_src_configure_segment (src, event);
629
630   /* and prepare to continue streaming */
631   if (flush)
632     /* send flush stop, peer will accept data and events again. We
633      * are not yet providing data as we still have the STREAM_LOCK. */
634     gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
635
636   /* now make sure the newsegment will be send from the streaming
637    * thread. We could opt to send it here too. */
638   src->need_newsegment = TRUE;
639
640   if (src->segment_loop) {
641     /* FIXME subclasses should be able to provide other formats */
642     gst_element_post_message (GST_ELEMENT (src),
643         gst_message_new_segment_start (GST_OBJECT (src), GST_FORMAT_BYTES,
644             src->segment_start));
645   }
646
647   /* and restart the task in case it got paused explicitely or by
648    * the FLUSH_START event we pushed out. */
649   gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
650       src->srcpad);
651
652   /* and release the lock again so we can continue streaming */
653   GST_STREAM_UNLOCK (src->srcpad);
654
655   return TRUE;
656
657   /* ERROR */
658 unsupported_seek:
659   {
660     GST_DEBUG_OBJECT (src, "invalid format, seek aborted.");
661
662     return FALSE;
663   }
664 }
665
666 /* all events send to this element directly
667  */
668 static gboolean
669 gst_base_src_send_event (GstElement * element, GstEvent * event)
670 {
671   GstBaseSrc *src;
672   gboolean result;
673
674   src = GST_BASE_SRC (element);
675
676   switch (GST_EVENT_TYPE (event)) {
677     case GST_EVENT_SEEK:
678       result = gst_base_src_configure_segment (src, event);
679       break;
680     default:
681       result = FALSE;
682       break;
683   }
684
685   return result;
686 }
687
688 static gboolean
689 gst_base_src_event_handler (GstPad * pad, GstEvent * event)
690 {
691   GstBaseSrc *src;
692   GstBaseSrcClass *bclass;
693   gboolean result;
694
695   src = GST_BASE_SRC (gst_pad_get_parent (pad));
696   bclass = GST_BASE_SRC_GET_CLASS (src);
697
698   if (bclass->event) {
699     if (!(result = bclass->event (src, event)))
700       goto subclass_failed;
701   }
702
703   switch (GST_EVENT_TYPE (event)) {
704     case GST_EVENT_SEEK:
705       /* is normally called when in push mode */
706       if (!src->seekable)
707         goto not_seekable;
708
709       result = gst_base_src_do_seek (src, event);
710       break;
711     case GST_EVENT_FLUSH_START:
712       /* cancel any blocking getrange, is normally called
713        * when in pull mode. */
714       result = gst_base_src_unlock (src);
715       break;
716     case GST_EVENT_FLUSH_STOP:
717     default:
718       result = TRUE;
719       break;
720   }
721   gst_event_unref (event);
722   gst_object_unref (src);
723
724   return result;
725
726   /* ERRORS */
727 subclass_failed:
728   {
729     GST_DEBUG_OBJECT (src, "subclass refused event");
730     gst_object_unref (src);
731     gst_event_unref (event);
732     return result;
733   }
734 not_seekable:
735   {
736     GST_DEBUG_OBJECT (src, "is not seekable");
737     gst_object_unref (src);
738     gst_event_unref (event);
739     return FALSE;
740   }
741 }
742
743 static void
744 gst_base_src_set_property (GObject * object, guint prop_id,
745     const GValue * value, GParamSpec * pspec)
746 {
747   GstBaseSrc *src;
748
749   src = GST_BASE_SRC (object);
750
751   switch (prop_id) {
752     case PROP_BLOCKSIZE:
753       src->blocksize = g_value_get_ulong (value);
754       break;
755     case PROP_NUM_BUFFERS:
756       src->num_buffers = g_value_get_int (value);
757       break;
758     default:
759       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
760       break;
761   }
762 }
763
764 static void
765 gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
766     GParamSpec * pspec)
767 {
768   GstBaseSrc *src;
769
770   src = GST_BASE_SRC (object);
771
772   switch (prop_id) {
773     case PROP_BLOCKSIZE:
774       g_value_set_ulong (value, src->blocksize);
775       break;
776     case PROP_NUM_BUFFERS:
777       g_value_set_int (value, src->num_buffers);
778       break;
779     default:
780       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
781       break;
782   }
783 }
784
785 /* with STREAM_LOCK and LOCK*/
786 static GstClockReturn
787 gst_base_src_wait (GstBaseSrc * basesrc, GstClockTime time)
788 {
789   GstClockReturn ret;
790   GstClockID id;
791   GstClock *clock;
792
793   if ((clock = GST_ELEMENT_CLOCK (basesrc)) == NULL)
794     return GST_CLOCK_OK;
795
796   /* clock_id should be NULL outside of this function */
797   g_assert (basesrc->clock_id == NULL);
798   g_assert (GST_CLOCK_TIME_IS_VALID (time));
799
800   id = gst_clock_new_single_shot_id (clock, time);
801
802   basesrc->clock_id = id;
803   /* release the object lock while waiting */
804   GST_UNLOCK (basesrc);
805
806   ret = gst_clock_id_wait (id, NULL);
807
808   GST_LOCK (basesrc);
809   gst_clock_id_unref (id);
810   basesrc->clock_id = NULL;
811
812   return ret;
813 }
814
815
816 /* perform synchronisation on a buffer
817  */
818 static GstClockReturn
819 gst_base_src_do_sync (GstBaseSrc * basesrc, GstBuffer * buffer)
820 {
821   GstClockReturn result = GST_CLOCK_OK;
822   GstClockTime start, end;
823   GstBaseSrcClass *bclass;
824   gboolean start_valid;
825   GstClockTime base_time;
826
827   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
828
829   start = end = -1;
830   if (bclass->get_times)
831     bclass->get_times (basesrc, buffer, &start, &end);
832
833   start_valid = GST_CLOCK_TIME_IS_VALID (start);
834
835   /* if we don't have a timestamp, we don't sync */
836   if (!start_valid) {
837     GST_DEBUG_OBJECT (basesrc, "get_times returned invalid start");
838     goto done;
839   }
840
841   GST_DEBUG_OBJECT (basesrc, "got times start: %" GST_TIME_FORMAT
842       ", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end));
843
844   /* now do clocking */
845   GST_LOCK (basesrc);
846   base_time = GST_ELEMENT_CAST (basesrc)->base_time;
847
848   GST_LOG_OBJECT (basesrc,
849       "waiting for clock, base time %" GST_TIME_FORMAT
850       ", stream_start %" GST_TIME_FORMAT,
851       GST_TIME_ARGS (base_time), GST_TIME_ARGS (start));
852
853   result = gst_base_src_wait (basesrc, start + base_time);
854   GST_UNLOCK (basesrc);
855
856   GST_LOG_OBJECT (basesrc, "clock entry done: %d", result);
857
858 done:
859   return result;
860 }
861
862
863 static GstFlowReturn
864 gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
865     GstBuffer ** buf)
866 {
867   GstFlowReturn ret;
868   GstBaseSrcClass *bclass;
869   gint64 maxsize;
870   GstClockReturn status;
871
872   bclass = GST_BASE_SRC_GET_CLASS (src);
873
874   GST_LIVE_LOCK (src);
875   if (src->is_live) {
876     while (!src->live_running) {
877       GST_DEBUG ("live source signal waiting");
878       GST_LIVE_SIGNAL (src);
879       GST_DEBUG ("live source waiting for running state");
880       GST_LIVE_WAIT (src);
881       GST_DEBUG ("live source unlocked");
882     }
883     /* FIXME, use another variable to signal stopping */
884     GST_LOCK (src->srcpad);
885     if (GST_PAD_IS_FLUSHING (src->srcpad))
886       goto flushing;
887     GST_UNLOCK (src->srcpad);
888   }
889   GST_LIVE_UNLOCK (src);
890
891   if (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED))
892     goto not_started;
893
894   if (G_UNLIKELY (!bclass->create))
895     goto no_function;
896
897   /* the max amount of bytes to read is the total size or
898    * up to the segment_end if present. */
899   if (src->segment_end != -1)
900     maxsize = MIN (src->size, src->segment_end);
901   else
902     maxsize = src->size;
903
904   GST_DEBUG_OBJECT (src,
905       "reading offset %" G_GUINT64_FORMAT ", length %u, size %" G_GINT64_FORMAT
906       ", segment_end %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
907       length, src->size, src->segment_end, maxsize);
908
909   /* check size */
910   if (maxsize != -1) {
911     if (offset > maxsize)
912       goto unexpected_length;
913
914     if (offset + length > maxsize) {
915       /* see if length of the file changed */
916       if (bclass->get_size)
917         bclass->get_size (src, &src->size);
918
919       if (src->segment_end != -1)
920         maxsize = MIN (src->size, src->segment_end);
921       else
922         maxsize = src->size;
923
924       if (offset + length > maxsize) {
925         length = maxsize - offset;
926       }
927     }
928   }
929   if (length == 0)
930     goto unexpected_length;
931
932   if (src->num_buffers_left == 0) {
933     goto reached_num_buffers;
934   } else {
935     if (src->num_buffers_left > 0)
936       src->num_buffers_left--;
937   }
938
939   ret = bclass->create (src, offset, length, buf);
940   if (ret != GST_FLOW_OK)
941     goto done;
942
943   /* now sync before pushing the buffer */
944   status = gst_base_src_do_sync (src, *buf);
945   switch (status) {
946     case GST_CLOCK_EARLY:
947       GST_DEBUG_OBJECT (src, "buffer too late!, returning anyway");
948       break;
949     case GST_CLOCK_OK:
950       GST_DEBUG_OBJECT (src, "buffer ok");
951       break;
952     default:
953       GST_DEBUG_OBJECT (src, "clock returned %d, not returning", status);
954       gst_buffer_unref (*buf);
955       *buf = NULL;
956       ret = GST_FLOW_WRONG_STATE;
957       break;
958   }
959 done:
960   return ret;
961
962   /* ERROR */
963 flushing:
964   {
965     GST_DEBUG_OBJECT (src, "pad is flushing");
966     GST_UNLOCK (src->srcpad);
967     GST_LIVE_UNLOCK (src);
968     return GST_FLOW_WRONG_STATE;
969   }
970 not_started:
971   {
972     GST_DEBUG_OBJECT (src, "getrange but not started");
973     return GST_FLOW_WRONG_STATE;
974   }
975 no_function:
976   {
977     GST_DEBUG_OBJECT (src, "no create function");
978     return GST_FLOW_ERROR;
979   }
980 unexpected_length:
981   {
982     GST_DEBUG_OBJECT (src, "unexpected length %u (offset=%" G_GUINT64_FORMAT
983         ", size=%" G_GUINT64_FORMAT ")", length, offset, src->size);
984     return GST_FLOW_UNEXPECTED;
985   }
986 reached_num_buffers:
987   {
988     GST_DEBUG_OBJECT (src, "sent all buffers");
989     return GST_FLOW_UNEXPECTED;
990   }
991 }
992
993 static GstFlowReturn
994 gst_base_src_pad_get_range (GstPad * pad, guint64 offset, guint length,
995     GstBuffer ** buf)
996 {
997   GstBaseSrc *src;
998   GstFlowReturn res;
999
1000   src = GST_BASE_SRC (gst_pad_get_parent (pad));
1001
1002   res = gst_base_src_get_range (src, offset, length, buf);
1003
1004   gst_object_unref (src);
1005
1006   return res;
1007 }
1008
1009 static gboolean
1010 gst_base_src_check_get_range (GstPad * pad)
1011 {
1012   GstBaseSrc *src;
1013
1014   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
1015
1016   if (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)) {
1017     gst_base_src_start (src);
1018     gst_base_src_stop (src);
1019   }
1020
1021   return src->seekable;
1022 }
1023
1024 static void
1025 gst_base_src_loop (GstPad * pad)
1026 {
1027   GstBaseSrc *src;
1028   GstBuffer *buf = NULL;
1029   GstFlowReturn ret;
1030
1031   src = GST_BASE_SRC (gst_pad_get_parent (pad));
1032
1033   /* only send segments when operating in push mode */
1034   if (G_UNLIKELY (src->need_newsegment)) {
1035     /* now send newsegment */
1036     gst_base_src_newsegment (src);
1037     src->need_newsegment = FALSE;
1038   }
1039
1040   ret = gst_base_src_get_range (src, src->offset, src->blocksize, &buf);
1041   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
1042     if (ret == GST_FLOW_UNEXPECTED)
1043       goto eos;
1044     else
1045       goto pause;
1046   }
1047   if (G_UNLIKELY (buf == NULL))
1048     goto error;
1049
1050   src->offset += GST_BUFFER_SIZE (buf);
1051
1052   ret = gst_pad_push (pad, buf);
1053   if (G_UNLIKELY (ret != GST_FLOW_OK))
1054     goto pause;
1055
1056   gst_object_unref (src);
1057   return;
1058
1059   /* special cases */
1060 eos:
1061   {
1062     GST_DEBUG_OBJECT (src, "going to EOS, getrange returned UNEXPECTED");
1063     gst_pad_pause_task (pad);
1064     if (src->segment_loop) {
1065       /* FIXME, subclass might want to use another format */
1066       gst_element_post_message (GST_ELEMENT (src),
1067           gst_message_new_segment_done (GST_OBJECT (src),
1068               GST_FORMAT_BYTES, src->segment_end));
1069     } else {
1070       gst_pad_push_event (pad, gst_event_new_eos ());
1071     }
1072
1073     gst_object_unref (src);
1074     return;
1075   }
1076 pause:
1077   {
1078     const gchar *reason = gst_flow_get_name (ret);
1079
1080     GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
1081     gst_pad_pause_task (pad);
1082     if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
1083       /* for fatal errors we post an error message */
1084       GST_ELEMENT_ERROR (src, STREAM, FAILED,
1085           (_("Internal data flow error.")),
1086           ("streaming task paused, reason %s", reason));
1087       gst_pad_push_event (pad, gst_event_new_eos ());
1088     }
1089     gst_object_unref (src);
1090     return;
1091   }
1092 error:
1093   {
1094     GST_ELEMENT_ERROR (src, STREAM, FAILED,
1095         (_("Internal data flow error.")), ("element returned NULL buffer"));
1096     gst_pad_pause_task (pad);
1097     gst_pad_push_event (pad, gst_event_new_eos ());
1098
1099     gst_object_unref (src);
1100     return;
1101   }
1102 }
1103
1104 /* this will always be called between start() and stop(). So you can rely on
1105    resources allocated by start() and freed from stop(). This needs to be added
1106    to the docs at some point. */
1107 static gboolean
1108 gst_base_src_unlock (GstBaseSrc * basesrc)
1109 {
1110   GstBaseSrcClass *bclass;
1111   gboolean result = TRUE;
1112
1113   GST_DEBUG ("unlock");
1114   /* unblock whatever the subclass is doing */
1115   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
1116   if (bclass->unlock)
1117     result = bclass->unlock (basesrc);
1118
1119   GST_DEBUG ("unschedule clock");
1120   /* and unblock the clock as well, if any */
1121   GST_LOCK (basesrc);
1122   if (basesrc->clock_id) {
1123     gst_clock_id_unschedule (basesrc->clock_id);
1124   }
1125   GST_UNLOCK (basesrc);
1126
1127   GST_DEBUG ("unlock done");
1128
1129   return result;
1130 }
1131
1132 static gboolean
1133 gst_base_src_get_size (GstBaseSrc * basesrc, guint64 * size)
1134 {
1135   GstBaseSrcClass *bclass;
1136   gboolean result = FALSE;
1137
1138   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
1139   if (bclass->get_size)
1140     result = bclass->get_size (basesrc, size);
1141
1142   if (result)
1143     basesrc->size = *size;
1144
1145   return result;
1146 }
1147
1148 static gboolean
1149 gst_base_src_is_seekable (GstBaseSrc * basesrc)
1150 {
1151   GstBaseSrcClass *bclass;
1152
1153   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
1154
1155   /* check if we can seek */
1156   if (bclass->is_seekable)
1157     basesrc->seekable = bclass->is_seekable (basesrc);
1158   else
1159     basesrc->seekable = FALSE;
1160
1161   GST_DEBUG_OBJECT (basesrc, "is seekable: %d", basesrc->seekable);
1162
1163   return basesrc->seekable;
1164 }
1165
1166 /* default negotiation code */
1167 static gboolean
1168 gst_base_src_default_negotiate (GstBaseSrc * basesrc)
1169 {
1170   GstCaps *thiscaps;
1171   GstCaps *caps = NULL;
1172   GstCaps *peercaps = NULL;
1173   gboolean result = FALSE;
1174
1175   /* first see what is possible on our source pad */
1176   thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
1177   GST_DEBUG ("caps of src: %" GST_PTR_FORMAT, thiscaps);
1178   /* nothing or anything is allowed, we're done */
1179   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
1180     goto no_nego_needed;
1181
1182   /* get the peer caps */
1183   peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
1184   GST_DEBUG ("caps of peer: %" GST_PTR_FORMAT, peercaps);
1185   if (peercaps) {
1186     GstCaps *icaps;
1187
1188     /* get intersection */
1189     icaps = gst_caps_intersect (thiscaps, peercaps);
1190     GST_DEBUG ("intersect: %" GST_PTR_FORMAT, icaps);
1191     gst_caps_unref (thiscaps);
1192     gst_caps_unref (peercaps);
1193     if (icaps) {
1194       /* take first (and best) possibility */
1195       caps = gst_caps_copy_nth (icaps, 0);
1196       gst_caps_unref (icaps);
1197     }
1198   } else {
1199     /* no peer, work with our own caps then */
1200     caps = thiscaps;
1201   }
1202   if (caps) {
1203     caps = gst_caps_make_writable (caps);
1204     gst_caps_truncate (caps);
1205
1206     /* now fixate */
1207     gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
1208     GST_DEBUG ("fixated to: %" GST_PTR_FORMAT, caps);
1209
1210     if (gst_caps_is_any (caps)) {
1211       /* hmm, still anything, so element can do anything and
1212        * nego is not needed */
1213       gst_caps_unref (caps);
1214       result = TRUE;
1215     } else if (gst_caps_is_fixed (caps)) {
1216       /* yay, fixed caps, use those then */
1217       gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
1218       gst_caps_unref (caps);
1219       result = TRUE;
1220     }
1221   }
1222   return result;
1223
1224 no_nego_needed:
1225   {
1226     GST_DEBUG ("no negotiation needed");
1227     if (thiscaps)
1228       gst_caps_unref (thiscaps);
1229     return TRUE;
1230   }
1231 }
1232
1233 static gboolean
1234 gst_base_src_negotiate (GstBaseSrc * basesrc)
1235 {
1236   GstBaseSrcClass *bclass;
1237   gboolean result = TRUE;
1238
1239   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
1240
1241   if (bclass->negotiate)
1242     result = bclass->negotiate (basesrc);
1243
1244   return result;
1245 }
1246
1247 static gboolean
1248 gst_base_src_start (GstBaseSrc * basesrc)
1249 {
1250   GstBaseSrcClass *bclass;
1251   gboolean result;
1252
1253   if (GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
1254     return TRUE;
1255
1256   GST_DEBUG_OBJECT (basesrc, "starting source");
1257
1258   basesrc->num_buffers_left = basesrc->num_buffers;
1259
1260   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
1261   if (bclass->start)
1262     result = bclass->start (basesrc);
1263   else
1264     result = TRUE;
1265
1266   if (!result)
1267     goto could_not_start;
1268
1269   GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_STARTED);
1270
1271   /* figure out the size */
1272   if (bclass->get_size) {
1273     result = bclass->get_size (basesrc, &basesrc->size);
1274     if (result == FALSE)
1275       basesrc->size = -1;
1276   } else {
1277     result = FALSE;
1278     basesrc->size = -1;
1279   }
1280
1281   GST_DEBUG ("size %d %lld", result, basesrc->size);
1282
1283   /* check if we can seek, updates ->seekable */
1284   gst_base_src_is_seekable (basesrc);
1285
1286   basesrc->need_newsegment = TRUE;
1287
1288   /* run typefind */
1289 #if 0
1290   if (basesrc->seekable) {
1291     GstCaps *caps;
1292
1293     caps = gst_type_find_helper (basesrc->srcpad, basesrc->size);
1294     gst_pad_set_caps (basesrc->srcpad, caps);
1295     gst_caps_unref (caps);
1296   }
1297 #endif
1298
1299   if (!gst_base_src_negotiate (basesrc))
1300     goto could_not_negotiate;
1301
1302   return TRUE;
1303
1304   /* ERROR */
1305 could_not_start:
1306   {
1307     GST_DEBUG_OBJECT (basesrc, "could not start");
1308     return FALSE;
1309   }
1310 could_not_negotiate:
1311   {
1312     GST_DEBUG_OBJECT (basesrc, "could not negotiate, stopping");
1313     GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
1314         ("Could not connect source to pipeline"),
1315         ("Check your filtered caps, if any"));
1316     gst_base_src_stop (basesrc);
1317     return FALSE;
1318   }
1319 }
1320
1321 static gboolean
1322 gst_base_src_stop (GstBaseSrc * basesrc)
1323 {
1324   GstBaseSrcClass *bclass;
1325   gboolean result = TRUE;
1326
1327   if (!GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
1328     return TRUE;
1329
1330   GST_DEBUG_OBJECT (basesrc, "stopping source");
1331
1332   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
1333   if (bclass->stop)
1334     result = bclass->stop (basesrc);
1335
1336   if (result)
1337     GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
1338
1339   return result;
1340 }
1341
1342 static gboolean
1343 gst_base_src_deactivate (GstBaseSrc * basesrc, GstPad * pad)
1344 {
1345   gboolean result;
1346
1347   GST_LIVE_LOCK (basesrc);
1348   basesrc->live_running = TRUE;
1349   GST_LIVE_SIGNAL (basesrc);
1350   GST_LIVE_UNLOCK (basesrc);
1351
1352   /* step 1, unblock clock sync (if any) */
1353   result = gst_base_src_unlock (basesrc);
1354
1355   /* step 2, make sure streaming finishes */
1356   result &= gst_pad_stop_task (pad);
1357
1358   return result;
1359 }
1360
1361 static gboolean
1362 gst_base_src_activate_push (GstPad * pad, gboolean active)
1363 {
1364   GstBaseSrc *basesrc;
1365   gboolean res;
1366
1367   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
1368
1369   /* prepare subclass first */
1370   if (active) {
1371     GST_DEBUG_OBJECT (basesrc, "Activating in push mode");
1372
1373     if (!basesrc->can_activate_push)
1374       goto no_push_activation;
1375
1376     if (!gst_base_src_start (basesrc))
1377       goto error_start;
1378
1379     res = gst_pad_start_task (pad, (GstTaskFunction) gst_base_src_loop, pad);
1380   } else {
1381     GST_DEBUG_OBJECT (basesrc, "Deactivating in push mode");
1382     res = gst_base_src_deactivate (basesrc, pad);
1383   }
1384   return res;
1385
1386   /* ERRORS */
1387 no_push_activation:
1388   {
1389     GST_DEBUG_OBJECT (basesrc, "Subclass disabled push-mode activation");
1390     return FALSE;
1391   }
1392 error_start:
1393   {
1394     gst_base_src_stop (basesrc);
1395     GST_DEBUG_OBJECT (basesrc, "Failed to start in push mode");
1396     return FALSE;
1397   }
1398 }
1399
1400 static gboolean
1401 gst_base_src_activate_pull (GstPad * pad, gboolean active)
1402 {
1403   GstBaseSrc *basesrc;
1404
1405   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
1406
1407   /* prepare subclass first */
1408   if (active) {
1409     GST_DEBUG_OBJECT (basesrc, "Activating in pull mode");
1410     if (!gst_base_src_start (basesrc))
1411       goto error_start;
1412
1413     if (!basesrc->seekable) {
1414       gst_base_src_stop (basesrc);
1415       return FALSE;
1416     }
1417
1418     return TRUE;
1419   } else {
1420     GST_DEBUG_OBJECT (basesrc, "Deactivating in pull mode");
1421
1422     if (!gst_base_src_stop (basesrc))
1423       goto error_stop;
1424
1425     return gst_base_src_deactivate (basesrc, pad);
1426   }
1427
1428 error_start:
1429   {
1430     gst_base_src_stop (basesrc);
1431     GST_DEBUG_OBJECT (basesrc, "Failed to start in pull mode");
1432     return FALSE;
1433   }
1434 error_stop:
1435   {
1436     GST_DEBUG_OBJECT (basesrc, "Failed to stop in pull mode");
1437     return FALSE;
1438   }
1439 }
1440
1441 static GstStateChangeReturn
1442 gst_base_src_change_state (GstElement * element, GstStateChange transition)
1443 {
1444   GstBaseSrc *basesrc;
1445   GstStateChangeReturn result;
1446   gboolean no_preroll = FALSE;
1447
1448   basesrc = GST_BASE_SRC (element);
1449
1450   switch (transition) {
1451     case GST_STATE_CHANGE_NULL_TO_READY:
1452       break;
1453     case GST_STATE_CHANGE_READY_TO_PAUSED:
1454       GST_LIVE_LOCK (element);
1455       if (basesrc->is_live) {
1456         no_preroll = TRUE;
1457         basesrc->live_running = FALSE;
1458       }
1459       GST_LIVE_UNLOCK (element);
1460       break;
1461     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1462       GST_LIVE_LOCK (element);
1463       if (basesrc->is_live) {
1464         basesrc->live_running = TRUE;
1465         GST_LIVE_SIGNAL (element);
1466       }
1467       GST_LIVE_UNLOCK (element);
1468       break;
1469     default:
1470       break;
1471   }
1472
1473   if ((result =
1474           GST_ELEMENT_CLASS (parent_class)->change_state (element,
1475               transition)) == GST_STATE_CHANGE_FAILURE)
1476     goto failure;
1477
1478   switch (transition) {
1479     case GST_STATE_CHANGE_NULL_TO_READY:
1480       /* we always run from start to end when in READY, after putting
1481        * the element to READY a seek can be done on the element to
1482        * configure the segment when going to PAUSED. */
1483       basesrc->segment_loop = FALSE;
1484       basesrc->segment_start = 0;
1485       basesrc->segment_end = -1;
1486       basesrc->offset = 0;
1487       break;
1488     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1489       GST_LIVE_LOCK (element);
1490       if (basesrc->is_live) {
1491         no_preroll = TRUE;
1492         basesrc->live_running = FALSE;
1493       }
1494       GST_LIVE_UNLOCK (element);
1495       break;
1496     case GST_STATE_CHANGE_PAUSED_TO_READY:
1497       if (!gst_base_src_stop (basesrc))
1498         goto error_stop;
1499       /* we always run from start to end when in READY */
1500       basesrc->segment_loop = FALSE;
1501       basesrc->segment_start = 0;
1502       basesrc->segment_end = -1;
1503       basesrc->offset = 0;
1504       break;
1505     case GST_STATE_CHANGE_READY_TO_NULL:
1506       break;
1507     default:
1508       break;
1509   }
1510
1511   if (no_preroll && result == GST_STATE_CHANGE_SUCCESS)
1512     result = GST_STATE_CHANGE_NO_PREROLL;
1513
1514   return result;
1515
1516   /* ERRORS */
1517 failure:
1518   {
1519     GST_DEBUG_OBJECT (basesrc, "parent failed state change");
1520     gst_base_src_stop (basesrc);
1521     return result;
1522   }
1523 error_stop:
1524   {
1525     GST_DEBUG_OBJECT (basesrc, "Failed to stop");
1526     return GST_STATE_CHANGE_FAILURE;
1527   }
1528 }