3 * Copyright (C) 2014 Samsung Electronics. All rights reserved.
4 * Author: Thiago Santos <thiagoss@osg.samsung.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
22 #ifndef _GST_ADAPTIVE_DEMUX_H_
23 #define _GST_ADAPTIVE_DEMUX_H_
26 #include <gst/base/gstadapter.h>
27 #include <gst/uridownloader/gsturidownloader.h>
31 #define GST_TYPE_ADAPTIVE_DEMUX \
32 (gst_adaptive_demux_get_type())
33 #define GST_ADAPTIVE_DEMUX(obj) \
34 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ADAPTIVE_DEMUX,GstAdaptiveDemux))
35 #define GST_ADAPTIVE_DEMUX_CLASS(klass) \
36 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ADAPTIVE_DEMUX,GstAdaptiveDemuxClass))
37 #define GST_ADAPTIVE_DEMUX_GET_CLASS(obj) \
38 (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_ADAPTIVE_DEMUX,GstAdaptiveDemuxClass))
39 #define GST_IS_ADAPTIVE_DEMUX(obj) \
40 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ADAPTIVE_DEMUX))
41 #define GST_IS_ADAPTIVE_DEMUX_CLASS(obj) \
42 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ADAPTIVE_DEMUX))
43 #define GST_ADAPTIVE_DEMUX_CAST(obj) ((GstAdaptiveDemux *)obj)
45 #define GST_ADAPTIVE_DEMUX_STREAM_CAST(obj) ((GstAdaptiveDemuxStream *)obj)
48 * GST_ADAPTIVE_DEMUX_SINK_NAME:
50 * The name of the templates for the sink pad.
52 #define GST_ADAPTIVE_DEMUX_SINK_NAME "sink"
55 * GST_ADAPTIVE_DEMUX_SINK_PAD:
56 * @obj: a #GstAdaptiveDemux
58 * Gives the pointer to the sink #GstPad object of the element.
60 #define GST_ADAPTIVE_DEMUX_SINK_PAD(obj) (((GstAdaptiveDemux *) (obj))->sinkpad)
62 #define GST_ADAPTIVE_DEMUX_STREAM_PAD(obj) (((GstAdaptiveDemuxStream *) (obj))->pad)
64 #define GST_ADAPTIVE_DEMUX_STREAM_NEED_HEADER(obj) (((GstAdaptiveDemuxStream *) (obj))->need_header)
67 * GST_ADAPTIVE_DEMUX_STATISTICS_MESSAGE_NAME:
69 * Name of the ELEMENT type messages posted by dashdemux with statistics.
73 #define GST_ADAPTIVE_DEMUX_STATISTICS_MESSAGE_NAME "adaptive-streaming-statistics"
74 #ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
75 #define GST_ADAPTIVE_DEMUX_VARIANT_MESSAGE_NAME "adaptive-streaming-variant"
78 #define GST_ELEMENT_ERROR_FROM_ERROR(el, msg, err) G_STMT_START { \
79 gchar *__dbg = g_strdup_printf ("%s: %s", msg, err->message); \
80 GST_WARNING_OBJECT (el, "error: %s", __dbg); \
81 gst_element_message_full (GST_ELEMENT(el), GST_MESSAGE_ERROR, \
82 err->domain, err->code, \
83 NULL, __dbg, __FILE__, GST_FUNCTION, __LINE__); \
84 g_clear_error (&err); \
87 #define GST_ADAPTIVE_DEMUX_FLOW_END_OF_FRAGMENT GST_FLOW_CUSTOM_SUCCESS_1
88 #ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
89 #define DEFAULT_ADAPTIVE_RETRY -1
90 #define DEFAULT_ADAPTIVE_TIMEOUT -1
91 #define PLAYLIST_ADAPTIVE_RETRY 3
92 #define PLAYLIST_ADAPTIVE_TIMEOUT 2
93 #define DEFAULT_ADAPTIVE_VARIANT -1
96 typedef struct _GstAdaptiveDemuxStreamFragment GstAdaptiveDemuxStreamFragment;
97 typedef struct _GstAdaptiveDemuxStream GstAdaptiveDemuxStream;
98 typedef struct _GstAdaptiveDemux GstAdaptiveDemux;
99 typedef struct _GstAdaptiveDemuxClass GstAdaptiveDemuxClass;
100 typedef struct _GstAdaptiveDemuxPrivate GstAdaptiveDemuxPrivate;
101 #ifdef TIZEN_FEATURE_AVOID_PAD_SWITCHING
102 typedef GstPad* (*GstAdaptiveDemuxStreamCreatePadFunc)(GstAdaptiveDemuxStream * stream);
105 struct _GstAdaptiveDemuxStreamFragment
107 GstClockTime timestamp;
108 GstClockTime duration;
114 /* when chunked downloading is used, may be be updated need_another_chunk() */
117 /* when headers are needed */
119 gint64 header_range_start;
120 gint64 header_range_end;
122 /* when index is needed */
124 gint64 index_range_start;
125 gint64 index_range_end;
127 /* Nominal bitrate as provided by
128 * sub-class or calculated by base-class */
134 struct _GstAdaptiveDemuxStream
137 GstPad *internal_pad;
139 GstAdaptiveDemux *demux;
141 #ifdef TIZEN_FEATURE_AVOID_PAD_SWITCHING
142 gint stream_id_counter;
146 GstCaps *pending_caps;
147 GstEvent *pending_segment;
148 GstTagList *pending_tags;
149 gboolean need_header;
150 GList *pending_events;
152 GstFlowReturn last_ret;
155 GstTask *download_task;
156 GRecMutex download_lock;
158 gboolean restart_download;
161 gboolean downloading_first_buffer;
162 gboolean downloading_header;
163 gboolean downloading_index;
165 gboolean bitrate_changed;
167 /* download tooling */
169 guint last_status_code;
171 GstElement *uri_handler;
173 GMutex fragment_download_lock;
174 GCond fragment_download_cond;
175 gboolean download_finished; /* protected by fragment_download_lock */
176 gboolean cancelled; /* protected by fragment_download_lock */
177 gboolean src_at_ready; /* protected by fragment_download_lock */
178 gboolean starting_fragment;
179 gboolean first_fragment_buffer;
180 gint64 download_start_time;
181 gint64 download_total_bytes;
182 guint64 current_download_rate;
184 /* amount of data downloaded in current fragment (pre-queue2) */
185 guint64 fragment_bytes_downloaded;
186 /* bitrate of the previous fragment (pre-queue2) */
187 guint64 last_bitrate;
188 /* latency (request to first byte) and full download time (request to EOS)
189 * of previous fragment (pre-queue2) */
190 GstClockTime last_latency;
191 GstClockTime last_download_time;
193 /* Average for the last fragments */
194 guint64 moving_bitrate;
196 guint64 *fragment_bitrates;
198 GstAdaptiveDemuxStreamFragment fragment;
200 guint download_error_count;
202 /* TODO check if used */
205 gboolean do_block; /* TRUE if stream should block on preroll */
211 * The opaque #GstAdaptiveDemux data structure.
213 struct _GstAdaptiveDemux
220 gsize stream_struct_size;
225 GstUriDownloader *downloader;
228 GList *prepared_streams;
234 gchar *manifest_base_uri;
235 #ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
241 gfloat bitrate_limit; /* limit of the available bitrate to use */
242 guint connection_speed;
244 gboolean have_group_id;
248 GstClock *realtime_clock;
249 gint64 clock_offset; /* offset between realtime_clock and UTC (in usec) */
252 GstAdaptiveDemuxPrivate *priv;
253 #ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
261 * GstAdaptiveDemuxClass:
264 struct _GstAdaptiveDemuxClass
267 GstBinClass bin_class;
272 * process_manifest: Parse the manifest
273 * @demux: #GstAdaptiveDemux
274 * @manifest: the manifest to be parsed
276 * Parse the manifest and add the created streams using
277 * gst_adaptive_demux_stream_new()
279 * Returns: #TRUE if successful
281 gboolean (*process_manifest) (GstAdaptiveDemux * demux, GstBuffer * manifest);
284 * get_manifest_update_interval:
285 * @demux: #GstAdaptiveDemux
287 * Used during live streaming, the subclass should return the interval
288 * between successive manifest updates
290 * Returns: the update interval in microseconds
292 gint64 (*get_manifest_update_interval) (GstAdaptiveDemux * demux);
296 * @demux: #GstAdaptiveDemux
298 * During live streaming, this will be called for the subclass to update its
299 * manifest with the new version. By default it fetches the manifest URI
300 * and passes it to GstAdaptiveDemux::update_manifest_data().
302 * Returns: #GST_FLOW_OK is all succeeded, #GST_FLOW_EOS if the stream ended
303 * or #GST_FLOW_ERROR if an error happened
305 GstFlowReturn (*update_manifest) (GstAdaptiveDemux * demux);
308 * update_manifest_data:
309 * @demux: #GstAdaptiveDemux
310 * @buf: Downloaded manifest data
312 * During live streaming, this will be called for the subclass to update its
313 * manifest with the new version
315 * Returns: #GST_FLOW_OK is all succeeded, #GST_FLOW_EOS if the stream ended
316 * or #GST_FLOW_ERROR if an error happened
318 GstFlowReturn (*update_manifest_data) (GstAdaptiveDemux * demux, GstBuffer * buf);
320 gboolean (*is_live) (GstAdaptiveDemux * demux);
321 GstClockTime (*get_duration) (GstAdaptiveDemux * demux);
325 * @demux: #GstAdaptiveDemux
327 * Reset the internal state of the subclass, getting ready to restart with
328 * a new stream afterwards
330 void (*reset) (GstAdaptiveDemux * demux);
334 * @demux: #GstAdaptiveDemux
335 * @seek: a seek #GstEvent
337 * The demuxer should seek on all its streams to the specified position
340 * Returns: #TRUE if successful
342 gboolean (*seek) (GstAdaptiveDemux * demux, GstEvent * seek);
346 * @demux: #GstAdaptiveDemux
348 * Checks if there is a next period following the current one.
349 * DASH can have multiple medias chained in its manifest, when one finishes
350 * this function is called to verify if there is a new period to be played
353 * Returns: #TRUE if there is another period
355 gboolean (*has_next_period) (GstAdaptiveDemux * demux);
358 * @demux: #GstAdaptiveDemux
360 * Advances the manifest to the next period. New streams should be created
361 * using gst_adaptive_demux_stream_new().
363 void (*advance_period) (GstAdaptiveDemux * demux);
365 void (*stream_free) (GstAdaptiveDemuxStream * stream);
366 GstFlowReturn (*stream_seek) (GstAdaptiveDemuxStream * stream, gboolean forward, GstSeekFlags flags, GstClockTime target_ts, GstClockTime * final_ts);
367 gboolean (*stream_has_next_fragment) (GstAdaptiveDemuxStream * stream);
368 GstFlowReturn (*stream_advance_fragment) (GstAdaptiveDemuxStream * stream);
371 * need_another_chunk:
372 * @stream: #GstAdaptiveDemuxStream
374 * If chunked downloading is used (chunk_size != 0) this is called once as
375 * chunk is finished to decide whether more has to be downloaded or not.
376 * May update chunk_size to a different value
378 gboolean (*need_another_chunk) (GstAdaptiveDemuxStream * stream);
381 * stream_update_fragment_info:
382 * @stream: #GstAdaptiveDemuxStream
384 * Requests the stream to set the information about the current fragment to its
385 * current fragment struct
387 * Returns: #GST_FLOW_OK in success, #GST_FLOW_ERROR on error and #GST_FLOW_EOS
388 * if there is no fragment.
390 GstFlowReturn (*stream_update_fragment_info) (GstAdaptiveDemuxStream * stream);
392 * stream_select_bitrate:
393 * @stream: #GstAdaptiveDemuxStream
394 * @bitrate: the bitrate to select (in bytes per second)
396 * The stream should try to select the bitrate that is the greater, but not
397 * greater than the requested bitrate. If it needs a codec change it should
398 * create the new stream using gst_adaptive_demux_stream_new(). If it only
399 * needs a caps change it should set the new caps using
400 * gst_adaptive_demux_stream_set_caps().
402 * Returns: #TRUE if the stream changed bitrate, #FALSE otherwise
404 gboolean (*stream_select_bitrate) (GstAdaptiveDemuxStream * stream, guint64 bitrate);
406 * stream_get_fragment_waiting_time:
407 * @stream: #GstAdaptiveDemuxStream
409 * For live streams, requests how much time should be waited before starting
410 * to download the fragment. This is useful to avoid downloading a fragment that
411 * isn't available yet.
413 * Returns: The waiting time in microsseconds
415 gint64 (*stream_get_fragment_waiting_time) (GstAdaptiveDemuxStream * stream);
419 * @demux: #GstAdaptiveDemux
420 * @stream: #GstAdaptiveDemuxStream
422 * Notifies the subclass that the given stream is starting the download
423 * of a new fragment. Can be used to reset/init internal state that is
424 * needed before each fragment, like decryption engines.
426 * Returns: #TRUE if successful.
428 gboolean (*start_fragment) (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream);
431 * @demux: #GstAdaptiveDemux
432 * @stream: #GstAdaptiveDemuxStream
434 * Notifies the subclass that a fragment download was finished.
435 * It can be used to cleanup internal state after a fragment and
436 * also push any pending data before moving to the next fragment.
438 GstFlowReturn (*finish_fragment) (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream);
441 * @demux: #GstAdaptiveDemux
442 * @stream: #GstAdaptiveDemuxStream
443 * @buffer: #GstBuffer
445 * Notifies the subclass that a fragment chunk was downloaded. The subclass
446 * can look at the data and modify/push data as desired.
448 * Returns: #GST_FLOW_OK if successful, #GST_FLOW_ERROR in case of error.
450 GstFlowReturn (*data_received) (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
453 * get_live_seek_range:
454 * @demux: #GstAdaptiveDemux
455 * @start: pointer to put the start position allowed to seek to
456 * @stop: pointer to put the stop position allowed to seek to
458 * Gets the allowed seek start and stop positions for the current live stream
460 * Return: %TRUE if successful
462 gboolean (*get_live_seek_range) (GstAdaptiveDemux * demux, gint64 * start, gint64 * stop);
465 * get_presentation_offset:
466 * @demux: #GstAdaptiveDemux
467 * @stream: #GstAdaptiveDemuxStream
469 * Gets the delay to apply to @stream.
471 * Return: a #GstClockTime representing the (positive) time offset to apply to
474 GstClockTime (*get_presentation_offset) (GstAdaptiveDemux *demux, GstAdaptiveDemuxStream *stream);
477 * get_period_start_time:
478 * @demux: #GstAdaptiveDemux
480 * Gets the start time of the current period. Timestamps are resetting to 0
481 * after each period but we have to maintain a continuous stream and running
482 * time so need to know the start time of the current period.
484 * Return: a #GstClockTime representing the start time of the currently
487 GstClockTime (*get_period_start_time) (GstAdaptiveDemux *demux);
490 * requires_periodical_playlist_update:
491 * @demux: #GstAdaptiveDemux
493 * Some adaptive streaming protocols allow the client to download
494 * the playlist once and build up the fragment list based on the
495 * current fragment metadata. For those protocols the demuxer
496 * doesn't need to periodically refresh the playlist. This vfunc
497 * is relevant only for live playback scenarios.
499 * Return: %TRUE if the playlist needs to be refreshed periodically by the demuxer.
501 gboolean (*requires_periodical_playlist_update) (GstAdaptiveDemux * demux);
504 GType gst_adaptive_demux_get_type (void);
506 void gst_adaptive_demux_set_stream_struct_size (GstAdaptiveDemux * demux,
510 GstAdaptiveDemuxStream *gst_adaptive_demux_stream_new (GstAdaptiveDemux * demux,
512 GstAdaptiveDemuxStream *gst_adaptive_demux_find_stream_for_pad (GstAdaptiveDemux * demux,
514 void gst_adaptive_demux_stream_set_caps (GstAdaptiveDemuxStream * stream,
516 void gst_adaptive_demux_stream_set_tags (GstAdaptiveDemuxStream * stream,
518 void gst_adaptive_demux_stream_fragment_clear (GstAdaptiveDemuxStreamFragment * f);
520 GstFlowReturn gst_adaptive_demux_stream_push_buffer (GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
522 gst_adaptive_demux_stream_advance_fragment (GstAdaptiveDemux * demux,
523 GstAdaptiveDemuxStream * stream, GstClockTime duration);
524 void gst_adaptive_demux_stream_queue_event (GstAdaptiveDemuxStream * stream,
527 GstClockTime gst_adaptive_demux_get_monotonic_time (GstAdaptiveDemux * demux);
528 GDateTime *gst_adaptive_demux_get_client_now_utc (GstAdaptiveDemux * demux);
530 #ifdef TIZEN_FEATURE_AVOID_PAD_SWITCHING
531 gboolean gst_adaptive_demux_stream_check_switch_pad (GstAdaptiveDemuxStream * stream,
532 GstCaps * caps, GstAdaptiveDemuxStreamCreatePadFunc create_pad_func);