check/Makefile.am: Use CHECK_CFLAGS and CHECK_LIBS
[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 #if 0
380 static const GstEventMask *
381 gst_base_src_get_event_mask (GstPad * pad)
382 {
383   static const GstEventMask masks[] = {
384     {GST_EVENT_SEEK, GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_SET |
385           GST_SEEK_METHOD_END | GST_SEEK_FLAG_FLUSH |
386           GST_SEEK_FLAG_SEGMENT_LOOP},
387     {GST_EVENT_FLUSH, 0},
388     {GST_EVENT_SIZE, 0},
389     {0, 0},
390   };
391   return masks;
392 }
393 #endif
394
395 static gboolean
396 gst_base_src_send_discont (GstBaseSrc * src)
397 {
398   GstEvent *event;
399
400   GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
401       " to %" G_GINT64_FORMAT, (gint64) src->segment_start,
402       (gint64) src->segment_end);
403   event = gst_event_new_newsegment (1.0,
404       GST_FORMAT_BYTES,
405       (gint64) src->segment_start, (gint64) src->segment_end, (gint64) 0);
406
407   return gst_pad_push_event (src->srcpad, event);
408 }
409
410 static gboolean
411 gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
412 {
413   gdouble rate;
414   GstFormat format;
415   GstSeekFlags flags;
416   GstSeekType cur_type, stop_type;
417   gint64 cur, stop;
418
419   gst_event_parse_seek (event, &rate, &format, &flags,
420       &cur_type, &cur, &stop_type, &stop);
421
422   /* get seek format */
423   if (format == GST_FORMAT_DEFAULT)
424     format = GST_FORMAT_BYTES;
425   /* we can only seek bytes */
426   if (format != GST_FORMAT_BYTES)
427     return FALSE;
428
429   /* get seek positions */
430   src->segment_loop = flags & GST_SEEK_FLAG_SEGMENT;
431
432   /* send flush start */
433   gst_pad_push_event (src->srcpad, gst_event_new_flush_start ());
434
435   /* unblock streaming thread */
436   gst_base_src_unlock (src);
437
438   /* grab streaming lock */
439   GST_STREAM_LOCK (src->srcpad);
440
441   /* send flush stop */
442   gst_pad_push_event (src->srcpad, gst_event_new_flush_stop ());
443
444   /* perform the seek */
445   switch (cur_type) {
446     case GST_SEEK_TYPE_SET:
447       if (cur < 0)
448         goto error;
449       src->offset = MIN (cur, src->size);
450       src->segment_start = src->offset;
451       src->segment_end = MIN (stop, src->size);
452       GST_DEBUG_OBJECT (src, "seek set pending to %" G_GINT64_FORMAT,
453           src->offset);
454       break;
455     case GST_SEEK_TYPE_CUR:
456       cur += src->offset;
457       src->offset = CLAMP (cur, 0, src->size);
458       src->segment_start = src->offset;
459       src->segment_end = stop;
460       GST_DEBUG_OBJECT (src, "seek cur pending to %" G_GINT64_FORMAT,
461           src->offset);
462       break;
463     case GST_SEEK_TYPE_END:
464       if (cur > 0)
465         goto error;
466       cur = src->size + cur;
467       src->offset = MAX (0, cur);
468       src->segment_start = src->offset;
469       src->segment_end = stop;
470       GST_DEBUG_OBJECT (src, "seek end pending to %" G_GINT64_FORMAT,
471           src->offset);
472       break;
473     default:
474       goto error;
475   }
476
477   /* now make sure the discont will be send */
478   src->need_discont = TRUE;
479
480   /* and restart the task */
481   gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
482       src->srcpad);
483   GST_STREAM_UNLOCK (src->srcpad);
484
485   gst_event_unref (event);
486
487   return TRUE;
488
489   /* ERROR */
490 error:
491   {
492     GST_DEBUG_OBJECT (src, "seek error");
493     GST_STREAM_UNLOCK (src->srcpad);
494     gst_event_unref (event);
495     return FALSE;
496   }
497 }
498
499 static gboolean
500 gst_base_src_event_handler (GstPad * pad, GstEvent * event)
501 {
502   GstBaseSrc *src;
503   GstBaseSrcClass *bclass;
504   gboolean result;
505
506   src = GST_BASE_SRC (GST_PAD_PARENT (pad));
507   bclass = GST_BASE_SRC_GET_CLASS (src);
508
509   if (bclass->event)
510     result = bclass->event (src, event);
511
512   switch (GST_EVENT_TYPE (event)) {
513     case GST_EVENT_SEEK:
514       return gst_base_src_do_seek (src, event);
515     case GST_EVENT_FLUSH_START:
516       /* cancel any blocking getrange */
517       gst_base_src_unlock (src);
518       break;
519     case GST_EVENT_FLUSH_STOP:
520       break;
521     default:
522       break;
523   }
524   gst_event_unref (event);
525
526   return TRUE;
527 }
528
529 static void
530 gst_base_src_set_property (GObject * object, guint prop_id,
531     const GValue * value, GParamSpec * pspec)
532 {
533   GstBaseSrc *src;
534
535   src = GST_BASE_SRC (object);
536
537   switch (prop_id) {
538     case PROP_BLOCKSIZE:
539       src->blocksize = g_value_get_ulong (value);
540       break;
541     case PROP_HAS_LOOP:
542       src->has_loop = g_value_get_boolean (value);
543       gst_base_src_set_dataflow_funcs (src);
544       break;
545     case PROP_HAS_GETRANGE:
546       src->has_getrange = g_value_get_boolean (value);
547       gst_base_src_set_dataflow_funcs (src);
548       break;
549     case PROP_NUM_BUFFERS:
550       src->num_buffers = g_value_get_int (value);
551       break;
552     default:
553       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
554       break;
555   }
556 }
557
558 static void
559 gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
560     GParamSpec * pspec)
561 {
562   GstBaseSrc *src;
563
564   src = GST_BASE_SRC (object);
565
566   switch (prop_id) {
567     case PROP_BLOCKSIZE:
568       g_value_set_ulong (value, src->blocksize);
569       break;
570     case PROP_HAS_LOOP:
571       g_value_set_boolean (value, src->has_loop);
572       break;
573     case PROP_HAS_GETRANGE:
574       g_value_set_boolean (value, src->has_getrange);
575       break;
576     case PROP_NUM_BUFFERS:
577       g_value_set_int (value, src->num_buffers);
578       break;
579     default:
580       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
581       break;
582   }
583 }
584
585 static GstFlowReturn
586 gst_base_src_get_range (GstPad * pad, guint64 offset, guint length,
587     GstBuffer ** buf)
588 {
589   GstFlowReturn ret;
590   GstBaseSrc *src;
591   GstBaseSrcClass *bclass;
592
593   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
594   bclass = GST_BASE_SRC_GET_CLASS (src);
595
596   GST_LIVE_LOCK (src);
597   if (src->is_live) {
598     while (!src->live_running) {
599       GST_DEBUG ("live source signal waiting");
600       GST_LIVE_SIGNAL (src);
601       GST_DEBUG ("live source waiting for running state");
602       GST_LIVE_WAIT (src);
603       GST_DEBUG ("live source unlocked");
604     }
605   }
606   GST_LIVE_UNLOCK (src);
607
608   GST_LOCK (pad);
609   if (GST_PAD_IS_FLUSHING (pad))
610     goto flushing;
611   GST_UNLOCK (pad);
612
613   if (!GST_FLAG_IS_SET (src, GST_BASE_SRC_STARTED))
614     goto not_started;
615
616   if (!bclass->create)
617     goto no_function;
618
619   /* check size */
620   if (src->size != -1) {
621     if (offset > src->size)
622       goto unexpected_length;
623
624     if (offset + length > src->size) {
625       if (bclass->get_size)
626         bclass->get_size (src, &src->size);
627
628       if (offset + length > src->size) {
629         length = src->size - offset;
630       }
631     }
632   }
633   if (length == 0)
634     goto unexpected_length;
635
636   if (src->num_buffers_left == 0) {
637     goto reached_num_buffers;
638   } else {
639     if (src->num_buffers_left > 0)
640       src->num_buffers_left--;
641   }
642
643   ret = bclass->create (src, offset, length, buf);
644
645   return ret;
646
647   /* ERROR */
648 flushing:
649   {
650     GST_DEBUG_OBJECT (src, "pad is flushing");
651     GST_UNLOCK (pad);
652     return GST_FLOW_WRONG_STATE;
653   }
654 not_started:
655   {
656     GST_DEBUG_OBJECT (src, "getrange but not started");
657     return GST_FLOW_WRONG_STATE;
658   }
659 no_function:
660   {
661     GST_DEBUG_OBJECT (src, "no create function");
662     return GST_FLOW_ERROR;
663   }
664 unexpected_length:
665   {
666     GST_DEBUG_OBJECT (src, "unexpected length %u", length);
667     return GST_FLOW_UNEXPECTED;
668   }
669 reached_num_buffers:
670   {
671     GST_DEBUG_OBJECT (src, "sent all buffers");
672     return GST_FLOW_UNEXPECTED;
673   }
674 }
675
676 static gboolean
677 gst_base_src_check_get_range (GstPad * pad)
678 {
679   GstBaseSrc *src;
680
681   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
682
683   if (!GST_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)) {
684     gst_base_src_start (src);
685     gst_base_src_stop (src);
686   }
687
688   return src->seekable;
689 }
690
691 static void
692 gst_base_src_loop (GstPad * pad)
693 {
694   GstBaseSrc *src;
695   GstBuffer *buf = NULL;
696   GstFlowReturn ret;
697
698   src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
699
700   if (src->need_discont) {
701     /* now send discont */
702     gst_base_src_send_discont (src);
703     src->need_discont = FALSE;
704   }
705
706   ret = gst_base_src_get_range (pad, src->offset, src->blocksize, &buf);
707   if (ret != GST_FLOW_OK)
708     goto eos;
709
710   if (buf == NULL)
711     goto error;
712
713   src->offset += GST_BUFFER_SIZE (buf);
714
715   ret = gst_pad_push (pad, buf);
716   if (ret != GST_FLOW_OK)
717     goto pause;
718
719   return;
720
721 eos:
722   {
723     GST_DEBUG_OBJECT (src, "going to EOS");
724     gst_pad_pause_task (pad);
725     gst_pad_push_event (pad, gst_event_new_eos ());
726     return;
727   }
728 pause:
729   {
730     GST_DEBUG_OBJECT (src, "pausing task");
731     gst_pad_pause_task (pad);
732     if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
733       /* for fatal errors we post an error message */
734       GST_ELEMENT_ERROR (src, STREAM, STOPPED,
735           ("streaming stopped, reason %s", gst_flow_get_name (ret)),
736           ("streaming stopped, reason %s", gst_flow_get_name (ret)));
737       gst_pad_push_event (pad, gst_event_new_eos ());
738     }
739     return;
740   }
741 error:
742   {
743     GST_ELEMENT_ERROR (src, STREAM, STOPPED,
744         ("internal: element returned NULL buffer"),
745         ("internal: element returned NULL buffer"));
746     gst_pad_pause_task (pad);
747     gst_pad_push_event (pad, gst_event_new_eos ());
748     return;
749   }
750 }
751
752 static gboolean
753 gst_base_src_unlock (GstBaseSrc * basesrc)
754 {
755   GstBaseSrcClass *bclass;
756   gboolean result = FALSE;
757
758   GST_DEBUG ("unlock");
759   /* unblock whatever the subclass is doing */
760   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
761   if (bclass->unlock)
762     result = bclass->unlock (basesrc);
763
764   GST_DEBUG ("unschedule clock");
765   /* and unblock the clock as well, if any */
766   GST_LOCK (basesrc);
767   if (basesrc->clock_id) {
768     gst_clock_id_unschedule (basesrc->clock_id);
769   }
770   GST_UNLOCK (basesrc);
771
772   GST_DEBUG ("unlock done");
773
774   return result;
775 }
776
777 static gboolean
778 gst_base_src_get_size (GstBaseSrc * basesrc, guint64 * size)
779 {
780   GstBaseSrcClass *bclass;
781   gboolean result = FALSE;
782
783   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
784   if (bclass->get_size)
785     result = bclass->get_size (basesrc, size);
786
787   if (result)
788     basesrc->size = *size;
789
790   return result;
791 }
792
793 static gboolean
794 gst_base_src_is_seekable (GstBaseSrc * basesrc)
795 {
796   GstBaseSrcClass *bclass;
797
798   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
799
800   /* check if we can seek */
801   if (bclass->is_seekable)
802     basesrc->seekable = bclass->is_seekable (basesrc);
803   else
804     basesrc->seekable = FALSE;
805
806   return basesrc->seekable;
807 }
808
809 static gboolean
810 gst_base_src_default_negotiate (GstBaseSrc * basesrc)
811 {
812   GstCaps *thiscaps;
813   GstCaps *caps = NULL;
814   GstCaps *peercaps = NULL;
815   gboolean result = FALSE;
816
817   thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
818   GST_DEBUG ("caps of src: %" GST_PTR_FORMAT, thiscaps);
819   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
820     goto no_nego_needed;
821
822   peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
823   GST_DEBUG ("caps of peer: %" GST_PTR_FORMAT, peercaps);
824   if (peercaps) {
825     GstCaps *icaps;
826
827     icaps = gst_caps_intersect (thiscaps, peercaps);
828     GST_DEBUG ("intersect: %" GST_PTR_FORMAT, icaps);
829     gst_caps_unref (thiscaps);
830     gst_caps_unref (peercaps);
831     if (icaps) {
832       caps = gst_caps_copy_nth (icaps, 0);
833       gst_caps_unref (icaps);
834     }
835   } else {
836     caps = thiscaps;
837   }
838   if (caps) {
839     caps = gst_caps_make_writable (caps);
840     gst_caps_truncate (caps);
841
842     gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
843     GST_DEBUG ("fixated to: %" GST_PTR_FORMAT, caps);
844
845     if (gst_caps_is_any (caps)) {
846       gst_caps_unref (caps);
847       result = TRUE;
848     } else if (gst_caps_is_fixed (caps)) {
849       gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
850       gst_caps_unref (caps);
851       result = TRUE;
852     }
853   }
854   return result;
855
856 no_nego_needed:
857   {
858     GST_DEBUG ("no negotiation needed");
859     if (thiscaps)
860       gst_caps_unref (thiscaps);
861     return TRUE;
862   }
863 }
864
865 static gboolean
866 gst_base_src_negotiate (GstBaseSrc * basesrc)
867 {
868   GstBaseSrcClass *bclass;
869   gboolean result = TRUE;
870
871   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
872
873   if (bclass->negotiate)
874     result = bclass->negotiate (basesrc);
875
876   return result;
877 }
878
879 static gboolean
880 gst_base_src_start (GstBaseSrc * basesrc)
881 {
882   GstBaseSrcClass *bclass;
883   gboolean result;
884
885   if (GST_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
886     return TRUE;
887
888   GST_DEBUG_OBJECT (basesrc, "starting source");
889
890   basesrc->num_buffers_left = basesrc->num_buffers;
891
892   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
893   if (bclass->start)
894     result = bclass->start (basesrc);
895   else
896     result = TRUE;
897
898   if (!result)
899     goto could_not_start;
900
901   GST_FLAG_SET (basesrc, GST_BASE_SRC_STARTED);
902
903   /* start in the beginning */
904   basesrc->offset = 0;
905
906   /* figure out the size */
907   if (bclass->get_size) {
908     result = bclass->get_size (basesrc, &basesrc->size);
909     if (result == FALSE)
910       basesrc->size = -1;
911   } else {
912     result = FALSE;
913     basesrc->size = -1;
914   }
915
916   GST_DEBUG ("size %d %lld", result, basesrc->size);
917
918   /* we always run to the end */
919   basesrc->segment_start = 0;
920   basesrc->segment_end = basesrc->size;
921   basesrc->need_discont = TRUE;
922
923   /* check if we can seek, updates ->seekable */
924   gst_base_src_is_seekable (basesrc);
925
926   /* run typefind */
927 #if 0
928   if (basesrc->seekable) {
929     GstCaps *caps;
930
931     caps = gst_type_find_helper (basesrc->srcpad, basesrc->size);
932     gst_pad_set_caps (basesrc->srcpad, caps);
933     gst_caps_unref (caps);
934   }
935 #endif
936
937   if (!gst_base_src_negotiate (basesrc))
938     goto could_not_negotiate;
939
940   return TRUE;
941
942   /* ERROR */
943 could_not_start:
944   {
945     GST_DEBUG_OBJECT (basesrc, "could not start");
946     return FALSE;
947   }
948 could_not_negotiate:
949   {
950     GST_DEBUG_OBJECT (basesrc, "could not negotiate, stopping");
951     GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
952         ("Could not connect source to pipeline"),
953         ("Check your filtered caps, if any"));
954     gst_base_src_stop (basesrc);
955     return FALSE;
956   }
957 }
958
959 static gboolean
960 gst_base_src_stop (GstBaseSrc * basesrc)
961 {
962   GstBaseSrcClass *bclass;
963   gboolean result = TRUE;
964
965   if (!GST_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
966     return TRUE;
967
968   GST_DEBUG_OBJECT (basesrc, "stopping source");
969
970   bclass = GST_BASE_SRC_GET_CLASS (basesrc);
971   if (bclass->stop)
972     result = bclass->stop (basesrc);
973
974   if (result)
975     GST_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
976
977   return result;
978 }
979
980 static gboolean
981 gst_base_src_deactivate (GstBaseSrc * basesrc, GstPad * pad)
982 {
983   gboolean result;
984
985   GST_LIVE_LOCK (basesrc);
986   basesrc->live_running = TRUE;
987   GST_LIVE_SIGNAL (basesrc);
988   GST_LIVE_UNLOCK (basesrc);
989
990   /* step 1, unblock clock sync (if any) */
991   gst_base_src_unlock (basesrc);
992
993   /* step 2, make sure streaming finishes */
994   result = gst_pad_stop_task (pad);
995
996   return result;
997 }
998
999 static gboolean
1000 gst_base_src_activate_push (GstPad * pad, gboolean active)
1001 {
1002   GstBaseSrc *basesrc;
1003
1004   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
1005
1006   /* prepare subclass first */
1007   if (active) {
1008     GST_DEBUG_OBJECT (basesrc, "Activating in push mode");
1009     if (!gst_base_src_start (basesrc))
1010       goto error_start;
1011
1012     return gst_pad_start_task (pad, (GstTaskFunction) gst_base_src_loop, pad);
1013   } else {
1014     GST_DEBUG_OBJECT (basesrc, "Deactivating in push mode");
1015     return gst_base_src_deactivate (basesrc, pad);
1016   }
1017
1018 error_start:
1019   {
1020     gst_base_src_stop (basesrc);
1021     GST_DEBUG_OBJECT (basesrc, "Failed to start in push mode");
1022     return FALSE;
1023   }
1024 }
1025
1026 static gboolean
1027 gst_base_src_activate_pull (GstPad * pad, gboolean active)
1028 {
1029   GstBaseSrc *basesrc;
1030
1031   basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
1032
1033   /* prepare subclass first */
1034   if (active) {
1035     GST_DEBUG_OBJECT (basesrc, "Activating in pull mode");
1036     if (!gst_base_src_start (basesrc))
1037       goto error_start;
1038
1039     if (!basesrc->seekable) {
1040       gst_base_src_stop (basesrc);
1041       return FALSE;
1042     }
1043
1044     return TRUE;
1045   } else {
1046     GST_DEBUG_OBJECT (basesrc, "Deactivating in pull mode");
1047
1048     if (!gst_base_src_stop (basesrc))
1049       goto error_stop;
1050
1051     return gst_base_src_deactivate (basesrc, pad);
1052   }
1053
1054 error_start:
1055   {
1056     gst_base_src_stop (basesrc);
1057     GST_DEBUG_OBJECT (basesrc, "Failed to start in pull mode");
1058     return FALSE;
1059   }
1060 error_stop:
1061   {
1062     GST_DEBUG_OBJECT (basesrc, "Failed to stop in pull mode");
1063     return FALSE;
1064   }
1065 }
1066
1067 static GstElementStateReturn
1068 gst_base_src_change_state (GstElement * element)
1069 {
1070   GstBaseSrc *basesrc;
1071   GstElementStateReturn result = GST_STATE_SUCCESS;
1072   GstElementStateReturn presult;
1073   GstElementState transition;
1074
1075   basesrc = GST_BASE_SRC (element);
1076
1077   transition = GST_STATE_TRANSITION (element);
1078
1079   switch (transition) {
1080     case GST_STATE_NULL_TO_READY:
1081       break;
1082     case GST_STATE_READY_TO_PAUSED:
1083       GST_LIVE_LOCK (element);
1084       if (basesrc->is_live) {
1085         result = GST_STATE_NO_PREROLL;
1086         basesrc->live_running = FALSE;
1087       }
1088       GST_LIVE_UNLOCK (element);
1089       break;
1090     case GST_STATE_PAUSED_TO_PLAYING:
1091       GST_LIVE_LOCK (element);
1092       if (basesrc->is_live) {
1093         basesrc->live_running = TRUE;
1094         GST_LIVE_SIGNAL (element);
1095       }
1096       GST_LIVE_UNLOCK (element);
1097       break;
1098     default:
1099       break;
1100   }
1101
1102   if ((presult = GST_ELEMENT_CLASS (parent_class)->change_state (element)) !=
1103       GST_STATE_SUCCESS) {
1104     gst_base_src_stop (basesrc);
1105     return presult;
1106   }
1107
1108   switch (transition) {
1109     case GST_STATE_PLAYING_TO_PAUSED:
1110       GST_LIVE_LOCK (element);
1111       if (basesrc->is_live) {
1112         result = GST_STATE_NO_PREROLL;
1113         basesrc->live_running = FALSE;
1114       }
1115       GST_LIVE_UNLOCK (element);
1116       break;
1117     case GST_STATE_PAUSED_TO_READY:
1118       if (!gst_base_src_stop (basesrc))
1119         result = GST_STATE_FAILURE;
1120       break;
1121     case GST_STATE_READY_TO_NULL:
1122       break;
1123     default:
1124       break;
1125   }
1126
1127   return result;
1128 }