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