GstActiveStream *active_stream;
GstFragment *download;
GstBuffer *header_buffer;
- gchar *next_fragment_uri;
- GstClockTime duration;
- GstClockTime timestamp;
- gboolean discont;
GTimeVal now;
GTimeVal start;
GstClockTime diff;
if (selected_stream) {
guint stream_idx = selected_stream->index;
GstBuffer *buffer;
- gint64 range_start, range_end;
+ GstMediaFragmentInfo fragment;
if (gst_mpd_client_get_next_fragment (demux->client,
- stream_idx, &discont, &next_fragment_uri, &range_start, &range_end,
- &duration, ×tamp)) {
+ stream_idx, &fragment)) {
g_get_current_time (&start);
GST_INFO_OBJECT (demux, "Next fragment for stream #%i", stream_idx);
GST_INFO_OBJECT (demux,
"Fetching next fragment %s ts:%" GST_TIME_FORMAT " dur:%"
GST_TIME_FORMAT " Range:%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT,
- next_fragment_uri, GST_TIME_ARGS (timestamp),
- GST_TIME_ARGS (duration), range_start, range_end);
+ fragment.uri, GST_TIME_ARGS (fragment.timestamp),
+ GST_TIME_ARGS (fragment.duration),
+ fragment.range_start, fragment.range_end);
/* got a fragment to fetch, no end of period */
end_of_period = FALSE;
download = gst_uri_downloader_fetch_uri_with_range (demux->downloader,
- next_fragment_uri, range_start, range_end);
- g_free (next_fragment_uri);
+ fragment.uri, fragment.range_start, fragment.range_end);
- if (download == NULL)
+ if (download == NULL) {
+ gst_media_fragment_info_clear (&fragment);
return FALSE;
+ }
active_stream =
gst_mpdparser_get_active_stream_by_index (demux->client, stream_idx);
if (active_stream == NULL) {
+ gst_media_fragment_info_clear (&fragment);
g_object_unref (download);
return FALSE;
}
buffer = gst_fragment_get_buffer (download);
g_object_unref (download);
+ /* it is possible to have an index per fragment, so check and download */
+ if (fragment.index_uri || fragment.index_range_start
+ || fragment.index_range_end != -1) {
+ const gchar *uri = fragment.index_uri;
+ GstBuffer *index_buffer;
+
+ if (!uri) /* fallback to default media uri */
+ uri = fragment.uri;
+
+ GST_DEBUG_OBJECT (demux,
+ "Fragment index download: %s %" G_GINT64_FORMAT "-%"
+ G_GINT64_FORMAT, uri, fragment.index_range_start,
+ fragment.index_range_end);
+ download =
+ gst_uri_downloader_fetch_uri_with_range (demux->downloader, uri,
+ fragment.index_range_start, fragment.index_range_end);
+ if (download) {
+ index_buffer = gst_fragment_get_buffer (download);
+ if (index_buffer)
+ buffer = gst_buffer_append (index_buffer, buffer);
+ g_object_unref (download);
+ }
+ }
+
if (selected_stream->need_header) {
/* We need to fetch a new header */
if ((header_buffer =
buffer = gst_buffer_make_writable (buffer);
- GST_BUFFER_TIMESTAMP (buffer) = timestamp;
- GST_BUFFER_DURATION (buffer) = duration;
+ GST_BUFFER_TIMESTAMP (buffer) = fragment.timestamp;
+ GST_BUFFER_DURATION (buffer) = fragment.duration;
GST_BUFFER_OFFSET (buffer) =
gst_mpd_client_get_segment_index (active_stream) - 1;
+ gst_media_fragment_info_clear (&fragment);
+
gst_dash_demux_stream_push_data (selected_stream, buffer);
selected_stream->has_data_queued = TRUE;
size_buffer += gst_buffer_get_size (buffer);
gboolean
gst_mpd_client_get_next_fragment (GstMpdClient * client,
- guint indexStream, gboolean * discontinuity, gchar ** uri,
- gint64 * range_start, gint64 * range_end,
- GstClockTime * duration, GstClockTime * timestamp)
+ guint indexStream, GstMediaFragmentInfo * fragment)
{
GstActiveStream *stream = NULL;
GstMediaSegment *currentChunk;
gchar *mediaURL = NULL;
+ gchar *indexURL = NULL;
guint segment_idx;
/* select stream */
stream = g_list_nth_data (client->active_streams, indexStream);
g_return_val_if_fail (stream != NULL, FALSE);
g_return_val_if_fail (stream->cur_representation != NULL, FALSE);
- g_return_val_if_fail (discontinuity != NULL, FALSE);
GST_MPD_CLIENT_LOCK (client);
segment_idx = gst_mpd_client_get_segment_index (stream);
GST_DEBUG ("currentChunk->SegmentURL = %p", currentChunk->SegmentURL);
if (currentChunk->SegmentURL != NULL) {
- mediaURL = g_strdup (gst_mpdparser_get_mediaURL (stream, currentChunk->SegmentURL));
+ mediaURL =
+ g_strdup (gst_mpdparser_get_mediaURL (stream,
+ currentChunk->SegmentURL));
+ indexURL = currentChunk->SegmentURL->index;
} else if (stream->cur_seg_template != NULL) {
mediaURL =
gst_mpdparser_build_URL_from_template (stream->cur_seg_template->media,
stream->cur_representation->id, currentChunk->number,
stream->cur_representation->bandwidth, currentChunk->start);
+ if (stream->cur_seg_template->index) {
+ indexURL =
+ gst_mpdparser_build_URL_from_template (stream->cur_seg_template->
+ index, stream->cur_representation->id, currentChunk->number,
+ stream->cur_representation->bandwidth, currentChunk->start);
+ }
}
GST_DEBUG ("mediaURL = %s", mediaURL);
-
- *timestamp = currentChunk->start_time;
- *duration = currentChunk->duration;
- *discontinuity = segment_idx != currentChunk->number;
- *range_start = 0;
- *range_end = -1;
- if (currentChunk->SegmentURL && currentChunk->SegmentURL->mediaRange) {
- *range_start = currentChunk->SegmentURL->mediaRange->first_byte_pos;
- *range_end = currentChunk->SegmentURL->mediaRange->last_byte_pos;
+ GST_DEBUG ("indexURL = %s", indexURL);
+
+ fragment->timestamp = currentChunk->start_time;
+ fragment->duration = currentChunk->duration;
+ fragment->discontinuity = segment_idx != currentChunk->number;
+ fragment->range_start = 0;
+ fragment->range_end = -1;
+ fragment->index_uri = NULL;
+ fragment->index_range_start = 0;
+ fragment->index_range_end = -1;
+ if (currentChunk->SegmentURL) {
+ if (currentChunk->SegmentURL->mediaRange) {
+ fragment->range_start =
+ currentChunk->SegmentURL->mediaRange->first_byte_pos;
+ fragment->range_end = currentChunk->SegmentURL->mediaRange->last_byte_pos;
+ }
+ if (currentChunk->SegmentURL->indexRange) {
+ fragment->index_range_start =
+ currentChunk->SegmentURL->indexRange->first_byte_pos;
+ fragment->index_range_end =
+ currentChunk->SegmentURL->indexRange->last_byte_pos;
+ }
}
if (mediaURL == NULL) {
/* single segment with URL encoded in the baseURL syntax element */
- *uri = g_strdup (stream->baseURL);
+ fragment->uri = g_strdup (stream->baseURL);
} else if (strncmp (mediaURL, "http://", 7) != 0) {
- *uri = g_strconcat (stream->baseURL, mediaURL, stream->queryURL, NULL);
+ fragment->uri =
+ g_strconcat (stream->baseURL, mediaURL, stream->queryURL, NULL);
} else {
- *uri = g_strconcat (mediaURL, stream->queryURL, NULL);
+ fragment->uri = g_strconcat (mediaURL, stream->queryURL, NULL);
}
g_free (mediaURL);
+
+ if (indexURL != NULL) {
+ if (strncmp (indexURL, "http://", 7) != 0) {
+ fragment->index_uri =
+ g_strconcat (stream->baseURL, indexURL, stream->queryURL, NULL);
+ } else {
+ fragment->index_uri = g_strconcat (indexURL, stream->queryURL, NULL);
+ }
+ g_free (indexURL);
+ } else if (fragment->index_range_start || fragment->index_range_end != -1) {
+ /* index has no specific URL but has a range, we should only use this if
+ * the media also has a range, otherwise we are serving some data twice
+ * (in the media fragment and again in the index) */
+ if (!(fragment->range_start || fragment->range_end != -1)) {
+ GST_WARNING ("Ignoring index ranges because there isn't a media range "
+ "and URIs would be the same");
+ /* removing index information */
+ fragment->index_range_start = 0;
+ fragment->index_range_end = -1;
+ }
+ }
+
gst_mpd_client_set_segment_index (stream, segment_idx + 1);
GST_MPD_CLIENT_UNLOCK (client);
- GST_DEBUG ("Loading chunk with URL %s", *uri);
+ GST_DEBUG ("Loading chunk with URL %s", fragment->uri);
return TRUE;
}
*uri = NULL;
if (stream->cur_segment_base && stream->cur_segment_base->Initialization) {
*uri =
- g_strdup (gst_mpdparser_get_initializationURL (stream, stream->cur_segment_base->
- Initialization));
+ g_strdup (gst_mpdparser_get_initializationURL (stream,
+ stream->cur_segment_base->Initialization));
if (stream->cur_segment_base->Initialization->range) {
*range_start =
stream->cur_segment_base->Initialization->range->first_byte_pos;
*uri = NULL;
if (stream->cur_segment_base && stream->cur_segment_base->indexRange) {
*uri =
- g_strdup (gst_mpdparser_get_initializationURL (stream, stream->cur_segment_base->
- Initialization));
- *range_start =
- stream->cur_segment_base->indexRange->first_byte_pos;
- *range_end =
- stream->cur_segment_base->indexRange->last_byte_pos;
+ g_strdup (gst_mpdparser_get_initializationURL (stream,
+ stream->cur_segment_base->Initialization));
+ *range_start = stream->cur_segment_base->indexRange->first_byte_pos;
+ *range_end = stream->cur_segment_base->indexRange->last_byte_pos;
} else if (stream->cur_seg_template) {
const gchar *initialization = NULL;
if (stream->cur_seg_template->index) {
return nb_adapatation_set;
}
+
+void
+gst_media_fragment_info_clear (GstMediaFragmentInfo * fragment)
+{
+ g_free (fragment->uri);
+ g_free (fragment->index_uri);
+}
typedef struct _GstMpdClient GstMpdClient;
typedef struct _GstActiveStream GstActiveStream;
typedef struct _GstStreamPeriod GstStreamPeriod;
+typedef struct _GstMediaFragmentInfo GstMediaFragmentInfo;
typedef struct _GstMediaSegment GstMediaSegment;
typedef struct _GstMPDNode GstMPDNode;
typedef struct _GstPeriodNode GstPeriodNode;
GstClockTime duration; /* segment duration */
};
+struct _GstMediaFragmentInfo
+{
+ gchar *uri;
+ gint64 range_start;
+ gint64 range_end;
+
+ gchar *index_uri;
+ gint64 index_range_start;
+ gint64 index_range_end;
+
+ gboolean discontinuity;
+ GstClockTime timestamp;
+ GstClockTime duration;
+};
+
/**
* GstActiveStream:
*
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);
/* MPD file parsing */
gboolean gst_mpd_parse (GstMpdClient *client, const gchar *data, gint size);
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_next_fragment_timestamp (GstMpdClient * client, guint stream_idx, GstClockTime * ts);
-gboolean gst_mpd_client_get_next_fragment (GstMpdClient *client, guint indexStream, gboolean *discontinuity, gchar **uri, gint64 * range_start, gint64 * range_end, GstClockTime *duration, GstClockTime *timestamp);
+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);