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