mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 00:06:36 +00:00
dashdemux: port to adaptive demux
This commit is contained in:
parent
023b284c2d
commit
58a1b0d058
5 changed files with 601 additions and 2123 deletions
|
@ -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
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
¤tChunk)) {
|
¤tChunk)) {
|
||||||
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,
|
||||||
¤tChunk)) {
|
¤tChunk)) {
|
||||||
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,
|
||||||
¤tChunk)) {
|
¤tChunk)) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue