dash: split mpdparser, mpdclient and xmlhelper

provide a separate namespace for mpd helper
for xml parsing and the real mpd parsing.
This commit is contained in:
Stéphane Cerveau 2019-05-20 18:48:23 +02:00
parent 4eac9d0ae6
commit 86b251b7d1
12 changed files with 5127 additions and 4920 deletions

View file

@ -520,7 +520,7 @@ gst_dash_demux_get_presentation_offset (GstAdaptiveDemux * demux,
GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
return gst_mpd_parser_get_stream_presentation_offset (dashdemux->client,
return gst_mpd_client_get_stream_presentation_offset (dashdemux->client,
dashstream->index);
}
@ -529,7 +529,7 @@ gst_dash_demux_get_period_start_time (GstAdaptiveDemux * demux)
{
GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
return gst_mpd_parser_get_period_start_time (dashdemux->client);
return gst_mpd_client_get_period_start_time (dashdemux->client);
}
static void
@ -778,14 +778,14 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
gst_mpd_client_get_period_index (demux->client));
/* clean old active stream list, if any */
gst_active_streams_free (demux->client);
gst_mpd_client_active_streams_free (demux->client);
if (!gst_dash_demux_setup_mpdparser_streams (demux, demux->client)) {
return FALSE;
}
GST_DEBUG_OBJECT (demux, "Creating stream objects");
for (i = 0; i < gst_mpdparser_get_nb_active_stream (demux->client); i++) {
for (i = 0; i < gst_mpd_client_get_nb_active_stream (demux->client); i++) {
GstDashDemuxStream *stream;
GstActiveStream *active_stream;
GstCaps *caps;
@ -794,7 +794,8 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
gchar *lang = NULL;
GstTagList *tags = NULL;
active_stream = gst_mpdparser_get_active_stream_by_index (demux->client, i);
active_stream =
gst_mpd_client_get_active_stream_by_index (demux->client, i);
if (active_stream == NULL)
continue;
@ -1036,7 +1037,7 @@ gst_dash_demux_process_manifest (GstAdaptiveDemux * demux, GstBuffer * buf)
if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) {
manifest = (gchar *) mapinfo.data;
if (gst_mpd_parse (dashdemux->client, manifest, mapinfo.size)) {
if (gst_mpd_client_parse (dashdemux->client, manifest, mapinfo.size)) {
if (gst_mpd_client_setup_media_presentation (dashdemux->client, 0, 0,
NULL)) {
ret = TRUE;
@ -1232,7 +1233,7 @@ gst_dash_demux_stream_update_headers_info (GstAdaptiveDemuxStream * stream)
if (path != NULL) {
stream->fragment.header_uri =
gst_uri_join_strings (gst_mpdparser_get_baseURL (dashdemux->client,
gst_uri_join_strings (gst_mpd_client_get_baseURL (dashdemux->client,
dashstream->index), path);
g_free (path);
path = NULL;
@ -1244,7 +1245,7 @@ gst_dash_demux_stream_update_headers_info (GstAdaptiveDemuxStream * stream)
if (path != NULL) {
stream->fragment.index_uri =
gst_uri_join_strings (gst_mpdparser_get_baseURL (dashdemux->client,
gst_uri_join_strings (gst_mpd_client_get_baseURL (dashdemux->client,
dashstream->index), path);
g_free (path);
}
@ -1501,9 +1502,9 @@ gst_dash_demux_stream_seek (GstAdaptiveDemuxStream * stream, gboolean forward,
if (is_isobmff) {
GstClockTime period_start, offset;
period_start = gst_mpd_parser_get_period_start_time (dashdemux->client);
period_start = gst_mpd_client_get_period_start_time (dashdemux->client);
offset =
gst_mpd_parser_get_stream_presentation_offset (dashdemux->client,
gst_mpd_client_get_stream_presentation_offset (dashdemux->client,
dashstream->index);
if (G_UNLIKELY (ts < period_start))
@ -2198,12 +2199,12 @@ gst_dash_demux_stream_select_bitrate (GstAdaptiveDemuxStream * stream,
if (GST_ADAPTIVE_DEMUX_IN_TRICKMODE_KEY_UNITS (base_demux) ||
ABS (base_demux->segment.rate) <= 1.0) {
new_index =
gst_mpdparser_get_rep_idx_with_max_bandwidth (rep_list, bitrate,
gst_mpd_client_get_rep_idx_with_max_bandwidth (rep_list, bitrate,
demux->max_video_width, demux->max_video_height,
demux->max_video_framerate_n, demux->max_video_framerate_d);
} else {
new_index =
gst_mpdparser_get_rep_idx_with_max_bandwidth (rep_list,
gst_mpd_client_get_rep_idx_with_max_bandwidth (rep_list,
bitrate / ABS (base_demux->segment.rate), demux->max_video_width,
demux->max_video_height, demux->max_video_framerate_n,
demux->max_video_framerate_d);
@ -2211,7 +2212,7 @@ gst_dash_demux_stream_select_bitrate (GstAdaptiveDemuxStream * stream,
/* if no representation has the required bandwidth, take the lowest one */
if (new_index == -1)
new_index = gst_mpdparser_get_rep_idx_with_min_bandwidth (rep_list);
new_index = gst_mpd_client_get_rep_idx_with_min_bandwidth (rep_list);
if (new_index != active_stream->representation_idx) {
GstRepresentationNode *rep = g_list_nth_data (rep_list, new_index);
@ -2346,7 +2347,7 @@ gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
GST_DEBUG_OBJECT (demux, "Seeking to Period %d", current_period);
/* clean old active stream list, if any */
gst_active_streams_free (dashdemux->client);
gst_mpd_client_active_streams_free (dashdemux->client);
dashdemux->trickmode_no_audio = trickmode_no_audio;
/* setup video, audio and subtitle streams, starting from the new Period */
@ -2356,7 +2357,7 @@ gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
streams = demux->next_streams;
} else if (dashdemux->trickmode_no_audio != trickmode_no_audio) {
/* clean old active stream list, if any */
gst_active_streams_free (dashdemux->client);
gst_mpd_client_active_streams_free (dashdemux->client);
dashdemux->trickmode_no_audio = trickmode_no_audio;
/* setup video, audio and subtitle streams, starting from the new Period */
@ -2404,7 +2405,7 @@ gst_dash_demux_update_manifest_data (GstAdaptiveDemux * demux,
new_client->mpd_base_uri = g_strdup (demux->manifest_base_uri);
gst_buffer_map (buffer, &mapinfo, GST_MAP_READ);
if (gst_mpd_parse (new_client, (gchar *) mapinfo.data, mapinfo.size)) {
if (gst_mpd_client_parse (new_client, (gchar *) mapinfo.data, mapinfo.size)) {
const gchar *period_id;
guint period_idx;
GList *iter;
@ -2490,7 +2491,7 @@ gst_dash_demux_update_manifest_data (GstAdaptiveDemux * demux,
/* _get_next_fragment_timestamp() returned relative timestamp to
* corresponding period start, but _client_stream_seek expects absolute
* MPD time. */
ts += gst_mpd_parser_get_period_start_time (dashdemux->client);
ts += gst_mpd_client_get_period_start_time (dashdemux->client);
GST_DEBUG_OBJECT (GST_ADAPTIVE_DEMUX_STREAM_PAD (demux_stream),
"Current position: %" GST_TIME_FORMAT ", updating to %"

View file

@ -34,7 +34,7 @@
#include <gst/adaptivedemux/gstadaptivedemux.h>
#include <gst/base/gstadapter.h>
#include <gst/base/gstdataqueue.h>
#include "gstmpdparser.h"
#include "gstmpdclient.h"
#include <gst/isoff/gstisoff.h>
#include <gst/uridownloader/gsturidownloader.h>

2915
ext/dash/gstmpdclient.c Normal file

File diff suppressed because it is too large Load diff

142
ext/dash/gstmpdclient.h Normal file
View file

@ -0,0 +1,142 @@
/* GStreamer
*
* Copyright (C) 2019 Collabora Ltd.
* Author: Stéphane Cerveau <scerveau@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library (COPYING); if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_MPDCLIENT_H__
#define __GST_MPDCLIENT_H__
#include "gstmpdparser.h"
G_BEGIN_DECLS
#define GST_MPD_CLIENT_LOCK(c) g_mutex_lock (&c->lock);
#define GST_MPD_CLIENT_UNLOCK(c) g_mutex_unlock (&c->lock);
typedef struct _GstMpdClient GstMpdClient;
struct _GstMpdClient
{
GstMPDNode *mpd_node; /* active MPD manifest file */
GList *periods; /* list of GstStreamPeriod */
guint period_idx; /* index of current Period */
GList *active_streams; /* list of GstActiveStream */
guint update_failed_count;
gchar *mpd_uri; /* manifest file URI */
gchar *mpd_base_uri; /* base URI for resolving relative URIs.
* this will be different for redirects */
/* profiles */
gboolean profile_isoff_ondemand;
GstUriDownloader * downloader;
};
/* Basic initialization/deinitialization functions */
GstMpdClient *gst_mpd_client_new (void);
void gst_mpd_client_active_streams_free (GstMpdClient * client);
void gst_mpd_client_free (GstMpdClient * client);
/* main mpd parsing methods from xml data */
gboolean gst_mpd_client_parse (GstMpdClient * client, const gchar * data, gint size);
void gst_mpd_client_set_uri_downloader (GstMpdClient * client, GstUriDownloader * download);
void gst_mpd_client_check_profiles (GstMpdClient * client);
void gst_mpd_client_fetch_on_load_external_resources (GstMpdClient * client);
/* Streaming management */
gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client, GstClockTime time, gint period_index, const gchar *period_id);
gboolean gst_mpd_client_setup_streaming (GstMpdClient * client, GstAdaptationSetNode * adapt_set);
gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation);
GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream);
GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client);
GstClockTime gst_mpd_client_get_maximum_segment_duration (GstMpdClient * client);
gboolean gst_mpd_client_get_last_fragment_timestamp_end (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 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_is_live (GstMpdClient * client);
gboolean gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream, gboolean forward, GstSeekFlags flags, GstClockTime ts, GstClockTime * final_ts);
gboolean gst_mpd_client_seek_to_time (GstMpdClient * client, GDateTime * time);
GstClockTime gst_mpd_client_get_stream_presentation_offset (GstMpdClient *client, guint stream_idx);
gchar** gst_mpd_client_get_utc_timing_sources (GstMpdClient *client, guint methods, GstMPDUTCTimingType *selected_method);
GstClockTime gst_mpd_client_get_period_start_time (GstMpdClient *client);
/* Period selection */
guint gst_mpd_client_get_period_index_at_time (GstMpdClient * client, GstDateTime * time);
gboolean gst_mpd_client_set_period_index (GstMpdClient *client, guint period_idx);
gboolean gst_mpd_client_set_period_id (GstMpdClient *client, const gchar * period_id);
guint gst_mpd_client_get_period_index (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_previous_period (GstMpdClient * client);
/* Representation selection */
gint gst_mpd_client_get_rep_idx_with_max_bandwidth (GList *Representations, gint64 max_bandwidth, gint max_video_width, gint max_video_height, gint max_video_framerate_n, gint max_video_framerate_d);
gint gst_mpd_client_get_rep_idx_with_min_bandwidth (GList * Representations);
GstDateTime *
gst_mpd_client_get_availability_start_time (GstMpdClient * client);
/* URL management */
const gchar *gst_mpd_client_get_baseURL (GstMpdClient *client, guint indexStream);
gchar *gst_mpd_client_parse_baseURL (GstMpdClient * client, GstActiveStream * stream, gchar ** query);
/* Active stream */
guint gst_mpd_client_get_nb_active_stream (GstMpdClient *client);
GstActiveStream *gst_mpd_client_get_active_stream_by_index (GstMpdClient *client, guint stream_idx);
gboolean gst_mpd_client_active_stream_contains_subtitles (GstActiveStream * stream);
/* AdaptationSet */
guint gst_mpd_client_get_nb_adaptationSet (GstMpdClient *client);
GList * gst_mpd_client_get_adaptation_sets (GstMpdClient * client);
/* Segment */
gboolean gst_mpd_client_has_next_segment (GstMpdClient * client, GstActiveStream * stream, gboolean forward);
GstFlowReturn gst_mpd_client_advance_segment (GstMpdClient * client, GstActiveStream * stream, gboolean forward);
void gst_mpd_client_seek_to_first_segment (GstMpdClient * client);
GstDateTime *gst_mpd_client_get_next_segment_availability_start_time (GstMpdClient * client, GstActiveStream * stream);
/* Get audio/video stream parameters (caps, width, height, rate, number of channels) */
GstCaps * gst_mpd_client_get_stream_caps (GstActiveStream * stream);
gboolean gst_mpd_client_get_bitstream_switching_flag (GstActiveStream * stream);
guint gst_mpd_client_get_video_stream_width (GstActiveStream * stream);
guint gst_mpd_client_get_video_stream_height (GstActiveStream * stream);
gboolean gst_mpd_client_get_video_stream_framerate (GstActiveStream * stream, gint * fps_num, gint * fps_den);
guint gst_mpd_client_get_audio_stream_rate (GstActiveStream * stream);
guint gst_mpd_client_get_audio_stream_num_channels (GstActiveStream * stream);
/* Support multi language */
guint gst_mpd_client_get_list_and_nb_of_audio_language (GstMpdClient *client, GList **lang);
gint64 gst_mpd_client_calculate_time_difference (const GstDateTime * t1, const GstDateTime * t2);
GstDateTime *gst_mpd_client_add_time_difference (GstDateTime * t1, gint64 usecs);
gint64 gst_mpd_client_parse_default_presentation_delay(GstMpdClient * client, const gchar * default_presentation_delay);
/* profiles */
gboolean gst_mpd_client_has_isoff_ondemand_profile (GstMpdClient *client);
G_END_DECLS
#endif /* __GST_MPDCLIENT_H__ */

78
ext/dash/gstmpdhelper.c Normal file
View file

@ -0,0 +1,78 @@
/* GStreamer
*
* Copyright (C) 2019 Collabora Ltd.
* Author: Stéphane Cerveau <scerveau@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "gstmpdhelper.h"
gboolean
gst_mpd_helper_get_mpd_type (xmlNode * a_node,
const gchar * property_name, GstMPDFileType * property_value)
{
xmlChar *prop_string;
gboolean exists = FALSE;
*property_value = GST_MPD_FILE_TYPE_STATIC; /* default */
prop_string = xmlGetProp (a_node, (const xmlChar *) property_name);
if (prop_string) {
if (xmlStrcmp (prop_string, (xmlChar *) "OnDemand") == 0
|| xmlStrcmp (prop_string, (xmlChar *) "static") == 0) {
exists = TRUE;
*property_value = GST_MPD_FILE_TYPE_STATIC;
GST_LOG (" - %s: static", property_name);
} else if (xmlStrcmp (prop_string, (xmlChar *) "Live") == 0
|| xmlStrcmp (prop_string, (xmlChar *) "dynamic") == 0) {
exists = TRUE;
*property_value = GST_MPD_FILE_TYPE_DYNAMIC;
GST_LOG (" - %s: dynamic", property_name);
} else {
GST_WARNING ("failed to parse MPD type property %s from xml string %s",
property_name, prop_string);
}
xmlFree (prop_string);
}
return exists;
}
gboolean
gst_mpd_helper_get_SAP_type (xmlNode * a_node,
const gchar * property_name, GstMPDSAPType * property_value)
{
xmlChar *prop_string;
guint prop_SAP_type = 0;
gboolean exists = FALSE;
prop_string = xmlGetProp (a_node, (const xmlChar *) property_name);
if (prop_string) {
if (sscanf ((gchar *) prop_string, "%u", &prop_SAP_type) == 1
&& prop_SAP_type <= 6) {
exists = TRUE;
*property_value = (GstMPDSAPType) prop_SAP_type;
GST_LOG (" - %s: %u", property_name, prop_SAP_type);
} else {
GST_WARNING
("failed to parse unsigned integer property %s from xml string %s",
property_name, prop_string);
}
xmlFree (prop_string);
}
return exists;
}

49
ext/dash/gstmpdhelper.h Normal file
View file

@ -0,0 +1,49 @@
/* GStreamer
*
* Copyright (C) 2019 Collabora Ltd.
* Author: Stéphane Cerveau <scerveau@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library (COPYING); if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_MPDHELPER_H__
#define __GST_MPDHELPER_H__
#include "gstxmlhelper.h"
G_BEGIN_DECLS
typedef enum
{
GST_MPD_FILE_TYPE_STATIC,
GST_MPD_FILE_TYPE_DYNAMIC
} GstMPDFileType;
typedef enum
{
GST_SAP_TYPE_0 = 0,
GST_SAP_TYPE_1,
GST_SAP_TYPE_2,
GST_SAP_TYPE_3,
GST_SAP_TYPE_4,
GST_SAP_TYPE_5,
GST_SAP_TYPE_6
} GstMPDSAPType;
gboolean gst_mpd_helper_get_mpd_type (xmlNode * a_node, const gchar * property_name, GstMPDFileType * property_value);
gboolean gst_mpd_helper_get_SAP_type (xmlNode * a_node, const gchar * property_name, GstMPDSAPType * property_value);
G_END_DECLS
#endif /* __GST_MPDHELPER_H__ */

File diff suppressed because it is too large Load diff

View file

@ -30,10 +30,10 @@
#include <gst/gst.h>
#include <gst/uridownloader/gsturidownloader.h>
#include <gst/base/gstadapter.h>
#include "gstmpdhelper.h"
G_BEGIN_DECLS
typedef struct _GstMpdClient GstMpdClient;
typedef struct _GstActiveStream GstActiveStream;
typedef struct _GstStreamPeriod GstStreamPeriod;
typedef struct _GstMediaFragmentInfo GstMediaFragmentInfo;
@ -50,10 +50,7 @@ typedef struct _GstSegmentListNode GstSegmentListNode;
typedef struct _GstSegmentTemplateNode GstSegmentTemplateNode;
typedef struct _GstSegmentURLNode GstSegmentURLNode;
typedef struct _GstBaseURL GstBaseURL;
typedef struct _GstRange GstRange;
typedef struct _GstRatio GstRatio;
typedef struct _GstFrameRate GstFrameRate;
typedef struct _GstConditionalUintType GstConditionalUintType;
typedef struct _GstSubsetNode GstSubsetNode;
typedef struct _GstProgramInformationNode GstProgramInformationNode;
typedef struct _GstMetricsRangeNode GstMetricsRangeNode;
@ -65,8 +62,6 @@ typedef struct _GstSegmentBaseType GstSegmentBaseType;
typedef struct _GstURLType GstURLType;
typedef struct _GstMultSegmentBaseType GstMultSegmentBaseType;
#define GST_MPD_CLIENT_LOCK(c) g_mutex_lock (&c->lock);
#define GST_MPD_CLIENT_UNLOCK(c) g_mutex_unlock (&c->lock);
#define GST_MPD_DURATION_NONE ((guint64)-1)
@ -78,22 +73,6 @@ typedef enum
GST_STREAM_APPLICATION /* application stream (optional): for timed text/subtitles */
} GstStreamMimeType;
typedef enum
{
GST_MPD_FILE_TYPE_STATIC,
GST_MPD_FILE_TYPE_DYNAMIC
} GstMPDFileType;
typedef enum
{
GST_SAP_TYPE_0 = 0,
GST_SAP_TYPE_1,
GST_SAP_TYPE_2,
GST_SAP_TYPE_3,
GST_SAP_TYPE_4,
GST_SAP_TYPE_5,
GST_SAP_TYPE_6
} GstSAPType;
typedef enum
{
@ -120,30 +99,6 @@ struct _GstBaseURL
gchar *byteRange;
};
struct _GstRange
{
guint64 first_byte_pos;
guint64 last_byte_pos;
};
struct _GstRatio
{
guint num;
guint den;
};
struct _GstFrameRate
{
guint num;
guint den;
};
struct _GstConditionalUintType
{
gboolean flag;
guint value;
};
struct _GstSNode
{
guint64 t;
@ -160,14 +115,14 @@ struct _GstSegmentTimelineNode
struct _GstURLType
{
gchar *sourceURL;
GstRange *range;
GstXMLRange *range;
};
struct _GstSegmentBaseType
{
guint timescale;
guint64 presentationTimeOffset;
GstRange *indexRange;
GstXMLRange *indexRange;
gboolean indexRangeExact;
/* Initialization node */
GstURLType *Initialization;
@ -211,9 +166,9 @@ struct _GstSegmentTemplateNode
struct _GstSegmentURLNode
{
gchar *media;
GstRange *mediaRange;
GstXMLRange *mediaRange;
gchar *index;
GstRange *indexRange;
GstXMLRange *indexRange;
};
struct _GstRepresentationBaseType
@ -221,16 +176,16 @@ struct _GstRepresentationBaseType
gchar *profiles;
guint width;
guint height;
GstRatio *sar;
GstFrameRate *minFrameRate;
GstFrameRate *maxFrameRate;
GstFrameRate *frameRate;
GstXMLRatio *sar;
GstXMLFrameRate *minFrameRate;
GstXMLFrameRate *maxFrameRate;
GstXMLFrameRate *frameRate;
gchar *audioSamplingRate;
gchar *mimeType;
gchar *segmentProfiles;
gchar *codecs;
gdouble maximumSAPPeriod;
GstSAPType startWithSAP;
GstMPDSAPType startWithSAP;
gdouble maxPlayoutRate;
gboolean codingDependency;
gchar *scanType;
@ -285,7 +240,7 @@ struct _GstContentComponentNode
guint id;
gchar *lang; /* LangVectorType RFC 5646 */
gchar *contentType;
GstRatio *par;
GstXMLRatio *par;
/* list of Accessibility DescriptorType nodes */
GList *Accessibility;
/* list of Role DescriptorType nodes */
@ -302,16 +257,16 @@ struct _GstAdaptationSetNode
guint group;
gchar *lang; /* LangVectorType RFC 5646 */
gchar *contentType;
GstRatio *par;
GstXMLRatio *par;
guint minBandwidth;
guint maxBandwidth;
guint minWidth;
guint maxWidth;
guint minHeight;
guint maxHeight;
GstConditionalUintType *segmentAlignment;
GstConditionalUintType *subsegmentAlignment;
GstSAPType subsegmentStartsWithSAP;
GstXMLConditionalUintType *segmentAlignment;
GstXMLConditionalUintType *subsegmentAlignment;
GstMPDSAPType subsegmentStartsWithSAP;
gboolean bitstreamSwitching;
/* list of Accessibility DescriptorType nodes */
GList *Accessibility;
@ -502,106 +457,35 @@ struct _GstActiveStream
GstClockTime presentationTimeOffset; /* presentation time offset of the current segment */
};
struct _GstMpdClient
{
GstMPDNode *mpd_node; /* active MPD manifest file */
GList *periods; /* list of GstStreamPeriod */
guint period_idx; /* index of current Period */
GList *active_streams; /* list of GstActiveStream */
guint update_failed_count;
gchar *mpd_uri; /* manifest file URI */
gchar *mpd_base_uri; /* base URI for resolving relative URIs.
* this will be different for redirects */
/* profiles */
gboolean profile_isoff_ondemand;
GstUriDownloader * downloader;
};
/* Basic initialization/deinitialization functions */
GstMpdClient *gst_mpd_client_new (void);
void gst_active_streams_free (GstMpdClient * client);
void gst_mpd_client_free (GstMpdClient * client);
void gst_media_fragment_info_clear (GstMediaFragmentInfo * fragment);
void gst_mpd_client_set_uri_downloader (GstMpdClient * client, GstUriDownloader * download);
/* MPD file parsing */
gboolean gst_mpd_parse (GstMpdClient *client, const gchar *data, gint size);
gboolean gst_mpdparser_get_mpd_node (GstMPDNode ** mpd_node, const gchar * data, gint size);
GstSegmentListNode * gst_mpdparser_get_external_segment_list (const gchar * data, gint size, GstSegmentListNode * parent);
GList * gst_mpdparser_get_external_periods (const gchar * data, gint size);
GList * gst_mpdparser_get_external_adaptation_sets (const gchar * data, gint size, GstPeriodNode* period);
/* Streaming management */
gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client, GstClockTime time, gint period_index, const gchar *period_id);
gboolean gst_mpd_client_setup_streaming (GstMpdClient * client, GstAdaptationSetNode * adapt_set);
gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation);
GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream);
GstClockTime gst_mpd_client_get_media_presentation_duration (GstMpdClient *client);
GstClockTime gst_mpd_client_get_maximum_segment_duration (GstMpdClient * client);
gboolean gst_mpd_client_get_last_fragment_timestamp_end (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 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_is_live (GstMpdClient * client);
gboolean gst_mpd_client_stream_seek (GstMpdClient * client, GstActiveStream * stream, gboolean forward, GstSeekFlags flags, GstClockTime ts, GstClockTime * final_ts);
gboolean gst_mpd_client_seek_to_time (GstMpdClient * client, GDateTime * time);
GstClockTime gst_mpd_parser_get_stream_presentation_offset (GstMpdClient *client, guint stream_idx);
gchar** gst_mpd_client_get_utc_timing_sources (GstMpdClient *client, guint methods, GstMPDUTCTimingType *selected_method);
GstClockTime gst_mpd_parser_get_period_start_time (GstMpdClient *client);
/* navigation functions */
GstStreamMimeType gst_mpdparser_representation_get_mimetype (GstAdaptationSetNode * adapt_set, GstRepresentationNode * rep);
/* Period selection */
guint gst_mpd_client_get_period_index_at_time (GstMpdClient * client, GstDateTime * time);
gboolean gst_mpd_client_set_period_index (GstMpdClient *client, guint period_idx);
gboolean gst_mpd_client_set_period_id (GstMpdClient *client, const gchar * period_id);
guint gst_mpd_client_get_period_index (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_previous_period (GstMpdClient * client);
/* Memory management */
void gst_mpdparser_free_mpd_node (GstMPDNode * mpd_node);
void gst_mpdparser_free_period_node (GstPeriodNode * period_node);
void gst_mpdparser_free_adaptation_set_node (GstAdaptationSetNode * adaptation_set_node);
void gst_mpdparser_free_segment_list_node (GstSegmentListNode * segment_list_node);
void gst_mpdparser_free_stream_period (GstStreamPeriod * stream_period);
void gst_mpdparser_free_media_segment (GstMediaSegment * media_segment);
void gst_mpdparser_free_active_stream (GstActiveStream * active_stream);
void gst_mpdparser_free_base_url_node (GstBaseURL * base_url_node);
/* Representation selection */
gint gst_mpdparser_get_rep_idx_with_max_bandwidth (GList *Representations, gint64 max_bandwidth, gint max_video_width, gint max_video_height, gint max_video_framerate_n, gint max_video_framerate_d);
gint gst_mpdparser_get_rep_idx_with_min_bandwidth (GList * Representations);
/* URL management */
const gchar *gst_mpdparser_get_baseURL (GstMpdClient *client, guint indexStream);
/* Active stream */
guint gst_mpdparser_get_nb_active_stream (GstMpdClient *client);
GstActiveStream *gst_mpdparser_get_active_stream_by_index (GstMpdClient *client, guint stream_idx);
gboolean gst_mpd_client_active_stream_contains_subtitles (GstActiveStream * stream);
/* AdaptationSet */
guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client);
GList * gst_mpd_client_get_adaptation_sets (GstMpdClient * client);
/* Segment */
gboolean gst_mpd_client_has_next_segment (GstMpdClient * client, GstActiveStream * stream, gboolean forward);
GstFlowReturn gst_mpd_client_advance_segment (GstMpdClient * client, GstActiveStream * stream, gboolean forward);
void gst_mpd_client_seek_to_first_segment (GstMpdClient * client);
GstDateTime *gst_mpd_client_get_next_segment_availability_start_time (GstMpdClient * client, GstActiveStream * stream);
/* Get audio/video stream parameters (caps, width, height, rate, number of channels) */
GstCaps * gst_mpd_client_get_stream_caps (GstActiveStream * stream);
gboolean gst_mpd_client_get_bitstream_switching_flag (GstActiveStream * stream);
guint gst_mpd_client_get_video_stream_width (GstActiveStream * stream);
guint gst_mpd_client_get_video_stream_height (GstActiveStream * stream);
gboolean gst_mpd_client_get_video_stream_framerate (GstActiveStream * stream, gint * fps_num, gint * fps_den);
guint gst_mpd_client_get_audio_stream_rate (GstActiveStream * stream);
guint gst_mpd_client_get_audio_stream_num_channels (GstActiveStream * stream);
/* Support multi language */
guint gst_mpdparser_get_list_and_nb_of_audio_language (GstMpdClient *client, GList **lang);
gint64 gst_mpd_client_calculate_time_difference (const GstDateTime * t1, const GstDateTime * t2);
GstDateTime *gst_mpd_client_add_time_difference (GstDateTime * t1, gint64 usecs);
gint64 gst_mpd_client_parse_default_presentation_delay(GstMpdClient * client, const gchar * default_presentation_delay);
/* profiles */
gboolean gst_mpd_client_has_isoff_ondemand_profile (GstMpdClient *client);
/* Active stream methods*/
void gst_mpdparser_init_active_stream_segments (GstActiveStream * stream);
gchar *gst_mpdparser_get_mediaURL (GstActiveStream * stream, GstSegmentURLNode * segmentURL);
const gchar *gst_mpdparser_get_initializationURL (GstActiveStream * stream, GstURLType * InitializationURL);
/*Helper methods */
gchar *gst_mpdparser_build_URL_from_template (const gchar * url_template, const gchar * id, guint number, guint bandwidth, guint64 time);
const gchar *gst_mpdparser_mimetype_to_caps (const gchar * mimeType);
GstUri *combine_urls (GstUri * base, GList * list, gchar ** query, guint idx);
int strncmp_ext (const char *s1, const char *s2);
G_END_DECLS
#endif /* __GST_MPDPARSER_H__ */

1024
ext/dash/gstxmlhelper.c Normal file

File diff suppressed because it is too large Load diff

113
ext/dash/gstxmlhelper.h Normal file
View file

@ -0,0 +1,113 @@
/* GStreamer
*
* Copyright (C) 2019 Collabora Ltd.
* Author: Stéphane Cerveau <scerveau@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library (COPYING); if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_XMLHELPER_H__
#define __GST_XMLHELPER_H__
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <gst/gst.h>
G_BEGIN_DECLS
typedef struct _GstXMLRange GstXMLRange;
typedef struct _GstXMLRatio GstXMLRatio;
typedef struct _GstXMLFrameRate GstXMLFrameRate;
typedef struct _GstXMLConditionalUintType GstXMLConditionalUintType;
struct _GstXMLRange
{
guint64 first_byte_pos;
guint64 last_byte_pos;
};
struct _GstXMLRatio
{
guint num;
guint den;
};
struct _GstXMLFrameRate
{
guint num;
guint den;
};
struct _GstXMLConditionalUintType
{
gboolean flag;
guint value;
};
GstXMLRange *gst_xml_helper_clone_range (GstXMLRange * range);
/* XML property get method */
gboolean gst_xml_helper_get_prop_validated_string (xmlNode * a_node,
const gchar * property_name, gchar ** property_value,
gboolean (*validator) (const char *));
gboolean gst_xml_helper_get_prop_string (xmlNode * a_node,
const gchar * property_name, gchar ** property_value);
gboolean gst_xml_helper_get_prop_string_stripped (xmlNode * a_node,
const gchar * property_name, gchar ** property_value);
gboolean gst_xml_helper_get_ns_prop_string (xmlNode * a_node,
const gchar * ns_name, const gchar * property_name,
gchar ** property_value);
gboolean gst_xml_helper_get_prop_string_vector_type (xmlNode * a_node,
const gchar * property_name, gchar *** property_value);
gboolean gst_xml_helper_get_prop_signed_integer (xmlNode * a_node,
const gchar * property_name, gint default_val, gint * property_value);
gboolean gst_xml_helper_get_prop_unsigned_integer (xmlNode * a_node,
const gchar * property_name, guint default_val, guint * property_value);
gboolean gst_xml_helper_get_prop_unsigned_integer_64 (xmlNode *
a_node, const gchar * property_name, guint64 default_val,
guint64 * property_value);
gboolean gst_xml_helper_get_prop_uint_vector_type (xmlNode * a_node,
const gchar * property_name, guint ** property_value, guint * value_size);
gboolean gst_xml_helper_get_prop_double (xmlNode * a_node,
const gchar * property_name, gdouble * property_value);
gboolean gst_xml_helper_get_prop_boolean (xmlNode * a_node,
const gchar * property_name, gboolean default_val,
gboolean * property_value);
gboolean gst_xml_helper_get_prop_range (xmlNode * a_node,
const gchar * property_name, GstXMLRange ** property_value);
gboolean gst_xml_helper_get_prop_ratio (xmlNode * a_node,
const gchar * property_name, GstXMLRatio ** property_value);
gboolean gst_xml_helper_get_prop_framerate (xmlNode * a_node,
const gchar * property_name, GstXMLFrameRate ** property_value);
gboolean gst_xml_helper_get_prop_cond_uint (xmlNode * a_node,
const gchar * property_name, GstXMLConditionalUintType ** property_value);
gboolean gst_xml_helper_get_prop_dateTime (xmlNode * a_node,
const gchar * property_name, GstDateTime ** property_value);
gboolean gst_xml_helper_get_prop_duration (xmlNode * a_node,
const gchar * property_name, guint64 default_value,
guint64 * property_value);
gboolean gst_xml_helper_get_prop_string_no_whitespace (xmlNode * a_node,
const gchar * property_name, gchar ** property_value);
/* XML node get method */
gboolean gst_xml_helper_get_node_content (xmlNode * a_node,
gchar ** content);
gchar *gst_xml_helper_get_node_namespace (xmlNode * a_node,
const gchar * prefix);
gboolean gst_xml_helper_get_node_as_string (xmlNode * a_node,
gchar ** content);
G_END_DECLS
#endif /* __GST_XMLHELPER_H__ */

View file

@ -1,6 +1,9 @@
dash_sources = [
'gstdashdemux.c',
'gstxmlhelper.c',
'gstmpdhelper.c',
'gstmpdparser.c',
'gstmpdclient.c',
'gstplugin.c',
]

File diff suppressed because it is too large Load diff