adaptivedemux2: Remove scheduler_lock mutex
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / ext / adaptivedemux2 / gstadaptivedemux-private.h
1 /* GStreamer
2  *
3  * Copyright (C) 2014 Samsung Electronics. All rights reserved.
4  *   Author: Thiago Santos <thiagoss@osg.samsung.com>
5  *
6  * Copyright (C) 2021-2022 Centricular Ltd
7  *   Author: Edward Hervey <edward@centricular.com>
8  *   Author: Jan Schmidt <jan@centricular.com>
9  *
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.
14  *
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.
19  *
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.
24  */
25 #ifndef _GST_ADAPTIVE_DEMUX_PRIVATE_H_
26 #define _GST_ADAPTIVE_DEMUX_PRIVATE_H_
27
28 #include <gst/base/gstadapter.h>
29 #include <gst/base/gstflowcombiner.h>
30
31 #define NUM_LOOKBACK_FRAGMENTS 3
32 #define MAX_DOWNLOAD_ERROR_COUNT 3
33
34 /* Internal, so not using GST_FLOW_CUSTOM_SUCCESS_N */
35 #define GST_ADAPTIVE_DEMUX_FLOW_SWITCH (GST_FLOW_CUSTOM_SUCCESS_2 + 2)
36
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))
40
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))
44
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()); \
50  } G_STMT_END
51
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)); \
55  } G_STMT_END
56
57 #define GST_ADAPTIVE_DEMUX_GET_SCHEDULER(d) (GST_ADAPTIVE_DEMUX_CAST(d)->priv->scheduler_task)
58
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)); \
63  } G_STMT_END
64
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))
68
69 struct _GstAdaptiveDemuxPrivate
70 {
71   GstAdapter *input_adapter;    /* protected by manifest_lock */
72   gint have_manifest;           /* MT safe */
73
74   /* Adaptive scheduling and parsing task */
75   GstAdaptiveDemuxLoop *scheduler_task;
76
77   /* Callback / timer id for the next manifest update */
78   guint manifest_updates_cb;
79
80   /* Count of failed manifest updates */
81   gint update_failed_count;
82
83   guint32 segment_seqnum;       /* protected by manifest_lock */
84
85   /* main lock used to protect adaptive demux and all its streams.
86    * It serializes the adaptive demux public API.
87    */
88   GRecMutex manifest_lock;
89
90   /* Duration, updated after manifest updates */
91   GstClockTime duration;
92
93   /* Set to TRUE if any stream is waiting on the manifest update */
94   gboolean stream_waiting_for_manifest;
95
96   GMutex api_lock;
97
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 */
102   GMutex segment_lock;
103
104   GstClockTime qos_earliest_time;
105
106   /* Protects all tracks and period content */
107   GMutex tracks_lock;
108   /* Used to notify addition to a waiting (i.e. previously empty) track */
109   GCond tracks_add;
110   /* TRUE if we are buffering */
111   gboolean is_buffering;
112   /* TRUE if percent changed and message should be posted */
113   gboolean percent_changed;
114   gint percent;
115
116   /* Serialises buffering message posting to avoid out-of-order
117    * posting */
118   GMutex buffering_lock;
119
120   /* Atomic */
121   guint32 requested_selection_seqnum;
122
123   /* Lock protecting all the following fields */
124   GRecMutex output_lock;
125   /* Output task */
126   GstTask *output_task;
127   /* List of enabled OutputSlot */
128   GList *outputs;
129   /* flow combiner of output slots */
130   GstFlowCombiner *flowcombiner;
131   /* protected by output_lock */
132   gboolean flushing;
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 */
138
139   gint n_audio_streams, n_video_streams, n_subtitle_streams;
140
141   /* Counter used for uniquely identifying periods */
142   gint n_periods;
143
144   /* Array of periods.
145    *
146    * Head is the period being outputted, or to be outputted first
147    * Tail is where new streams get added */
148   GQueue *periods;
149 };
150
151 static inline gboolean gst_adaptive_demux_scheduler_lock(GstAdaptiveDemux *d)
152 {
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)))
155       return FALSE;
156
157     GST_TRACE("Locked scheduler from thread %p", g_thread_self());
158     return TRUE;
159 }
160
161 void demux_update_buffering_locked (GstAdaptiveDemux * demux);
162 void demux_post_buffering_locked (GstAdaptiveDemux * demux);
163
164 GstFlowReturn gst_adaptive_demux_update_manifest (GstAdaptiveDemux *demux);
165
166 void gst_adaptive_demux2_stream_wants_manifest_update (GstAdaptiveDemux * demux);
167
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);
174
175 gboolean gst_adaptive_demux_is_live (GstAdaptiveDemux * demux);
176
177 void gst_adaptive_demux2_stream_on_manifest_update (GstAdaptiveDemux2Stream * stream);
178 void gst_adaptive_demux2_stream_on_output_space_available (GstAdaptiveDemux2Stream *stream);
179
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);
192
193 gboolean gst_adaptive_demux_has_next_period (GstAdaptiveDemux * demux);
194 void gst_adaptive_demux_advance_period (GstAdaptiveDemux * demux);
195
196 void gst_adaptive_demux2_stream_stop (GstAdaptiveDemux2Stream * stream);
197
198 gboolean gst_adaptive_demux_handle_lost_sync (GstAdaptiveDemux * demux);
199
200 typedef struct
201 {
202   GstMiniObject *item;
203   gsize size;
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;
210 } TrackQueueItem;
211
212 GstAdaptiveDemux2Stream *find_stream_for_track_locked (GstAdaptiveDemux *
213     demux, GstAdaptiveDemuxTrack * track);
214
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);
220
221 /* Period functions */
222 GstAdaptiveDemuxPeriod * gst_adaptive_demux_period_new (GstAdaptiveDemux * demux);
223
224 GstAdaptiveDemuxPeriod * gst_adaptive_demux_period_ref (GstAdaptiveDemuxPeriod * period);
225 void                     gst_adaptive_demux_period_unref (GstAdaptiveDemuxPeriod * period);
226
227 gboolean                 gst_adaptive_demux_period_add_track (GstAdaptiveDemuxPeriod * period,
228                                                               GstAdaptiveDemuxTrack * track);
229 gboolean                 gst_adaptive_demux_track_add_elements (GstAdaptiveDemuxTrack * track,
230                                                                 guint period_num);
231
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);
239
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);
242
243 #endif