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