tools/gst-typefind.c: Update, add copyright block.
[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     if (GST_FLOW_IS_FATAL (ret)) {
682       /* for fatal errors we post an error message */
683       GST_ELEMENT_ERROR (src, STREAM, STOPPED,
684           ("streaming stopped, reason %d", ret),
685           ("streaming stopped, reason %d", ret));
686       gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
687     }
688     return;
689   }
690 error:
691   {
692     GST_ELEMENT_ERROR (src, STREAM, STOPPED,
693         ("internal: element returned NULL buffer"),
694         ("internal: element returned NULL buffer"));
695     gst_pad_pause_task (pad);
696     gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
697     return;
698   }
699 }
700
701 static gboolean
702 gst_base_src_unlock (GstBaseSrc * basesrc)
703 {
704   GstBaseSrcClass *bclass;
705   gboolean result = FALSE;
706
707   GST_DEBUG ("unlock");
708   /* unblock whatever the subclass is doing */
709   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
710   if (bclass->unlock)
711     result = bclass->unlock (basesrc);
712
713   GST_DEBUG ("unschedule clock");
714   /* and unblock the clock as well, if any */
715   GST_LOCK (basesrc);
716   if (basesrc->clock_id) {
717     gst_clock_id_unschedule (basesrc->clock_id);
718   }
719   GST_UNLOCK (basesrc);
720
721   GST_DEBUG ("unlock done");
722
723   return result;
724 }
725
726 static gboolean
727 gst_base_src_get_size (GstBaseSrc * basesrc, guint64 * size)
728 {
729   GstBaseSrcClass *bclass;
730   gboolean result = FALSE;
731
732   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
733   if (bclass->get_size)
734     result = bclass->get_size (basesrc, size);
735
736   if (result)
737     basesrc->size = *size;
738
739   return result;
740 }
741
742 static gboolean
743 gst_base_src_is_seekable (GstBaseSrc * basesrc)
744 {
745   GstBaseSrcClass *bclass;
746
747   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
748
749   /* check if we can seek */
750   if (bclass->is_seekable)
751     basesrc->seekable = bclass->is_seekable (basesrc);
752   else
753     basesrc->seekable = FALSE;
754
755   return basesrc->seekable;
756 }
757
758 static gboolean
759 gst_base_src_default_negotiate (GstBaseSrc * basesrc)
760 {
761   GstCaps *thiscaps;
762   GstCaps *caps = NULL;
763   GstCaps *peercaps = NULL;
764   gboolean result = FALSE;
765
766   thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
767   GST_DEBUG ("caps of src: %" GST_PTR_FORMAT, thiscaps);
768   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
769     goto no_nego_needed;
770
771   peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
772   GST_DEBUG ("caps of peer: %" GST_PTR_FORMAT, peercaps);
773   if (peercaps) {
774     GstCaps *icaps;
775
776     icaps = gst_caps_intersect (thiscaps, peercaps);
777     GST_DEBUG ("intersect: %" GST_PTR_FORMAT, icaps);
778     gst_caps_unref (thiscaps);
779     gst_caps_unref (peercaps);
780     if (icaps) {
781       caps = gst_caps_copy_nth (icaps, 0);
782       gst_caps_unref (icaps);
783     }
784   } else {
785     caps = thiscaps;
786   }
787   if (caps) {
788     GstCaps *normalized;
789
790     normalized = gst_caps_make_writable (caps);
791     gst_caps_unref (caps);
792     caps = normalized;
793     gst_caps_truncate (caps);
794
795     gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
796     GST_DEBUG ("fixated to: %" GST_PTR_FORMAT, caps);
797
798     if (gst_caps_is_any (caps)) {
799       gst_caps_unref (caps);
800       result = TRUE;
801     } else if (gst_caps_is_fixed (caps)) {
802       gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
803       gst_caps_unref (caps);
804       result = TRUE;
805     }
806   }
807   return result;
808
809 no_nego_needed:
810   {
811     GST_DEBUG ("no negotiation needed");
812     if (thiscaps)
813       gst_caps_unref (thiscaps);
814     return TRUE;
815   }
816 }
817
818 static gboolean
819 gst_base_src_negotiate (GstBaseSrc * basesrc)
820 {
821   GstBaseSrcClass *bclass;
822   gboolean result = TRUE;
823
824   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
825
826   if (bclass->negotiate)
827     result = bclass->negotiate (basesrc);
828
829   return result;
830 }
831
832 static gboolean
833 gst_base_src_start (GstBaseSrc * basesrc)
834 {
835   GstBaseSrcClass *bclass;
836   gboolean result;
837
838   if (GST_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
839     return TRUE;
840
841   basesrc->num_buffers_left = basesrc->num_buffers;
842
843   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
844   if (bclass->start)
845     result = bclass->start (basesrc);
846   else
847     result = TRUE;
848
849   if (!result)
850     goto could_not_start;
851
852   GST_FLAG_SET (basesrc, GST_BASE_SRC_STARTED);
853
854   /* start in the beginning */
855   basesrc->offset = 0;
856   basesrc->segment_start = 0;
857
858   /* figure out the size */
859   if (bclass->get_size) {
860     result = bclass->get_size (basesrc, &basesrc->size);
861     if (result == FALSE)
862       basesrc->size = -1;
863   } else {
864     result = FALSE;
865     basesrc->size = -1;
866   }
867
868   GST_DEBUG ("size %d %lld", result, basesrc->size);
869
870   /* we always run to the end */
871   basesrc->segment_end = -1;
872
873   /* check if we can seek, updates ->seekable */
874   gst_base_src_is_seekable (basesrc);
875
876   /* run typefind */
877 #if 0
878   if (basesrc->seekable) {
879     GstCaps *caps;
880
881     caps = gst_type_find_helper (basesrc->srcpad, basesrc->size);
882     gst_pad_set_caps (basesrc->srcpad, caps);
883     gst_caps_unref (caps);
884   }
885 #endif
886
887   if (!gst_base_src_negotiate (basesrc))
888     goto could_not_negotiate;
889
890   return TRUE;
891
892   /* ERROR */
893 could_not_start:
894   {
895     GST_DEBUG_OBJECT (basesrc, "could not start");
896     return FALSE;
897   }
898 could_not_negotiate:
899   {
900     GST_DEBUG_OBJECT (basesrc, "could not negotiate, stopping");
901     GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
902         ("Could not connect source to pipeline"),
903         ("Check your filtered caps, if any"));
904     gst_base_src_stop (basesrc);
905     return FALSE;
906   }
907 }
908
909 static gboolean
910 gst_base_src_stop (GstBaseSrc * basesrc)
911 {
912   GstBaseSrcClass *bclass;
913   gboolean result = TRUE;
914
915   if (!GST_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
916     return TRUE;
917
918   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
919   if (bclass->stop)
920     result = bclass->stop (basesrc);
921
922   if (result)
923     GST_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
924
925   return result;
926 }
927
928 static gboolean
929 gst_base_src_deactivate (GstBaseSrc * basesrc, GstPad * pad)
930 {
931   gboolean result;
932
933   GST_LIVE_LOCK (basesrc);
934   basesrc->live_running = TRUE;
935   GST_LIVE_SIGNAL (basesrc);
936   GST_LIVE_UNLOCK (basesrc);
937
938   /* step 1, unblock clock sync (if any) */
939   gst_base_src_unlock (basesrc);
940
941   /* step 2, make sure streaming finishes */
942   result = gst_pad_stop_task (pad);
943
944   return result;
945 }
946
947 static gboolean
948 gst_base_src_activate_push (GstPad * pad, gboolean active)
949 {
950   GstBaseSrc *basesrc;
951
952   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
953
954   /* prepare subclass first */
955   if (active) {
956     if (!gst_base_src_start (basesrc))
957       goto error_start;
958
959     return gst_pad_start_task (pad, (GstTaskFunction) gst_base_src_loop, pad);
960   } else {
961     return gst_base_src_deactivate (basesrc, pad);
962   }
963
964 error_start:
965   {
966     GST_DEBUG_OBJECT (basesrc, "failed to start");
967     return FALSE;
968   }
969 }
970
971 static gboolean
972 gst_base_src_activate_pull (GstPad * pad, gboolean active)
973 {
974   GstBaseSrc *basesrc;
975
976   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
977
978   /* prepare subclass first */
979   if (active) {
980     if (!gst_base_src_start (basesrc))
981       goto error_start;
982
983     if (!basesrc->seekable) {
984       gst_base_src_stop (basesrc);
985       return FALSE;
986     }
987
988     return TRUE;
989   } else {
990     return gst_base_src_deactivate (basesrc, pad);
991   }
992
993 error_start:
994   {
995     GST_DEBUG_OBJECT (basesrc, "failed to start");
996     return FALSE;
997   }
998 }
999
1000 static GstElementStateReturn
1001 gst_base_src_change_state (GstElement * element)
1002 {
1003   GstBaseSrc *basesrc;
1004   GstElementStateReturn result = GST_STATE_SUCCESS;
1005   GstElementStateReturn presult;
1006   GstElementState transition;
1007
1008   basesrc = GST_BASE_SRC (element);
1009
1010   transition = GST_STATE_TRANSITION (element);
1011
1012   switch (transition) {
1013     case GST_STATE_NULL_TO_READY:
1014       break;
1015     case GST_STATE_READY_TO_PAUSED:
1016       GST_LIVE_LOCK (element);
1017       if (basesrc->is_live) {
1018         result = GST_STATE_NO_PREROLL;
1019         basesrc->live_running = FALSE;
1020       }
1021       GST_LIVE_UNLOCK (element);
1022       break;
1023     case GST_STATE_PAUSED_TO_PLAYING:
1024       GST_LIVE_LOCK (element);
1025       if (basesrc->is_live) {
1026         basesrc->live_running = TRUE;
1027         GST_LIVE_SIGNAL (element);
1028       }
1029       GST_LIVE_UNLOCK (element);
1030       break;
1031     default:
1032       break;
1033   }
1034
1035   if ((presult = GST_ELEMENT_CLASS (parent_class)->change_state (element)) !=
1036       GST_STATE_SUCCESS)
1037     return presult;
1038
1039   switch (transition) {
1040     case GST_STATE_PLAYING_TO_PAUSED:
1041       GST_LIVE_LOCK (element);
1042       if (basesrc->is_live) {
1043         result = GST_STATE_NO_PREROLL;
1044         basesrc->live_running = FALSE;
1045       }
1046       GST_LIVE_UNLOCK (element);
1047       break;
1048     case GST_STATE_PAUSED_TO_READY:
1049       if (!gst_base_src_stop (basesrc))
1050         result = GST_STATE_FAILURE;
1051       break;
1052     case GST_STATE_READY_TO_NULL:
1053       break;
1054     default:
1055       break;
1056   }
1057
1058   return result;
1059 }