• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  *
3  * Copyright (C) 2014 Samsung Electronics. All rights reserved.
4  *   Author: Thiago Santos <thiagoss@osg.samsung.com>
5  *
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.
10  *
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.
15  *
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.
20  */
21 
22 #ifndef _GST_ADAPTIVE_DEMUX_H_
23 #define _GST_ADAPTIVE_DEMUX_H_
24 
25 #include <gst/gst.h>
26 #include <gst/base/gstadapter.h>
27 #include <gst/uridownloader/gsturidownloader.h>
28 #include <gst/adaptivedemux/adaptive-demux-prelude.h>
29 
30 G_BEGIN_DECLS
31 
32 #define GST_TYPE_ADAPTIVE_DEMUX \
33   (gst_adaptive_demux_get_type())
34 #define GST_ADAPTIVE_DEMUX(obj) \
35   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ADAPTIVE_DEMUX,GstAdaptiveDemux))
36 #define GST_ADAPTIVE_DEMUX_CLASS(klass) \
37   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ADAPTIVE_DEMUX,GstAdaptiveDemuxClass))
38 #define GST_ADAPTIVE_DEMUX_GET_CLASS(obj) \
39   (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_ADAPTIVE_DEMUX,GstAdaptiveDemuxClass))
40 #define GST_IS_ADAPTIVE_DEMUX(obj) \
41   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ADAPTIVE_DEMUX))
42 #define GST_IS_ADAPTIVE_DEMUX_CLASS(obj) \
43   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ADAPTIVE_DEMUX))
44 #define GST_ADAPTIVE_DEMUX_CAST(obj) ((GstAdaptiveDemux *)obj)
45 
46 #define GST_ADAPTIVE_DEMUX_STREAM_CAST(obj) ((GstAdaptiveDemuxStream *)obj)
47 
48 /**
49  * GST_ADAPTIVE_DEMUX_SINK_NAME:
50  *
51  * The name of the templates for the sink pad.
52  */
53 #define GST_ADAPTIVE_DEMUX_SINK_NAME    "sink"
54 
55 /**
56  * GST_ADAPTIVE_DEMUX_SINK_PAD:
57  * @obj: a #GstAdaptiveDemux
58  *
59  * Gives the pointer to the sink #GstPad object of the element.
60  */
61 #define GST_ADAPTIVE_DEMUX_SINK_PAD(obj)        (((GstAdaptiveDemux *) (obj))->sinkpad)
62 
63 #define GST_ADAPTIVE_DEMUX_IN_TRICKMODE_KEY_UNITS(obj) ((((GstAdaptiveDemux*)(obj))->segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS) == GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)
64 
65 #define GST_ADAPTIVE_DEMUX_STREAM_PAD(obj)      (((GstAdaptiveDemuxStream *) (obj))->pad)
66 
67 #define GST_ADAPTIVE_DEMUX_STREAM_NEED_HEADER(obj) (((GstAdaptiveDemuxStream *) (obj))->need_header)
68 
69 /**
70  * GST_ADAPTIVE_DEMUX_STATISTICS_MESSAGE_NAME:
71  *
72  * Name of the ELEMENT type messages posted by dashdemux with statistics.
73  *
74  * Since: 1.6
75  */
76 #define GST_ADAPTIVE_DEMUX_STATISTICS_MESSAGE_NAME "adaptive-streaming-statistics"
77 
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); \
85 } G_STMT_END
86 
87 /* DEPRECATED */
88 #define GST_ADAPTIVE_DEMUX_FLOW_END_OF_FRAGMENT GST_FLOW_CUSTOM_SUCCESS_1
89 
90 typedef struct _GstAdaptiveDemuxStreamFragment GstAdaptiveDemuxStreamFragment;
91 typedef struct _GstAdaptiveDemuxStream GstAdaptiveDemuxStream;
92 typedef struct _GstAdaptiveDemux GstAdaptiveDemux;
93 typedef struct _GstAdaptiveDemuxClass GstAdaptiveDemuxClass;
94 typedef struct _GstAdaptiveDemuxPrivate GstAdaptiveDemuxPrivate;
95 
96 #ifdef OHOS_EXT_FUNC
97 // ohos.ext.func.0028
98 typedef struct _GstAdaptiveDemuxBitrateInfo GstAdaptiveDemuxBitrateInfo;
99 struct _GstAdaptiveDemuxBitrateInfo {
100   guint *bitrate_list;
101   guint bitrate_num;
102 };
103 #endif
104 
105 struct _GstAdaptiveDemuxStreamFragment
106 {
107   GstClockTime timestamp;
108   GstClockTime duration;
109 
110   gchar *uri;
111   gint64 range_start;
112   gint64 range_end;
113 
114   /* when chunked downloading is used, may be be updated need_another_chunk() */
115   guint chunk_size;
116 
117   /* when headers are needed */
118   gchar *header_uri;
119   gint64 header_range_start;
120   gint64 header_range_end;
121 
122   /* when index is needed */
123   gchar *index_uri;
124   gint64 index_range_start;
125   gint64 index_range_end;
126 
127   /* Nominal bitrate as provided by
128    * sub-class or calculated by base-class */
129   guint bitrate;
130 
131   gboolean finished;
132 };
133 
134 struct _GstAdaptiveDemuxStream
135 {
136   GstPad *pad;
137   GstPad *internal_pad;
138 
139   GstAdaptiveDemux *demux;
140 
141   GstSegment segment;
142 
143   GstCaps *pending_caps;
144   GstEvent *pending_segment;
145   GstTagList *pending_tags;
146   gboolean need_header;
147   GList *pending_events;
148 
149   GstFlowReturn last_ret;
150   GError *last_error;
151 
152   GstTask *download_task;
153   GRecMutex download_lock;
154 
155   gboolean restart_download;
156   gboolean discont;
157 
158   gboolean downloading_first_buffer;
159   gboolean downloading_header;
160   gboolean downloading_index;
161 
162   gboolean bitrate_changed;
163 
164   /* download tooling */
165   GstElement *src;
166   guint last_status_code;
167   GstPad *src_srcpad;
168   GstElement *uri_handler;
169   GstElement *queue;
170   GMutex fragment_download_lock;
171   GCond fragment_download_cond;
172   gboolean download_finished;   /* protected by fragment_download_lock */
173   gboolean cancelled; /* protected by fragment_download_lock */
174   gboolean replaced; /* replaced in a bitrate switch (used with cancelled) */
175   gboolean src_at_ready;     /* protected by fragment_download_lock */
176   gboolean starting_fragment;
177   gboolean first_fragment_buffer;
178   gint64 download_start_time;
179   gint64 download_total_bytes;
180   guint64 current_download_rate;
181 
182   /* amount of data downloaded in current fragment (pre-queue2) */
183   guint64 fragment_bytes_downloaded;
184   /* bitrate of the previous fragment (pre-queue2) */
185   guint64 last_bitrate;
186   /* latency (request to first byte) and full download time (request to EOS)
187    * of previous fragment (pre-queue2) */
188   GstClockTime last_latency;
189   GstClockTime last_download_time;
190 
191   /* Average for the last fragments */
192   guint64 moving_bitrate;
193   guint moving_index;
194   guint64 *fragment_bitrates;
195 
196   /* QoS data : UNUSED !!! */
197   GstClockTime qos_earliest_time;
198 
199   GstAdaptiveDemuxStreamFragment fragment;
200 
201   guint download_error_count;
202 
203   /* TODO check if used */
204   gboolean eos;
205 
206   gboolean do_block; /* TRUE if stream should block on preroll */
207 
208 #ifdef OHOS_EXT_FUNC
209   // ohos.ext.func.0033
210   gint errcode;
211 #endif
212 };
213 
214 /**
215  * GstAdaptiveDemux:
216  *
217  * The opaque #GstAdaptiveDemux data structure.
218  */
219 struct _GstAdaptiveDemux
220 {
221   /*< private >*/
222   GstBin     bin;
223 
224   gint running;
225 
226   gsize stream_struct_size;
227 
228   /*< protected >*/
229   GstPad         *sinkpad;
230 
231   GstUriDownloader *downloader;
232 
233   GList *streams;
234   GList *prepared_streams;
235   GList *next_streams;
236 
237   GstSegment segment;
238 
239   gchar *manifest_uri;
240   gchar *manifest_base_uri;
241 
242   /* Properties */
243   gfloat bitrate_limit;         /* limit of the available bitrate to use */
244   guint connection_speed;
245 #ifdef OHOS_EXT_FUNC
246   // ohos.ext.func.0043 Clear data in the multiqueue to speed up switching bitrate
247   GstClockTime slice_position;
248 #endif
249 
250   gboolean have_group_id;
251   guint group_id;
252 
253   /* Realtime clock */
254   GstClock *realtime_clock;
255   gint64 clock_offset; /* offset between realtime_clock and UTC (in usec) */
256 
257   /* < private > */
258   GstAdaptiveDemuxPrivate *priv;
259 };
260 
261 /**
262  * GstAdaptiveDemuxClass:
263  *
264  */
265 struct _GstAdaptiveDemuxClass
266 {
267   /*< private >*/
268   GstBinClass bin_class;
269 
270   /*< public >*/
271 
272   /**
273    * process_manifest: Parse the manifest
274    * @demux: #GstAdaptiveDemux
275    * @manifest: the manifest to be parsed
276    *
277    * Parse the manifest and add the created streams using
278    * gst_adaptive_demux_stream_new()
279    *
280    * Returns: %TRUE if successful
281    */
282   gboolean      (*process_manifest) (GstAdaptiveDemux * demux, GstBuffer * manifest);
283 
284   /**
285    * get_manifest_update_interval:
286    * @demux: #GstAdaptiveDemux
287    *
288    * Used during live streaming, the subclass should return the interval
289    * between successive manifest updates
290    *
291    * Returns: the update interval in microseconds
292    */
293   gint64        (*get_manifest_update_interval) (GstAdaptiveDemux * demux);
294 
295   /**
296    * update_manifest:
297    * @demux: #GstAdaptiveDemux
298    *
299    * During live streaming, this will be called for the subclass to update its
300    * manifest with the new version. By default it fetches the manifest URI
301    * and passes it to GstAdaptiveDemux::update_manifest_data().
302    *
303    * Returns: #GST_FLOW_OK is all succeeded, #GST_FLOW_EOS if the stream ended
304    *          or #GST_FLOW_ERROR if an error happened
305    */
306   GstFlowReturn (*update_manifest) (GstAdaptiveDemux * demux);
307 
308   /**
309    * update_manifest_data:
310    * @demux: #GstAdaptiveDemux
311    * @buf: Downloaded manifest data
312    *
313    * During live streaming, this will be called for the subclass to update its
314    * manifest with the new version
315    *
316    * Returns: #GST_FLOW_OK is all succeeded, #GST_FLOW_EOS if the stream ended
317    *          or #GST_FLOW_ERROR if an error happened
318    */
319   GstFlowReturn (*update_manifest_data) (GstAdaptiveDemux * demux, GstBuffer * buf);
320 
321   gboolean      (*is_live)          (GstAdaptiveDemux * demux);
322   GstClockTime  (*get_duration)     (GstAdaptiveDemux * demux);
323 
324   /**
325    * reset:
326    * @demux: #GstAdaptiveDemux
327    *
328    * Reset the internal state of the subclass, getting ready to restart with
329    * a new stream afterwards
330    */
331   void          (*reset)            (GstAdaptiveDemux * demux);
332 
333   /**
334    * seek:
335    * @demux: #GstAdaptiveDemux
336    * @seek: a seek #GstEvent
337    *
338    * The demuxer should seek on all its streams to the specified position
339    * in the seek event
340    *
341    * Returns: %TRUE if successful
342    */
343   gboolean      (*seek)             (GstAdaptiveDemux * demux, GstEvent * seek);
344 
345   /**
346    * has_next_period:
347    * @demux: #GstAdaptiveDemux
348    *
349    * Checks if there is a next period following the current one.
350    * DASH can have multiple medias chained in its manifest, when one finishes
351    * this function is called to verify if there is a new period to be played
352    * in sequence.
353    *
354    * Returns: %TRUE if there is another period
355    */
356   gboolean      (*has_next_period)  (GstAdaptiveDemux * demux);
357   /**
358    * advance_period:
359    * @demux: #GstAdaptiveDemux
360    *
361    * Advances the manifest to the next period. New streams should be created
362    * using gst_adaptive_demux_stream_new().
363    */
364   void          (*advance_period)  (GstAdaptiveDemux * demux);
365 
366   void          (*stream_free)     (GstAdaptiveDemuxStream * stream);
367   GstFlowReturn (*stream_seek)     (GstAdaptiveDemuxStream * stream, gboolean forward, GstSeekFlags flags, GstClockTime target_ts, GstClockTime * final_ts);
368   gboolean      (*stream_has_next_fragment)  (GstAdaptiveDemuxStream * stream);
369   GstFlowReturn (*stream_advance_fragment) (GstAdaptiveDemuxStream * stream);
370 
371   /**
372    * need_another_chunk:
373    * @stream: #GstAdaptiveDemuxStream
374    *
375    * If chunked downloading is used (chunk_size != 0) this is called once a
376    * chunk is finished to decide whether more has to be downloaded or not.
377    * May update chunk_size to a different value
378    */
379   gboolean      (*need_another_chunk) (GstAdaptiveDemuxStream * stream);
380 
381   /**
382    * stream_update_fragment_info:
383    * @stream: #GstAdaptiveDemuxStream
384    *
385    * Requests the stream to set the information about the current fragment to its
386    * current fragment struct
387    *
388    * Returns: #GST_FLOW_OK in success, #GST_FLOW_ERROR on error and #GST_FLOW_EOS
389    *          if there is no fragment.
390    */
391   GstFlowReturn (*stream_update_fragment_info) (GstAdaptiveDemuxStream * stream);
392   /**
393    * stream_select_bitrate:
394    * @stream: #GstAdaptiveDemuxStream
395    * @bitrate: the bitrate to select (in bytes per second)
396    *
397    * The stream should try to select the bitrate that is the greater, but not
398    * greater than the requested bitrate. If it needs a codec change it should
399    * create the new stream using gst_adaptive_demux_stream_new(). If it only
400    * needs a caps change it should set the new caps using
401    * gst_adaptive_demux_stream_set_caps().
402    *
403    * Returns: %TRUE if the stream changed bitrate, %FALSE otherwise
404    */
405   gboolean      (*stream_select_bitrate) (GstAdaptiveDemuxStream * stream, guint64 bitrate);
406   /**
407    * stream_get_fragment_waiting_time:
408    * @stream: #GstAdaptiveDemuxStream
409    *
410    * For live streams, requests how much time should be waited before starting
411    * to download the fragment. This is useful to avoid downloading a fragment that
412    * isn't available yet.
413    *
414    * Returns: The waiting time in microseconds
415    */
416   gint64        (*stream_get_fragment_waiting_time) (GstAdaptiveDemuxStream * stream);
417 
418 #ifdef OHOS_EXT_FUNC
419   // ohos.ext.func.0042 report selectBitrateDone
420   gint          (*get_current_bandwidth) (GstAdaptiveDemuxStream * stream);
421   guint64       (*get_current_position) (GstAdaptiveDemuxStream * stream);
422 #endif
423 
424   /**
425    * start_fragment:
426    * @demux: #GstAdaptiveDemux
427    * @stream: #GstAdaptiveDemuxStream
428    *
429    * Notifies the subclass that the given stream is starting the download
430    * of a new fragment. Can be used to reset/init internal state that is
431    * needed before each fragment, like decryption engines.
432    *
433    * Returns: %TRUE if successful.
434    */
435   gboolean      (*start_fragment) (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream);
436   /**
437    * finish_fragment:
438    * @demux: #GstAdaptiveDemux
439    * @stream: #GstAdaptiveDemuxStream
440    *
441    * Notifies the subclass that a fragment download was finished.
442    * It can be used to cleanup internal state after a fragment and
443    * also push any pending data before moving to the next fragment.
444    */
445   GstFlowReturn (*finish_fragment) (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream);
446   /**
447    * data_received:
448    * @demux: #GstAdaptiveDemux
449    * @stream: #GstAdaptiveDemuxStream
450    * @buffer: #GstBuffer
451    *
452    * Notifies the subclass that a fragment chunk was downloaded. The subclass
453    * can look at the data and modify/push data as desired.
454    *
455    * Returns: #GST_FLOW_OK if successful, #GST_FLOW_ERROR in case of error.
456    */
457   GstFlowReturn (*data_received) (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
458 
459   /**
460    * get_live_seek_range:
461    * @demux: #GstAdaptiveDemux
462    * @start: pointer to put the start position allowed to seek to
463    * @stop: pointer to put the stop position allowed to seek to
464    *
465    * Gets the allowed seek start and stop positions for the current live stream
466    *
467    * Return: %TRUE if successful
468    */
469   gboolean (*get_live_seek_range) (GstAdaptiveDemux * demux, gint64 * start, gint64 * stop);
470 
471   /**
472    * get_presentation_offset:
473    * @demux: #GstAdaptiveDemux
474    * @stream: #GstAdaptiveDemuxStream
475    *
476    * Gets the delay to apply to @stream.
477    *
478    * Return: a #GstClockTime representing the (positive) time offset to apply to
479    * @stream.
480    */
481   GstClockTime (*get_presentation_offset) (GstAdaptiveDemux *demux, GstAdaptiveDemuxStream *stream);
482 
483   /**
484    * get_period_start_time:
485    * @demux: #GstAdaptiveDemux
486    *
487    * Gets the start time of the current period. Timestamps are resetting to 0
488    * after each period but we have to maintain a continuous stream and running
489    * time so need to know the start time of the current period.
490    *
491    * Return: a #GstClockTime representing the start time of the currently
492    * selected period.
493    */
494   GstClockTime (*get_period_start_time) (GstAdaptiveDemux *demux);
495 
496   /**
497    * requires_periodical_playlist_update:
498    * @demux: #GstAdaptiveDemux
499    *
500    * Some adaptive streaming protocols allow the client to download
501    * the playlist once and build up the fragment list based on the
502    * current fragment metadata. For those protocols the demuxer
503    * doesn't need to periodically refresh the playlist. This vfunc
504    * is relevant only for live playback scenarios.
505    *
506    * Return: %TRUE if the playlist needs to be refreshed periodically by the demuxer.
507    */
508   gboolean (*requires_periodical_playlist_update) (GstAdaptiveDemux * demux);
509 
510 #ifdef OHOS_EXT_FUNC
511   // ohos.ext.func.0028
512   gboolean (*get_bitrate_info) (GstAdaptiveDemux *demux, GstAdaptiveDemuxBitrateInfo * bitrate_info);
513 #endif
514 };
515 
516 GST_ADAPTIVE_DEMUX_API
517 GType    gst_adaptive_demux_get_type (void);
518 
519 GST_ADAPTIVE_DEMUX_API
520 void     gst_adaptive_demux_set_stream_struct_size (GstAdaptiveDemux * demux,
521                                                     gsize struct_size);
522 
523 
524 GST_ADAPTIVE_DEMUX_API
525 GstAdaptiveDemuxStream *gst_adaptive_demux_stream_new (GstAdaptiveDemux * demux,
526                                                        GstPad * pad);
527 
528 GST_ADAPTIVE_DEMUX_API
529 GstAdaptiveDemuxStream *gst_adaptive_demux_find_stream_for_pad (GstAdaptiveDemux * demux,
530                                                                 GstPad * pad);
531 
532 GST_ADAPTIVE_DEMUX_API
533 void gst_adaptive_demux_stream_set_caps (GstAdaptiveDemuxStream * stream,
534                                          GstCaps * caps);
535 
536 GST_ADAPTIVE_DEMUX_API
537 void gst_adaptive_demux_stream_set_tags (GstAdaptiveDemuxStream * stream,
538                                          GstTagList * tags);
539 
540 GST_ADAPTIVE_DEMUX_API
541 void gst_adaptive_demux_stream_fragment_clear (GstAdaptiveDemuxStreamFragment * f);
542 
543 GST_ADAPTIVE_DEMUX_API
544 GstFlowReturn gst_adaptive_demux_stream_push_buffer (GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
545 
546 GST_ADAPTIVE_DEMUX_API
547 GstFlowReturn
548 gst_adaptive_demux_stream_advance_fragment (GstAdaptiveDemux * demux,
549     GstAdaptiveDemuxStream * stream, GstClockTime duration);
550 
551 GST_ADAPTIVE_DEMUX_API
552 void gst_adaptive_demux_stream_queue_event (GstAdaptiveDemuxStream * stream,
553     GstEvent * event);
554 
555 GST_ADAPTIVE_DEMUX_API
556 GstClockTime gst_adaptive_demux_get_monotonic_time (GstAdaptiveDemux * demux);
557 
558 GST_ADAPTIVE_DEMUX_API
559 GDateTime *gst_adaptive_demux_get_client_now_utc (GstAdaptiveDemux * demux);
560 
561 GST_ADAPTIVE_DEMUX_API
562 gboolean gst_adaptive_demux_is_running (GstAdaptiveDemux * demux);
563 
564 GST_ADAPTIVE_DEMUX_API
565 GstClockTime gst_adaptive_demux_get_qos_earliest_time (GstAdaptiveDemux *demux);
566 
567 G_END_DECLS
568 
569 #endif
570 
571