3 * Copyright (C) 2014 Samsung Electronics. All rights reserved.
4 * Author: Thiago Santos <thiagoss@osg.samsung.com>
6 * Copyright (C) 2021-2022 Centricular Ltd
7 * Author: Edward Hervey <edward@centricular.com>
8 * Author: Jan Schmidt <jan@centricular.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
25 #ifndef _GST_ADAPTIVE_DEMUX_PRIVATE_H_
26 #define _GST_ADAPTIVE_DEMUX_PRIVATE_H_
28 #include <gst/base/gstadapter.h>
29 #include <gst/base/gstflowcombiner.h>
31 #define NUM_LOOKBACK_FRAGMENTS 3
32 #define MAX_DOWNLOAD_ERROR_COUNT 3
34 /* Internal, so not using GST_FLOW_CUSTOM_SUCCESS_N */
35 #define GST_ADAPTIVE_DEMUX_FLOW_SWITCH (GST_FLOW_CUSTOM_SUCCESS_2 + 2)
37 #define TRACKS_GET_LOCK(d) (&GST_ADAPTIVE_DEMUX_CAST(d)->priv->tracks_lock)
38 #define TRACKS_LOCK(d) g_mutex_lock (TRACKS_GET_LOCK (d))
39 #define TRACKS_UNLOCK(d) g_mutex_unlock (TRACKS_GET_LOCK (d))
41 #define BUFFERING_GET_LOCK(d) (&GST_ADAPTIVE_DEMUX_CAST(d)->priv->buffering_lock)
42 #define BUFFERING_LOCK(d) g_mutex_lock (BUFFERING_GET_LOCK (d))
43 #define BUFFERING_UNLOCK(d) g_mutex_unlock (BUFFERING_GET_LOCK (d))
45 #define GST_MANIFEST_GET_LOCK(d) (&(GST_ADAPTIVE_DEMUX_CAST(d)->priv->manifest_lock))
46 #define GST_MANIFEST_LOCK(d) G_STMT_START { \
47 GST_TRACE("Locking manifest from thread %p", g_thread_self()); \
48 g_rec_mutex_lock (GST_MANIFEST_GET_LOCK (d)); \
49 GST_TRACE("Locked manifest from thread %p", g_thread_self()); \
52 #define GST_MANIFEST_UNLOCK(d) G_STMT_START { \
53 GST_TRACE("Unlocking manifest from thread %p", g_thread_self()); \
54 g_rec_mutex_unlock (GST_MANIFEST_GET_LOCK (d)); \
57 #define GST_ADAPTIVE_DEMUX_GET_SCHEDULER(d) (GST_ADAPTIVE_DEMUX_CAST(d)->priv->scheduler_task)
59 #define GST_ADAPTIVE_SCHEDULER_LOCK(d) gst_adaptive_demux_scheduler_lock(demux)
60 #define GST_ADAPTIVE_SCHEDULER_UNLOCK(d) G_STMT_START { \
61 GST_TRACE("Unlocking scheduler from thread %p", g_thread_self()); \
62 gst_adaptive_demux_loop_unlock_and_unpause (GST_ADAPTIVE_DEMUX_GET_SCHEDULER (d)); \
65 #define GST_ADAPTIVE_DEMUX_SEGMENT_GET_LOCK(d) (&GST_ADAPTIVE_DEMUX_CAST(d)->priv->segment_lock)
66 #define GST_ADAPTIVE_DEMUX_SEGMENT_LOCK(d) g_mutex_lock (GST_ADAPTIVE_DEMUX_SEGMENT_GET_LOCK (d))
67 #define GST_ADAPTIVE_DEMUX_SEGMENT_UNLOCK(d) g_mutex_unlock (GST_ADAPTIVE_DEMUX_SEGMENT_GET_LOCK (d))
69 struct _GstAdaptiveDemuxPrivate
71 GstAdapter *input_adapter; /* protected by manifest_lock */
72 gint have_manifest; /* MT safe */
74 /* Adaptive scheduling and parsing task */
75 GstAdaptiveDemuxLoop *scheduler_task;
77 /* Callback / timer id for the next manifest update */
78 guint manifest_updates_cb;
80 /* Count of failed manifest updates */
81 gint update_failed_count;
83 guint32 segment_seqnum; /* protected by manifest_lock */
85 /* main lock used to protect adaptive demux and all its streams.
86 * It serializes the adaptive demux public API.
88 GRecMutex manifest_lock;
90 /* Duration, updated after manifest updates */
91 GstClockTime duration;
93 /* Set to TRUE if any stream is waiting on the manifest update */
94 gboolean stream_waiting_for_manifest;
98 /* Protects demux and stream segment information
99 * Needed because seeks can update segment information
100 * without needing to stop tasks when they just want to
101 * update the segment boundaries */
104 GstClockTime qos_earliest_time;
106 /* Protects all tracks and period content */
108 /* Used to notify addition to a waiting (i.e. previously empty) track */
110 /* TRUE if we are buffering */
111 gboolean is_buffering;
112 /* TRUE if percent changed and message should be posted */
113 gboolean percent_changed;
116 /* Serialises buffering message posting to avoid out-of-order
118 GMutex buffering_lock;
121 guint32 requested_selection_seqnum;
123 /* Lock protecting all the following fields */
124 GRecMutex output_lock;
126 GstTask *output_task;
127 /* List of enabled OutputSlot */
129 /* flow combiner of output slots */
130 GstFlowCombiner *flowcombiner;
131 /* protected by output_lock */
133 /* Current output selection seqnum */
134 guint32 current_selection_seqnum;
135 /* Current output position (in running time) */
136 GstClockTimeDiff global_output_position;
137 /* End of fields protected by output_lock */
139 gint n_audio_streams, n_video_streams, n_subtitle_streams;
141 /* Counter used for uniquely identifying periods */
146 * Head is the period being outputted, or to be outputted first
147 * Tail is where new streams get added */
151 static inline gboolean gst_adaptive_demux_scheduler_lock(GstAdaptiveDemux *d)
153 GST_TRACE("Locking scheduler from thread %p", g_thread_self());
154 if (!gst_adaptive_demux_loop_pause_and_lock (GST_ADAPTIVE_DEMUX_GET_SCHEDULER (d)))
157 GST_TRACE("Locked scheduler from thread %p", g_thread_self());
161 void demux_update_buffering_locked (GstAdaptiveDemux * demux);
162 void demux_post_buffering_locked (GstAdaptiveDemux * demux);
164 GstFlowReturn gst_adaptive_demux_update_manifest (GstAdaptiveDemux *demux);
166 void gst_adaptive_demux2_stream_wants_manifest_update (GstAdaptiveDemux * demux);
168 void gst_adaptive_demux2_stream_parse_error (GstAdaptiveDemux2Stream *stream, GError * err);
169 GstClockTime gst_adaptive_demux2_stream_get_fragment_waiting_time (GstAdaptiveDemux *
170 demux, GstAdaptiveDemux2Stream * stream);
171 GstClockTime gst_adaptive_demux2_stream_get_presentation_offset (GstAdaptiveDemux * demux,
172 GstAdaptiveDemux2Stream * stream);
173 GstClockTime gst_adaptive_demux_get_period_start_time (GstAdaptiveDemux * demux);
175 gboolean gst_adaptive_demux_is_live (GstAdaptiveDemux * demux);
177 void gst_adaptive_demux2_stream_on_manifest_update (GstAdaptiveDemux2Stream * stream);
178 void gst_adaptive_demux2_stream_on_output_space_available (GstAdaptiveDemux2Stream *stream);
180 gboolean gst_adaptive_demux2_stream_has_next_fragment (GstAdaptiveDemux * demux,
181 GstAdaptiveDemux2Stream * stream);
182 GstFlowReturn gst_adaptive_demux2_stream_update_fragment_info (GstAdaptiveDemux * demux,
183 GstAdaptiveDemux2Stream * stream);
184 GstFlowReturn gst_adaptive_demux2_stream_seek (GstAdaptiveDemux * demux,
185 GstAdaptiveDemux2Stream * stream, gboolean forward, GstSeekFlags flags,
186 GstClockTimeDiff ts, GstClockTimeDiff * final_ts);
187 gboolean gst_adaptive_demux_get_live_seek_range (GstAdaptiveDemux * demux,
188 gint64 * range_start, gint64 * range_stop);
189 gboolean gst_adaptive_demux2_stream_in_live_seek_range (GstAdaptiveDemux * demux,
190 GstAdaptiveDemux2Stream * stream);
191 gboolean gst_adaptive_demux2_stream_is_selected_locked (GstAdaptiveDemux2Stream *stream);
193 gboolean gst_adaptive_demux_has_next_period (GstAdaptiveDemux * demux);
194 void gst_adaptive_demux_advance_period (GstAdaptiveDemux * demux);
196 void gst_adaptive_demux2_stream_stop (GstAdaptiveDemux2Stream * stream);
198 gboolean gst_adaptive_demux_handle_lost_sync (GstAdaptiveDemux * demux);
204 /* running time of item : GST_CLOCK_STIME_NONE for non-timed data */
205 GstClockTimeDiff runningtime;
206 /* GST_CLOCK_STIME_NONE for non-timed data */
207 GstClockTimeDiff runningtime_end;
208 /* running time of item for buffering tracking: GST_CLOCK_STIME_NONE for non-timed data */
209 GstClockTimeDiff runningtime_buffering;
212 GstAdaptiveDemux2Stream *find_stream_for_track_locked (GstAdaptiveDemux *
213 demux, GstAdaptiveDemuxTrack * track);
215 GstMiniObject * track_dequeue_data_locked (GstAdaptiveDemux * demux, GstAdaptiveDemuxTrack * track, gboolean check_sticky_events);
216 void gst_adaptive_demux_track_flush (GstAdaptiveDemuxTrack * track);
217 void gst_adaptive_demux_track_drain_to (GstAdaptiveDemuxTrack * track, GstClockTime drain_running_time);
218 void gst_adaptive_demux_track_update_next_position (GstAdaptiveDemuxTrack * track);
219 void gst_adaptive_demux_track_update_level_locked (GstAdaptiveDemuxTrack * track);
221 /* Period functions */
222 GstAdaptiveDemuxPeriod * gst_adaptive_demux_period_new (GstAdaptiveDemux * demux);
224 GstAdaptiveDemuxPeriod * gst_adaptive_demux_period_ref (GstAdaptiveDemuxPeriod * period);
225 void gst_adaptive_demux_period_unref (GstAdaptiveDemuxPeriod * period);
227 gboolean gst_adaptive_demux_period_add_track (GstAdaptiveDemuxPeriod * period,
228 GstAdaptiveDemuxTrack * track);
229 gboolean gst_adaptive_demux_track_add_elements (GstAdaptiveDemuxTrack * track,
232 void gst_adaptive_demux_period_select_default_tracks (GstAdaptiveDemux * demux,
233 GstAdaptiveDemuxPeriod * period);
234 void gst_adaptive_demux_period_transfer_selection (GstAdaptiveDemux * demux,
235 GstAdaptiveDemuxPeriod * next_period,
236 GstAdaptiveDemuxPeriod * current_period);
237 void gst_adaptive_demux_period_stop_tasks (GstAdaptiveDemuxPeriod * period);
238 GstFlowReturn gst_adaptive_demux_period_combine_stream_flows (GstAdaptiveDemuxPeriod * period);
240 gboolean gst_adaptive_demux_period_has_pending_tracks (GstAdaptiveDemuxPeriod * period);
241 void gst_adaptive_demux_period_check_input_wakeup_locked (GstAdaptiveDemuxPeriod * period, GstClockTimeDiff current_output_position);