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