Branch data Line data Source code
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: #GstPushSrc, #GstBaseTransform, #GstBaseSink
27 : : *
28 : : * This is a generice base class for source elements. The following
29 : : * types of sources are supported:
30 : : * <itemizedlist>
31 : : * <listitem><para>random access sources like files</para></listitem>
32 : : * <listitem><para>seekable sources</para></listitem>
33 : : * <listitem><para>live sources</para></listitem>
34 : : * </itemizedlist>
35 : : *
36 : : * The source can be configured to operate in any #GstFormat with the
37 : : * gst_base_src_set_format() method. The currently set format determines
38 : : * the format of the internal #GstSegment and any #GST_EVENT_NEWSEGMENT
39 : : * events. The default format for #GstBaseSrc is #GST_FORMAT_BYTES.
40 : : *
41 : : * #GstBaseSrc always supports push mode scheduling. If the following
42 : : * conditions are met, it also supports pull mode scheduling:
43 : : * <itemizedlist>
44 : : * <listitem><para>The format is set to #GST_FORMAT_BYTES (default).</para>
45 : : * </listitem>
46 : : * <listitem><para>#GstBaseSrcClass.is_seekable() returns %TRUE.</para>
47 : : * </listitem>
48 : : * </itemizedlist>
49 : : *
50 : : * Since 0.10.9, any #GstBaseSrc can enable pull based scheduling at any time
51 : : * by overriding #GstBaseSrcClass.check_get_range() so that it returns %TRUE.
52 : : *
53 : : * If all the conditions are met for operating in pull mode, #GstBaseSrc is
54 : : * automatically seekable in push mode as well. The following conditions must
55 : : * be met to make the element seekable in push mode when the format is not
56 : : * #GST_FORMAT_BYTES:
57 : : * <itemizedlist>
58 : : * <listitem><para>
59 : : * #GstBaseSrcClass.is_seekable() returns %TRUE.
60 : : * </para></listitem>
61 : : * <listitem><para>
62 : : * #GstBaseSrcClass.query() can convert all supported seek formats to the
63 : : * internal format as set with gst_base_src_set_format().
64 : : * </para></listitem>
65 : : * <listitem><para>
66 : : * #GstBaseSrcClass.do_seek() is implemented, performs the seek and returns
67 : : * %TRUE.
68 : : * </para></listitem>
69 : : * </itemizedlist>
70 : : *
71 : : * When the element does not meet the requirements to operate in pull mode, the
72 : : * offset and length in the #GstBaseSrcClass.create() method should be ignored.
73 : : * It is recommended to subclass #GstPushSrc instead, in this situation. If the
74 : : * element can operate in pull mode but only with specific offsets and
75 : : * lengths, it is allowed to generate an error when the wrong values are passed
76 : : * to the #GstBaseSrcClass.create() function.
77 : : *
78 : : * #GstBaseSrc has support for live sources. Live sources are sources that when
79 : : * paused discard data, such as audio or video capture devices. A typical live
80 : : * source also produces data at a fixed rate and thus provides a clock to publish
81 : : * this rate.
82 : : * Use gst_base_src_set_live() to activate the live source mode.
83 : : *
84 : : * A live source does not produce data in the PAUSED state. This means that the
85 : : * #GstBaseSrcClass.create() method will not be called in PAUSED but only in
86 : : * PLAYING. To signal the pipeline that the element will not produce data, the
87 : : * return value from the READY to PAUSED state will be
88 : : * #GST_STATE_CHANGE_NO_PREROLL.
89 : : *
90 : : * A typical live source will timestamp the buffers it creates with the
91 : : * current running time of the pipeline. This is one reason why a live source
92 : : * can only produce data in the PLAYING state, when the clock is actually
93 : : * distributed and running.
94 : : *
95 : : * Live sources that synchronize and block on the clock (an audio source, for
96 : : * example) can since 0.10.12 use gst_base_src_wait_playing() when the
97 : : * #GstBaseSrcClass.create() function was interrupted by a state change to
98 : : * PAUSED.
99 : : *
100 : : * The #GstBaseSrcClass.get_times() method can be used to implement pseudo-live
101 : : * sources. It only makes sense to implement the #GstBaseSrcClass.get_times()
102 : : * function if the source is a live source. The #GstBaseSrcClass.get_times()
103 : : * function should return timestamps starting from 0, as if it were a non-live
104 : : * source. The base class will make sure that the timestamps are transformed
105 : : * into the current running_time. The base source will then wait for the
106 : : * calculated running_time before pushing out the buffer.
107 : : *
108 : : * For live sources, the base class will by default report a latency of 0.
109 : : * For pseudo live sources, the base class will by default measure the difference
110 : : * between the first buffer timestamp and the start time of get_times and will
111 : : * report this value as the latency.
112 : : * Subclasses should override the query function when this behaviour is not
113 : : * acceptable.
114 : : *
115 : : * There is only support in #GstBaseSrc for exactly one source pad, which
116 : : * should be named "src". A source implementation (subclass of #GstBaseSrc)
117 : : * should install a pad template in its class_init function, like so:
118 : : * |[
119 : : * static void
120 : : * my_element_class_init (GstMyElementClass *klass)
121 : : * {
122 : : * GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
123 : : * // srctemplate should be a #GstStaticPadTemplate with direction
124 : : * // #GST_PAD_SRC and name "src"
125 : : * gst_element_class_add_pad_template (gstelement_class,
126 : : * gst_static_pad_template_get (&srctemplate));
127 : : * // see #GstElementDetails
128 : : * gst_element_class_set_details (gstelement_class, &details);
129 : : * }
130 : : * ]|
131 : : *
132 : : * <refsect2>
133 : : * <title>Controlled shutdown of live sources in applications</title>
134 : : * <para>
135 : : * Applications that record from a live source may want to stop recording
136 : : * in a controlled way, so that the recording is stopped, but the data
137 : : * already in the pipeline is processed to the end (remember that many live
138 : : * sources would go on recording forever otherwise). For that to happen the
139 : : * application needs to make the source stop recording and send an EOS
140 : : * event down the pipeline. The application would then wait for an
141 : : * EOS message posted on the pipeline's bus to know when all data has
142 : : * been processed and the pipeline can safely be stopped.
143 : : *
144 : : * Since GStreamer 0.10.16 an application may send an EOS event to a source
145 : : * element to make it perform the EOS logic (send EOS event downstream or post a
146 : : * #GST_MESSAGE_SEGMENT_DONE on the bus). This can typically be done
147 : : * with the gst_element_send_event() function on the element or its parent bin.
148 : : *
149 : : * After the EOS has been sent to the element, the application should wait for
150 : : * an EOS message to be posted on the pipeline's bus. Once this EOS message is
151 : : * received, it may safely shut down the entire pipeline.
152 : : *
153 : : * The old behaviour for controlled shutdown introduced since GStreamer 0.10.3
154 : : * is still available but deprecated as it is dangerous and less flexible.
155 : : *
156 : : * Last reviewed on 2007-12-19 (0.10.16)
157 : : * </para>
158 : : * </refsect2>
159 : : */
160 : :
161 : : #ifdef HAVE_CONFIG_H
162 : : # include "config.h"
163 : : #endif
164 : :
165 : : #include <stdlib.h>
166 : : #include <string.h>
167 : :
168 : : #include <gst/gst_private.h>
169 : :
170 : : #include "gstbasesrc.h"
171 : : #include "gsttypefindhelper.h"
172 : : #include <gst/gstmarshal.h>
173 : : #include <gst/gst-i18n-lib.h>
174 : :
175 : : GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);
176 : : #define GST_CAT_DEFAULT gst_base_src_debug
177 : :
178 : : #define GST_LIVE_GET_LOCK(elem) (GST_BASE_SRC_CAST(elem)->live_lock)
179 : : #define GST_LIVE_LOCK(elem) g_mutex_lock(GST_LIVE_GET_LOCK(elem))
180 : : #define GST_LIVE_TRYLOCK(elem) g_mutex_trylock(GST_LIVE_GET_LOCK(elem))
181 : : #define GST_LIVE_UNLOCK(elem) g_mutex_unlock(GST_LIVE_GET_LOCK(elem))
182 : : #define GST_LIVE_GET_COND(elem) (GST_BASE_SRC_CAST(elem)->live_cond)
183 : : #define GST_LIVE_WAIT(elem) g_cond_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem))
184 : : #define GST_LIVE_TIMED_WAIT(elem, timeval) g_cond_timed_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem),\
185 : : timeval)
186 : : #define GST_LIVE_SIGNAL(elem) g_cond_signal (GST_LIVE_GET_COND (elem));
187 : : #define GST_LIVE_BROADCAST(elem) g_cond_broadcast (GST_LIVE_GET_COND (elem));
188 : :
189 : : /* BaseSrc signals and args */
190 : : enum
191 : : {
192 : : /* FILL ME */
193 : : LAST_SIGNAL
194 : : };
195 : :
196 : : #define DEFAULT_BLOCKSIZE 4096
197 : : #define DEFAULT_NUM_BUFFERS -1
198 : : #define DEFAULT_TYPEFIND FALSE
199 : : #define DEFAULT_DO_TIMESTAMP FALSE
200 : :
201 : : enum
202 : : {
203 : : PROP_0,
204 : : PROP_BLOCKSIZE,
205 : : PROP_NUM_BUFFERS,
206 : : PROP_TYPEFIND,
207 : : PROP_DO_TIMESTAMP
208 : : };
209 : :
210 : : #define GST_BASE_SRC_GET_PRIVATE(obj) \
211 : : (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_SRC, GstBaseSrcPrivate))
212 : :
213 : : struct _GstBaseSrcPrivate
214 : : {
215 : : gboolean last_sent_eos; /* last thing we did was send an EOS (we set this
216 : : * to avoid the sending of two EOS in some cases) */
217 : : gboolean discont;
218 : : gboolean flushing;
219 : :
220 : : /* two segments to be sent in the streaming thread with STREAM_LOCK */
221 : : GstEvent *close_segment;
222 : : GstEvent *start_segment;
223 : : gboolean newsegment_pending;
224 : :
225 : : /* if EOS is pending (atomic) */
226 : : gint pending_eos;
227 : :
228 : : /* startup latency is the time it takes between going to PLAYING and producing
229 : : * the first BUFFER with running_time 0. This value is included in the latency
230 : : * reporting. */
231 : : GstClockTime latency;
232 : : /* timestamp offset, this is the offset add to the values of gst_times for
233 : : * pseudo live sources */
234 : : GstClockTimeDiff ts_offset;
235 : :
236 : : gboolean do_timestamp;
237 : :
238 : : /* stream sequence number */
239 : : guint32 seqnum;
240 : :
241 : : /* pending tags to be pushed in the data stream */
242 : : GList *pending_tags;
243 : : volatile gint have_tags;
244 : :
245 : : /* QoS *//* with LOCK */
246 : : gboolean qos_enabled;
247 : : gdouble proportion;
248 : : GstClockTime earliest_time;
249 : : };
250 : :
251 : : static GstElementClass *parent_class = NULL;
252 : :
253 : : static void gst_base_src_base_init (gpointer g_class);
254 : : static void gst_base_src_class_init (GstBaseSrcClass * klass);
255 : : static void gst_base_src_init (GstBaseSrc * src, gpointer g_class);
256 : : static void gst_base_src_finalize (GObject * object);
257 : :
258 : :
259 : : GType
260 : 1188303 : gst_base_src_get_type (void)
261 : : {
262 : : static volatile gsize base_src_type = 0;
263 : :
264 [ + + ]: 1188303 : if (g_once_init_enter (&base_src_type)) {
265 : : GType _type;
266 : : static const GTypeInfo base_src_info = {
267 : : sizeof (GstBaseSrcClass),
268 : : (GBaseInitFunc) gst_base_src_base_init,
269 : : NULL,
270 : : (GClassInitFunc) gst_base_src_class_init,
271 : : NULL,
272 : : NULL,
273 : : sizeof (GstBaseSrc),
274 : : 0,
275 : : (GInstanceInitFunc) gst_base_src_init,
276 : : };
277 : :
278 : 153 : _type = g_type_register_static (GST_TYPE_ELEMENT,
279 : : "GstBaseSrc", &base_src_info, G_TYPE_FLAG_ABSTRACT);
280 : 153 : g_once_init_leave (&base_src_type, _type);
281 : : }
282 : 1188304 : return base_src_type;
283 : : }
284 : :
285 : : static GstCaps *gst_base_src_getcaps (GstPad * pad);
286 : : static gboolean gst_base_src_setcaps (GstPad * pad, GstCaps * caps);
287 : : static void gst_base_src_fixate (GstPad * pad, GstCaps * caps);
288 : :
289 : : static gboolean gst_base_src_activate_push (GstPad * pad, gboolean active);
290 : : static gboolean gst_base_src_activate_pull (GstPad * pad, gboolean active);
291 : : static void gst_base_src_set_property (GObject * object, guint prop_id,
292 : : const GValue * value, GParamSpec * pspec);
293 : : static void gst_base_src_get_property (GObject * object, guint prop_id,
294 : : GValue * value, GParamSpec * pspec);
295 : : static gboolean gst_base_src_event_handler (GstPad * pad, GstEvent * event);
296 : : static gboolean gst_base_src_send_event (GstElement * elem, GstEvent * event);
297 : : static gboolean gst_base_src_default_event (GstBaseSrc * src, GstEvent * event);
298 : : static const GstQueryType *gst_base_src_get_query_types (GstElement * element);
299 : :
300 : : static gboolean gst_base_src_query (GstPad * pad, GstQuery * query);
301 : :
302 : : static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc);
303 : : static gboolean gst_base_src_default_do_seek (GstBaseSrc * src,
304 : : GstSegment * segment);
305 : : static gboolean gst_base_src_default_query (GstBaseSrc * src, GstQuery * query);
306 : : static gboolean gst_base_src_default_prepare_seek_segment (GstBaseSrc * src,
307 : : GstEvent * event, GstSegment * segment);
308 : :
309 : : static gboolean gst_base_src_set_flushing (GstBaseSrc * basesrc,
310 : : gboolean flushing, gboolean live_play, gboolean unlock, gboolean * playing);
311 : : static gboolean gst_base_src_start (GstBaseSrc * basesrc);
312 : : static gboolean gst_base_src_stop (GstBaseSrc * basesrc);
313 : :
314 : : static GstStateChangeReturn gst_base_src_change_state (GstElement * element,
315 : : GstStateChange transition);
316 : :
317 : : static void gst_base_src_loop (GstPad * pad);
318 : : static gboolean gst_base_src_pad_check_get_range (GstPad * pad);
319 : : static gboolean gst_base_src_default_check_get_range (GstBaseSrc * bsrc);
320 : : static GstFlowReturn gst_base_src_pad_get_range (GstPad * pad, guint64 offset,
321 : : guint length, GstBuffer ** buf);
322 : : static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset,
323 : : guint length, GstBuffer ** buf);
324 : : static gboolean gst_base_src_seekable (GstBaseSrc * src);
325 : :
326 : : static void
327 : 253 : gst_base_src_base_init (gpointer g_class)
328 : : {
329 [ + + ]: 253 : GST_DEBUG_CATEGORY_INIT (gst_base_src_debug, "basesrc", 0, "basesrc element");
330 : 253 : }
331 : :
332 : : static void
333 : 111 : gst_base_src_class_init (GstBaseSrcClass * klass)
334 : : {
335 : : GObjectClass *gobject_class;
336 : : GstElementClass *gstelement_class;
337 : :
338 : 111 : gobject_class = G_OBJECT_CLASS (klass);
339 : 111 : gstelement_class = GST_ELEMENT_CLASS (klass);
340 : :
341 : 111 : g_type_class_add_private (klass, sizeof (GstBaseSrcPrivate));
342 : :
343 : 111 : parent_class = g_type_class_peek_parent (klass);
344 : :
345 : 111 : gobject_class->finalize = gst_base_src_finalize;
346 : 111 : gobject_class->set_property = gst_base_src_set_property;
347 : 111 : gobject_class->get_property = gst_base_src_get_property;
348 : :
349 : : /* FIXME 0.11: blocksize property should be int, not ulong (min is >max here) */
350 : 111 : g_object_class_install_property (gobject_class, PROP_BLOCKSIZE,
351 : : g_param_spec_ulong ("blocksize", "Block size",
352 : : "Size in bytes to read per buffer (-1 = default)", 0, G_MAXULONG,
353 : : DEFAULT_BLOCKSIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
354 : 111 : g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS,
355 : : g_param_spec_int ("num-buffers", "num-buffers",
356 : : "Number of buffers to output before sending EOS (-1 = unlimited)",
357 : : -1, G_MAXINT, DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE |
358 : : G_PARAM_STATIC_STRINGS));
359 : 111 : g_object_class_install_property (gobject_class, PROP_TYPEFIND,
360 : : g_param_spec_boolean ("typefind", "Typefind",
361 : : "Run typefind before negotiating", DEFAULT_TYPEFIND,
362 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
363 : 111 : g_object_class_install_property (gobject_class, PROP_DO_TIMESTAMP,
364 : : g_param_spec_boolean ("do-timestamp", "Do timestamp",
365 : : "Apply current stream time to buffers", DEFAULT_DO_TIMESTAMP,
366 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
367 : :
368 : 111 : gstelement_class->change_state =
369 : 111 : GST_DEBUG_FUNCPTR (gst_base_src_change_state);
370 : 111 : gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_base_src_send_event);
371 : 111 : gstelement_class->get_query_types =
372 : 111 : GST_DEBUG_FUNCPTR (gst_base_src_get_query_types);
373 : :
374 : 111 : klass->negotiate = GST_DEBUG_FUNCPTR (gst_base_src_default_negotiate);
375 : 111 : klass->event = GST_DEBUG_FUNCPTR (gst_base_src_default_event);
376 : 111 : klass->do_seek = GST_DEBUG_FUNCPTR (gst_base_src_default_do_seek);
377 : 111 : klass->query = GST_DEBUG_FUNCPTR (gst_base_src_default_query);
378 : 111 : klass->check_get_range =
379 : 111 : GST_DEBUG_FUNCPTR (gst_base_src_default_check_get_range);
380 : 111 : klass->prepare_seek_segment =
381 : 111 : GST_DEBUG_FUNCPTR (gst_base_src_default_prepare_seek_segment);
382 : :
383 : : /* Registering debug symbols for function pointers */
384 : 111 : GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_push);
385 : 111 : GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_activate_pull);
386 : 111 : GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_event_handler);
387 : 111 : GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_query);
388 : 111 : GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_pad_get_range);
389 : 111 : GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_pad_check_get_range);
390 : 111 : GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_getcaps);
391 : 111 : GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_setcaps);
392 : 111 : GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_fixate);
393 : 111 : }
394 : :
395 : : static void
396 : 164 : gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
397 : : {
398 : : GstPad *pad;
399 : : GstPadTemplate *pad_template;
400 : :
401 : 164 : basesrc->priv = GST_BASE_SRC_GET_PRIVATE (basesrc);
402 : :
403 : 164 : basesrc->is_live = FALSE;
404 : 164 : basesrc->live_lock = g_mutex_new ();
405 : 164 : basesrc->live_cond = g_cond_new ();
406 : 164 : basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
407 : 164 : basesrc->num_buffers_left = -1;
408 : :
409 : 164 : basesrc->can_activate_push = TRUE;
410 : 164 : basesrc->pad_mode = GST_ACTIVATE_NONE;
411 : :
412 : 164 : pad_template =
413 : 164 : gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
414 [ - + ]: 328 : g_return_if_fail (pad_template != NULL);
415 : :
416 [ - + ]: 164 : GST_DEBUG_OBJECT (basesrc, "creating src pad");
417 : 164 : pad = gst_pad_new_from_template (pad_template, "src");
418 : :
419 [ - + ]: 164 : GST_DEBUG_OBJECT (basesrc, "setting functions on src pad");
420 : 164 : gst_pad_set_activatepush_function (pad, gst_base_src_activate_push);
421 : 164 : gst_pad_set_activatepull_function (pad, gst_base_src_activate_pull);
422 : 164 : gst_pad_set_event_function (pad, gst_base_src_event_handler);
423 : 164 : gst_pad_set_query_function (pad, gst_base_src_query);
424 : 164 : gst_pad_set_checkgetrange_function (pad, gst_base_src_pad_check_get_range);
425 : 164 : gst_pad_set_getrange_function (pad, gst_base_src_pad_get_range);
426 : 164 : gst_pad_set_getcaps_function (pad, gst_base_src_getcaps);
427 : 164 : gst_pad_set_setcaps_function (pad, gst_base_src_setcaps);
428 : 164 : gst_pad_set_fixatecaps_function (pad, gst_base_src_fixate);
429 : :
430 : : /* hold pointer to pad */
431 : 164 : basesrc->srcpad = pad;
432 [ - + ]: 164 : GST_DEBUG_OBJECT (basesrc, "adding src pad");
433 : 164 : gst_element_add_pad (GST_ELEMENT (basesrc), pad);
434 : :
435 : 164 : basesrc->blocksize = DEFAULT_BLOCKSIZE;
436 : 164 : basesrc->clock_id = NULL;
437 : : /* we operate in BYTES by default */
438 : 164 : gst_base_src_set_format (basesrc, GST_FORMAT_BYTES);
439 : 164 : basesrc->data.ABI.typefind = DEFAULT_TYPEFIND;
440 : 164 : basesrc->priv->do_timestamp = DEFAULT_DO_TIMESTAMP;
441 : 164 : g_atomic_int_set (&basesrc->priv->have_tags, FALSE);
442 : :
443 : 164 : GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
444 : 164 : GST_OBJECT_FLAG_SET (basesrc, GST_ELEMENT_IS_SOURCE);
445 : :
446 [ - + ]: 164 : GST_DEBUG_OBJECT (basesrc, "init done");
447 : : }
448 : :
449 : : static void
450 : 156 : gst_base_src_finalize (GObject * object)
451 : : {
452 : : GstBaseSrc *basesrc;
453 : : GstEvent **event_p;
454 : :
455 : 156 : basesrc = GST_BASE_SRC (object);
456 : :
457 : 156 : g_mutex_free (basesrc->live_lock);
458 : 156 : g_cond_free (basesrc->live_cond);
459 : :
460 : 156 : event_p = &basesrc->data.ABI.pending_seek;
461 : 156 : gst_event_replace (event_p, NULL);
462 : :
463 [ - + ]: 156 : if (basesrc->priv->pending_tags) {
464 : 0 : g_list_foreach (basesrc->priv->pending_tags, (GFunc) gst_event_unref, NULL);
465 : 0 : g_list_free (basesrc->priv->pending_tags);
466 : : }
467 : :
468 : 156 : G_OBJECT_CLASS (parent_class)->finalize (object);
469 : 156 : }
470 : :
471 : : /**
472 : : * gst_base_src_wait_playing:
473 : : * @src: the src
474 : : *
475 : : * If the #GstBaseSrcClass.create() method performs its own synchronisation
476 : : * against the clock it must unblock when going from PLAYING to the PAUSED state
477 : : * and call this method before continuing to produce the remaining data.
478 : : *
479 : : * This function will block until a state change to PLAYING happens (in which
480 : : * case this function returns #GST_FLOW_OK) or the processing must be stopped due
481 : : * to a state change to READY or a FLUSH event (in which case this function
482 : : * returns #GST_FLOW_WRONG_STATE).
483 : : *
484 : : * Since: 0.10.12
485 : : *
486 : : * Returns: #GST_FLOW_OK if @src is PLAYING and processing can
487 : : * continue. Any other return value should be returned from the create vmethod.
488 : : */
489 : : GstFlowReturn
490 : 0 : gst_base_src_wait_playing (GstBaseSrc * src)
491 : : {
492 [ # # ][ # # ]: 0 : g_return_val_if_fail (GST_IS_BASE_SRC (src), GST_FLOW_ERROR);
[ # # ][ # # ]
493 : :
494 : : do {
495 : : /* block until the state changes, or we get a flush, or something */
496 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "live source waiting for running state");
497 : 0 : GST_LIVE_WAIT (src);
498 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "live source unlocked");
499 [ # # ]: 0 : if (src->priv->flushing)
500 : 0 : goto flushing;
501 [ # # ]: 0 : } while (G_UNLIKELY (!src->live_running));
502 : :
503 : 0 : return GST_FLOW_OK;
504 : :
505 : : /* ERRORS */
506 : : flushing:
507 : : {
508 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "we are flushing");
509 : 0 : return GST_FLOW_WRONG_STATE;
510 : : }
511 : : }
512 : :
513 : : /**
514 : : * gst_base_src_set_live:
515 : : * @src: base source instance
516 : : * @live: new live-mode
517 : : *
518 : : * If the element listens to a live source, @live should
519 : : * be set to %TRUE.
520 : : *
521 : : * A live source will not produce data in the PAUSED state and
522 : : * will therefore not be able to participate in the PREROLL phase
523 : : * of a pipeline. To signal this fact to the application and the
524 : : * pipeline, the state change return value of the live source will
525 : : * be GST_STATE_CHANGE_NO_PREROLL.
526 : : */
527 : : void
528 : 137 : gst_base_src_set_live (GstBaseSrc * src, gboolean live)
529 : : {
530 [ - + ][ + - ]: 274 : g_return_if_fail (GST_IS_BASE_SRC (src));
[ - + ][ - + ]
531 : :
532 : 137 : GST_OBJECT_LOCK (src);
533 : 137 : src->is_live = live;
534 : 137 : GST_OBJECT_UNLOCK (src);
535 : : }
536 : :
537 : : /**
538 : : * gst_base_src_is_live:
539 : : * @src: base source instance
540 : : *
541 : : * Check if an element is in live mode.
542 : : *
543 : : * Returns: %TRUE if element is in live mode.
544 : : */
545 : : gboolean
546 : 534553 : gst_base_src_is_live (GstBaseSrc * src)
547 : : {
548 : : gboolean result;
549 : :
550 [ - + ][ + - ]: 534553 : g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
[ - + ][ - + ]
551 : :
552 : 534553 : GST_OBJECT_LOCK (src);
553 : 534553 : result = src->is_live;
554 : 534553 : GST_OBJECT_UNLOCK (src);
555 : :
556 : 534553 : return result;
557 : : }
558 : :
559 : : /**
560 : : * gst_base_src_set_format:
561 : : * @src: base source instance
562 : : * @format: the format to use
563 : : *
564 : : * Sets the default format of the source. This will be the format used
565 : : * for sending NEW_SEGMENT events and for performing seeks.
566 : : *
567 : : * If a format of GST_FORMAT_BYTES is set, the element will be able to
568 : : * operate in pull mode if the #GstBaseSrcClass.is_seekable() returns TRUE.
569 : : *
570 : : * This function must only be called in states < %GST_STATE_PAUSED.
571 : : *
572 : : * Since: 0.10.1
573 : : */
574 : : void
575 : 558 : gst_base_src_set_format (GstBaseSrc * src, GstFormat format)
576 : : {
577 [ - + ][ + - ]: 558 : g_return_if_fail (GST_IS_BASE_SRC (src));
[ + + ][ - + ]
578 [ - + ]: 558 : g_return_if_fail (GST_STATE (src) <= GST_STATE_READY);
579 : :
580 : 558 : GST_OBJECT_LOCK (src);
581 : 558 : gst_segment_init (&src->segment, format);
582 : 558 : GST_OBJECT_UNLOCK (src);
583 : : }
584 : :
585 : : /**
586 : : * gst_base_src_query_latency:
587 : : * @src: the source
588 : : * @live: (out) (allow-none): if the source is live
589 : : * @min_latency: (out) (allow-none): the min latency of the source
590 : : * @max_latency: (out) (allow-none): the max latency of the source
591 : : *
592 : : * Query the source for the latency parameters. @live will be TRUE when @src is
593 : : * configured as a live source. @min_latency will be set to the difference
594 : : * between the running time and the timestamp of the first buffer.
595 : : * @max_latency is always the undefined value of -1.
596 : : *
597 : : * This function is mostly used by subclasses.
598 : : *
599 : : * Returns: TRUE if the query succeeded.
600 : : *
601 : : * Since: 0.10.13
602 : : */
603 : : gboolean
604 : 102 : gst_base_src_query_latency (GstBaseSrc * src, gboolean * live,
605 : : GstClockTime * min_latency, GstClockTime * max_latency)
606 : : {
607 : : GstClockTime min;
608 : :
609 [ - + ][ + - ]: 102 : g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
[ - + ][ - + ]
610 : :
611 : 102 : GST_OBJECT_LOCK (src);
612 [ + - ]: 102 : if (live)
613 : 102 : *live = src->is_live;
614 : :
615 : : /* if we have a startup latency, report this one, else report 0. Subclasses
616 : : * are supposed to override the query function if they want something
617 : : * else. */
618 [ + - ]: 102 : if (src->priv->latency != -1)
619 : 102 : min = src->priv->latency;
620 : : else
621 : 0 : min = 0;
622 : :
623 [ + - ]: 102 : if (min_latency)
624 : 102 : *min_latency = min;
625 [ + - ]: 102 : if (max_latency)
626 : 102 : *max_latency = -1;
627 : :
628 [ - + ][ # # ]: 102 : GST_LOG_OBJECT (src, "latency: live %d, min %" GST_TIME_FORMAT
[ # # ][ # # ]
[ # # ]
629 : : ", max %" GST_TIME_FORMAT, src->is_live, GST_TIME_ARGS (min),
630 : : GST_TIME_ARGS (-1));
631 : 102 : GST_OBJECT_UNLOCK (src);
632 : :
633 : 102 : return TRUE;
634 : : }
635 : :
636 : : /**
637 : : * gst_base_src_set_blocksize:
638 : : * @src: the source
639 : : * @blocksize: the new blocksize in bytes
640 : : *
641 : : * Set the number of bytes that @src will push out with each buffer. When
642 : : * @blocksize is set to -1, a default length will be used.
643 : : *
644 : : * Since: 0.10.22
645 : : */
646 : : /* FIXME 0.11: blocksize property should be int, not ulong */
647 : : void
648 : 1 : gst_base_src_set_blocksize (GstBaseSrc * src, gulong blocksize)
649 : : {
650 [ - + ][ + - ]: 2 : g_return_if_fail (GST_IS_BASE_SRC (src));
[ - + ][ - + ]
651 : :
652 : 1 : GST_OBJECT_LOCK (src);
653 : 1 : src->blocksize = blocksize;
654 : 1 : GST_OBJECT_UNLOCK (src);
655 : : }
656 : :
657 : : /**
658 : : * gst_base_src_get_blocksize:
659 : : * @src: the source
660 : : *
661 : : * Get the number of bytes that @src will push out with each buffer.
662 : : *
663 : : * Returns: the number of bytes pushed with each buffer.
664 : : *
665 : : * Since: 0.10.22
666 : : */
667 : : /* FIXME 0.11: blocksize property should be int, not ulong */
668 : : gulong
669 : 0 : gst_base_src_get_blocksize (GstBaseSrc * src)
670 : : {
671 : : gulong res;
672 : :
673 [ # # ][ # # ]: 0 : g_return_val_if_fail (GST_IS_BASE_SRC (src), 0);
[ # # ][ # # ]
674 : :
675 : 0 : GST_OBJECT_LOCK (src);
676 : 0 : res = src->blocksize;
677 : 0 : GST_OBJECT_UNLOCK (src);
678 : :
679 : 0 : return res;
680 : : }
681 : :
682 : :
683 : : /**
684 : : * gst_base_src_set_do_timestamp:
685 : : * @src: the source
686 : : * @timestamp: enable or disable timestamping
687 : : *
688 : : * Configure @src to automatically timestamp outgoing buffers based on the
689 : : * current running_time of the pipeline. This property is mostly useful for live
690 : : * sources.
691 : : *
692 : : * Since: 0.10.15
693 : : */
694 : : void
695 : 0 : gst_base_src_set_do_timestamp (GstBaseSrc * src, gboolean timestamp)
696 : : {
697 [ # # ][ # # ]: 0 : g_return_if_fail (GST_IS_BASE_SRC (src));
[ # # ][ # # ]
698 : :
699 : 0 : GST_OBJECT_LOCK (src);
700 : 0 : src->priv->do_timestamp = timestamp;
701 : 0 : GST_OBJECT_UNLOCK (src);
702 : : }
703 : :
704 : : /**
705 : : * gst_base_src_get_do_timestamp:
706 : : * @src: the source
707 : : *
708 : : * Query if @src timestamps outgoing buffers based on the current running_time.
709 : : *
710 : : * Returns: %TRUE if the base class will automatically timestamp outgoing buffers.
711 : : *
712 : : * Since: 0.10.15
713 : : */
714 : : gboolean
715 : 0 : gst_base_src_get_do_timestamp (GstBaseSrc * src)
716 : : {
717 : : gboolean res;
718 : :
719 [ # # ][ # # ]: 0 : g_return_val_if_fail (GST_IS_BASE_SRC (src), FALSE);
[ # # ][ # # ]
720 : :
721 : 0 : GST_OBJECT_LOCK (src);
722 : 0 : res = src->priv->do_timestamp;
723 : 0 : GST_OBJECT_UNLOCK (src);
724 : :
725 : 0 : return res;
726 : : }
727 : :
728 : : /**
729 : : * gst_base_src_new_seamless_segment:
730 : : * @src: The source
731 : : * @start: The new start value for the segment
732 : : * @stop: Stop value for the new segment
733 : : * @position: The position value for the new segent
734 : : *
735 : : * Prepare a new seamless segment for emission downstream. This function must
736 : : * only be called by derived sub-classes, and only from the create() function,
737 : : * as the stream-lock needs to be held.
738 : : *
739 : : * The format for the new segment will be the current format of the source, as
740 : : * configured with gst_base_src_set_format()
741 : : *
742 : : * Returns: %TRUE if preparation of the seamless segment succeeded.
743 : : *
744 : : * Since: 0.10.26
745 : : */
746 : : gboolean
747 : 0 : gst_base_src_new_seamless_segment (GstBaseSrc * src, gint64 start, gint64 stop,
748 : : gint64 position)
749 : : {
750 : 0 : gboolean res = TRUE;
751 : :
752 [ # # ][ # # ]: 0 : GST_DEBUG_OBJECT (src,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
753 : : "Starting new seamless segment. Start %" GST_TIME_FORMAT " stop %"
754 : : GST_TIME_FORMAT " position %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
755 : : GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
756 : :
757 : 0 : GST_OBJECT_LOCK (src);
758 [ # # ][ # # ]: 0 : if (src->data.ABI.running && !src->priv->newsegment_pending) {
759 [ # # ]: 0 : if (src->priv->close_segment)
760 : 0 : gst_event_unref (src->priv->close_segment);
761 : 0 : src->priv->close_segment =
762 : 0 : gst_event_new_new_segment_full (TRUE,
763 : : src->segment.rate, src->segment.applied_rate, src->segment.format,
764 : : src->segment.start, src->segment.last_stop, src->segment.time);
765 : : }
766 : :
767 : 0 : gst_segment_set_newsegment_full (&src->segment, FALSE, src->segment.rate,
768 : : src->segment.applied_rate, src->segment.format, start, stop, position);
769 : :
770 [ # # ]: 0 : if (src->priv->start_segment)
771 : 0 : gst_event_unref (src->priv->start_segment);
772 [ # # ]: 0 : if (src->segment.rate >= 0.0) {
773 : : /* forward, we send data from last_stop to stop */
774 : 0 : src->priv->start_segment =
775 : 0 : gst_event_new_new_segment_full (FALSE,
776 : : src->segment.rate, src->segment.applied_rate, src->segment.format,
777 : : src->segment.last_stop, stop, src->segment.time);
778 : : } else {
779 : : /* reverse, we send data from last_stop to start */
780 : 0 : src->priv->start_segment =
781 : 0 : gst_event_new_new_segment_full (FALSE,
782 : : src->segment.rate, src->segment.applied_rate, src->segment.format,
783 : : src->segment.start, src->segment.last_stop, src->segment.time);
784 : : }
785 : 0 : GST_OBJECT_UNLOCK (src);
786 : :
787 : 0 : src->priv->discont = TRUE;
788 : 0 : src->data.ABI.running = TRUE;
789 : :
790 : 0 : return res;
791 : : }
792 : :
793 : : static gboolean
794 : 0 : gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
795 : : {
796 : : GstBaseSrcClass *bclass;
797 : : GstBaseSrc *bsrc;
798 : 0 : gboolean res = TRUE;
799 : :
800 : 0 : bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
801 : 0 : bclass = GST_BASE_SRC_GET_CLASS (bsrc);
802 : :
803 [ # # ]: 0 : if (bclass->set_caps)
804 : 0 : res = bclass->set_caps (bsrc, caps);
805 : :
806 : 0 : return res;
807 : : }
808 : :
809 : : static GstCaps *
810 : 742 : gst_base_src_getcaps (GstPad * pad)
811 : : {
812 : : GstBaseSrcClass *bclass;
813 : : GstBaseSrc *bsrc;
814 : 742 : GstCaps *caps = NULL;
815 : :
816 : 742 : bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
817 : 742 : bclass = GST_BASE_SRC_GET_CLASS (bsrc);
818 [ - + ]: 742 : if (bclass->get_caps)
819 : 0 : caps = bclass->get_caps (bsrc);
820 : :
821 [ + - ]: 742 : if (caps == NULL) {
822 : : GstPadTemplate *pad_template;
823 : :
824 : 742 : pad_template =
825 : 742 : gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
826 [ + - ]: 742 : if (pad_template != NULL) {
827 : 742 : caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
828 : : }
829 : : }
830 : 742 : return caps;
831 : : }
832 : :
833 : : static void
834 : 0 : gst_base_src_fixate (GstPad * pad, GstCaps * caps)
835 : : {
836 : : GstBaseSrcClass *bclass;
837 : : GstBaseSrc *bsrc;
838 : :
839 : 0 : bsrc = GST_BASE_SRC (gst_pad_get_parent (pad));
840 : 0 : bclass = GST_BASE_SRC_GET_CLASS (bsrc);
841 : :
842 [ # # ]: 0 : if (bclass->fixate)
843 : 0 : bclass->fixate (bsrc, caps);
844 : :
845 : 0 : gst_object_unref (bsrc);
846 : 0 : }
847 : :
848 : : static gboolean
849 : 120 : gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
850 : : {
851 : : gboolean res;
852 : :
853 [ + + + - : 120 : switch (GST_QUERY_TYPE (query)) {
- - + - -
- ]
854 : : case GST_QUERY_POSITION:
855 : : {
856 : : GstFormat format;
857 : :
858 : 6 : gst_query_parse_position (query, &format, NULL);
859 : :
860 [ - + ]: 6 : GST_DEBUG_OBJECT (src, "position query in format %s",
861 : : gst_format_get_name (format));
862 : :
863 [ - + ]: 6 : switch (format) {
864 : : case GST_FORMAT_PERCENT:
865 : : {
866 : : gint64 percent;
867 : : gint64 position;
868 : : gint64 duration;
869 : :
870 : 0 : GST_OBJECT_LOCK (src);
871 : 0 : position = src->segment.last_stop;
872 : 0 : duration = src->segment.duration;
873 : 0 : GST_OBJECT_UNLOCK (src);
874 : :
875 [ # # ][ # # ]: 0 : if (position != -1 && duration != -1) {
876 [ # # ]: 0 : if (position < duration)
877 : 0 : percent = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, position,
878 : : duration);
879 : : else
880 : 0 : percent = GST_FORMAT_PERCENT_MAX;
881 : : } else
882 : 0 : percent = -1;
883 : :
884 : 0 : gst_query_set_position (query, GST_FORMAT_PERCENT, percent);
885 : 0 : res = TRUE;
886 : 0 : break;
887 : : }
888 : : default:
889 : : {
890 : : gint64 position;
891 : : GstFormat seg_format;
892 : :
893 : 6 : GST_OBJECT_LOCK (src);
894 : 6 : position =
895 : 6 : gst_segment_to_stream_time (&src->segment, src->segment.format,
896 : : src->segment.last_stop);
897 : 6 : seg_format = src->segment.format;
898 : 6 : GST_OBJECT_UNLOCK (src);
899 : :
900 [ + - ]: 6 : if (position != -1) {
901 : : /* convert to requested format */
902 : 6 : res =
903 : 6 : gst_pad_query_convert (src->srcpad, seg_format,
904 : : position, &format, &position);
905 : : } else
906 : 0 : res = TRUE;
907 : :
908 : 6 : gst_query_set_position (query, format, position);
909 : 6 : break;
910 : : }
911 : : }
912 : 6 : break;
913 : : }
914 : : case GST_QUERY_DURATION:
915 : : {
916 : : GstFormat format;
917 : :
918 : 8 : gst_query_parse_duration (query, &format, NULL);
919 : :
920 [ - + ]: 8 : GST_DEBUG_OBJECT (src, "duration query in format %s",
921 : : gst_format_get_name (format));
922 : :
923 [ - + ]: 8 : switch (format) {
924 : : case GST_FORMAT_PERCENT:
925 : 0 : gst_query_set_duration (query, GST_FORMAT_PERCENT,
926 : : GST_FORMAT_PERCENT_MAX);
927 : 0 : res = TRUE;
928 : 0 : break;
929 : : default:
930 : : {
931 : : gint64 duration;
932 : : GstFormat seg_format;
933 : :
934 : 8 : GST_OBJECT_LOCK (src);
935 : : /* this is the duration as configured by the subclass. */
936 : 8 : duration = src->segment.duration;
937 : 8 : seg_format = src->segment.format;
938 : 8 : GST_OBJECT_UNLOCK (src);
939 : :
940 [ - + ]: 8 : GST_LOG_OBJECT (src, "duration %" G_GINT64_FORMAT ", format %s",
941 : : duration, gst_format_get_name (seg_format));
942 : :
943 [ - + ]: 8 : if (duration != -1) {
944 : : /* convert to requested format, if this fails, we have a duration
945 : : * but we cannot answer the query, we must return FALSE. */
946 : 0 : res =
947 : 0 : gst_pad_query_convert (src->srcpad, seg_format,
948 : : duration, &format, &duration);
949 : : } else {
950 : : /* The subclass did not configure a duration, we assume that the
951 : : * media has an unknown duration then and we return TRUE to report
952 : : * this. Note that this is not the same as returning FALSE, which
953 : : * means that we cannot report the duration at all. */
954 : 8 : res = TRUE;
955 : : }
956 : 8 : gst_query_set_duration (query, format, duration);
957 : 8 : break;
958 : : }
959 : : }
960 : 8 : break;
961 : : }
962 : :
963 : : case GST_QUERY_SEEKING:
964 : : {
965 : : GstFormat format, seg_format;
966 : : gint64 duration;
967 : :
968 : 4 : GST_OBJECT_LOCK (src);
969 : 4 : duration = src->segment.duration;
970 : 4 : seg_format = src->segment.format;
971 : 4 : GST_OBJECT_UNLOCK (src);
972 : :
973 : 4 : gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
974 [ + - ]: 4 : if (format == seg_format) {
975 : 4 : gst_query_set_seeking (query, seg_format,
976 : : gst_base_src_seekable (src), 0, duration);
977 : 4 : res = TRUE;
978 : : } else {
979 : : /* FIXME 0.11: return TRUE + seekable=FALSE for SEEKING query here */
980 : : /* Don't reply to the query to make up for demuxers which don't
981 : : * handle the SEEKING query yet. Players like Totem will fall back
982 : : * to the duration when the SEEKING query isn't answered. */
983 : 0 : res = FALSE;
984 : : }
985 : 4 : break;
986 : : }
987 : : case GST_QUERY_SEGMENT:
988 : : {
989 : : gint64 start, stop;
990 : :
991 : 0 : GST_OBJECT_LOCK (src);
992 : : /* no end segment configured, current duration then */
993 [ # # ]: 0 : if ((stop = src->segment.stop) == -1)
994 : 0 : stop = src->segment.duration;
995 : 0 : start = src->segment.start;
996 : :
997 : : /* adjust to stream time */
998 [ # # ]: 0 : if (src->segment.time != -1) {
999 : 0 : start -= src->segment.time;
1000 [ # # ]: 0 : if (stop != -1)
1001 : 0 : stop -= src->segment.time;
1002 : : }
1003 : :
1004 : 0 : gst_query_set_segment (query, src->segment.rate, src->segment.format,
1005 : : start, stop);
1006 : 0 : GST_OBJECT_UNLOCK (src);
1007 : 0 : res = TRUE;
1008 : 0 : break;
1009 : : }
1010 : :
1011 : : case GST_QUERY_FORMATS:
1012 : : {
1013 : 0 : gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT,
1014 : : GST_FORMAT_BYTES, GST_FORMAT_PERCENT);
1015 : 0 : res = TRUE;
1016 : 0 : break;
1017 : : }
1018 : : case GST_QUERY_CONVERT:
1019 : : {
1020 : : GstFormat src_fmt, dest_fmt;
1021 : : gint64 src_val, dest_val;
1022 : :
1023 : 0 : gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
1024 : :
1025 : : /* we can only convert between equal formats... */
1026 [ # # ]: 0 : if (src_fmt == dest_fmt) {
1027 : 0 : dest_val = src_val;
1028 : 0 : res = TRUE;
1029 : : } else
1030 : 0 : res = FALSE;
1031 : :
1032 : 0 : gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
1033 : 0 : break;
1034 : : }
1035 : : case GST_QUERY_LATENCY:
1036 : : {
1037 : : GstClockTime min, max;
1038 : : gboolean live;
1039 : :
1040 : : /* Subclasses should override and implement something usefull */
1041 : 102 : res = gst_base_src_query_latency (src, &live, &min, &max);
1042 : :
1043 [ - + ][ # # ]: 102 : GST_LOG_OBJECT (src, "report latency: live %d, min %" GST_TIME_FORMAT
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1044 : : ", max %" GST_TIME_FORMAT, live, GST_TIME_ARGS (min),
1045 : : GST_TIME_ARGS (max));
1046 : :
1047 : 102 : gst_query_set_latency (query, live, min, max);
1048 : 102 : break;
1049 : : }
1050 : : case GST_QUERY_JITTER:
1051 : : case GST_QUERY_RATE:
1052 : 0 : res = FALSE;
1053 : 0 : break;
1054 : : case GST_QUERY_BUFFERING:
1055 : : {
1056 : : GstFormat format, seg_format;
1057 : : gint64 start, stop, estimated;
1058 : :
1059 : 0 : gst_query_parse_buffering_range (query, &format, NULL, NULL, NULL);
1060 : :
1061 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "buffering query in format %s",
1062 : : gst_format_get_name (format));
1063 : :
1064 : 0 : GST_OBJECT_LOCK (src);
1065 [ # # ]: 0 : if (src->random_access) {
1066 : 0 : estimated = 0;
1067 : 0 : start = 0;
1068 [ # # ]: 0 : if (format == GST_FORMAT_PERCENT)
1069 : 0 : stop = GST_FORMAT_PERCENT_MAX;
1070 : : else
1071 : 0 : stop = src->segment.duration;
1072 : : } else {
1073 : 0 : estimated = -1;
1074 : 0 : start = -1;
1075 : 0 : stop = -1;
1076 : : }
1077 : 0 : seg_format = src->segment.format;
1078 : 0 : GST_OBJECT_UNLOCK (src);
1079 : :
1080 : : /* convert to required format. When the conversion fails, we can't answer
1081 : : * the query. When the value is unknown, we can don't perform conversion
1082 : : * but report TRUE. */
1083 [ # # ][ # # ]: 0 : if (format != GST_FORMAT_PERCENT && stop != -1) {
1084 : 0 : res = gst_pad_query_convert (src->srcpad, seg_format,
1085 : : stop, &format, &stop);
1086 : : } else {
1087 : 0 : res = TRUE;
1088 : : }
1089 [ # # ][ # # ]: 0 : if (res && format != GST_FORMAT_PERCENT && start != -1)
[ # # ]
1090 : 0 : res = gst_pad_query_convert (src->srcpad, seg_format,
1091 : : start, &format, &start);
1092 : :
1093 : 0 : gst_query_set_buffering_range (query, format, start, stop, estimated);
1094 : 0 : break;
1095 : : }
1096 : : default:
1097 : 0 : res = FALSE;
1098 : 0 : break;
1099 : : }
1100 [ - + ]: 120 : GST_DEBUG_OBJECT (src, "query %s returns %d", GST_QUERY_TYPE_NAME (query),
1101 : : res);
1102 : 120 : return res;
1103 : : }
1104 : :
1105 : : static gboolean
1106 : 134 : gst_base_src_query (GstPad * pad, GstQuery * query)
1107 : : {
1108 : : GstBaseSrc *src;
1109 : : GstBaseSrcClass *bclass;
1110 : 134 : gboolean result = FALSE;
1111 : :
1112 : 134 : src = GST_BASE_SRC (gst_pad_get_parent (pad));
1113 : :
1114 : 134 : bclass = GST_BASE_SRC_GET_CLASS (src);
1115 : :
1116 [ + - ]: 134 : if (bclass->query)
1117 : 134 : result = bclass->query (src, query);
1118 : : else
1119 : 0 : result = gst_pad_query_default (pad, query);
1120 : :
1121 : 134 : gst_object_unref (src);
1122 : :
1123 : 134 : return result;
1124 : : }
1125 : :
1126 : : static gboolean
1127 : 397 : gst_base_src_default_do_seek (GstBaseSrc * src, GstSegment * segment)
1128 : : {
1129 : 397 : gboolean res = TRUE;
1130 : :
1131 : : /* update our offset if the start/stop position was updated */
1132 [ + - ]: 397 : if (segment->format == GST_FORMAT_BYTES) {
1133 : 397 : segment->time = segment->start;
1134 [ # # ]: 0 : } else if (segment->start == 0) {
1135 : : /* seek to start, we can implement a default for this. */
1136 : 0 : segment->time = 0;
1137 : : } else {
1138 : 0 : res = FALSE;
1139 [ # # ]: 0 : GST_INFO_OBJECT (src, "Can't do a default seek");
1140 : : }
1141 : :
1142 : 397 : return res;
1143 : : }
1144 : :
1145 : : static gboolean
1146 : 407 : gst_base_src_do_seek (GstBaseSrc * src, GstSegment * segment)
1147 : : {
1148 : : GstBaseSrcClass *bclass;
1149 : 407 : gboolean result = FALSE;
1150 : :
1151 : 407 : bclass = GST_BASE_SRC_GET_CLASS (src);
1152 : :
1153 [ + - ]: 407 : if (bclass->do_seek)
1154 : 407 : result = bclass->do_seek (src, segment);
1155 : :
1156 : 407 : return result;
1157 : : }
1158 : :
1159 : : #define SEEK_TYPE_IS_RELATIVE(t) (((t) != GST_SEEK_TYPE_NONE) && ((t) != GST_SEEK_TYPE_SET))
1160 : :
1161 : : static gboolean
1162 : 1 : gst_base_src_default_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
1163 : : GstSegment * segment)
1164 : : {
1165 : : /* By default, we try one of 2 things:
1166 : : * - For absolute seek positions, convert the requested position to our
1167 : : * configured processing format and place it in the output segment \
1168 : : * - For relative seek positions, convert our current (input) values to the
1169 : : * seek format, adjust by the relative seek offset and then convert back to
1170 : : * the processing format
1171 : : */
1172 : : GstSeekType cur_type, stop_type;
1173 : : gint64 cur, stop;
1174 : : GstSeekFlags flags;
1175 : : GstFormat seek_format, dest_format;
1176 : : gdouble rate;
1177 : : gboolean update;
1178 : 1 : gboolean res = TRUE;
1179 : :
1180 : 1 : gst_event_parse_seek (event, &rate, &seek_format, &flags,
1181 : : &cur_type, &cur, &stop_type, &stop);
1182 : 1 : dest_format = segment->format;
1183 : :
1184 [ - + ]: 1 : if (seek_format == dest_format) {
1185 : 0 : gst_segment_set_seek (segment, rate, seek_format, flags,
1186 : : cur_type, cur, stop_type, stop, &update);
1187 : 0 : return TRUE;
1188 : : }
1189 : :
1190 [ - + ]: 1 : if (cur_type != GST_SEEK_TYPE_NONE) {
1191 : : /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
1192 : 0 : res =
1193 : 0 : gst_pad_query_convert (src->srcpad, seek_format, cur, &dest_format,
1194 : : &cur);
1195 : 0 : cur_type = GST_SEEK_TYPE_SET;
1196 : : }
1197 : :
1198 [ + - ][ - + ]: 1 : if (res && stop_type != GST_SEEK_TYPE_NONE) {
1199 : : /* FIXME: Handle seek_cur & seek_end by converting the input segment vals */
1200 : 0 : res =
1201 : 0 : gst_pad_query_convert (src->srcpad, seek_format, stop, &dest_format,
1202 : : &stop);
1203 : 0 : stop_type = GST_SEEK_TYPE_SET;
1204 : : }
1205 : :
1206 : : /* And finally, configure our output segment in the desired format */
1207 : 1 : gst_segment_set_seek (segment, rate, dest_format, flags, cur_type, cur,
1208 : : stop_type, stop, &update);
1209 : :
1210 [ - + ]: 1 : if (!res)
1211 : 0 : goto no_format;
1212 : :
1213 : 1 : return res;
1214 : :
1215 : : no_format:
1216 : : {
1217 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "undefined format given, seek aborted.");
1218 : 1 : return FALSE;
1219 : : }
1220 : : }
1221 : :
1222 : : static gboolean
1223 : 1 : gst_base_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * event,
1224 : : GstSegment * seeksegment)
1225 : : {
1226 : : GstBaseSrcClass *bclass;
1227 : 1 : gboolean result = FALSE;
1228 : :
1229 : 1 : bclass = GST_BASE_SRC_GET_CLASS (src);
1230 : :
1231 [ + - ]: 1 : if (bclass->prepare_seek_segment)
1232 : 1 : result = bclass->prepare_seek_segment (src, event, seeksegment);
1233 : :
1234 : 1 : return result;
1235 : : }
1236 : :
1237 : : /* this code implements the seeking. It is a good example
1238 : : * handling all cases.
1239 : : *
1240 : : * A seek updates the currently configured segment.start
1241 : : * and segment.stop values based on the SEEK_TYPE. If the
1242 : : * segment.start value is updated, a seek to this new position
1243 : : * should be performed.
1244 : : *
1245 : : * The seek can only be executed when we are not currently
1246 : : * streaming any data, to make sure that this is the case, we
1247 : : * acquire the STREAM_LOCK which is taken when we are in the
1248 : : * _loop() function or when a getrange() is called. Normally
1249 : : * we will not receive a seek if we are operating in pull mode
1250 : : * though. When we operate as a live source we might block on the live
1251 : : * cond, which does not release the STREAM_LOCK. Therefore we will try
1252 : : * to grab the LIVE_LOCK instead of the STREAM_LOCK to make sure it is
1253 : : * safe to perform the seek.
1254 : : *
1255 : : * When we are in the loop() function, we might be in the middle
1256 : : * of pushing a buffer, which might block in a sink. To make sure
1257 : : * that the push gets unblocked we push out a FLUSH_START event.
1258 : : * Our loop function will get a WRONG_STATE return value from
1259 : : * the push and will pause, effectively releasing the STREAM_LOCK.
1260 : : *
1261 : : * For a non-flushing seek, we pause the task, which might eventually
1262 : : * release the STREAM_LOCK. We say eventually because when the sink
1263 : : * blocks on the sample we might wait a very long time until the sink
1264 : : * unblocks the sample. In any case we acquire the STREAM_LOCK and
1265 : : * can continue the seek. A non-flushing seek is normally done in a
1266 : : * running pipeline to perform seamless playback, this means that the sink is
1267 : : * PLAYING and will return from its chain function.
1268 : : * In the case of a non-flushing seek we need to make sure that the
1269 : : * data we output after the seek is continuous with the previous data,
1270 : : * this is because a non-flushing seek does not reset the running-time
1271 : : * to 0. We do this by closing the currently running segment, ie. sending
1272 : : * a new_segment event with the stop position set to the last processed
1273 : : * position.
1274 : : *
1275 : : * After updating the segment.start/stop values, we prepare for
1276 : : * streaming again. We push out a FLUSH_STOP to make the peer pad
1277 : : * accept data again and we start our task again.
1278 : : *
1279 : : * A segment seek posts a message on the bus saying that the playback
1280 : : * of the segment started. We store the segment flag internally because
1281 : : * when we reach the segment.stop we have to post a segment.done
1282 : : * instead of EOS when doing a segment seek.
1283 : : */
1284 : : /* FIXME (0.11), we have the unlock gboolean here because most current
1285 : : * implementations (fdsrc, -base/gst/tcp/, ...) unconditionally unlock, even when
1286 : : * the streaming thread isn't running, resulting in bogus unlocks later when it
1287 : : * starts. This is fixed by adding unlock_stop, but we should still avoid unlocking
1288 : : * unnecessarily for backwards compatibility. Ergo, the unlock variable stays
1289 : : * until 0.11
1290 : : */
1291 : : static gboolean
1292 : 407 : gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
1293 : : {
1294 : 407 : gboolean res = TRUE, tres;
1295 : : gdouble rate;
1296 : : GstFormat seek_format, dest_format;
1297 : : GstSeekFlags flags;
1298 : : GstSeekType cur_type, stop_type;
1299 : : gint64 cur, stop;
1300 : : gboolean flush, playing;
1301 : : gboolean update;
1302 : 407 : gboolean relative_seek = FALSE;
1303 : 407 : gboolean seekseg_configured = FALSE;
1304 : : GstSegment seeksegment;
1305 : : guint32 seqnum;
1306 : : GstEvent *tevent;
1307 : :
1308 [ - + ]: 407 : GST_DEBUG_OBJECT (src, "doing seek: %" GST_PTR_FORMAT, event);
1309 : :
1310 : 407 : GST_OBJECT_LOCK (src);
1311 : 407 : dest_format = src->segment.format;
1312 : 407 : GST_OBJECT_UNLOCK (src);
1313 : :
1314 [ + + ]: 407 : if (event) {
1315 : 4 : gst_event_parse_seek (event, &rate, &seek_format, &flags,
1316 : : &cur_type, &cur, &stop_type, &stop);
1317 : :
1318 [ + + ][ + - ]: 7 : relative_seek = SEEK_TYPE_IS_RELATIVE (cur_type) ||
[ + + ]
1319 [ - + ]: 3 : SEEK_TYPE_IS_RELATIVE (stop_type);
1320 : :
1321 [ + + ][ + - ]: 4 : if (dest_format != seek_format && !relative_seek) {
1322 : : /* If we have an ABSOLUTE position (SEEK_SET only), we can convert it
1323 : : * here before taking the stream lock, otherwise we must convert it later,
1324 : : * once we have the stream lock and can read the last configures segment
1325 : : * start and stop positions */
1326 : 1 : gst_segment_init (&seeksegment, dest_format);
1327 : :
1328 [ - + ]: 1 : if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment))
1329 : 0 : goto prepare_failed;
1330 : :
1331 : 1 : seekseg_configured = TRUE;
1332 : : }
1333 : :
1334 : 4 : flush = flags & GST_SEEK_FLAG_FLUSH;
1335 : 4 : seqnum = gst_event_get_seqnum (event);
1336 : : } else {
1337 : 403 : flush = FALSE;
1338 : : /* get next seqnum */
1339 : 403 : seqnum = gst_util_seqnum_next ();
1340 : : }
1341 : :
1342 : : /* send flush start */
1343 [ + + ]: 407 : if (flush) {
1344 : 2 : tevent = gst_event_new_flush_start ();
1345 : 2 : gst_event_set_seqnum (tevent, seqnum);
1346 : 2 : gst_pad_push_event (src->srcpad, tevent);
1347 : : } else
1348 : 405 : gst_pad_pause_task (src->srcpad);
1349 : :
1350 : : /* unblock streaming thread. */
1351 : 407 : gst_base_src_set_flushing (src, TRUE, FALSE, unlock, &playing);
1352 : :
1353 : : /* grab streaming lock, this should eventually be possible, either
1354 : : * because the task is paused, our streaming thread stopped
1355 : : * or because our peer is flushing. */
1356 : 407 : GST_PAD_STREAM_LOCK (src->srcpad);
1357 [ - + ]: 407 : if (G_UNLIKELY (src->priv->seqnum == seqnum)) {
1358 : : /* we have seen this event before, issue a warning for now */
1359 [ # # ]: 0 : GST_WARNING_OBJECT (src, "duplicate event found %" G_GUINT32_FORMAT,
1360 : : seqnum);
1361 : : } else {
1362 : 407 : src->priv->seqnum = seqnum;
1363 [ - + ]: 407 : GST_DEBUG_OBJECT (src, "seek with seqnum %" G_GUINT32_FORMAT, seqnum);
1364 : : }
1365 : :
1366 : 407 : gst_base_src_set_flushing (src, FALSE, playing, unlock, NULL);
1367 : :
1368 : : /* If we configured the seeksegment above, don't overwrite it now. Otherwise
1369 : : * copy the current segment info into the temp segment that we can actually
1370 : : * attempt the seek with. We only update the real segment if the seek suceeds. */
1371 [ + + ]: 407 : if (!seekseg_configured) {
1372 : 406 : memcpy (&seeksegment, &src->segment, sizeof (GstSegment));
1373 : :
1374 : : /* now configure the final seek segment */
1375 [ + + ]: 406 : if (event) {
1376 [ - + ]: 3 : if (seeksegment.format != seek_format) {
1377 : : /* OK, here's where we give the subclass a chance to convert the relative
1378 : : * seek into an absolute one in the processing format. We set up any
1379 : : * absolute seek above, before taking the stream lock. */
1380 [ # # ]: 0 : if (!gst_base_src_prepare_seek_segment (src, event, &seeksegment)) {
1381 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "Preparing the seek failed after flushing. "
1382 : : "Aborting seek");
1383 : 0 : res = FALSE;
1384 : : }
1385 : : } else {
1386 : : /* The seek format matches our processing format, no need to ask the
1387 : : * the subclass to configure the segment. */
1388 : 3 : gst_segment_set_seek (&seeksegment, rate, seek_format, flags,
1389 : : cur_type, cur, stop_type, stop, &update);
1390 : : }
1391 : : }
1392 : : /* Else, no seek event passed, so we're just (re)starting the
1393 : : current segment. */
1394 : : }
1395 : :
1396 [ + - ]: 407 : if (res) {
1397 [ - + ]: 407 : GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT
1398 : : " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
1399 : : seeksegment.start, seeksegment.stop, seeksegment.last_stop);
1400 : :
1401 : : /* do the seek, segment.last_stop contains the new position. */
1402 : 407 : res = gst_base_src_do_seek (src, &seeksegment);
1403 : : }
1404 : :
1405 : : /* and prepare to continue streaming */
1406 [ + + ]: 407 : if (flush) {
1407 : 2 : tevent = gst_event_new_flush_stop ();
1408 : 2 : gst_event_set_seqnum (tevent, seqnum);
1409 : : /* send flush stop, peer will accept data and events again. We
1410 : : * are not yet providing data as we still have the STREAM_LOCK. */
1411 : 2 : gst_pad_push_event (src->srcpad, tevent);
1412 [ + - ][ + + ]: 405 : } else if (res && src->data.ABI.running) {
1413 : : /* we are running the current segment and doing a non-flushing seek,
1414 : : * close the segment first based on the last_stop. */
1415 [ - + ]: 1 : GST_DEBUG_OBJECT (src, "closing running segment %" G_GINT64_FORMAT
1416 : : " to %" G_GINT64_FORMAT, src->segment.start, src->segment.last_stop);
1417 : :
1418 : : /* queue the segment for sending in the stream thread */
1419 [ - + ]: 1 : if (src->priv->close_segment)
1420 : 0 : gst_event_unref (src->priv->close_segment);
1421 : 2 : src->priv->close_segment =
1422 : 1 : gst_event_new_new_segment_full (TRUE,
1423 : : src->segment.rate, src->segment.applied_rate, src->segment.format,
1424 : : src->segment.start, src->segment.last_stop, src->segment.time);
1425 : 1 : gst_event_set_seqnum (src->priv->close_segment, seqnum);
1426 : : }
1427 : :
1428 : : /* The subclass must have converted the segment to the processing format
1429 : : * by now */
1430 [ + - ][ - + ]: 407 : if (res && seeksegment.format != dest_format) {
1431 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "Subclass failed to prepare a seek segment "
1432 : : "in the correct format. Aborting seek.");
1433 : 0 : res = FALSE;
1434 : : }
1435 : :
1436 : : /* if the seek was successful, we update our real segment and push
1437 : : * out the new segment. */
1438 [ + - ]: 407 : if (res) {
1439 : 407 : GST_OBJECT_LOCK (src);
1440 : 407 : memcpy (&src->segment, &seeksegment, sizeof (GstSegment));
1441 : 407 : GST_OBJECT_UNLOCK (src);
1442 : :
1443 [ - + ]: 407 : if (seeksegment.flags & GST_SEEK_FLAG_SEGMENT) {
1444 : : GstMessage *message;
1445 : :
1446 : 0 : message = gst_message_new_segment_start (GST_OBJECT (src),
1447 : : seeksegment.format, seeksegment.last_stop);
1448 : 0 : gst_message_set_seqnum (message, seqnum);
1449 : :
1450 : 0 : gst_element_post_message (GST_ELEMENT (src), message);
1451 : : }
1452 : :
1453 : : /* for deriving a stop position for the playback segment from the seek
1454 : : * segment, we must take the duration when the stop is not set */
1455 [ + - ]: 407 : if ((stop = seeksegment.stop) == -1)
1456 : 407 : stop = seeksegment.duration;
1457 : :
1458 [ - + ]: 407 : GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
1459 : : " to %" G_GINT64_FORMAT, seeksegment.start, stop);
1460 : :
1461 : : /* now replace the old segment so that we send it in the stream thread the
1462 : : * next time it is scheduled. */
1463 [ - + ]: 407 : if (src->priv->start_segment)
1464 : 0 : gst_event_unref (src->priv->start_segment);
1465 [ + + ]: 407 : if (seeksegment.rate >= 0.0) {
1466 : : /* forward, we send data from last_stop to stop */
1467 : 406 : src->priv->start_segment =
1468 : 406 : gst_event_new_new_segment_full (FALSE,
1469 : : seeksegment.rate, seeksegment.applied_rate, seeksegment.format,
1470 : : seeksegment.last_stop, stop, seeksegment.time);
1471 : : } else {
1472 : : /* reverse, we send data from last_stop to start */
1473 : 1 : src->priv->start_segment =
1474 : 1 : gst_event_new_new_segment_full (FALSE,
1475 : : seeksegment.rate, seeksegment.applied_rate, seeksegment.format,
1476 : : seeksegment.start, seeksegment.last_stop, seeksegment.time);
1477 : : }
1478 : 407 : gst_event_set_seqnum (src->priv->start_segment, seqnum);
1479 : 407 : src->priv->newsegment_pending = TRUE;
1480 : : }
1481 : :
1482 : 407 : src->priv->discont = TRUE;
1483 : 407 : src->data.ABI.running = TRUE;
1484 : : /* and restart the task in case it got paused explicitly or by
1485 : : * the FLUSH_START event we pushed out. */
1486 : 407 : tres = gst_pad_start_task (src->srcpad, (GstTaskFunction) gst_base_src_loop,
1487 : 407 : src->srcpad);
1488 [ + - ][ - + ]: 407 : if (res && !tres)
1489 : 0 : res = FALSE;
1490 : :
1491 : : /* and release the lock again so we can continue streaming */
1492 : 407 : GST_PAD_STREAM_UNLOCK (src->srcpad);
1493 : :
1494 : 407 : return res;
1495 : :
1496 : : /* ERROR */
1497 : : prepare_failed:
1498 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "Preparing the seek failed before flushing. "
1499 : : "Aborting seek");
1500 : 407 : return FALSE;
1501 : : }
1502 : :
1503 : : static const GstQueryType *
1504 : 0 : gst_base_src_get_query_types (GstElement * element)
1505 : : {
1506 : : static const GstQueryType query_types[] = {
1507 : : GST_QUERY_DURATION,
1508 : : GST_QUERY_POSITION,
1509 : : GST_QUERY_SEEKING,
1510 : : GST_QUERY_SEGMENT,
1511 : : GST_QUERY_FORMATS,
1512 : : GST_QUERY_LATENCY,
1513 : : GST_QUERY_JITTER,
1514 : : GST_QUERY_RATE,
1515 : : GST_QUERY_CONVERT,
1516 : : 0
1517 : : };
1518 : :
1519 : 0 : return query_types;
1520 : : }
1521 : :
1522 : : /* all events send to this element directly. This is mainly done from the
1523 : : * application.
1524 : : */
1525 : : static gboolean
1526 : 4 : gst_base_src_send_event (GstElement * element, GstEvent * event)
1527 : : {
1528 : : GstBaseSrc *src;
1529 : 4 : gboolean result = FALSE;
1530 : :
1531 : 4 : src = GST_BASE_SRC (element);
1532 : :
1533 [ - + ]: 4 : GST_DEBUG_OBJECT (src, "handling event %p %" GST_PTR_FORMAT, event, event);
1534 : :
1535 [ - + - - : 4 : switch (GST_EVENT_TYPE (event)) {
- - + - -
- - - - ]
1536 : : /* bidirectional events */
1537 : : case GST_EVENT_FLUSH_START:
1538 : : case GST_EVENT_FLUSH_STOP:
1539 : : /* sending random flushes downstream can break stuff,
1540 : : * especially sync since all segment info will get flushed */
1541 : 0 : break;
1542 : :
1543 : : /* downstream serialized events */
1544 : : case GST_EVENT_EOS:
1545 : : {
1546 : : GstBaseSrcClass *bclass;
1547 : :
1548 : 2 : bclass = GST_BASE_SRC_GET_CLASS (src);
1549 : :
1550 : : /* queue EOS and make sure the task or pull function performs the EOS
1551 : : * actions.
1552 : : *
1553 : : * We have two possibilities:
1554 : : *
1555 : : * - Before we are to enter the _create function, we check the pending_eos
1556 : : * first and do EOS instead of entering it.
1557 : : * - If we are in the _create function or we did not manage to set the
1558 : : * flag fast enough and we are about to enter the _create function,
1559 : : * we unlock it so that we exit with WRONG_STATE immediatly. We then
1560 : : * check the EOS flag and do the EOS logic.
1561 : : */
1562 : 2 : g_atomic_int_set (&src->priv->pending_eos, TRUE);
1563 [ - + ]: 2 : GST_DEBUG_OBJECT (src, "EOS marked, calling unlock");
1564 : :
1565 : : /* unlock the _create function so that we can check the pending_eos flag
1566 : : * and we can do EOS. This will eventually release the LIVE_LOCK again so
1567 : : * that we can grab it and stop the unlock again. We don't take the stream
1568 : : * lock so that this operation is guaranteed to never block. */
1569 [ - + ]: 2 : if (bclass->unlock)
1570 : 0 : bclass->unlock (src);
1571 : :
1572 [ - + ]: 2 : GST_DEBUG_OBJECT (src, "unlock called, waiting for LIVE_LOCK");
1573 : :
1574 : 2 : GST_LIVE_LOCK (src);
1575 [ - + ]: 2 : GST_DEBUG_OBJECT (src, "LIVE_LOCK acquired, calling unlock_stop");
1576 : : /* now stop the unlock of the streaming thread again. Grabbing the live
1577 : : * lock is enough because that protects the create function. */
1578 [ - + ]: 2 : if (bclass->unlock_stop)
1579 : 0 : bclass->unlock_stop (src);
1580 : 2 : GST_LIVE_UNLOCK (src);
1581 : :
1582 : 2 : result = TRUE;
1583 : 2 : break;
1584 : : }
1585 : : case GST_EVENT_NEWSEGMENT:
1586 : : /* sending random NEWSEGMENT downstream can break sync. */
1587 : 0 : break;
1588 : : case GST_EVENT_TAG:
1589 : : /* Insert tag in the dataflow */
1590 : 0 : GST_OBJECT_LOCK (src);
1591 : 0 : src->priv->pending_tags = g_list_append (src->priv->pending_tags, event);
1592 : 0 : g_atomic_int_set (&src->priv->have_tags, TRUE);
1593 : 0 : GST_OBJECT_UNLOCK (src);
1594 : 0 : event = NULL;
1595 : 0 : result = TRUE;
1596 : 0 : break;
1597 : : case GST_EVENT_BUFFERSIZE:
1598 : : /* does not seem to make much sense currently */
1599 : 0 : break;
1600 : :
1601 : : /* upstream events */
1602 : : case GST_EVENT_QOS:
1603 : : /* elements should override send_event and do something */
1604 : 0 : break;
1605 : : case GST_EVENT_SEEK:
1606 : : {
1607 : : gboolean started;
1608 : :
1609 : 2 : GST_OBJECT_LOCK (src->srcpad);
1610 [ - + ]: 2 : if (GST_PAD_ACTIVATE_MODE (src->srcpad) == GST_ACTIVATE_PULL)
1611 : 0 : goto wrong_mode;
1612 : 2 : started = GST_PAD_ACTIVATE_MODE (src->srcpad) == GST_ACTIVATE_PUSH;
1613 : 2 : GST_OBJECT_UNLOCK (src->srcpad);
1614 : :
1615 [ + + ]: 2 : if (started) {
1616 [ - + ]: 1 : GST_DEBUG_OBJECT (src, "performing seek");
1617 : : /* when we are running in push mode, we can execute the
1618 : : * seek right now, we need to unlock. */
1619 : 1 : result = gst_base_src_perform_seek (src, event, TRUE);
1620 : : } else {
1621 : : GstEvent **event_p;
1622 : :
1623 : : /* else we store the event and execute the seek when we
1624 : : * get activated */
1625 : 1 : GST_OBJECT_LOCK (src);
1626 [ - + ]: 1 : GST_DEBUG_OBJECT (src, "queueing seek");
1627 : 1 : event_p = &src->data.ABI.pending_seek;
1628 : 1 : gst_event_replace ((GstEvent **) event_p, event);
1629 : 1 : GST_OBJECT_UNLOCK (src);
1630 : : /* assume the seek will work */
1631 : 1 : result = TRUE;
1632 : : }
1633 : 2 : break;
1634 : : }
1635 : : case GST_EVENT_NAVIGATION:
1636 : : /* could make sense for elements that do something with navigation events
1637 : : * but then they would need to override the send_event function */
1638 : 0 : break;
1639 : : case GST_EVENT_LATENCY:
1640 : : /* does not seem to make sense currently */
1641 : 0 : break;
1642 : :
1643 : : /* custom events */
1644 : : case GST_EVENT_CUSTOM_UPSTREAM:
1645 : : /* override send_event if you want this */
1646 : 0 : break;
1647 : : case GST_EVENT_CUSTOM_DOWNSTREAM:
1648 : : case GST_EVENT_CUSTOM_BOTH:
1649 : : /* FIXME, insert event in the dataflow */
1650 : 0 : break;
1651 : : case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
1652 : : case GST_EVENT_CUSTOM_BOTH_OOB:
1653 : : /* insert a random custom event into the pipeline */
1654 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "pushing custom OOB event downstream");
1655 : 0 : result = gst_pad_push_event (src->srcpad, event);
1656 : : /* we gave away the ref to the event in the push */
1657 : 0 : event = NULL;
1658 : 0 : break;
1659 : : default:
1660 : 0 : break;
1661 : : }
1662 : : done:
1663 : : /* if we still have a ref to the event, unref it now */
1664 [ + - ]: 4 : if (event)
1665 : 4 : gst_event_unref (event);
1666 : :
1667 : 4 : return result;
1668 : :
1669 : : /* ERRORS */
1670 : : wrong_mode:
1671 : : {
1672 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "cannot perform seek when operating in pull mode");
1673 : 0 : GST_OBJECT_UNLOCK (src->srcpad);
1674 : 0 : result = FALSE;
1675 : 0 : goto done;
1676 : : }
1677 : : }
1678 : :
1679 : : static gboolean
1680 : 423 : gst_base_src_seekable (GstBaseSrc * src)
1681 : : {
1682 : : GstBaseSrcClass *bclass;
1683 : 423 : bclass = GST_BASE_SRC_GET_CLASS (src);
1684 [ + + ]: 423 : if (bclass->is_seekable)
1685 : 413 : return bclass->is_seekable (src);
1686 : : else
1687 : 423 : return FALSE;
1688 : : }
1689 : :
1690 : : static void
1691 : 0 : gst_base_src_update_qos (GstBaseSrc * src,
1692 : : gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp)
1693 : : {
1694 [ # # ][ # # ]: 0 : GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, src,
[ # # ][ # # ]
[ # # ]
1695 : : "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
1696 : : GST_TIME_FORMAT, proportion, diff, GST_TIME_ARGS (timestamp));
1697 : :
1698 : 0 : GST_OBJECT_LOCK (src);
1699 : 0 : src->priv->proportion = proportion;
1700 : 0 : src->priv->earliest_time = timestamp + diff;
1701 : 0 : GST_OBJECT_UNLOCK (src);
1702 : 0 : }
1703 : :
1704 : :
1705 : : static gboolean
1706 : 107 : gst_base_src_default_event (GstBaseSrc * src, GstEvent * event)
1707 : : {
1708 : : gboolean result;
1709 : :
1710 [ - + ]: 107 : GST_DEBUG_OBJECT (src, "handle event %" GST_PTR_FORMAT, event);
1711 : :
1712 [ + - - - : 107 : switch (GST_EVENT_TYPE (event)) {
+ ]
1713 : : case GST_EVENT_SEEK:
1714 : : /* is normally called when in push mode */
1715 [ - + ]: 2 : if (!gst_base_src_seekable (src))
1716 : 0 : goto not_seekable;
1717 : :
1718 : 2 : result = gst_base_src_perform_seek (src, event, TRUE);
1719 : 2 : break;
1720 : : case GST_EVENT_FLUSH_START:
1721 : : /* cancel any blocking getrange, is normally called
1722 : : * when in pull mode. */
1723 : 0 : result = gst_base_src_set_flushing (src, TRUE, FALSE, TRUE, NULL);
1724 : 0 : break;
1725 : : case GST_EVENT_FLUSH_STOP:
1726 : 0 : result = gst_base_src_set_flushing (src, FALSE, TRUE, TRUE, NULL);
1727 : 0 : break;
1728 : : case GST_EVENT_QOS:
1729 : : {
1730 : : gdouble proportion;
1731 : : GstClockTimeDiff diff;
1732 : : GstClockTime timestamp;
1733 : :
1734 : 0 : gst_event_parse_qos (event, &proportion, &diff, ×tamp);
1735 : 0 : gst_base_src_update_qos (src, proportion, diff, timestamp);
1736 : 0 : result = TRUE;
1737 : 0 : break;
1738 : : }
1739 : : default:
1740 : 105 : result = TRUE;
1741 : 105 : break;
1742 : : }
1743 : 107 : return result;
1744 : :
1745 : : /* ERRORS */
1746 : : not_seekable:
1747 : : {
1748 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "is not seekable");
1749 : 107 : return FALSE;
1750 : : }
1751 : : }
1752 : :
1753 : : static gboolean
1754 : 107 : gst_base_src_event_handler (GstPad * pad, GstEvent * event)
1755 : : {
1756 : : GstBaseSrc *src;
1757 : : GstBaseSrcClass *bclass;
1758 : 107 : gboolean result = FALSE;
1759 : :
1760 : 107 : src = GST_BASE_SRC (gst_pad_get_parent (pad));
1761 : 107 : bclass = GST_BASE_SRC_GET_CLASS (src);
1762 : :
1763 [ + - ]: 107 : if (bclass->event) {
1764 [ - + ]: 107 : if (!(result = bclass->event (src, event)))
1765 : 0 : goto subclass_failed;
1766 : : }
1767 : :
1768 : : done:
1769 : 107 : gst_event_unref (event);
1770 : 107 : gst_object_unref (src);
1771 : :
1772 : 107 : return result;
1773 : :
1774 : : /* ERRORS */
1775 : : subclass_failed:
1776 : : {
1777 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "subclass refused event");
1778 : 0 : goto done;
1779 : : }
1780 : : }
1781 : :
1782 : : static void
1783 : 35 : gst_base_src_set_property (GObject * object, guint prop_id,
1784 : : const GValue * value, GParamSpec * pspec)
1785 : : {
1786 : : GstBaseSrc *src;
1787 : :
1788 : 35 : src = GST_BASE_SRC (object);
1789 : :
1790 [ + + - - : 35 : switch (prop_id) {
- ]
1791 : : case PROP_BLOCKSIZE:
1792 : 1 : gst_base_src_set_blocksize (src, g_value_get_ulong (value));
1793 : 1 : break;
1794 : : case PROP_NUM_BUFFERS:
1795 : 34 : src->num_buffers = g_value_get_int (value);
1796 : 34 : break;
1797 : : case PROP_TYPEFIND:
1798 : 0 : src->data.ABI.typefind = g_value_get_boolean (value);
1799 : 0 : break;
1800 : : case PROP_DO_TIMESTAMP:
1801 : 0 : gst_base_src_set_do_timestamp (src, g_value_get_boolean (value));
1802 : 0 : break;
1803 : : default:
1804 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1805 : 0 : break;
1806 : : }
1807 : 35 : }
1808 : :
1809 : : static void
1810 : 1 : gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
1811 : : GParamSpec * pspec)
1812 : : {
1813 : : GstBaseSrc *src;
1814 : :
1815 : 1 : src = GST_BASE_SRC (object);
1816 : :
1817 [ - + - - : 1 : switch (prop_id) {
- ]
1818 : : case PROP_BLOCKSIZE:
1819 : 0 : g_value_set_ulong (value, gst_base_src_get_blocksize (src));
1820 : 0 : break;
1821 : : case PROP_NUM_BUFFERS:
1822 : 1 : g_value_set_int (value, src->num_buffers);
1823 : 1 : break;
1824 : : case PROP_TYPEFIND:
1825 : 0 : g_value_set_boolean (value, src->data.ABI.typefind);
1826 : 0 : break;
1827 : : case PROP_DO_TIMESTAMP:
1828 : 0 : g_value_set_boolean (value, gst_base_src_get_do_timestamp (src));
1829 : 0 : break;
1830 : : default:
1831 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1832 : 0 : break;
1833 : : }
1834 : 1 : }
1835 : :
1836 : : /* with STREAM_LOCK and LOCK */
1837 : : static GstClockReturn
1838 : 0 : gst_base_src_wait (GstBaseSrc * basesrc, GstClock * clock, GstClockTime time)
1839 : : {
1840 : : GstClockReturn ret;
1841 : : GstClockID id;
1842 : :
1843 : 0 : id = gst_clock_new_single_shot_id (clock, time);
1844 : :
1845 : 0 : basesrc->clock_id = id;
1846 : : /* release the live lock while waiting */
1847 : 0 : GST_LIVE_UNLOCK (basesrc);
1848 : :
1849 : 0 : ret = gst_clock_id_wait (id, NULL);
1850 : :
1851 : 0 : GST_LIVE_LOCK (basesrc);
1852 : 0 : gst_clock_id_unref (id);
1853 : 0 : basesrc->clock_id = NULL;
1854 : :
1855 : 0 : return ret;
1856 : : }
1857 : :
1858 : : /* perform synchronisation on a buffer.
1859 : : * with STREAM_LOCK.
1860 : : */
1861 : : static GstClockReturn
1862 : 686564 : gst_base_src_do_sync (GstBaseSrc * basesrc, GstBuffer * buffer)
1863 : : {
1864 : : GstClockReturn result;
1865 : : GstClockTime start, end;
1866 : : GstBaseSrcClass *bclass;
1867 : : GstClockTime base_time;
1868 : : GstClock *clock;
1869 : 686564 : GstClockTime now = GST_CLOCK_TIME_NONE, timestamp;
1870 : : gboolean do_timestamp, first, pseudo_live;
1871 : :
1872 : 686564 : bclass = GST_BASE_SRC_GET_CLASS (basesrc);
1873 : :
1874 : 686564 : start = end = -1;
1875 [ + + ]: 686564 : if (bclass->get_times)
1876 : 539213 : bclass->get_times (basesrc, buffer, &start, &end);
1877 : :
1878 : : /* get buffer timestamp */
1879 : 686564 : timestamp = GST_BUFFER_TIMESTAMP (buffer);
1880 : :
1881 : : /* grab the lock to prepare for clocking and calculate the startup
1882 : : * latency. */
1883 : 686564 : GST_OBJECT_LOCK (basesrc);
1884 : :
1885 : : /* if we are asked to sync against the clock we are a pseudo live element */
1886 [ - + ][ # # ]: 686553 : pseudo_live = (start != -1 && basesrc->is_live);
1887 : : /* check for the first buffer */
1888 : 686553 : first = (basesrc->priv->latency == -1);
1889 : :
1890 [ + + ][ - + ]: 686553 : if (timestamp != -1 && pseudo_live) {
1891 : : GstClockTime latency;
1892 : :
1893 : : /* we have a timestamp and a sync time, latency is the diff */
1894 [ # # ]: 0 : if (timestamp <= start)
1895 : 0 : latency = start - timestamp;
1896 : : else
1897 : 0 : latency = 0;
1898 : :
1899 [ # # ]: 0 : if (first) {
1900 [ # # ][ # # ]: 0 : GST_DEBUG_OBJECT (basesrc, "pseudo_live with latency %" GST_TIME_FORMAT,
[ # # ][ # # ]
[ # # ]
1901 : : GST_TIME_ARGS (latency));
1902 : : /* first time we calculate latency, just configure */
1903 : 0 : basesrc->priv->latency = latency;
1904 : : } else {
1905 [ # # ]: 0 : if (basesrc->priv->latency != latency) {
1906 : : /* we have a new latency, FIXME post latency message */
1907 : 0 : basesrc->priv->latency = latency;
1908 [ # # ][ # # ]: 0 : GST_DEBUG_OBJECT (basesrc, "latency changed to %" GST_TIME_FORMAT,
[ # # ][ # # ]
[ # # ]
1909 : : GST_TIME_ARGS (latency));
1910 : : }
1911 : : }
1912 [ + + ]: 686553 : } else if (first) {
1913 [ - + ]: 7 : GST_DEBUG_OBJECT (basesrc, "no latency needed, live %d, sync %d",
1914 : : basesrc->is_live, start != -1);
1915 : 7 : basesrc->priv->latency = 0;
1916 : : }
1917 : :
1918 : : /* get clock, if no clock, we can't sync or do timestamps */
1919 [ + + ]: 686553 : if ((clock = GST_ELEMENT_CLOCK (basesrc)) == NULL)
1920 : 83657 : goto no_clock;
1921 : :
1922 : 602896 : base_time = GST_ELEMENT_CAST (basesrc)->base_time;
1923 : :
1924 : 602896 : do_timestamp = basesrc->priv->do_timestamp;
1925 : :
1926 : : /* first buffer, calculate the timestamp offset */
1927 [ + + ]: 602896 : if (first) {
1928 : : GstClockTime running_time;
1929 : :
1930 : 7 : now = gst_clock_get_time (clock);
1931 : 7 : running_time = now - base_time;
1932 : :
1933 [ - + ][ # # ]: 7 : GST_LOG_OBJECT (basesrc,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1934 : : "startup timestamp: %" GST_TIME_FORMAT ", running_time %"
1935 : : GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
1936 : : GST_TIME_ARGS (running_time));
1937 : :
1938 [ - + ][ # # ]: 7 : if (pseudo_live && timestamp != -1) {
1939 : : /* live source and we need to sync, add startup latency to all timestamps
1940 : : * to get the real running_time. Live sources should always timestamp
1941 : : * according to the current running time. */
1942 : 0 : basesrc->priv->ts_offset = GST_CLOCK_DIFF (timestamp, running_time);
1943 : :
1944 [ # # ][ # # ]: 0 : GST_LOG_OBJECT (basesrc, "live with sync, ts_offset %" GST_TIME_FORMAT,
[ # # ][ # # ]
[ # # ]
1945 : : GST_TIME_ARGS (basesrc->priv->ts_offset));
1946 : : } else {
1947 : 7 : basesrc->priv->ts_offset = 0;
1948 [ - + ]: 7 : GST_LOG_OBJECT (basesrc, "no timestamp offset needed");
1949 : : }
1950 : :
1951 [ - + ]: 7 : if (!GST_CLOCK_TIME_IS_VALID (timestamp)) {
1952 [ # # ]: 0 : if (do_timestamp)
1953 : 0 : timestamp = running_time;
1954 : : else
1955 : 0 : timestamp = 0;
1956 : :
1957 : 0 : GST_BUFFER_TIMESTAMP (buffer) = timestamp;
1958 : :
1959 [ # # ][ # # ]: 0 : GST_LOG_OBJECT (basesrc, "created timestamp: %" GST_TIME_FORMAT,
[ # # ][ # # ]
[ # # ]
1960 : : GST_TIME_ARGS (timestamp));
1961 : : }
1962 : :
1963 : : /* add the timestamp offset we need for sync */
1964 : 7 : timestamp += basesrc->priv->ts_offset;
1965 : : } else {
1966 : : /* not the first buffer, the timestamp is the diff between the clock and
1967 : : * base_time */
1968 [ - + ][ # # ]: 602889 : if (do_timestamp && !GST_CLOCK_TIME_IS_VALID (timestamp)) {
1969 : 0 : now = gst_clock_get_time (clock);
1970 : :
1971 : 0 : GST_BUFFER_TIMESTAMP (buffer) = now - base_time;
1972 : :
1973 [ # # ][ # # ]: 0 : GST_LOG_OBJECT (basesrc, "created timestamp: %" GST_TIME_FORMAT,
[ # # ][ # # ]
[ # # ]
1974 : : GST_TIME_ARGS (now - base_time));
1975 : : }
1976 : : }
1977 : :
1978 : : /* if we don't have a buffer timestamp, we don't sync */
1979 [ + - ]: 602882 : if (!GST_CLOCK_TIME_IS_VALID (start))
1980 : 602882 : goto no_sync;
1981 : :
1982 [ # # ][ # # ]: 0 : if (basesrc->is_live && GST_CLOCK_TIME_IS_VALID (timestamp)) {
1983 : : /* for pseudo live sources, add our ts_offset to the timestamp */
1984 : 0 : GST_BUFFER_TIMESTAMP (buffer) += basesrc->priv->ts_offset;
1985 : 0 : start += basesrc->priv->ts_offset;
1986 : : }
1987 : :
1988 [ # # ][ # # ]: 0 : GST_LOG_OBJECT (basesrc,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1989 : : "waiting for clock, base time %" GST_TIME_FORMAT
1990 : : ", stream_start %" GST_TIME_FORMAT,
1991 : : GST_TIME_ARGS (base_time), GST_TIME_ARGS (start));
1992 : 0 : GST_OBJECT_UNLOCK (basesrc);
1993 : :
1994 : 0 : result = gst_base_src_wait (basesrc, clock, start + base_time);
1995 : :
1996 [ # # ]: 0 : GST_LOG_OBJECT (basesrc, "clock entry done: %d", result);
1997 : :
1998 : 0 : return result;
1999 : :
2000 : : /* special cases */
2001 : : no_clock:
2002 : : {
2003 [ - + ]: 83657 : GST_DEBUG_OBJECT (basesrc, "we have no clock");
2004 : 83657 : GST_OBJECT_UNLOCK (basesrc);
2005 : 83657 : return GST_CLOCK_OK;
2006 : : }
2007 : : no_sync:
2008 : : {
2009 [ - + ]: 602882 : GST_DEBUG_OBJECT (basesrc, "no sync needed");
2010 : 602882 : GST_OBJECT_UNLOCK (basesrc);
2011 : 686563 : return GST_CLOCK_OK;
2012 : : }
2013 : : }
2014 : :
2015 : : /* Called with STREAM_LOCK and LIVE_LOCK */
2016 : : static gboolean
2017 : 686580 : gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length)
2018 : : {
2019 : : guint64 size, maxsize;
2020 : : GstBaseSrcClass *bclass;
2021 : : GstFormat format;
2022 : : gint64 stop;
2023 : :
2024 : 686580 : bclass = GST_BASE_SRC_GET_CLASS (src);
2025 : :
2026 : 686580 : format = src->segment.format;
2027 : 686580 : stop = src->segment.stop;
2028 : : /* get total file size */
2029 : 686580 : size = (guint64) src->segment.duration;
2030 : :
2031 : : /* only operate if we are working with bytes */
2032 [ - + ]: 686580 : if (format != GST_FORMAT_BYTES)
2033 : 0 : return TRUE;
2034 : :
2035 : : /* the max amount of bytes to read is the total size or
2036 : : * up to the segment.stop if present. */
2037 [ - + ]: 686580 : if (stop != -1)
2038 : 0 : maxsize = MIN (size, stop);
2039 : : else
2040 : 686580 : maxsize = size;
2041 : :
2042 [ - + ]: 686580 : GST_DEBUG_OBJECT (src,
2043 : : "reading offset %" G_GUINT64_FORMAT ", length %u, size %" G_GINT64_FORMAT
2044 : : ", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
2045 : : *length, size, stop, maxsize);
2046 : :
2047 : : /* check size if we have one */
2048 [ + + ]: 686591 : if (maxsize != -1) {
2049 : : /* if we run past the end, check if the file became bigger and
2050 : : * retry. */
2051 [ + + ]: 19 : if (G_UNLIKELY (offset + *length >= maxsize)) {
2052 : : /* see if length of the file changed */
2053 [ + - ]: 8 : if (bclass->get_size)
2054 [ - + ]: 8 : if (!bclass->get_size (src, &size))
2055 : 0 : size = -1;
2056 : :
2057 : : /* make sure we don't exceed the configured segment stop
2058 : : * if it was set */
2059 [ - + ]: 8 : if (stop != -1)
2060 : 0 : maxsize = MIN (size, stop);
2061 : : else
2062 : 8 : maxsize = size;
2063 : :
2064 : : /* if we are at or past the end, EOS */
2065 [ + + ]: 8 : if (G_UNLIKELY (offset >= maxsize))
2066 : 4 : goto unexpected_length;
2067 : :
2068 : : /* else we can clip to the end */
2069 [ + - ]: 4 : if (G_UNLIKELY (offset + *length >= maxsize))
2070 : 4 : *length = maxsize - offset;
2071 : :
2072 : : }
2073 : : }
2074 : :
2075 : : /* keep track of current position and update duration.
2076 : : * segment is in bytes, we checked that above. */
2077 : 686587 : GST_OBJECT_LOCK (src);
2078 : 686590 : gst_segment_set_duration (&src->segment, GST_FORMAT_BYTES, size);
2079 : 686575 : gst_segment_set_last_stop (&src->segment, GST_FORMAT_BYTES, offset);
2080 : 686584 : GST_OBJECT_UNLOCK (src);
2081 : :
2082 : 686584 : return TRUE;
2083 : :
2084 : : /* ERRORS */
2085 : : unexpected_length:
2086 : : {
2087 : 686588 : return FALSE;
2088 : : }
2089 : : }
2090 : :
2091 : : /* must be called with LIVE_LOCK */
2092 : : static GstFlowReturn
2093 : 686587 : gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
2094 : : GstBuffer ** buf)
2095 : : {
2096 : : GstFlowReturn ret;
2097 : : GstBaseSrcClass *bclass;
2098 : : GstClockReturn status;
2099 : :
2100 : 686587 : bclass = GST_BASE_SRC_GET_CLASS (src);
2101 : :
2102 : : again:
2103 [ + + ]: 686587 : if (src->is_live) {
2104 [ - + ]: 3446 : if (G_UNLIKELY (!src->live_running)) {
2105 : 0 : ret = gst_base_src_wait_playing (src);
2106 [ # # ]: 0 : if (ret != GST_FLOW_OK)
2107 : 0 : goto stopped;
2108 : : }
2109 : : }
2110 : :
2111 [ - + ]: 686587 : if (G_UNLIKELY (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)))
2112 : 0 : goto not_started;
2113 : :
2114 [ - + ]: 686587 : if (G_UNLIKELY (!bclass->create))
2115 : 0 : goto no_function;
2116 : :
2117 [ + + ]: 686587 : if (G_UNLIKELY (!gst_base_src_update_length (src, offset, &length)))
2118 : 4 : goto unexpected_length;
2119 : :
2120 : : /* normally we don't count buffers */
2121 [ + + ]: 686585 : if (G_UNLIKELY (src->num_buffers_left >= 0)) {
2122 [ + + ]: 7706 : if (src->num_buffers_left == 0)
2123 : 23 : goto reached_num_buffers;
2124 : : else
2125 : 7683 : src->num_buffers_left--;
2126 : : }
2127 : :
2128 : : /* don't enter the create function if a pending EOS event was set. For the
2129 : : * logic of the pending_eos, check the event function of this class. */
2130 [ + + ]: 686562 : if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos)))
2131 : 1 : goto eos;
2132 : :
2133 [ - + ]: 686567 : GST_DEBUG_OBJECT (src,
2134 : : "calling create offset %" G_GUINT64_FORMAT " length %u, time %"
2135 : : G_GINT64_FORMAT, offset, length, src->segment.time);
2136 : :
2137 : 686567 : ret = bclass->create (src, offset, length, buf);
2138 : :
2139 : : /* The create function could be unlocked because we have a pending EOS. It's
2140 : : * possible that we have a valid buffer from create that we need to
2141 : : * discard when the create function returned _OK. */
2142 [ + + ]: 686553 : if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos))) {
2143 [ + - ]: 1 : if (ret == GST_FLOW_OK) {
2144 : 1 : gst_buffer_unref (*buf);
2145 : 1 : *buf = NULL;
2146 : : }
2147 : 1 : goto eos;
2148 : : }
2149 : :
2150 [ + + ]: 686565 : if (G_UNLIKELY (ret != GST_FLOW_OK))
2151 : 2 : goto not_ok;
2152 : :
2153 : : /* no timestamp set and we are at offset 0, we can timestamp with 0 */
2154 [ + + ][ + + ]: 686563 : if (offset == 0 && src->segment.time == 0
2155 [ + + ]: 686035 : && GST_BUFFER_TIMESTAMP (*buf) == -1) {
2156 : 677587 : *buf = gst_buffer_make_metadata_writable (*buf);
2157 : 677586 : GST_BUFFER_TIMESTAMP (*buf) = 0;
2158 : : }
2159 : :
2160 : : /* set pad caps on the buffer if the buffer had no caps */
2161 [ + ]: 686562 : if (GST_BUFFER_CAPS (*buf) == NULL) {
2162 : 686563 : *buf = gst_buffer_make_metadata_writable (*buf);
2163 : 686561 : gst_buffer_set_caps (*buf, GST_PAD_CAPS (src->srcpad));
2164 : : }
2165 : :
2166 : : /* now sync before pushing the buffer */
2167 : 686563 : status = gst_base_src_do_sync (src, *buf);
2168 : :
2169 : : /* waiting for the clock could have made us flushing */
2170 [ - + ]: 686563 : if (G_UNLIKELY (src->priv->flushing))
2171 : 0 : goto flushing;
2172 : :
2173 [ - + - - ]: 686563 : switch (status) {
2174 : : case GST_CLOCK_EARLY:
2175 : : /* the buffer is too late. We currently don't drop the buffer. */
2176 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "buffer too late!, returning anyway");
2177 : 0 : break;
2178 : : case GST_CLOCK_OK:
2179 : : /* buffer synchronised properly */
2180 [ - + ]: 686563 : GST_DEBUG_OBJECT (src, "buffer ok");
2181 : 686563 : break;
2182 : : case GST_CLOCK_UNSCHEDULED:
2183 : : /* this case is triggered when we were waiting for the clock and
2184 : : * it got unlocked because we did a state change. In any case, get rid of
2185 : : * the buffer. */
2186 : 0 : gst_buffer_unref (*buf);
2187 : 0 : *buf = NULL;
2188 [ # # ]: 0 : if (!src->live_running) {
2189 : : /* We return WRONG_STATE when we are not running to stop the dataflow also
2190 : : * get rid of the produced buffer. */
2191 [ # # ]: 0 : GST_DEBUG_OBJECT (src,
2192 : : "clock was unscheduled (%d), returning WRONG_STATE", status);
2193 : 0 : ret = GST_FLOW_WRONG_STATE;
2194 : : } else {
2195 : : /* If we are running when this happens, we quickly switched between
2196 : : * pause and playing. We try to produce a new buffer */
2197 [ # # ]: 0 : GST_DEBUG_OBJECT (src,
2198 : : "clock was unscheduled (%d), but we are running", status);
2199 : 0 : goto again;
2200 : : }
2201 : 0 : break;
2202 : : default:
2203 : : /* all other result values are unexpected and errors */
2204 [ # # ][ # # ]: 0 : GST_ELEMENT_ERROR (src, CORE, CLOCK,
[ # # ][ # # ]
2205 : : (_("Internal clock error.")),
2206 : : ("clock returned unexpected return value %d", status));
2207 : 0 : gst_buffer_unref (*buf);
2208 : 0 : *buf = NULL;
2209 : 0 : ret = GST_FLOW_ERROR;
2210 : 0 : break;
2211 : : }
2212 : 686539 : return ret;
2213 : :
2214 : : /* ERROR */
2215 : : stopped:
2216 : : {
2217 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "wait_playing returned %d (%s)", ret,
2218 : : gst_flow_get_name (ret));
2219 : 0 : return ret;
2220 : : }
2221 : : not_ok:
2222 : : {
2223 [ - + ]: 2 : GST_DEBUG_OBJECT (src, "create returned %d (%s)", ret,
2224 : : gst_flow_get_name (ret));
2225 : 2 : return ret;
2226 : : }
2227 : : not_started:
2228 : : {
2229 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "getrange but not started");
2230 : 0 : return GST_FLOW_WRONG_STATE;
2231 : : }
2232 : : no_function:
2233 : : {
2234 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "no create function");
2235 : 0 : return GST_FLOW_ERROR;
2236 : : }
2237 : : unexpected_length:
2238 : : {
2239 [ - + ]: 4 : GST_DEBUG_OBJECT (src, "unexpected length %u (offset=%" G_GUINT64_FORMAT
2240 : : ", size=%" G_GINT64_FORMAT ")", length, offset, src->segment.duration);
2241 : 4 : return GST_FLOW_UNEXPECTED;
2242 : : }
2243 : : reached_num_buffers:
2244 : : {
2245 [ - + ]: 23 : GST_DEBUG_OBJECT (src, "sent all buffers");
2246 : 23 : return GST_FLOW_UNEXPECTED;
2247 : : }
2248 : : flushing:
2249 : : {
2250 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "we are flushing");
2251 : 0 : gst_buffer_unref (*buf);
2252 : 0 : *buf = NULL;
2253 : 0 : return GST_FLOW_WRONG_STATE;
2254 : : }
2255 : : eos:
2256 : : {
2257 [ - + ]: 2 : GST_DEBUG_OBJECT (src, "we are EOS");
2258 : 686570 : return GST_FLOW_UNEXPECTED;
2259 : : }
2260 : : }
2261 : :
2262 : : static GstFlowReturn
2263 : 38629 : gst_base_src_pad_get_range (GstPad * pad, guint64 offset, guint length,
2264 : : GstBuffer ** buf)
2265 : : {
2266 : : GstBaseSrc *src;
2267 : : GstFlowReturn res;
2268 : :
2269 : 38629 : src = GST_BASE_SRC_CAST (gst_object_ref (GST_OBJECT_PARENT (pad)));
2270 : :
2271 : 38629 : GST_LIVE_LOCK (src);
2272 [ - + ]: 38629 : if (G_UNLIKELY (src->priv->flushing))
2273 : 0 : goto flushing;
2274 : :
2275 : 38629 : res = gst_base_src_get_range (src, offset, length, buf);
2276 : :
2277 : : done:
2278 : 38629 : GST_LIVE_UNLOCK (src);
2279 : :
2280 : 38629 : gst_object_unref (src);
2281 : :
2282 : 38629 : return res;
2283 : :
2284 : : /* ERRORS */
2285 : : flushing:
2286 : : {
2287 [ # # ]: 0 : GST_DEBUG_OBJECT (src, "we are flushing");
2288 : 0 : res = GST_FLOW_WRONG_STATE;
2289 : 0 : goto done;
2290 : : }
2291 : : }
2292 : :
2293 : : static gboolean
2294 : 13 : gst_base_src_default_check_get_range (GstBaseSrc * src)
2295 : : {
2296 : : gboolean res;
2297 : :
2298 [ + + ]: 13 : if (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)) {
2299 [ - + ]: 6 : GST_LOG_OBJECT (src, "doing start/stop to check get_range support");
2300 [ + - ]: 6 : if (G_LIKELY (gst_base_src_start (src)))
2301 : 6 : gst_base_src_stop (src);
2302 : : }
2303 : :
2304 : : /* we can operate in getrange mode if the native format is bytes
2305 : : * and we are seekable, this condition is set in the random_access
2306 : : * flag and is set in the _start() method. */
2307 : 13 : res = src->random_access;
2308 : :
2309 : 13 : return res;
2310 : : }
2311 : :
2312 : : static gboolean
2313 : 13 : gst_base_src_check_get_range (GstBaseSrc * src)
2314 : : {
2315 : : GstBaseSrcClass *bclass;
2316 : : gboolean res;
2317 : :
2318 : 13 : bclass = GST_BASE_SRC_GET_CLASS (src);
2319 : :
2320 [ - + ]: 13 : if (bclass->check_get_range == NULL)
2321 : 0 : goto no_function;
2322 : :
2323 : 13 : res = bclass->check_get_range (src);
2324 [ - + ]: 13 : GST_LOG_OBJECT (src, "%s() returned %d",
2325 : : GST_DEBUG_FUNCPTR_NAME (bclass->check_get_range), (gint) res);
2326 : :
2327 : 13 : return res;
2328 : :
2329 : : /* ERRORS */
2330 : : no_function:
2331 : : {
2332 [ # # ]: 0 : GST_WARNING_OBJECT (src, "no check_get_range function set");
2333 : 13 : return FALSE;
2334 : : }
2335 : : }
2336 : :
2337 : : static gboolean
2338 : 6 : gst_base_src_pad_check_get_range (GstPad * pad)
2339 : : {
2340 : : GstBaseSrc *src;
2341 : : gboolean res;
2342 : :
2343 : 6 : src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
2344 : :
2345 : 6 : res = gst_base_src_check_get_range (src);
2346 : :
2347 : 6 : return res;
2348 : : }
2349 : :
2350 : : static void
2351 : 647972 : gst_base_src_loop (GstPad * pad)
2352 : : {
2353 : : GstBaseSrc *src;
2354 : 647972 : GstBuffer *buf = NULL;
2355 : : GstFlowReturn ret;
2356 : : gint64 position;
2357 : : gboolean eos;
2358 : : gulong blocksize;
2359 : 647972 : GList *tags = NULL, *tmp;
2360 : :
2361 : 647972 : eos = FALSE;
2362 : :
2363 : 647972 : src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
2364 : :
2365 : 647970 : GST_LIVE_LOCK (src);
2366 : :
2367 [ + + ]: 647971 : if (G_UNLIKELY (src->priv->flushing))
2368 : 6 : goto flushing;
2369 : :
2370 : 647965 : src->priv->last_sent_eos = FALSE;
2371 : :
2372 : 647965 : blocksize = src->blocksize;
2373 : :
2374 : : /* if we operate in bytes, we can calculate an offset */
2375 [ + - ]: 647965 : if (src->segment.format == GST_FORMAT_BYTES) {
2376 : 647965 : position = src->segment.last_stop;
2377 : : /* for negative rates, start with subtracting the blocksize */
2378 [ + + ]: 647965 : if (src->segment.rate < 0.0) {
2379 : : /* we cannot go below segment.start */
2380 [ + + ]: 8 : if (position > src->segment.start + blocksize)
2381 : 7 : position -= blocksize;
2382 : : else {
2383 : : /* last block, remainder up to segment.start */
2384 : 1 : blocksize = position - src->segment.start;
2385 : 1 : position = src->segment.start;
2386 : : }
2387 : : }
2388 : : } else
2389 : 0 : position = -1;
2390 : :
2391 [ - + ][ # # ]: 647965 : GST_LOG_OBJECT (src, "next_ts %" GST_TIME_FORMAT " size %lu",
[ # # ][ # # ]
[ # # ]
2392 : : GST_TIME_ARGS (position), blocksize);
2393 : :
2394 : 647965 : ret = gst_base_src_get_range (src, position, blocksize, &buf);
2395 [ + + ]: 647926 : if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2396 [ - + ]: 24 : GST_INFO_OBJECT (src, "pausing after gst_base_src_get_range() = %s",
2397 : : gst_flow_get_name (ret));
2398 : 24 : GST_LIVE_UNLOCK (src);
2399 : 24 : goto pause;
2400 : : }
2401 : : /* this should not happen */
2402 [ - + ]: 647902 : if (G_UNLIKELY (buf == NULL))
2403 : 0 : goto null_buffer;
2404 : :
2405 : : /* push events to close/start our segment before we push the buffer. */
2406 [ + + ]: 647902 : if (G_UNLIKELY (src->priv->close_segment)) {
2407 : 1 : gst_pad_push_event (pad, src->priv->close_segment);
2408 : 1 : src->priv->close_segment = NULL;
2409 : : }
2410 [ + + ]: 647902 : if (G_UNLIKELY (src->priv->start_segment)) {
2411 : 200 : gst_pad_push_event (pad, src->priv->start_segment);
2412 : 200 : src->priv->start_segment = NULL;
2413 : : }
2414 : 647902 : src->priv->newsegment_pending = FALSE;
2415 : :
2416 [ - + ]: 647902 : if (g_atomic_int_get (&src->priv->have_tags)) {
2417 : 0 : GST_OBJECT_LOCK (src);
2418 : : /* take the tags */
2419 : 0 : tags = src->priv->pending_tags;
2420 : 0 : src->priv->pending_tags = NULL;
2421 : 0 : g_atomic_int_set (&src->priv->have_tags, FALSE);
2422 : 0 : GST_OBJECT_UNLOCK (src);
2423 : : }
2424 : :
2425 : : /* Push out pending tags if any */
2426 [ - + ]: 647942 : if (G_UNLIKELY (tags != NULL)) {
2427 [ # # ][ # # ]: 0 : for (tmp = tags; tmp; tmp = g_list_next (tmp)) {
2428 : 0 : GstEvent *ev = (GstEvent *) tmp->data;
2429 : 0 : gst_pad_push_event (pad, ev);
2430 : : }
2431 : 0 : g_list_free (tags);
2432 : : }
2433 : :
2434 : : /* figure out the new position */
2435 [ + - - - ]: 647942 : switch (src->segment.format) {
2436 : : case GST_FORMAT_BYTES:
2437 : : {
2438 : 647942 : guint bufsize = GST_BUFFER_SIZE (buf);
2439 : :
2440 : : /* we subtracted above for negative rates */
2441 [ + + ]: 647942 : if (src->segment.rate >= 0.0)
2442 : 647934 : position += bufsize;
2443 : 647942 : break;
2444 : : }
2445 : : case GST_FORMAT_TIME:
2446 : : {
2447 : : GstClockTime start, duration;
2448 : :
2449 : 0 : start = GST_BUFFER_TIMESTAMP (buf);
2450 : 0 : duration = GST_BUFFER_DURATION (buf);
2451 : :
2452 [ # # ]: 0 : if (GST_CLOCK_TIME_IS_VALID (start))
2453 : 0 : position = start;
2454 : : else
2455 : 0 : position = src->segment.last_stop;
2456 : :
2457 [ # # ]: 0 : if (GST_CLOCK_TIME_IS_VALID (duration)) {
2458 [ # # ]: 0 : if (src->segment.rate >= 0.0)
2459 : 0 : position += duration;
2460 [ # # ]: 0 : else if (position > duration)
2461 : 0 : position -= duration;
2462 : : else
2463 : 0 : position = 0;
2464 : : }
2465 : 0 : break;
2466 : : }
2467 : : case GST_FORMAT_DEFAULT:
2468 [ # # ]: 0 : if (src->segment.rate >= 0.0)
2469 : 0 : position = GST_BUFFER_OFFSET_END (buf);
2470 : : else
2471 : 0 : position = GST_BUFFER_OFFSET (buf);
2472 : 0 : break;
2473 : : default:
2474 : 0 : position = -1;
2475 : 0 : break;
2476 : : }
2477 [ + + ]: 647942 : if (position != -1) {
2478 [ + + ]: 647941 : if (src->segment.rate >= 0.0) {
2479 : : /* positive rate, check if we reached the stop */
2480 [ - + ]: 647933 : if (src->segment.stop != -1) {
2481 [ # # ]: 0 : if (position >= src->segment.stop) {
2482 : 0 : eos = TRUE;
2483 : 0 : position = src->segment.stop;
2484 : : }
2485 : : }
2486 : : } else {
2487 : : /* negative rate, check if we reached the start. start is always set to
2488 : : * something different from -1 */
2489 [ + + ]: 8 : if (position <= src->segment.start) {
2490 : 1 : eos = TRUE;
2491 : 1 : position = src->segment.start;
2492 : : }
2493 : : /* when going reverse, all buffers are DISCONT */
2494 : 8 : src->priv->discont = TRUE;
2495 : : }
2496 : 647941 : GST_OBJECT_LOCK (src);
2497 : 647942 : gst_segment_set_last_stop (&src->segment, src->segment.format, position);
2498 : 647942 : GST_OBJECT_UNLOCK (src);
2499 : : }
2500 : :
2501 [ + + ]: 647942 : if (G_UNLIKELY (src->priv->discont)) {
2502 : 207 : buf = gst_buffer_make_metadata_writable (buf);
2503 : 207 : GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
2504 : 207 : src->priv->discont = FALSE;
2505 : : }
2506 : 647942 : GST_LIVE_UNLOCK (src);
2507 : :
2508 : 647942 : ret = gst_pad_push (pad, buf);
2509 [ + + ]: 647932 : if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2510 [ - + ]: 153 : GST_INFO_OBJECT (src, "pausing after gst_pad_push() = %s",
2511 : : gst_flow_get_name (ret));
2512 : 153 : goto pause;
2513 : : }
2514 : :
2515 [ + + ]: 647779 : if (G_UNLIKELY (eos)) {
2516 [ - + ]: 1 : GST_INFO_OBJECT (src, "pausing after end of segment");
2517 : 1 : ret = GST_FLOW_UNEXPECTED;
2518 : 1 : goto pause;
2519 : : }
2520 : :
2521 : : done:
2522 : 647962 : return;
2523 : :
2524 : : /* special cases */
2525 : : flushing:
2526 : : {
2527 [ - + ]: 6 : GST_DEBUG_OBJECT (src, "we are flushing");
2528 : 6 : GST_LIVE_UNLOCK (src);
2529 : 6 : ret = GST_FLOW_WRONG_STATE;
2530 : 6 : goto pause;
2531 : : }
2532 : : pause:
2533 : : {
2534 : 184 : const gchar *reason = gst_flow_get_name (ret);
2535 : : GstEvent *event;
2536 : :
2537 [ - + ]: 184 : GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
2538 : 184 : src->data.ABI.running = FALSE;
2539 : 184 : gst_pad_pause_task (pad);
2540 [ + + ]: 184 : if (ret == GST_FLOW_UNEXPECTED) {
2541 : : gboolean flag_segment;
2542 : : GstFormat format;
2543 : : gint64 last_stop;
2544 : :
2545 : : /* perform EOS logic */
2546 : 23 : flag_segment = (src->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0;
2547 : 23 : format = src->segment.format;
2548 : 23 : last_stop = src->segment.last_stop;
2549 : :
2550 [ - + ]: 23 : if (flag_segment) {
2551 : : GstMessage *message;
2552 : :
2553 : 0 : message = gst_message_new_segment_done (GST_OBJECT_CAST (src),
2554 : : format, last_stop);
2555 : 0 : gst_message_set_seqnum (message, src->priv->seqnum);
2556 : 0 : gst_element_post_message (GST_ELEMENT_CAST (src), message);
2557 : : } else {
2558 : 23 : event = gst_event_new_eos ();
2559 : 23 : gst_event_set_seqnum (event, src->priv->seqnum);
2560 : 23 : gst_pad_push_event (pad, event);
2561 : 23 : src->priv->last_sent_eos = TRUE;
2562 : : }
2563 [ + + ][ + + ]: 161 : } else if (ret == GST_FLOW_NOT_LINKED || ret <= GST_FLOW_UNEXPECTED) {
2564 : 4 : event = gst_event_new_eos ();
2565 : 4 : gst_event_set_seqnum (event, src->priv->seqnum);
2566 : : /* for fatal errors we post an error message, post the error
2567 : : * first so the app knows about the error first.
2568 : : * Also don't do this for WRONG_STATE because it happens
2569 : : * due to flushing and posting an error message because of
2570 : : * that is the wrong thing to do, e.g. when we're doing
2571 : : * a flushing seek. */
2572 [ + - ][ - + ]: 4 : GST_ELEMENT_ERROR (src, STREAM, FAILED,
[ + - ][ - + ]
2573 : : (_("Internal data flow error.")),
2574 : : ("streaming task paused, reason %s (%d)", reason, ret));
2575 : 4 : gst_pad_push_event (pad, event);
2576 : 4 : src->priv->last_sent_eos = TRUE;
2577 : : }
2578 : 184 : goto done;
2579 : : }
2580 : : null_buffer:
2581 : : {
2582 [ # # ][ # # ]: 0 : GST_ELEMENT_ERROR (src, STREAM, FAILED,
[ # # ][ # # ]
2583 : : (_("Internal data flow error.")), ("element returned NULL buffer"));
2584 : 0 : GST_LIVE_UNLOCK (src);
2585 : 0 : goto done;
2586 : : }
2587 : : }
2588 : :
2589 : : /* default negotiation code.
2590 : : *
2591 : : * Take intersection between src and sink pads, take first
2592 : : * caps and fixate.
2593 : : */
2594 : : static gboolean
2595 : 417 : gst_base_src_default_negotiate (GstBaseSrc * basesrc)
2596 : : {
2597 : : GstCaps *thiscaps;
2598 : 417 : GstCaps *caps = NULL;
2599 : 417 : GstCaps *peercaps = NULL;
2600 : 417 : gboolean result = FALSE;
2601 : :
2602 : : /* first see what is possible on our source pad */
2603 : 417 : thiscaps = gst_pad_get_caps_reffed (GST_BASE_SRC_PAD (basesrc));
2604 [ - + ]: 417 : GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
2605 : : /* nothing or anything is allowed, we're done */
2606 [ + - ][ - + ]: 417 : if (thiscaps == NULL || gst_caps_is_any (thiscaps))
2607 : : goto no_nego_needed;
2608 : :
2609 [ # # ]: 0 : if (G_UNLIKELY (gst_caps_is_empty (thiscaps)))
2610 : 0 : goto no_caps;
2611 : :
2612 : : /* get the peer caps */
2613 : 0 : peercaps = gst_pad_peer_get_caps_reffed (GST_BASE_SRC_PAD (basesrc));
2614 [ # # ]: 0 : GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
2615 [ # # ]: 0 : if (peercaps) {
2616 : : /* get intersection */
2617 : 0 : caps = gst_caps_intersect_full (peercaps, thiscaps, GST_CAPS_INTERSECT_FIRST);
2618 [ # # ]: 0 : GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, caps);
2619 : 0 : gst_caps_unref (peercaps);
2620 : : } else {
2621 : : /* no peer, work with our own caps then */
2622 : 0 : caps = gst_caps_copy (thiscaps);
2623 : : }
2624 : 0 : gst_caps_unref (thiscaps);
2625 [ # # ]: 0 : if (caps) {
2626 : : /* take first (and best, since they are sorted) possibility */
2627 : 0 : gst_caps_truncate (caps);
2628 : :
2629 : : /* now fixate */
2630 [ # # ]: 0 : if (!gst_caps_is_empty (caps)) {
2631 : 0 : gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
2632 [ # # ]: 0 : GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
2633 : :
2634 [ # # ]: 0 : if (gst_caps_is_any (caps)) {
2635 : : /* hmm, still anything, so element can do anything and
2636 : : * nego is not needed */
2637 : 0 : result = TRUE;
2638 [ # # ]: 0 : } else if (gst_caps_is_fixed (caps)) {
2639 : : /* yay, fixed caps, use those then, it's possible that the subclass does
2640 : : * not accept this caps after all and we have to fail. */
2641 : 0 : result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
2642 : : }
2643 : : }
2644 : 0 : gst_caps_unref (caps);
2645 : : } else {
2646 [ # # ]: 0 : GST_DEBUG_OBJECT (basesrc, "no common caps");
2647 : : }
2648 : 0 : return result;
2649 : :
2650 : : no_nego_needed:
2651 : : {
2652 [ - + ]: 417 : GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
2653 [ + - ]: 417 : if (thiscaps)
2654 : 417 : gst_caps_unref (thiscaps);
2655 : 417 : return TRUE;
2656 : : }
2657 : : no_caps:
2658 : : {
2659 [ # # ][ # # ]: 0 : GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
[ # # ][ # # ]
2660 : : ("No supported formats found"),
2661 : : ("This element did not produce valid caps"));
2662 [ # # ]: 0 : if (thiscaps)
2663 : 0 : gst_caps_unref (thiscaps);
2664 : 417 : return TRUE;
2665 : : }
2666 : : }
2667 : :
2668 : : static gboolean
2669 : 417 : gst_base_src_negotiate (GstBaseSrc * basesrc)
2670 : : {
2671 : : GstBaseSrcClass *bclass;
2672 : 417 : gboolean result = TRUE;
2673 : :
2674 : 417 : bclass = GST_BASE_SRC_GET_CLASS (basesrc);
2675 : :
2676 [ + - ]: 417 : if (bclass->negotiate)
2677 : 417 : result = bclass->negotiate (basesrc);
2678 : :
2679 : 417 : return result;
2680 : : }
2681 : :
2682 : : static gboolean
2683 : 436 : gst_base_src_start (GstBaseSrc * basesrc)
2684 : : {
2685 : : GstBaseSrcClass *bclass;
2686 : : gboolean result;
2687 : : guint64 size;
2688 : : gboolean seekable;
2689 : : GstFormat format;
2690 : :
2691 [ - + ]: 436 : if (GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
2692 : 0 : return TRUE;
2693 : :
2694 [ - + ]: 436 : GST_DEBUG_OBJECT (basesrc, "starting source");
2695 : :
2696 : 436 : basesrc->num_buffers_left = basesrc->num_buffers;
2697 : :
2698 : 436 : GST_OBJECT_LOCK (basesrc);
2699 : 436 : gst_segment_init (&basesrc->segment, basesrc->segment.format);
2700 : 436 : GST_OBJECT_UNLOCK (basesrc);
2701 : :
2702 : 436 : basesrc->data.ABI.running = FALSE;
2703 : 436 : basesrc->priv->newsegment_pending = FALSE;
2704 : :
2705 : 436 : bclass = GST_BASE_SRC_GET_CLASS (basesrc);
2706 [ + + ]: 436 : if (bclass->start)
2707 : 426 : result = bclass->start (basesrc);
2708 : : else
2709 : 10 : result = TRUE;
2710 : :
2711 [ + + ]: 436 : if (!result)
2712 : 19 : goto could_not_start;
2713 : :
2714 : 417 : GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_STARTED);
2715 : :
2716 : 417 : format = basesrc->segment.format;
2717 : :
2718 : : /* figure out the size */
2719 [ + - ]: 417 : if (format == GST_FORMAT_BYTES) {
2720 [ + + ]: 417 : if (bclass->get_size) {
2721 [ + + ]: 13 : if (!(result = bclass->get_size (basesrc, &size)))
2722 : 9 : size = -1;
2723 : : } else {
2724 : 404 : result = FALSE;
2725 : 404 : size = -1;
2726 : : }
2727 [ - + ]: 417 : GST_DEBUG_OBJECT (basesrc, "setting size %" G_GUINT64_FORMAT, size);
2728 : : /* only update the size when operating in bytes, subclass is supposed
2729 : : * to set duration in the start method for other formats */
2730 : 417 : GST_OBJECT_LOCK (basesrc);
2731 : 417 : gst_segment_set_duration (&basesrc->segment, GST_FORMAT_BYTES, size);
2732 : 417 : GST_OBJECT_UNLOCK (basesrc);
2733 : : } else {
2734 : 0 : size = -1;
2735 : : }
2736 : :
2737 [ - + ]: 417 : GST_DEBUG_OBJECT (basesrc,
2738 : : "format: %s, have size: %d, size: %" G_GUINT64_FORMAT ", duration: %"
2739 : : G_GINT64_FORMAT, gst_format_get_name (format), result, size,
2740 : : basesrc->segment.duration);
2741 : :
2742 : 417 : seekable = gst_base_src_seekable (basesrc);
2743 [ - + ]: 417 : GST_DEBUG_OBJECT (basesrc, "is seekable: %d", seekable);
2744 : :
2745 : : /* update for random access flag */
2746 [ + + ][ + - ]: 417 : basesrc->random_access = seekable && format == GST_FORMAT_BYTES;
2747 : :
2748 [ - + ]: 417 : GST_DEBUG_OBJECT (basesrc, "is random_access: %d", basesrc->random_access);
2749 : :
2750 : : /* run typefind if we are random_access and the typefinding is enabled. */
2751 [ + + ][ - + ]: 417 : if (basesrc->random_access && basesrc->data.ABI.typefind && size != -1) {
[ # # ]
2752 : : GstCaps *caps;
2753 : :
2754 [ # # ]: 0 : if (!(caps = gst_type_find_helper (basesrc->srcpad, size)))
2755 : 0 : goto typefind_failed;
2756 : :
2757 : 0 : result = gst_pad_set_caps (basesrc->srcpad, caps);
2758 : 0 : gst_caps_unref (caps);
2759 : : } else {
2760 : : /* use class or default negotiate function */
2761 [ - + ]: 417 : if (!(result = gst_base_src_negotiate (basesrc)))
2762 : 0 : goto could_not_negotiate;
2763 : : }
2764 : :
2765 : 417 : return result;
2766 : :
2767 : : /* ERROR */
2768 : : could_not_start:
2769 : : {
2770 [ - + ]: 19 : GST_DEBUG_OBJECT (basesrc, "could not start");
2771 : : /* subclass is supposed to post a message. We don't have to call _stop. */
2772 : 19 : return FALSE;
2773 : : }
2774 : : could_not_negotiate:
2775 : : {
2776 [ # # ]: 0 : GST_DEBUG_OBJECT (basesrc, "could not negotiate, stopping");
2777 [ # # ][ # # ]: 0 : GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
[ # # ][ # # ]
2778 : : ("Could not negotiate format"), ("Check your filtered caps, if any"));
2779 : : /* we must call stop */
2780 : 0 : gst_base_src_stop (basesrc);
2781 : 0 : return FALSE;
2782 : : }
2783 : : typefind_failed:
2784 : : {
2785 [ # # ]: 0 : GST_DEBUG_OBJECT (basesrc, "could not typefind, stopping");
2786 [ # # ][ # # ]: 0 : GST_ELEMENT_ERROR (basesrc, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
[ # # ][ # # ]
2787 : : /* we must call stop */
2788 : 0 : gst_base_src_stop (basesrc);
2789 : 436 : return FALSE;
2790 : : }
2791 : : }
2792 : :
2793 : : static gboolean
2794 : 417 : gst_base_src_stop (GstBaseSrc * basesrc)
2795 : : {
2796 : : GstBaseSrcClass *bclass;
2797 : 417 : gboolean result = TRUE;
2798 : :
2799 [ - + ]: 417 : if (!GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED))
2800 : 0 : return TRUE;
2801 : :
2802 [ - + ]: 417 : GST_DEBUG_OBJECT (basesrc, "stopping source");
2803 : :
2804 : 417 : bclass = GST_BASE_SRC_GET_CLASS (basesrc);
2805 [ + + ]: 417 : if (bclass->stop)
2806 : 407 : result = bclass->stop (basesrc);
2807 : :
2808 [ + - ]: 417 : if (result)
2809 : 417 : GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
2810 : :
2811 : 417 : return result;
2812 : : }
2813 : :
2814 : : /* start or stop flushing dataprocessing
2815 : : */
2816 : : static gboolean
2817 : 1636 : gst_base_src_set_flushing (GstBaseSrc * basesrc,
2818 : : gboolean flushing, gboolean live_play, gboolean unlock, gboolean * playing)
2819 : : {
2820 : : GstBaseSrcClass *bclass;
2821 : :
2822 : 1636 : bclass = GST_BASE_SRC_GET_CLASS (basesrc);
2823 : :
2824 [ + + ][ + + ]: 1636 : if (flushing && unlock) {
2825 : : /* unlock any subclasses, we need to do this before grabbing the
2826 : : * LIVE_LOCK since we hold this lock before going into ::create. We pass an
2827 : : * unlock to the params because of backwards compat (see seek handler)*/
2828 [ + + ]: 414 : if (bclass->unlock)
2829 : 10 : bclass->unlock (basesrc);
2830 : : }
2831 : :
2832 : : /* the live lock is released when we are blocked, waiting for playing or
2833 : : * when we sync to the clock. */
2834 : 1636 : GST_LIVE_LOCK (basesrc);
2835 [ + + ]: 1636 : if (playing)
2836 : 407 : *playing = basesrc->live_running;
2837 : 1636 : basesrc->priv->flushing = flushing;
2838 [ + + ]: 1636 : if (flushing) {
2839 : : /* if we are locked in the live lock, signal it to make it flush */
2840 : 818 : basesrc->live_running = TRUE;
2841 : :
2842 : : /* clear pending EOS if any */
2843 : 818 : g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
2844 : :
2845 : : /* step 1, now that we have the LIVE lock, clear our unlock request */
2846 [ + + ]: 818 : if (bclass->unlock_stop)
2847 : 20 : bclass->unlock_stop (basesrc);
2848 : :
2849 : : /* step 2, unblock clock sync (if any) or any other blocking thing */
2850 [ - + ]: 818 : if (basesrc->clock_id)
2851 : 0 : gst_clock_id_unschedule (basesrc->clock_id);
2852 : : } else {
2853 : : /* signal the live source that it can start playing */
2854 : 818 : basesrc->live_running = live_play;
2855 : : }
2856 : 1636 : GST_LIVE_SIGNAL (basesrc);
2857 : 1636 : GST_LIVE_UNLOCK (basesrc);
2858 : :
2859 : 1636 : return TRUE;
2860 : : }
2861 : :
2862 : : /* the purpose of this function is to make sure that a live source blocks in the
2863 : : * LIVE lock or leaves the LIVE lock and continues playing. */
2864 : : static gboolean
2865 : 16 : gst_base_src_set_playing (GstBaseSrc * basesrc, gboolean live_play)
2866 : : {
2867 : : GstBaseSrcClass *bclass;
2868 : :
2869 : 16 : bclass = GST_BASE_SRC_GET_CLASS (basesrc);
2870 : :
2871 : : /* unlock subclasses locked in ::create, we only do this when we stop playing. */
2872 [ + + ]: 16 : if (!live_play) {
2873 [ - + ]: 8 : GST_DEBUG_OBJECT (basesrc, "unlock");
2874 [ - + ]: 8 : if (bclass->unlock)
2875 : 0 : bclass->unlock (basesrc);
2876 : : }
2877 : :
2878 : : /* we are now able to grab the LIVE lock, when we get it, we can be
2879 : : * waiting for PLAYING while blocked in the LIVE cond or we can be waiting
2880 : : * for the clock. */
2881 : 16 : GST_LIVE_LOCK (basesrc);
2882 [ - + ]: 16 : GST_DEBUG_OBJECT (basesrc, "unschedule clock");
2883 : :
2884 : : /* unblock clock sync (if any) */
2885 [ - + ]: 16 : if (basesrc->clock_id)
2886 : 0 : gst_clock_id_unschedule (basesrc->clock_id);
2887 : :
2888 : : /* configure what to do when we get to the LIVE lock. */
2889 [ - + ]: 16 : GST_DEBUG_OBJECT (basesrc, "live running %d", live_play);
2890 : 16 : basesrc->live_running = live_play;
2891 : :
2892 [ + + ]: 16 : if (live_play) {
2893 : : gboolean start;
2894 : :
2895 : : /* clear our unlock request when going to PLAYING */
2896 [ - + ]: 8 : GST_DEBUG_OBJECT (basesrc, "unlock stop");
2897 [ - + ]: 8 : if (bclass->unlock_stop)
2898 : 0 : bclass->unlock_stop (basesrc);
2899 : :
2900 : : /* for live sources we restart the timestamp correction */
2901 : 8 : basesrc->priv->latency = -1;
2902 : : /* have to restart the task in case it stopped because of the unlock when
2903 : : * we went to PAUSED. Only do this if we operating in push mode. */
2904 : 8 : GST_OBJECT_LOCK (basesrc->srcpad);
2905 : 8 : start = (GST_PAD_ACTIVATE_MODE (basesrc->srcpad) == GST_ACTIVATE_PUSH);
2906 : 8 : GST_OBJECT_UNLOCK (basesrc->srcpad);
2907 [ + - ]: 8 : if (start)
2908 : 8 : gst_pad_start_task (basesrc->srcpad, (GstTaskFunction) gst_base_src_loop,
2909 : 8 : basesrc->srcpad);
2910 [ - + ]: 8 : GST_DEBUG_OBJECT (basesrc, "signal");
2911 : 8 : GST_LIVE_SIGNAL (basesrc);
2912 : : }
2913 : 16 : GST_LIVE_UNLOCK (basesrc);
2914 : :
2915 : 16 : return TRUE;
2916 : : }
2917 : :
2918 : : static gboolean
2919 : 828 : gst_base_src_activate_push (GstPad * pad, gboolean active)
2920 : : {
2921 : : GstBaseSrc *basesrc;
2922 : : GstEvent *event;
2923 : :
2924 : 828 : basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
2925 : :
2926 : : /* prepare subclass first */
2927 [ + + ]: 828 : if (active) {
2928 [ - + ]: 424 : GST_DEBUG_OBJECT (basesrc, "Activating in push mode");
2929 : :
2930 [ + + ]: 424 : if (G_UNLIKELY (!basesrc->can_activate_push))
2931 : 1 : goto no_push_activation;
2932 : :
2933 [ + + ]: 423 : if (G_UNLIKELY (!gst_base_src_start (basesrc)))
2934 : 19 : goto error_start;
2935 : :
2936 : 404 : basesrc->priv->last_sent_eos = FALSE;
2937 : 404 : basesrc->priv->discont = TRUE;
2938 : 404 : gst_base_src_set_flushing (basesrc, FALSE, FALSE, FALSE, NULL);
2939 : :
2940 : : /* do initial seek, which will start the task */
2941 : 404 : GST_OBJECT_LOCK (basesrc);
2942 : 404 : event = basesrc->data.ABI.pending_seek;
2943 : 404 : basesrc->data.ABI.pending_seek = NULL;
2944 : 404 : GST_OBJECT_UNLOCK (basesrc);
2945 : :
2946 : : /* no need to unlock anything, the task is certainly
2947 : : * not running here. The perform seek code will start the task when
2948 : : * finished. */
2949 [ - + ]: 404 : if (G_UNLIKELY (!gst_base_src_perform_seek (basesrc, event, FALSE)))
2950 : 0 : goto seek_failed;
2951 : :
2952 [ + + ]: 404 : if (event)
2953 : 1 : gst_event_unref (event);
2954 : : } else {
2955 [ - + ]: 404 : GST_DEBUG_OBJECT (basesrc, "Deactivating in push mode");
2956 : : /* flush all */
2957 : 404 : gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
2958 : : /* stop the task */
2959 : 404 : gst_pad_stop_task (pad);
2960 : : /* now we can stop the source */
2961 [ - + ]: 404 : if (G_UNLIKELY (!gst_base_src_stop (basesrc)))
2962 : 0 : goto error_stop;
2963 : : }
2964 : 808 : return TRUE;
2965 : :
2966 : : /* ERRORS */
2967 : : no_push_activation:
2968 : : {
2969 [ - + ]: 1 : GST_WARNING_OBJECT (basesrc, "Subclass disabled push-mode activation");
2970 : 1 : return FALSE;
2971 : : }
2972 : : error_start:
2973 : : {
2974 [ - + ]: 19 : GST_WARNING_OBJECT (basesrc, "Failed to start in push mode");
2975 : 19 : return FALSE;
2976 : : }
2977 : : seek_failed:
2978 : : {
2979 [ # # ]: 0 : GST_ERROR_OBJECT (basesrc, "Failed to perform initial seek");
2980 : : /* flush all */
2981 : 0 : gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
2982 : : /* stop the task */
2983 : 0 : gst_pad_stop_task (pad);
2984 : : /* Stop the basesrc */
2985 : 0 : gst_base_src_stop (basesrc);
2986 [ # # ]: 0 : if (event)
2987 : 0 : gst_event_unref (event);
2988 : 0 : return FALSE;
2989 : : }
2990 : : error_stop:
2991 : : {
2992 [ # # ]: 0 : GST_DEBUG_OBJECT (basesrc, "Failed to stop in push mode");
2993 : 828 : return FALSE;
2994 : : }
2995 : : }
2996 : :
2997 : : static gboolean
2998 : 14 : gst_base_src_activate_pull (GstPad * pad, gboolean active)
2999 : : {
3000 : : GstBaseSrc *basesrc;
3001 : :
3002 : 14 : basesrc = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
3003 : :
3004 : : /* prepare subclass first */
3005 [ + + ]: 14 : if (active) {
3006 [ - + ]: 7 : GST_DEBUG_OBJECT (basesrc, "Activating in pull mode");
3007 [ - + ]: 7 : if (G_UNLIKELY (!gst_base_src_start (basesrc)))
3008 : 0 : goto error_start;
3009 : :
3010 : : /* if not random_access, we cannot operate in pull mode for now */
3011 [ - + ]: 7 : if (G_UNLIKELY (!gst_base_src_check_get_range (basesrc)))
3012 : 0 : goto no_get_range;
3013 : :
3014 : : /* stop flushing now but for live sources, still block in the LIVE lock when
3015 : : * we are not yet PLAYING */
3016 : 7 : gst_base_src_set_flushing (basesrc, FALSE, FALSE, FALSE, NULL);
3017 : : } else {
3018 [ - + ]: 7 : GST_DEBUG_OBJECT (basesrc, "Deactivating in pull mode");
3019 : : /* flush all, there is no task to stop */
3020 : 7 : gst_base_src_set_flushing (basesrc, TRUE, FALSE, TRUE, NULL);
3021 : :
3022 : : /* don't send EOS when going from PAUSED => READY when in pull mode */
3023 : 7 : basesrc->priv->last_sent_eos = TRUE;
3024 : :
3025 [ - + ]: 7 : if (G_UNLIKELY (!gst_base_src_stop (basesrc)))
3026 : 0 : goto error_stop;
3027 : : }
3028 : 14 : return TRUE;
3029 : :
3030 : : /* ERRORS */
3031 : : error_start:
3032 : : {
3033 [ # # ]: 0 : GST_ERROR_OBJECT (basesrc, "Failed to start in pull mode");
3034 : 0 : return FALSE;
3035 : : }
3036 : : no_get_range:
3037 : : {
3038 [ # # ]: 0 : GST_ERROR_OBJECT (basesrc, "Cannot operate in pull mode, stopping");
3039 : 0 : gst_base_src_stop (basesrc);
3040 : 0 : return FALSE;
3041 : : }
3042 : : error_stop:
3043 : : {
3044 [ # # ]: 0 : GST_ERROR_OBJECT (basesrc, "Failed to stop in pull mode");
3045 : 14 : return FALSE;
3046 : : }
3047 : : }
3048 : :
3049 : : static GstStateChangeReturn
3050 : 1529 : gst_base_src_change_state (GstElement * element, GstStateChange transition)
3051 : : {
3052 : : GstBaseSrc *basesrc;
3053 : : GstStateChangeReturn result;
3054 : 1529 : gboolean no_preroll = FALSE;
3055 : :
3056 : 1529 : basesrc = GST_BASE_SRC (element);
3057 : :
3058 [ + + + + ]: 1529 : switch (transition) {
3059 : : case GST_STATE_CHANGE_NULL_TO_READY:
3060 : 217 : break;
3061 : : case GST_STATE_CHANGE_READY_TO_PAUSED:
3062 : 431 : no_preroll = gst_base_src_is_live (basesrc);
3063 : 431 : break;
3064 : : case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3065 [ - + ]: 113 : GST_DEBUG_OBJECT (basesrc, "PAUSED->PLAYING");
3066 [ + + ]: 113 : if (gst_base_src_is_live (basesrc)) {
3067 : : /* now we can start playback */
3068 : 8 : gst_base_src_set_playing (basesrc, TRUE);
3069 : : }
3070 : 113 : break;
3071 : : default:
3072 : 768 : break;
3073 : : }
3074 : :
3075 [ + + ]: 1529 : if ((result =
3076 : 1529 : GST_ELEMENT_CLASS (parent_class)->change_state (element,
3077 : : transition)) == GST_STATE_CHANGE_FAILURE)
3078 : 20 : goto failure;
3079 : :
3080 [ + + + + ]: 1509 : switch (transition) {
3081 : : case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3082 [ - + ]: 113 : GST_DEBUG_OBJECT (basesrc, "PLAYING->PAUSED");
3083 [ + + ]: 113 : if (gst_base_src_is_live (basesrc)) {
3084 : : /* make sure we block in the live lock in PAUSED */
3085 : 8 : gst_base_src_set_playing (basesrc, FALSE);
3086 : 8 : no_preroll = TRUE;
3087 : : }
3088 : 113 : break;
3089 : : case GST_STATE_CHANGE_PAUSED_TO_READY:
3090 : : {
3091 : : GstEvent **event_p, *event;
3092 : :
3093 : : /* we don't need to unblock anything here, the pad deactivation code
3094 : : * already did this */
3095 : :
3096 : : /* FIXME, deprecate this behaviour, it is very dangerous.
3097 : : * the prefered way of sending EOS downstream is by sending
3098 : : * the EOS event to the element */
3099 [ + + ]: 411 : if (!basesrc->priv->last_sent_eos) {
3100 [ - + ]: 377 : GST_DEBUG_OBJECT (basesrc, "Sending EOS event");
3101 : 377 : event = gst_event_new_eos ();
3102 : 377 : gst_event_set_seqnum (event, basesrc->priv->seqnum);
3103 : 377 : gst_pad_push_event (basesrc->srcpad, event);
3104 : 377 : basesrc->priv->last_sent_eos = TRUE;
3105 : : }
3106 : 411 : g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
3107 : 411 : event_p = &basesrc->data.ABI.pending_seek;
3108 : 411 : gst_event_replace (event_p, NULL);
3109 : 411 : event_p = &basesrc->priv->close_segment;
3110 : 411 : gst_event_replace (event_p, NULL);
3111 : 411 : event_p = &basesrc->priv->start_segment;
3112 : 411 : gst_event_replace (event_p, NULL);
3113 : 411 : break;
3114 : : }
3115 : : case GST_STATE_CHANGE_READY_TO_NULL:
3116 : 216 : break;
3117 : : default:
3118 : 769 : break;
3119 : : }
3120 : :
3121 [ + + ][ + - ]: 1509 : if (no_preroll && result == GST_STATE_CHANGE_SUCCESS)
3122 : 20 : result = GST_STATE_CHANGE_NO_PREROLL;
3123 : :
3124 : 1509 : return result;
3125 : :
3126 : : /* ERRORS */
3127 : : failure:
3128 : : {
3129 [ - + ]: 20 : GST_DEBUG_OBJECT (basesrc, "parent failed state change");
3130 : 1529 : return result;
3131 : : }
3132 : : }
|