dashdemux: port to adaptive demux

This commit is contained in:
Thiago Santos 2014-08-26 16:45:46 -03:00
parent 023b284c2d
commit 58a1b0d058
5 changed files with 601 additions and 2123 deletions

View file

@ -13,14 +13,14 @@ noinst_HEADERS = \
gstdash_debug.h gstdash_debug.h
# compiler and linker flags used to compile this plugin, set in configure.ac # compiler and linker flags used to compile this plugin, set in configure.ac
libgstdashdemux_la_CFLAGS = \ libgstdashdemux_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) \
$(GST_PLUGINS_BAD_CFLAGS) \
$(GST_PLUGINS_BASE_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) \ $(GST_BASE_CFLAGS) \
$(GST_CFLAGS) \ $(GST_CFLAGS) \
$(LIBXML2_CFLAGS) $(LIBXML2_CFLAGS)
libgstdashdemux_la_LIBADD = \ libgstdashdemux_la_LIBADD = \
$(top_builddir)/gst-libs/gst/uridownloader/libgsturidownloader-@GST_API_VERSION@.la \ $(top_builddir)/gst-libs/gst/uridownloader/libgsturidownloader-@GST_API_VERSION@.la \
$(top_builddir)/gst-libs/gst/adaptivedemux/libgstadaptivedemux-@GST_API_VERSION@.la \
-lgsttag-$(GST_API_VERSION) \ -lgsttag-$(GST_API_VERSION) \
$(GST_BASE_LIBS) \ $(GST_BASE_LIBS) \
$(GST_LIBS) \ $(GST_LIBS) \

File diff suppressed because it is too large Load diff

View file

@ -31,10 +31,10 @@
#define __GST_DASH_DEMUX_H__ #define __GST_DASH_DEMUX_H__
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/adaptivedemux/gstadaptivedemux.h>
#include <gst/base/gstadapter.h> #include <gst/base/gstadapter.h>
#include <gst/base/gstdataqueue.h> #include <gst/base/gstdataqueue.h>
#include "gstmpdparser.h" #include "gstmpdparser.h"
#include <gst/tag/tag.h>
#include <gst/uridownloader/gsturidownloader.h> #include <gst/uridownloader/gsturidownloader.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -57,43 +57,12 @@ typedef struct _GstDashDemuxClass GstDashDemuxClass;
struct _GstDashDemuxStream struct _GstDashDemuxStream
{ {
GstPad *pad; GstAdaptiveDemuxStream parent;
GstDashDemux *demux;
gint index; gint index;
GstActiveStream *active_stream; GstActiveStream *active_stream;
GstCaps *input_caps;
GstFlowReturn last_ret;
GstClockTime position;
gboolean restart_download;
GstEvent *pending_segment;
gboolean stream_eos;
gboolean need_header;
gboolean discont;
/* Download task */
GMutex download_mutex;
GCond download_cond;
GstTask *download_task;
GRecMutex download_task_lock;
/* download tooling */
GstElement *src;
GstPad *src_srcpad;
GMutex fragment_download_lock;
GCond fragment_download_cond;
gboolean download_finished;
GstMediaFragmentInfo current_fragment; GstMediaFragmentInfo current_fragment;
gboolean starting_fragment;
gint64 download_start_time;
gint64 download_total_time;
gint64 download_total_bytes;
gint current_download_rate;
}; };
/** /**
@ -103,20 +72,12 @@ struct _GstDashDemuxStream
*/ */
struct _GstDashDemux struct _GstDashDemux
{ {
GstBin parent; GstAdaptiveDemux parent;
GstPad *sinkpad;
gboolean have_group_id;
guint group_id;
GSList *streams;
GSList *next_periods; GSList *next_periods;
GstSegment segment; GstSegment segment;
GstClockTime timestamp_offset;
GstBuffer *manifest;
GstUriDownloader *downloader;
GstMpdClient *client; /* MPD client */ GstMpdClient *client; /* MPD client */
GMutex client_lock; GMutex client_lock;
@ -127,16 +88,11 @@ struct _GstDashDemux
GstClockTime max_buffering_time; /* Maximum buffering time accumulated during playback */ GstClockTime max_buffering_time; /* Maximum buffering time accumulated during playback */
gfloat bandwidth_usage; /* Percentage of the available bandwidth to use */ gfloat bandwidth_usage; /* Percentage of the available bandwidth to use */
guint64 max_bitrate; /* max of bitrate supported by target decoder */ guint64 max_bitrate; /* max of bitrate supported by target decoder */
gboolean cancelled;
/* Manifest update */
GstClockTime last_manifest_update;
}; };
struct _GstDashDemuxClass struct _GstDashDemuxClass
{ {
GstBinClass parent_class; GstAdaptiveDemuxClass parent_class;
}; };
GType gst_dash_demux_get_type (void); GType gst_dash_demux_get_type (void);

