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