gst/base/gstbasesrc.c (gst_base_src_unlock): Comment a bit in lieu of real docs...
[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: #GstBaseTransformc, #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 sinkpad</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
54 #define DEFAULT_BLOCKSIZE       4096
55 #define DEFAULT_NUM_BUFFERS     -1
56
57 GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);
58 #define GST_CAT_DEFAULT gst_base_src_debug
59
60 /* BaseSrc signals and args */
61 enum
62 {
63   /* FILL ME */
64   LAST_SIGNAL
65 };
66
67 enum
68 {
69   PROP_0,
70   PROP_BLOCKSIZE,
71   PROP_NUM_BUFFERS,
72 };
73
74 static GstElementClass *parent_class = NULL;
75
76 static void gst_base_src_base_init (gpointer g_class);
77 static void gst_base_src_class_init (GstBaseSrcClass * klass);
78 static void gst_base_src_init (GstBaseSrc * src, gpointer g_class);
79 static void gst_base_src_finalize (GObject * object);
80
81
82 GType
83 gst_base_src_get_type (void)
84 {
85   static GType base_src_type = 0;
86
87   if (!base_src_type) {
88     static const GTypeInfo base_src_info = {
89       sizeof (GstBaseSrcClass),
90       (GBaseInitFunc) gst_base_src_base_init,
91       NULL,
92       (GClassInitFunc) gst_base_src_class_init,
93       NULL,
94       NULL,
95       sizeof (GstBaseSrc),
96       0,
97       (GInstanceInitFunc) gst_base_src_init,
98     };
99
100     base_src_type = g_type_register_static (GST_TYPE_ELEMENT,
101         "GstBaseSrc", &base_src_info, G_TYPE_FLAG_ABSTRACT);
102   }
103   return base_src_type;
104 }
105 static GstCaps *gst_base_src_getcaps (GstPad * pad);
106 static gboolean gst_base_src_setcaps (GstPad * pad, GstCaps * caps);
107
108 static gboolean gst_base_src_activate_push (GstPad * pad, gboolean active);
109 static gboolean gst_base_src_activate_pull (GstPad * pad, gboolean active);
110 static void gst_base_src_set_property (GObject * object, guint prop_id,
111     const GValue * value, GParamSpec * pspec);
112 static void gst_base_src_get_property (GObject * object, guint prop_id,
113     GValue * value, GParamSpec * pspec);
114 static gboolean gst_base_src_event_handler (GstPad * pad, GstEvent * event);
115
116 static gboolean gst_base_src_query (GstPad * pad, GstQuery * query);
117
118 #if 0
119 static const GstEventMask *gst_base_src_get_event_mask (GstPad * pad);
120 #endif
121 static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc);
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_get_range (GstPad * pad, guint64 offset,
134     guint length, GstBuffer ** buf);
135
136 static void
137 gst_base_src_base_init (gpointer g_class)
138 {
139   GST_DEBUG_CATEGORY_INIT (gst_base_src_debug, "basesrc", 0, "basesrc element");
140 }
141
142 static void
143 gst_base_src_class_init (GstBaseSrcClass * klass)
144 {
145   GObjectClass *gobject_class;
146   GstElementClass *gstelement_class;
147
148   gobject_class = (GObjectClass *) klass;
149   gstelement_class = (GstElementClass *) klass;
150
151   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
152
153   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_src_finalize);
154   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_src_set_property);
155   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_src_get_property);
156
157   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BLOCKSIZE,
158       g_param_spec_ulong ("blocksize", "Block size",
159           "Size in bytes to read per buffer", 1, G_MAXULONG, DEFAULT_BLOCKSIZE,
160           G_PARAM_READWRITE));
161
162   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NUM_BUFFERS,
163       g_param_spec_int ("num-buffers", "num-buffers",
164           "Number of buffers to output before sending EOS", -1, G_MAXINT,
165           DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE));
166
167   gstelement_class->change_state =
168       GST_DEBUG_FUNCPTR (gst_base_src_change_state);
169
170   klass->negotiate = gst_base_src_default_negotiate;
171 }
172
173 static void
174 gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
175 {
176   GstPad *pad;
177   GstPadTemplate *pad_template;
178
179   basesrc->is_live = FALSE;
180   basesrc->live_lock = g_mutex_new ();
181   basesrc->live_cond = g_cond_new ();
182   basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
183   basesrc->num_buffers_left = -1;
184
185   basesrc->can_activate_push = TRUE;
186   basesrc->pad_mode = GST_ACTIVATE_NONE;
187
188   pad_template =
189       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
190   g_return_if_fail (pad_template != NULL);
191
192   GST_DEBUG_OBJECT (basesrc, "creating src pad");
193   pad = gst_pad_new_from_template (pad_template, "src");
194
195   GST_DEBUG_OBJECT (basesrc, "setting functions on src pad");
196   gst_pad_set_activatepush_function (pad, gst_base_src_activate_push);
197   gst_pad_set_activatepull_function (pad, gst_base_src_activate_pull);
198   gst_pad_set_event_function (pad, gst_base_src_event_handler);
199   gst_pad_set_query_function (pad, gst_base_src_query);
200   gst_pad_set_checkgetrange_function (pad, gst_base_src_check_get_range);
201   gst_pad_set_getrange_function (pad, gst_base_src_get_range);
202   gst_pad_set_getcaps_function (pad, gst_base_src_getcaps);
203   gst_pad_set_setcaps_function (pad, gst_base_src_setcaps);
204
205   /* hold pointer to pad */
206   basesrc->srcpad = pad;
207   GST_DEBUG_OBJECT (basesrc, "adding src pad");
208   gst_element_add_pad (GST_ELEMENT (basesrc), pad);
209
210   basesrc->segment_start = -1;
211   basesrc->segment_end = -1;
212   basesrc->need_discont = TRUE;
213   basesrc->blocksize = DEFAULT_BLOCKSIZE;
214   basesrc->clock_id = NULL;
215
216   GST_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
217
218   GST_DEBUG_OBJECT (basesrc, "init done");
219 }
220
221 static void
222 gst_base_src_finalize (GObject * object)
223 {
224   GstBaseSrc *basesrc;
225
226   basesrc = GST_BASE_SRC (object);
227
228   g_mutex_free (basesrc->live_lock);
229   g_cond_free (basesrc->live_cond);
230
231   G_OBJECT_CLASS (parent_class)->finalize (object);
232 }
233
234 /**
235  * gst_base_src_set_live:
236  * @src: base source instance
237  * @live: new live-mode
238  *
239  * If the element listens to a live source, the @livemode should
240  * be set to %TRUE. This declares that this source can't seek.
241  */
242 void
243 gst_base_src_set_live (GstBaseSrc * src, gboolean live)
244 {
245   GST_LIVE_LOCK (src);
246   src->is_live = live;
247   GST_LIVE_UNLOCK (src);
248 }
249
250 /**
251  * gst_base_src_is_live:
252  * @src: base source instance
253  *
254  * Check if an element is in live mode.
255  *
256  * Returns: %TRUE if element is in live mode.
257  */
258 gboolean
259 gst_base_src_is_live (GstBaseSrc * src)
260 {
261   gboolean result;
262
263   GST_LIVE_LOCK (src);
264   result = src->is_live;
265   GST_LIVE_UNLOCK (src);
266
267   return result;
268 }
269
270 static gboolean
271 gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
272 {
273   GstBaseSrcClass *bclass;
274   GstBaseSrc *bsrc;
275   gboolean res = TRUE;
276
277   bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
278   bclass = GST_BASE_SRC_GET_CLASS (bsrc);
279
280   if (bclass->set_caps)
281     res = bclass->set_caps (bsrc, caps);
282
283   return res;
284 }
285
286 static GstCaps *
287 gst_base_src_getcaps (GstPad * pad)
288 {
289   GstBaseSrcClass *bclass;
290   GstBaseSrc *bsrc;
291   GstCaps *caps = NULL;
292
293   bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
294   bclass = GST_BASE_SRC_GET_CLASS (bsrc);
295   if (bclass->get_caps)
296     caps = bclass->get_caps (bsrc);
297
298   if (caps == NULL) {
299     GstPadTemplate *pad_template;
300
301     pad_template =
302         gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
303     if (pad_template != NULL) {
304       caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
305     }
306   }
307   return caps;
308 }
309
310 static gboolean
311 gst_base_src_query (GstPad * pad, GstQuery * query)
312 {
313   gboolean b;
314   guint64 ui64;
315   gint64 i64;
316   GstBaseSrc *src;
317
318   src = GST_BASE_SRC (GST_PAD_PARENT (pad));
319
320   switch (GST_QUERY_TYPE (query)) {
321     case GST_QUERY_POSITION:
322     {
323       GstFormat format;
324
325       gst_query_parse_position (query, &format, NULL, NULL);
326       switch (format) {
327         case GST_FORMAT_DEFAULT:
328         case GST_FORMAT_BYTES:
329           b = gst_base_src_get_size (src, &ui64);
330           /* better to make get_size take an int64 */
331           i64 = b ? (gint64) ui64 : -1;
332           gst_query_set_position (query, GST_FORMAT_BYTES, src->offset, i64);
333           return TRUE;
334         case GST_FORMAT_PERCENT:
335           b = gst_base_src_get_size (src, &ui64);
336           i64 = GST_FORMAT_PERCENT_MAX;
337           i64 *= b ? (src->offset / (gdouble) ui64) : 1.0;
338           gst_query_set_position (query, GST_FORMAT_PERCENT,
339               i64, GST_FORMAT_PERCENT_MAX);
340           return TRUE;
341         default:
342           return FALSE;
343       }
344     }
345
346     case GST_QUERY_SEEKING:
347       gst_query_set_seeking (query, GST_FORMAT_BYTES,
348           src->seekable, src->segment_start, src->segment_end);
349       return TRUE;
350
351     case GST_QUERY_FORMATS:
352       gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT,
353           GST_FORMAT_BYTES, GST_FORMAT_PERCENT);
354       return TRUE;
355
356     case GST_QUERY_LATENCY:
357     case GST_QUERY_JITTER:
358     case GST_QUERY_RATE:
359     case GST_QUERY_CONVERT:
360     default:
361       return gst_pad_query_default (pad, query);
362   }
363 }
364
365 static gboolean
366 gst_base_src_send_discont (GstBaseSrc * src)
367 {
368   GstEvent *event;
369
370   GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
371       " to %" G_GINT64_FORMAT, (gint64) src->segment_start,
372       (gint64) src->segment_end);
373   event = gst_event_new_newsegment (1.0,
374       GST_FORMAT_BYTES,
375       (gint64) src->segment_start, (gint64) src->segment_end, (gint64) 0);
376
377   return gst_pad_push_event (src->srcpad, event);
378 }
379
380 static gboolean
381 gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
382 {
383   gdouble rate;
384   GstFormat format;
385   GstSeekFlags flags;
386   GstSeekType cur_type, stop_type;
387   gint64 cur, stop;
388
389   gst_event_parse_seek (event, &rate, &format, &flags,
390       &cur_type, &cur, &stop_type, &stop);
391
392   /* get seek format */
393   if (format == GST_FORMAT_DEFAULT)
394     format = GST_FORMAT_BYTES;
395   /* we can only seek bytes */
396   if (format != GST_FORMAT_BYTES)
397     return FALSE;
398
399   /* get seek positions */
400   src->segment_loop = flags & GST_SEEK_FLAG_SEGMENT;
401
402   /* send flush start */
403   gst_pad_push_event (src->srcpad, gst_event_new_flush_start ());
404
405   /* unblock streaming thread */
406   gst_base_src_unlock (src);
407
408   /* grab streaming lock */
409   GST_STREAM_LOCK (src->srcpad);
410
411   /* send flush stop */
412   gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
413
414   /* perform the seek */
415   switch (cur_type) {
416     case GST_SEEK_TYPE_NONE:
417       break;
418     case GST_SEEK_TYPE_SET:
419       if (cur < 0)
420         goto error;
421       src->offset = MIN (cur, src->size);
422       src->segment_start = src->offset;
423       break;
424     case GST_SEEK_TYPE_CUR:
425       src->offset = CLAMP (src->offset + cur, 0, src->size);
426       src->segment_start = src->offset;
427       break;
428     case GST_SEEK_TYPE_END:
429       if (cur > 0)
430         goto error;
431       src->offset = MAX (0, src->size + cur);
432       src->segment_start = src->offset;
433       break;
434     default:
435       goto error;
436   }
437
438   switch (stop_type) {
439     case GST_SEEK_TYPE_NONE:
440       break;
441     case GST_SEEK_TYPE_SET:
442       if (stop < 0)
443         goto error;
444       src->segment_end = MIN (stop, src->size);
445       break;
446     case GST_SEEK_TYPE_CUR:
447       src->segment_end = CLAMP (src->segment_end + stop, 0, src->size);
448       break;
449     case GST_SEEK_TYPE_END:
450       if (stop > 0)
451         goto error;
452       src->segment_end = src->size + stop;
453       break;
454     default:
455       goto error;
456   }
457
458   GST_DEBUG_OBJECT (src, "seek pending for segment from %" G_GINT64_FORMAT
459       " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
460
461   /* now make sure the discont will be send */
462   src->need_discont = TRUE;
463
464   /* and restart the task */
465   gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
466       src->srcpad);
467   GST_STREAM_UNLOCK (src->srcpad);
468
469   gst_event_unref (event);
470
471   return TRUE;
472
473   /* ERROR */
474 error:
475   {
476     GST_DEBUG_OBJECT (src, "seek error");
477     GST_STREAM_UNLOCK (src->srcpad);
478     gst_event_unref (event);
479     return FALSE;
480   }
481 }
482
483 static gboolean
484 gst_base_src_event_handler (GstPad * pad, GstEvent * event)
485 {
486   GstBaseSrc *src;
487   GstBaseSrcClass *bclass;
488   gboolean result;
489
490   src = GST_BASE_SRC (GST_PAD_PARENT (pad));
491   bclass = GST_BASE_SRC_GET_CLASS (src);
492
493   if (bclass->event)
494     result = bclass->event (src, event);
495
496   switch (GST_EVENT_TYPE (event)) {
497     case GST_EVENT_SEEK:
498       if (!src->seekable) {
499         gst_event_unref (event);
500         return FALSE;
501       }
502       return gst_base_src_do_seek (src, event);
503     case GST_EVENT_FLUSH_START:
504       /* cancel any blocking getrange */
505       gst_base_src_unlock (src);
506       break;
507     case GST_EVENT_FLUSH_STOP:
508       break;
509     default:
510       break;
511   }
512   gst_event_unref (event);
513
514   return TRUE;
515 }
516
517 static void
518 gst_base_src_set_property (GObject * object, guint prop_id,
519     const GValue * value, GParamSpec * pspec)
520 {
521   GstBaseSrc *src;
522
523   src = GST_BASE_SRC (object);
524
525   switch (prop_id) {
526     case PROP_BLOCKSIZE:
527       src->blocksize = g_value_get_ulong (value);
528       break;
529     case PROP_NUM_BUFFERS:
530       src->num_buffers = g_value_get_int (value);
531       break;
532     default:
533       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
534       break;
535   }
536 }
537
538 static void
539 gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
540     GParamSpec * pspec)
541 {
542   GstBaseSrc *src;
543
544   src = GST_BASE_SRC (object);
545
546   switch (prop_id) {
547     case PROP_BLOCKSIZE:
548       g_value_set_ulong (value, src->blocksize);
549       break;
550     case PROP_NUM_BUFFERS:
551       g_value_set_int (value, src->num_buffers);
552       break;
553     default:
554       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
555       break;
556   }
557 }
558
559 static GstFlowReturn
560 gst_base_src_get_range (GstPad * pad, guint64 offset, guint length,
561     GstBuffer ** buf)
562 {
563   GstFlowReturn ret;
564   GstBaseSrc *src;
565   GstBaseSrcClass *bclass;
566
567   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
568   bclass = GST_BASE_SRC_GET_CLASS (src);
569
570   GST_LIVE_LOCK (src);
571   if (src->is_live) {
572     while (!src->live_running) {
573       GST_DEBUG ("live source signal waiting");
574       GST_LIVE_SIGNAL (src);
575       GST_DEBUG ("live source waiting for running state");
576       GST_LIVE_WAIT (src);
577       GST_DEBUG ("live source unlocked");
578     }
579   }
580   GST_LIVE_UNLOCK (src);
581
582   GST_LOCK (pad);
583   if (GST_PAD_IS_FLUSHING (pad))
584     goto flushing;
585   GST_UNLOCK (pad);
586
587   if (!GST_FLAG_IS_SET (src, GST_BASE_SRC_STARTED))
588     goto not_started;
589
590   if (!bclass->create)
591     goto no_function;
592
593   GST_DEBUG_OBJECT (src,
594       "reading offset %" G_GUINT64_FORMAT ", length %u, size %"
595       G_GUINT64_FORMAT, offset, length, src->size);
596
597   /* check size */
598   if (src->size != -1) {
599     if (offset > src->size)
600       goto unexpected_length;
601
602     if (offset + length > src->size) {
603       if (bclass->get_size)
604         bclass->get_size (src, &src->size);
605
606       if (offset + length > src->size) {
607         length = src->size - offset;
608       }
609     }
610   }
611   if (length == 0)
612     goto unexpected_length;
613
614   if (src->num_buffers_left == 0) {
615     goto reached_num_buffers;
616   } else {
617     if (src->num_buffers_left > 0)
618       src->num_buffers_left--;
619   }
620
621   ret = bclass->create (src, offset, length, buf);
622
623   return ret;
624
625   /* ERROR */
626 flushing:
627   {
628     GST_DEBUG_OBJECT (src, "pad is flushing");
629     GST_UNLOCK (pad);
630     return GST_FLOW_WRONG_STATE;
631   }
632 not_started:
633   {
634     GST_DEBUG_OBJECT (src, "getrange but not started");
635     return GST_FLOW_WRONG_STATE;
636   }
637 no_function:
638   {
639     GST_DEBUG_OBJECT (src, "no create function");
640     return GST_FLOW_ERROR;
641   }
642 unexpected_length:
643   {
644     GST_DEBUG_OBJECT (src, "unexpected length %u", length);
645     return GST_FLOW_UNEXPECTED;
646   }
647 reached_num_buffers:
648   {
649     GST_DEBUG_OBJECT (src, "sent all buffers");
650     return GST_FLOW_UNEXPECTED;
651   }
652 }
653
654 static gboolean
655 gst_base_src_check_get_range (GstPad * pad)
656 {
657   GstBaseSrc *src;
658
659   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
660
661   if (!GST_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)) {
662     gst_base_src_start (src);
663     gst_base_src_stop (src);
664   }
665
666   return src->seekable;
667 }
668
669 static void
670 gst_base_src_loop (GstPad * pad)
671 {
672   GstBaseSrc *src;
673   GstBuffer *buf = NULL;
674   GstFlowReturn ret;
675
676   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
677
678   if (src->need_discont) {
679     /* now send discont */
680     gst_base_src_send_discont (src);
681     src->need_discont = FALSE;
682   }
683
684   ret = gst_base_src_get_range (pad, src->offset, src->blocksize, &buf);
685   if (ret != GST_FLOW_OK)
686     goto eos;
687
688   if (buf == NULL)
689     goto error;
690
691   src->offset += GST_BUFFER_SIZE (buf);
692
693   ret = gst_pad_push (pad, buf);
694   if (ret != GST_FLOW_OK)
695     goto pause;
696
697   return;
698
699 eos:
700   {
701     GST_DEBUG_OBJECT (src, "going to EOS");
702     gst_pad_pause_task (pad);
703     gst_pad_push_event (pad, gst_event_new_eos ());
704     return;
705   }
706 pause:
707   {
708     GST_DEBUG_OBJECT (src, "pausing task");
709     gst_pad_pause_task (pad);
710     if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
711       /* for fatal errors we post an error message */
712       GST_ELEMENT_ERROR (src, STREAM, STOPPED,
713           ("streaming stopped, reason %s", gst_flow_get_name (ret)),
714           ("streaming stopped, reason %s", gst_flow_get_name (ret)));
715       gst_pad_push_event (pad, gst_event_new_eos ());
716     }
717     return;
718   }
719 error:
720   {
721     GST_ELEMENT_ERROR (src, STREAM, STOPPED,
722         ("internal: element returned NULL buffer"),
723         ("internal: element returned NULL buffer"));
724     gst_pad_pause_task (pad);
725     gst_pad_push_event (pad, gst_event_new_eos ());
726     return;
727   }
728 }
729
730 /* this will always be called between start() and stop(). So you can rely on
731    resources allocated by start() and freed from stop(). This needs to be added
732    to the docs at some point. */
733 static gboolean
734 gst_base_src_unlock (GstBaseSrc * basesrc)
735 {
736   GstBaseSrcClass *bclass;
737   gboolean result = FALSE;
738
739   GST_DEBUG ("unlock");
740   /* unblock whatever the subclass is doing */
741   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
742   if (bclass->unlock)
743     result = bclass->unlock (basesrc);
744
745   GST_DEBUG ("unschedule clock");
746   /* and unblock the clock as well, if any */
747   GST_LOCK (basesrc);
748   if (basesrc->clock_id) {
749     gst_clock_id_unschedule (basesrc->clock_id);
750   }
751   GST_UNLOCK (basesrc);
752
753   GST_DEBUG ("unlock done");
754
755   return result;
756 }
757
758 static gboolean
759 gst_base_src_get_size (GstBaseSrc * basesrc, guint64 * size)
760 {
761   GstBaseSrcClass *bclass;
762   gboolean result = FALSE;
763
764   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
765   if (bclass->get_size)
766     result = bclass->get_size (basesrc, size);
767
768   if (result)
769     basesrc->size = *size;
770
771   return result;
772 }
773
774 static gboolean
775 gst_base_src_is_seekable (GstBaseSrc * basesrc)
776 {
777   GstBaseSrcClass *bclass;
778
779   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
780
781   /* check if we can seek */
782   if (bclass->is_seekable)
783     basesrc->seekable = bclass->is_seekable (basesrc);
784   else
785     basesrc->seekable = FALSE;
786
787   GST_DEBUG_OBJECT (basesrc, "is seekable: %d", basesrc->seekable);
788
789   return basesrc->seekable;
790 }
791
792 static gboolean
793 gst_base_src_default_negotiate (GstBaseSrc * basesrc)
794 {
795   GstCaps *thiscaps;
796   GstCaps *caps = NULL;
797   GstCaps *peercaps = NULL;
798   gboolean result = FALSE;
799
800   thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
801   GST_DEBUG ("caps of src: %" GST_PTR_FORMAT, thiscaps);
802   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
803     goto no_nego_needed;
804
805   peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
806   GST_DEBUG ("caps of peer: %" GST_PTR_FORMAT, peercaps);
807   if (peercaps) {
808     GstCaps *icaps;
809
810     icaps = gst_caps_intersect (thiscaps, peercaps);
811     GST_DEBUG ("intersect: %" GST_PTR_FORMAT, icaps);
812     gst_caps_unref (thiscaps);
813     gst_caps_unref (peercaps);
814     if (icaps) {
815       caps = gst_caps_copy_nth (icaps, 0);
816       gst_caps_unref (icaps);
817     }
818   } else {
819     caps = thiscaps;
820   }
821   if (caps) {
822     caps = gst_caps_make_writable (caps);
823     gst_caps_truncate (caps);
824
825     gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
826     GST_DEBUG ("fixated to: %" GST_PTR_FORMAT, caps);
827
828     if (gst_caps_is_any (caps)) {
829       gst_caps_unref (caps);
830       result = TRUE;
831     } else if (gst_caps_is_fixed (caps)) {
832       gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
833       gst_caps_unref (caps);
834       result = TRUE;
835     }
836   }
837   return result;
838
839 no_nego_needed:
840   {
841     GST_DEBUG ("no negotiation needed");
842     if (thiscaps)
843       gst_caps_unref (thiscaps);
844     return TRUE;
845   }
846 }
847
848 static gboolean
849 gst_base_src_negotiate (GstBaseSrc * basesrc)
850 {
851   GstBaseSrcClass *bclass;
852   gboolean result = TRUE;
853
854   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
855
856   if (bclass->negotiate)
857     result = bclass->negotiate (basesrc);
858
859   return result;
860 }
861
862 static gboolean
863 gst_base_src_start (GstBaseSrc * basesrc)
864 {
865   GstBaseSrcClass *bclass;
866   gboolean result;
867
868   if (GST_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
869     return TRUE;
870
871   GST_DEBUG_OBJECT (basesrc, "starting source");
872
873   basesrc->num_buffers_left = basesrc->num_buffers;
874
875   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
876   if (bclass->start)
877     result = bclass->start (basesrc);
878   else
879     result = TRUE;
880
881   if (!result)
882     goto could_not_start;
883
884   GST_FLAG_SET (basesrc, GST_BASE_SRC_STARTED);
885
886   /* start in the beginning */
887   basesrc->offset = 0;
888
889   /* figure out the size */
890   if (bclass->get_size) {
891     result = bclass->get_size (basesrc, &basesrc->size);
892     if (result == FALSE)
893       basesrc->size = -1;
894   } else {
895     result = FALSE;
896     basesrc->size = -1;
897   }
898
899   GST_DEBUG ("size %d %lld", result, basesrc->size);
900
901   /* we always run to the end */
902   basesrc->segment_start = 0;
903   basesrc->segment_end = basesrc->size;
904   basesrc->need_discont = TRUE;
905
906   /* check if we can seek, updates ->seekable */
907   gst_base_src_is_seekable (basesrc);
908
909   /* run typefind */
910 #if 0
911   if (basesrc->seekable) {
912     GstCaps *caps;
913
914     caps = gst_type_find_helper (basesrc->srcpad, basesrc->size);
915     gst_pad_set_caps (basesrc->srcpad, caps);
916     gst_caps_unref (caps);
917   }
918 #endif
919
920   if (!gst_base_src_negotiate (basesrc))
921     goto could_not_negotiate;
922
923   return TRUE;
924
925   /* ERROR */
926 could_not_start:
927   {
928     GST_DEBUG_OBJECT (basesrc, "could not start");
929     return FALSE;
930   }
931 could_not_negotiate:
932   {
933     GST_DEBUG_OBJECT (basesrc, "could not negotiate, stopping");
934     GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
935         ("Could not connect source to pipeline"),
936         ("Check your filtered caps, if any"));
937     gst_base_src_stop (basesrc);
938     return FALSE;
939   }
940 }
941
942 static gboolean
943 gst_base_src_stop (GstBaseSrc * basesrc)
944 {
945   GstBaseSrcClass *bclass;
946   gboolean result = TRUE;
947
948   if (!GST_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
949     return TRUE;
950
951   GST_DEBUG_OBJECT (basesrc, "stopping source");
952
953   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
954   if (bclass->stop)
955     result = bclass->stop (basesrc);
956
957   if (result)
958     GST_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
959
960   return result;
961 }
962
963 static gboolean
964 gst_base_src_deactivate (GstBaseSrc * basesrc, GstPad * pad)
965 {
966   gboolean result;
967
968   GST_LIVE_LOCK (basesrc);
969   basesrc->live_running = TRUE;
970   GST_LIVE_SIGNAL (basesrc);
971   GST_LIVE_UNLOCK (basesrc);
972
973   /* step 1, unblock clock sync (if any) */
974   gst_base_src_unlock (basesrc);
975
976   /* step 2, make sure streaming finishes */
977   result = gst_pad_stop_task (pad);
978
979   return result;
980 }
981
982 static gboolean
983 gst_base_src_activate_push (GstPad * pad, gboolean active)
984 {
985   GstBaseSrc *basesrc;
986
987   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
988
989   /* prepare subclass first */
990   if (active) {
991     GST_DEBUG_OBJECT (basesrc, "Activating in push mode");
992
993     if (!basesrc->can_activate_push)
994       goto no_push_activation;
995
996     if (!gst_base_src_start (basesrc))
997       goto error_start;
998
999     return gst_pad_start_task (pad, (GstTaskFunction) gst_base_src_loop, pad);
1000   } else {
1001     GST_DEBUG_OBJECT (basesrc, "Deactivating in push mode");
1002     return gst_base_src_deactivate (basesrc, pad);
1003   }
1004
1005 no_push_activation:
1006   {
1007     GST_DEBUG_OBJECT (basesrc, "Subclass disabled push-mode activation");
1008     return FALSE;
1009   }
1010 error_start:
1011   {
1012     gst_base_src_stop (basesrc);
1013     GST_DEBUG_OBJECT (basesrc, "Failed to start in push mode");
1014     return FALSE;
1015   }
1016 }
1017
1018 static gboolean
1019 gst_base_src_activate_pull (GstPad * pad, gboolean active)
1020 {
1021   GstBaseSrc *basesrc;
1022
1023   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
1024
1025   /* prepare subclass first */
1026   if (active) {
1027     GST_DEBUG_OBJECT (basesrc, "Activating in pull mode");
1028     if (!gst_base_src_start (basesrc))
1029       goto error_start;
1030
1031     if (!basesrc->seekable) {
1032       gst_base_src_stop (basesrc);
1033       return FALSE;
1034     }
1035
1036     return TRUE;
1037   } else {
1038     GST_DEBUG_OBJECT (basesrc, "Deactivating in pull mode");
1039
1040     if (!gst_base_src_stop (basesrc))
1041       goto error_stop;
1042
1043     return gst_base_src_deactivate (basesrc, pad);
1044   }
1045
1046 error_start:
1047   {
1048     gst_base_src_stop (basesrc);
1049     GST_DEBUG_OBJECT (basesrc, "Failed to start in pull mode");
1050     return FALSE;
1051   }
1052 error_stop:
1053   {
1054     GST_DEBUG_OBJECT (basesrc, "Failed to stop in pull mode");
1055     return FALSE;
1056   }
1057 }
1058
1059 static GstStateChangeReturn
1060 gst_base_src_change_state (GstElement * element, GstStateChange transition)
1061 {
1062   GstBaseSrc *basesrc;
1063   GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
1064   GstStateChangeReturn presult;
1065
1066   basesrc = GST_BASE_SRC (element);
1067
1068
1069   switch (transition) {
1070     case GST_STATE_CHANGE_NULL_TO_READY:
1071       break;
1072     case GST_STATE_CHANGE_READY_TO_PAUSED:
1073       GST_LIVE_LOCK (element);
1074       if (basesrc->is_live) {
1075         result = GST_STATE_CHANGE_NO_PREROLL;
1076         basesrc->live_running = FALSE;
1077       }
1078       GST_LIVE_UNLOCK (element);
1079       break;
1080     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1081       GST_LIVE_LOCK (element);
1082       if (basesrc->is_live) {
1083         basesrc->live_running = TRUE;
1084         GST_LIVE_SIGNAL (element);
1085       }
1086       GST_LIVE_UNLOCK (element);
1087       break;
1088     default:
1089       break;
1090   }
1091
1092   if ((presult =
1093           GST_ELEMENT_CLASS (parent_class)->change_state (element,
1094               transition)) == GST_STATE_CHANGE_FAILURE)
1095     goto failure;
1096
1097   switch (transition) {
1098     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1099       GST_LIVE_LOCK (element);
1100       if (basesrc->is_live) {
1101         result = GST_STATE_CHANGE_NO_PREROLL;
1102         basesrc->live_running = FALSE;
1103       }
1104       GST_LIVE_UNLOCK (element);
1105       break;
1106     case GST_STATE_CHANGE_PAUSED_TO_READY:
1107       if (!gst_base_src_stop (basesrc))
1108         result = GST_STATE_CHANGE_FAILURE;
1109       break;
1110     case GST_STATE_CHANGE_READY_TO_NULL:
1111       break;
1112     default:
1113       break;
1114   }
1115
1116   return result;
1117
1118   /* ERRORS */
1119 failure:
1120   {
1121     gst_base_src_stop (basesrc);
1122     return presult;
1123   }
1124 }