View file

@ -2009,14 +2009,14 @@ gst_mpdparser_get_segment_base (GstPeriodNode * Period,
if (Representation && Representation->SegmentList if (Representation && Representation->SegmentList
&& Representation->SegmentList->MultSegBaseType && Representation->SegmentList->MultSegBaseType
&& Representation->SegmentList->MultSegBaseType->SegBaseType && Representation->SegmentList->MultSegBaseType->SegBaseType
&& Representation->SegmentList->MultSegBaseType-> && Representation->SegmentList->MultSegBaseType->SegBaseType->
SegBaseType->Initialization) { Initialization) {
SegmentBase = Representation->SegmentList->MultSegBaseType->SegBaseType; SegmentBase = Representation->SegmentList->MultSegBaseType->SegBaseType;
} else if (AdaptationSet && AdaptationSet->SegmentList } else if (AdaptationSet && AdaptationSet->SegmentList
&& AdaptationSet->SegmentList->MultSegBaseType && AdaptationSet->SegmentList->MultSegBaseType
&& AdaptationSet->SegmentList->MultSegBaseType->SegBaseType && AdaptationSet->SegmentList->MultSegBaseType->SegBaseType
&& AdaptationSet->SegmentList->MultSegBaseType-> && AdaptationSet->SegmentList->MultSegBaseType->SegBaseType->
SegBaseType->Initialization) { Initialization) {
SegmentBase = AdaptationSet->SegmentList->MultSegBaseType->SegBaseType; SegmentBase = AdaptationSet->SegmentList->MultSegBaseType->SegBaseType;
} else if (Period && Period->SegmentList } else if (Period && Period->SegmentList
&& Period->SegmentList->MultSegBaseType && Period->SegmentList->MultSegBaseType
@ -2771,7 +2771,6 @@ gst_mpd_client_new (void)
GstMpdClient *client; GstMpdClient *client;
client = g_new0 (GstMpdClient, 1); client = g_new0 (GstMpdClient, 1);
g_mutex_init (&client->lock);
return client; return client;
} }
@ -2802,8 +2801,6 @@ gst_mpd_client_free (GstMpdClient * client)
gst_active_streams_free (client); gst_active_streams_free (client);
g_mutex_clear (&client->lock);
g_free (client->mpd_uri); g_free (client->mpd_uri);
client->mpd_uri = NULL; client->mpd_uri = NULL;
g_free (client->mpd_base_uri); g_free (client->mpd_base_uri);
@ -2821,7 +2818,6 @@ gst_mpd_parse (GstMpdClient * client, const gchar * data, gint size)
GST_DEBUG ("MPD file fully buffered, start parsing..."); GST_DEBUG ("MPD file fully buffered, start parsing...");
GST_MPD_CLIENT_LOCK (client);
/* parse the complete MPD file into a tree (using the libxml2 default parser API) */ /* parse the complete MPD file into a tree (using the libxml2 default parser API) */
/* this initialize the library and check potential ABI mismatches /* this initialize the library and check potential ABI mismatches
@ -2833,7 +2829,6 @@ gst_mpd_parse (GstMpdClient * client, const gchar * data, gint size)
doc = xmlReadMemory (data, size, "noname.xml", NULL, 0); doc = xmlReadMemory (data, size, "noname.xml", NULL, 0);
if (doc == NULL) { if (doc == NULL) {
GST_ERROR ("failed to parse the MPD file"); GST_ERROR ("failed to parse the MPD file");
GST_MPD_CLIENT_UNLOCK (client);
return FALSE; return FALSE;
} else { } else {
/* get the root element node */ /* get the root element node */
@ -2850,7 +2845,6 @@ gst_mpd_parse (GstMpdClient * client, const gchar * data, gint size)
/* free the document */ /* free the document */
xmlFreeDoc (doc); xmlFreeDoc (doc);
} }
GST_MPD_CLIENT_UNLOCK (client);
return TRUE; return TRUE;
} }
@ -2899,8 +2893,8 @@ gst_mpdparser_get_chunk_by_index (GstMpdClient * client, guint indexStream,
GstClockTime duration; GstClockTime duration;
GstStreamPeriod *stream_period; GstStreamPeriod *stream_period;
g_return_val_if_fail (stream->cur_seg_template-> g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->
MultSegBaseType->SegmentTimeline == NULL, FALSE); SegmentTimeline == NULL, FALSE);
/* segment template generator */ /* segment template generator */
duration = gst_mpd_client_get_segment_duration (client, stream); duration = gst_mpd_client_get_segment_duration (client, stream);
if (!GST_CLOCK_TIME_IS_VALID (duration)) if (!GST_CLOCK_TIME_IS_VALID (duration))
@ -3182,7 +3176,6 @@ gst_mpd_client_setup_media_presentation (GstMpdClient * client)
g_return_val_if_fail (client->mpd_node != NULL, FALSE); g_return_val_if_fail (client->mpd_node != NULL, FALSE);
GST_DEBUG ("Building the list of Periods in the Media Presentation"); GST_DEBUG ("Building the list of Periods in the Media Presentation");
GST_MPD_CLIENT_LOCK (client);
/* clean the old period list, if any */ /* clean the old period list, if any */
if (client->periods) { if (client->periods) {
g_list_foreach (client->periods, g_list_foreach (client->periods,
@ -3251,26 +3244,22 @@ gst_mpd_client_setup_media_presentation (GstMpdClient * client)
GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration)); GST_TIME_FORMAT, idx, GST_TIME_ARGS (start), GST_TIME_ARGS (duration));
} }
GST_MPD_CLIENT_UNLOCK (client);
GST_DEBUG ("Found a total of %d valid Periods in the Media Presentation", GST_DEBUG ("Found a total of %d valid Periods in the Media Presentation",
idx); idx);
return ret; return ret;
early: early:
GST_MPD_CLIENT_UNLOCK (client);
GST_WARNING GST_WARNING
("Found an Early Available Period, skipping the rest of the Media Presentation"); ("Found an Early Available Period, skipping the rest of the Media Presentation");
return ret; return ret;
syntax_error: syntax_error:
GST_MPD_CLIENT_UNLOCK (client);
GST_WARNING GST_WARNING
("Cannot get the duration of the Period %d, skipping the rest of the Media Presentation", ("Cannot get the duration of the Period %d, skipping the rest of the Media Presentation",
idx); idx);
return ret; return ret;
no_mem: no_mem:
GST_MPD_CLIENT_UNLOCK (client);
GST_WARNING ("Allocation of GstStreamPeriod struct failed!"); GST_WARNING ("Allocation of GstStreamPeriod struct failed!");
return FALSE; return FALSE;
} }
@ -3374,7 +3363,6 @@ gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream,
g_return_val_if_fail (stream != NULL, 0); g_return_val_if_fail (stream != NULL, 0);
GST_MPD_CLIENT_LOCK (client);
if (stream->segments) { if (stream->segments) {
for (index = 0; index < stream->segments->len; index++) { for (index = 0; index < stream->segments->len; index++) {
GstMediaSegment *segment = g_ptr_array_index (stream->segments, index); GstMediaSegment *segment = g_ptr_array_index (stream->segments, index);
@ -3388,16 +3376,14 @@ gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream,
} }
if (selectedChunk == NULL) { if (selectedChunk == NULL) {
GST_MPD_CLIENT_UNLOCK (client);
return FALSE; return FALSE;
} }
} else { } else {
GstClockTime duration = GstClockTime duration =
gst_mpd_client_get_segment_duration (client, stream); gst_mpd_client_get_segment_duration (client, stream);
g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType-> g_return_val_if_fail (stream->cur_seg_template->
SegmentTimeline == NULL, FALSE); MultSegBaseType->SegmentTimeline == NULL, FALSE);
if (!GST_CLOCK_TIME_IS_VALID (duration)) { if (!GST_CLOCK_TIME_IS_VALID (duration)) {
GST_MPD_CLIENT_UNLOCK (client);
return FALSE; return FALSE;
} }
index = ts / duration; index = ts / duration;
@ -3405,7 +3391,6 @@ gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream,
gst_mpd_client_set_segment_index (stream, index); gst_mpd_client_set_segment_index (stream, index);
GST_MPD_CLIENT_UNLOCK (client);
return TRUE; return TRUE;
} }
@ -3492,10 +3477,8 @@ gst_mpd_client_get_availability_start_time (GstMpdClient * client)
if (client == NULL) if (client == NULL)
return (GstDateTime *) NULL; return (GstDateTime *) NULL;
GST_MPD_CLIENT_LOCK (client);
start_time = client->mpd_node->availabilityStartTime; start_time = client->mpd_node->availabilityStartTime;
gst_date_time_ref (start_time); gst_date_time_ref (start_time);
GST_MPD_CLIENT_UNLOCK (client);
return start_time; return start_time;
} }
@ -3511,18 +3494,15 @@ gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client,
stream = g_list_nth_data (client->active_streams, stream_idx); stream = g_list_nth_data (client->active_streams, stream_idx);
g_return_val_if_fail (stream != NULL, 0); g_return_val_if_fail (stream != NULL, 0);
GST_MPD_CLIENT_LOCK (client);
segment_idx = gst_mpd_client_get_segments_counts (stream) - 1; segment_idx = gst_mpd_client_get_segments_counts (stream) - 1;
GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx); GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx);
if (!gst_mpdparser_get_chunk_by_index (client, stream_idx, segment_idx, if (!gst_mpdparser_get_chunk_by_index (client, stream_idx, segment_idx,
&currentChunk)) { &currentChunk)) {
GST_MPD_CLIENT_UNLOCK (client);
return FALSE; return FALSE;
} }
*ts = currentChunk.start_time; *ts = currentChunk.start_time;
GST_MPD_CLIENT_UNLOCK (client);
return TRUE; return TRUE;
} }
@ -3539,25 +3519,22 @@ gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client,
stream = g_list_nth_data (client->active_streams, stream_idx); stream = g_list_nth_data (client->active_streams, stream_idx);
g_return_val_if_fail (stream != NULL, 0); g_return_val_if_fail (stream != NULL, 0);
GST_MPD_CLIENT_LOCK (client);
segment_idx = gst_mpd_client_get_segment_index (stream); segment_idx = gst_mpd_client_get_segment_index (stream);
GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx); GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx);
if (!gst_mpdparser_get_chunk_by_index (client, stream_idx, segment_idx, if (!gst_mpdparser_get_chunk_by_index (client, stream_idx, segment_idx,
&currentChunk)) { &currentChunk)) {
GST_MPD_CLIENT_UNLOCK (client);
return FALSE; return FALSE;
} }
*ts = currentChunk.start_time; *ts = currentChunk.start_time;
GST_MPD_CLIENT_UNLOCK (client);
return TRUE; return TRUE;
} }
gboolean gboolean
gst_mpd_client_get_next_fragment (GstMpdClient * client, gst_mpd_client_get_next_fragment (GstMpdClient * client,
guint indexStream, GstMediaFragmentInfo * fragment, gboolean forward) guint indexStream, GstMediaFragmentInfo * fragment)
{ {
GstActiveStream *stream = NULL; GstActiveStream *stream = NULL;
GstMediaSegment currentChunk; GstMediaSegment currentChunk;
@ -3573,13 +3550,11 @@ gst_mpd_client_get_next_fragment (GstMpdClient * client,
g_return_val_if_fail (stream != NULL, FALSE); g_return_val_if_fail (stream != NULL, FALSE);
g_return_val_if_fail (stream->cur_representation != NULL, FALSE); g_return_val_if_fail (stream->cur_representation != NULL, FALSE);
GST_MPD_CLIENT_LOCK (client);
segment_idx = gst_mpd_client_get_segment_index (stream); segment_idx = gst_mpd_client_get_segment_index (stream);
GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx); GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx);
if (!gst_mpdparser_get_chunk_by_index (client, indexStream, segment_idx, if (!gst_mpdparser_get_chunk_by_index (client, indexStream, segment_idx,
&currentChunk)) { &currentChunk)) {
GST_MPD_CLIENT_UNLOCK (client);
return FALSE; return FALSE;
} }
@ -3595,9 +3570,10 @@ gst_mpd_client_get_next_fragment (GstMpdClient * client,
stream->cur_representation->bandwidth, currentChunk.start); stream->cur_representation->bandwidth, currentChunk.start);
if (stream->cur_seg_template->index) { if (stream->cur_seg_template->index) {
indexURL = indexURL =
gst_mpdparser_build_URL_from_template (stream->cur_seg_template-> gst_mpdparser_build_URL_from_template (stream->
index, stream->cur_representation->id, currentChunk.number, cur_seg_template->index, stream->cur_representation->id,
stream->cur_representation->bandwidth, currentChunk.start); currentChunk.number, stream->cur_representation->bandwidth,
currentChunk.start);
} }
} }
GST_DEBUG ("mediaURL = %s", mediaURL); GST_DEBUG ("mediaURL = %s", mediaURL);
@ -3658,15 +3634,37 @@ gst_mpd_client_get_next_fragment (GstMpdClient * client,
} }
} }
gst_mpd_client_set_segment_index (stream,
forward ? segment_idx + 1 : segment_idx - 1);
GST_MPD_CLIENT_UNLOCK (client);
GST_DEBUG ("Loading chunk with URL %s", fragment->uri); GST_DEBUG ("Loading chunk with URL %s", fragment->uri);
return TRUE; return TRUE;
} }
static GstFlowReturn
gst_mpd_client_update_segment (GstMpdClient * client, GstActiveStream * stream,
gint update)
{
guint segment_idx;
segment_idx = gst_mpd_client_get_segment_index (stream);
GST_DEBUG ("Looking for fragment sequence chunk %d", segment_idx);
gst_mpd_client_set_segment_index (stream, segment_idx + update);
return GST_FLOW_OK;
}
GstFlowReturn
gst_mpd_client_advance_segment (GstMpdClient * client, GstActiveStream * stream,
gboolean forward)
{
if (forward)
return gst_mpd_client_update_segment (client, stream, 1);
else
return gst_mpd_client_update_segment (client, stream, -1);
}
gboolean gboolean
gst_mpd_client_get_next_header (GstMpdClient * client, gchar ** uri, gst_mpd_client_get_next_header (GstMpdClient * client, gchar ** uri,
guint stream_idx, gint64 * range_start, gint64 * range_end) guint stream_idx, gint64 * range_start, gint64 * range_end)
@ -3685,7 +3683,6 @@ gst_mpd_client_get_next_header (GstMpdClient * client, gchar ** uri,
*range_end = -1; *range_end = -1;
GST_DEBUG ("Looking for current representation header"); GST_DEBUG ("Looking for current representation header");
GST_MPD_CLIENT_LOCK (client);
*uri = NULL; *uri = NULL;
if (stream->cur_segment_base && stream->cur_segment_base->Initialization) { if (stream->cur_segment_base && stream->cur_segment_base->Initialization) {
*uri = *uri =
@ -3714,7 +3711,6 @@ gst_mpd_client_get_next_header (GstMpdClient * client, gchar ** uri,
stream->cur_representation->bandwidth, 0); stream->cur_representation->bandwidth, 0);
} }
} }
GST_MPD_CLIENT_UNLOCK (client);
return *uri == NULL ? FALSE : TRUE; return *uri == NULL ? FALSE : TRUE;
} }
@ -3737,7 +3733,6 @@ gst_mpd_client_get_next_header_index (GstMpdClient * client, gchar ** uri,
*range_end = -1; *range_end = -1;
GST_DEBUG ("Looking for current representation index"); GST_DEBUG ("Looking for current representation index");
GST_MPD_CLIENT_LOCK (client);
*uri = NULL; *uri = NULL;
if (stream->cur_segment_base && stream->cur_segment_base->indexRange) { if (stream->cur_segment_base && stream->cur_segment_base->indexRange) {
*uri = *uri =
@ -3761,7 +3756,6 @@ gst_mpd_client_get_next_header_index (GstMpdClient * client, gchar ** uri,
stream->cur_representation->id, 0, stream->cur_representation->id, 0,
stream->cur_representation->bandwidth, 0); stream->cur_representation->bandwidth, 0);
} }
GST_MPD_CLIENT_UNLOCK (client);
return *uri == NULL ? FALSE : TRUE; return *uri == NULL ? FALSE : TRUE;
} }
@ -3785,8 +3779,8 @@ gst_mpd_client_get_next_fragment_duration (GstMpdClient * client,
} else { } else {
GstClockTime duration = GstClockTime duration =
gst_mpd_client_get_segment_duration (client, stream); gst_mpd_client_get_segment_duration (client, stream);
g_return_val_if_fail (stream->cur_seg_template-> g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->
MultSegBaseType->SegmentTimeline == NULL, 0); SegmentTimeline == NULL, 0);
if (GST_CLOCK_TIME_IS_VALID (duration)) if (GST_CLOCK_TIME_IS_VALID (duration))
return duration; return duration;
@ -3801,14 +3795,12 @@ gst_mpd_client_get_media_presentation_duration (GstMpdClient * client)
g_return_val_if_fail (client != NULL, GST_CLOCK_TIME_NONE); g_return_val_if_fail (client != NULL, GST_CLOCK_TIME_NONE);
GST_MPD_CLIENT_LOCK (client);
if (client->mpd_node->mediaPresentationDuration != -1) { if (client->mpd_node->mediaPresentationDuration != -1) {
duration = client->mpd_node->mediaPresentationDuration * GST_MSECOND; duration = client->mpd_node->mediaPresentationDuration * GST_MSECOND;
} else { } else {
/* We can only get the duration for on-demand streams */ /* We can only get the duration for on-demand streams */
duration = GST_CLOCK_TIME_NONE; duration = GST_CLOCK_TIME_NONE;
} }
GST_MPD_CLIENT_UNLOCK (client);
return duration; return duration;
} }
@ -3824,7 +3816,6 @@ gst_mpd_client_set_period_id (GstMpdClient * client, const gchar * period_id)
g_return_val_if_fail (client->periods != NULL, FALSE); g_return_val_if_fail (client->periods != NULL, FALSE);
g_return_val_if_fail (period_id != NULL, FALSE); g_return_val_if_fail (period_id != NULL, FALSE);
GST_MPD_CLIENT_LOCK (client);
for (iter = client->periods; iter; iter = g_list_next (iter)) { for (iter = client->periods; iter; iter = g_list_next (iter)) {
next_stream_period = iter->data; next_stream_period = iter->data;
@ -3834,7 +3825,6 @@ gst_mpd_client_set_period_id (GstMpdClient * client, const gchar * period_id)
break; break;
} }
} }
GST_MPD_CLIENT_UNLOCK (client);
return ret; return ret;
} }
@ -3848,13 +3838,11 @@ gst_mpd_client_set_period_index (GstMpdClient * client, guint period_idx)
g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (client != NULL, FALSE);
g_return_val_if_fail (client->periods != NULL, FALSE); g_return_val_if_fail (client->periods != NULL, FALSE);
GST_MPD_CLIENT_LOCK (client);
next_stream_period = g_list_nth_data (client->periods, period_idx); next_stream_period = g_list_nth_data (client->periods, period_idx);
if (next_stream_period != NULL) { if (next_stream_period != NULL) {
client->period_idx = period_idx; client->period_idx = period_idx;
ret = TRUE; ret = TRUE;
} }
GST_MPD_CLIENT_UNLOCK (client);
return ret; return ret;
} }
@ -3865,9 +3853,7 @@ gst_mpd_client_get_period_index (GstMpdClient * client)
guint period_idx; guint period_idx;
g_return_val_if_fail (client != NULL, 0); g_return_val_if_fail (client != NULL, 0);
GST_MPD_CLIENT_LOCK (client);
period_idx = client->period_idx; period_idx = client->period_idx;
GST_MPD_CLIENT_UNLOCK (client);
return period_idx; return period_idx;
} }
@ -3879,15 +3865,26 @@ gst_mpd_client_get_period_id (GstMpdClient * client)
gchar *period_id = NULL; gchar *period_id = NULL;
g_return_val_if_fail (client != NULL, 0); g_return_val_if_fail (client != NULL, 0);
GST_MPD_CLIENT_LOCK (client);
period = g_list_nth_data (client->periods, client->period_idx); period = g_list_nth_data (client->periods, client->period_idx);
if (period && period->period) if (period && period->period)
period_id = period->period->id; period_id = period->period->id;
GST_MPD_CLIENT_UNLOCK (client);
return period_id; return period_id;
} }
gboolean
gst_mpd_client_has_previous_period (GstMpdClient * client)
{
GList *next_stream_period;
g_return_val_if_fail (client != NULL, FALSE);
g_return_val_if_fail (client->periods != NULL, FALSE);
next_stream_period =
g_list_nth_data (client->periods, client->period_idx - 1);
return next_stream_period != NULL;
}
gboolean gboolean
gst_mpd_client_has_next_period (GstMpdClient * client) gst_mpd_client_has_next_period (GstMpdClient * client)
{ {
@ -3895,11 +3892,8 @@ gst_mpd_client_has_next_period (GstMpdClient * client)
g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (client != NULL, FALSE);
g_return_val_if_fail (client->periods != NULL, FALSE); g_return_val_if_fail (client->periods != NULL, FALSE);
GST_MPD_CLIENT_LOCK (client);
next_stream_period = next_stream_period =
g_list_nth_data (client->periods, client->period_idx + 1); g_list_nth_data (client->periods, client->period_idx + 1);
GST_MPD_CLIENT_UNLOCK (client);
return next_stream_period != NULL; return next_stream_period != NULL;
} }
@ -3945,8 +3939,8 @@ gst_mpd_client_get_segments_counts (GstActiveStream * stream)
if (stream->segments) if (stream->segments)
return stream->segments->len; return stream->segments->len;
g_return_val_if_fail (stream->cur_seg_template-> g_return_val_if_fail (stream->cur_seg_template->MultSegBaseType->
MultSegBaseType->SegmentTimeline == NULL, 0); SegmentTimeline == NULL, 0);
return 0; return 0;
} }

