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