View file

@ -471,7 +471,6 @@ struct _GstMpdClient
gchar *mpd_uri; /* manifest file URI */ gchar *mpd_uri; /* manifest file URI */
gchar *mpd_base_uri; /* base URI for resolving relative URIs. gchar *mpd_base_uri; /* base URI for resolving relative URIs.
* this will be different for redirects */ * this will be different for redirects */
GMutex lock;
}; };
/* Basic initialization/deinitialization functions */ /* Basic initialization/deinitialization functions */
@ -492,7 +491,7 @@ GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, G
GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client); GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client);
gboolean gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts); gboolean gst_mpd_client_get_last_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
gboolean gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts); gboolean gst_mpd_client_get_next_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
gboolean gst_mpd_client_get_next_fragment (GstMpdClient *client, guint indexStream, GstMediaFragmentInfo * fragment, gboolean forward); gboolean gst_mpd_client_get_next_fragment (GstMpdClient *client, guint indexStream, GstMediaFragmentInfo * fragment);
gboolean gst_mpd_client_get_next_header (GstMpdClient *client, gchar **uri, guint stream_idx, gint64 * range_start, gint64 * range_end); gboolean gst_mpd_client_get_next_header (GstMpdClient *client, gchar **uri, guint stream_idx, gint64 * range_start, gint64 * range_end);
gboolean gst_mpd_client_get_next_header_index (GstMpdClient *client, gchar **uri, guint stream_idx, gint64 * range_start, gint64 * range_end); gboolean gst_mpd_client_get_next_header_index (GstMpdClient *client, gchar **uri, guint stream_idx, gint64 * range_start, gint64 * range_end);
gboolean gst_mpd_client_is_live (GstMpdClient * client); gboolean gst_mpd_client_is_live (GstMpdClient * client);
@ -508,6 +507,7 @@ gboolean gst_mpd_client_set_period_id (GstMpdClient *client, const gchar * perio
guint gst_mpd_client_get_period_index (GstMpdClient *client); guint gst_mpd_client_get_period_index (GstMpdClient *client);
const gchar *gst_mpd_client_get_period_id (GstMpdClient *client); const gchar *gst_mpd_client_get_period_id (GstMpdClient *client);
gboolean gst_mpd_client_has_next_period (GstMpdClient *client); gboolean gst_mpd_client_has_next_period (GstMpdClient *client);
gboolean gst_mpd_client_has_previous_period (GstMpdClient * client);
GstDateTime *gst_mpd_client_get_next_segment_availability_end_time (GstMpdClient * client, GstActiveStream * stream); GstDateTime *gst_mpd_client_get_next_segment_availability_end_time (GstMpdClient * client, GstActiveStream * stream);
/* Representation selection */ /* Representation selection */
@ -529,6 +529,7 @@ guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client);
void gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client, guint segment_idx); void gst_mpd_client_set_segment_index_for_all_streams (GstMpdClient * client, guint segment_idx);
guint gst_mpd_client_get_segment_index (GstActiveStream * stream); guint gst_mpd_client_get_segment_index (GstActiveStream * stream);
void gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx); void gst_mpd_client_set_segment_index (GstActiveStream * stream, guint segment_idx);
GstFlowReturn gst_mpd_client_advance_segment (GstMpdClient * client, GstActiveStream * stream, gboolean forward);
/* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */ /* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */
const gchar *gst_mpd_client_get_stream_mimeType (GstActiveStream * stream); const gchar *gst_mpd_client_get_stream_mimeType (GstActiveStream * stream);