stream = (GstDashDemuxStream *)
gst_adaptive_demux_stream_new (GST_ADAPTIVE_DEMUX_CAST (demux), srcpad);
stream->active_stream = active_stream;
+
+ if (active_stream->cur_representation) {
+ stream->last_representation_id =
+ g_strdup (stream->active_stream->cur_representation->id);
+ } else {
+ stream->last_representation_id = NULL;
+ }
+
s = gst_caps_get_structure (caps, 0);
stream->allow_sidx =
gst_mpd_client_has_isoff_ondemand_profile (demux->client);
if (gst_mpd_client_get_next_fragment_timestamp (dashdemux->client,
dashstream->index, &ts)) {
+ /* For live streams, check whether the underlying representation changed
+ * (due to a manifest update with no matching representation) */
+ if (gst_mpd_client_is_live (dashdemux->client)
+ && !GST_ADAPTIVE_DEMUX_STREAM_NEED_HEADER (stream)) {
+ if (dashstream->active_stream
+ && dashstream->active_stream->cur_representation) {
+ /* id specifies an identifier for this Representation. The
+ * identifier shall be unique within a Period unless the
+ * Representation is functionally identically to another
+ * Representation in the same Period. */
+ if (g_strcmp0 (dashstream->active_stream->cur_representation->id,
+ dashstream->last_representation_id)) {
+ GstCaps *caps;
+ stream->need_header = TRUE;
+
+ GST_INFO_OBJECT (dashdemux,
+ "Representation changed from %s to %s - updating to bitrate %d",
+ GST_STR_NULL (dashstream->last_representation_id),
+ GST_STR_NULL (dashstream->active_stream->cur_representation->id),
+ dashstream->active_stream->cur_representation->bandwidth);
+
+ caps =
+ gst_dash_demux_get_input_caps (dashdemux,
+ dashstream->active_stream);
+ gst_adaptive_demux_stream_set_caps (stream, caps);
+
+ /* Update the stored last representation id */
+ g_free (dashstream->last_representation_id);
+ dashstream->last_representation_id =
+ g_strdup (dashstream->active_stream->cur_representation->id);
+ }
+ } else {
+ g_free (dashstream->last_representation_id);
+ dashstream->last_representation_id = NULL;
+ }
+ }
+
if (GST_ADAPTIVE_DEMUX_STREAM_NEED_HEADER (stream)) {
gst_adaptive_demux_stream_fragment_clear (&stream->fragment);
gst_dash_demux_stream_update_headers_info (stream);
gst_adaptive_demux_stream_set_caps (stream, caps);
ret = TRUE;
+ /* Update the stored last representation id */
+ g_free (dashstream->last_representation_id);
+ dashstream->last_representation_id =
+ g_strdup (active_stream->cur_representation->id);
} else {
GST_WARNING_OBJECT (demux, "Can not switch representation, aborting...");
}
streams = demux->streams;
}
- /* update the streams to play from the next segment */
+ /* update the streams to preserve the current representation if there is one,
+ * and to play from the next segment */
for (iter = streams, streams_iter = new_client->active_streams;
iter && streams_iter;
iter = g_list_next (iter), streams_iter = g_list_next (streams_iter)) {
return GST_FLOW_EOS;
}
+ if (new_stream->cur_adapt_set
+ && demux_stream->last_representation_id != NULL) {
+
+ GList *rep_list = new_stream->cur_adapt_set->Representations;
+ GstMPDRepresentationNode *rep_node =
+ gst_mpd_client_get_representation_with_id (rep_list,
+ demux_stream->last_representation_id);
+ if (rep_node != NULL) {
+ if (gst_mpd_client_setup_representation (new_client, new_stream,
+ rep_node)) {
+ GST_DEBUG_OBJECT (GST_ADAPTIVE_DEMUX_STREAM_PAD (demux_stream),
+ "Found and set up matching representation %s in new manifest",
+ demux_stream->last_representation_id);
+ } else {
+ GST_ERROR_OBJECT (GST_ADAPTIVE_DEMUX_STREAM_PAD (demux_stream),
+ "Failed to set up representation %s in new manifest",
+ demux_stream->last_representation_id);
+ gst_mpd_client_free (new_client);
+ gst_buffer_unmap (buffer, &mapinfo);
+ return GST_FLOW_EOS;
+ }
+ } else {
+ /* If we failed to find the current representation,
+ * then update_fragment_info() will reconfigure to the
+ * new settings after the current download finishes */
+ GST_WARNING_OBJECT (GST_ADAPTIVE_DEMUX_STREAM_PAD (demux_stream),
+ "Failed to find representation %s in new manifest",
+ demux_stream->last_representation_id);
+ }
+ }
+
if (gst_mpd_client_get_next_fragment_timestamp (dashdemux->client,
demux_stream->index, &ts)
|| gst_mpd_client_get_last_fragment_timestamp_end (dashdemux->client,
gst_isoff_moof_box_free (dash_stream->moof);
if (dash_stream->moof_sync_samples)
g_array_free (dash_stream->moof_sync_samples, TRUE);
+ g_free (dash_stream->last_representation_id);
}
static GstDashDemuxClockDrift *
return NULL;
}
-static GstMPDNode *
+GstMPDRepresentationNode *
gst_mpd_client_get_representation_with_id (GList * representations,
gchar * rep_id)
{
for (list = g_list_first (representations); list; list = g_list_next (list)) {
representation = (GstMPDRepresentationNode *) list->data;
if (!g_strcmp0 (representation->id, rep_id))
- return GST_MPD_NODE (representation);
+ return GST_MPD_REPRESENTATION_NODE (representation);
}
return NULL;
}
+static GstMPDNode *
+gst_mpd_client_get_representation_with_id_filter (GList * representations,
+ gchar * rep_id)
+{
+ GstMPDRepresentationNode *representation =
+ gst_mpd_client_get_representation_with_id (representations, rep_id);
+
+ if (representation != NULL)
+ return GST_MPD_NODE (representation);
+
+ return NULL;
+}
+
static gchar *
_generate_new_string_id (GList * list, const gchar * tuple,
MpdClientStringIDFilter filter)
(period_node->AdaptationSets, adaptation_set_id));
g_return_val_if_fail (adap_set_node != NULL, NULL);
rep_node =
- GST_MPD_REPRESENTATION_NODE (gst_mpd_client_get_representation_with_id
- (adap_set_node->Representations, representation_id));
+ gst_mpd_client_get_representation_with_id (adap_set_node->Representations,
+ representation_id);
if (!rep_node) {
rep_node = gst_mpd_representation_node_new ();
if (representation_id)
else
rep_node->id =
_generate_new_string_id (adap_set_node->Representations,
- "representation_%.2d", gst_mpd_client_get_representation_with_id);
+ "representation_%.2d",
+ gst_mpd_client_get_representation_with_id_filter);
GST_DEBUG_OBJECT (client, "Add a new representation with id %s",
rep_node->id);
adap_set_node->Representations =
g_return_val_if_fail (adaptation_set != NULL, FALSE);
representation =
- GST_MPD_REPRESENTATION_NODE (gst_mpd_client_get_representation_with_id
- (adaptation_set->Representations, rep_id));
+ gst_mpd_client_get_representation_with_id
+ (adaptation_set->Representations, rep_id);
if (!representation->SegmentList) {
representation->SegmentList = gst_mpd_segment_list_node_new ();
}
g_return_val_if_fail (adaptation_set != NULL, FALSE);
representation =
- GST_MPD_REPRESENTATION_NODE (gst_mpd_client_get_representation_with_id
- (adaptation_set->Representations, rep_id));
+ gst_mpd_client_get_representation_with_id
+ (adaptation_set->Representations, rep_id);
if (!representation->SegmentTemplate) {
representation->SegmentTemplate = gst_mpd_segment_template_node_new ();
}
g_return_val_if_fail (adaptation_set != NULL, FALSE);
representation =
- GST_MPD_REPRESENTATION_NODE (gst_mpd_client_get_representation_with_id
- (adaptation_set->Representations, rep_id));
+ gst_mpd_client_get_representation_with_id
+ (adaptation_set->Representations, rep_id);
if (!representation->SegmentList) {
representation->SegmentList = gst_mpd_segment_list_node_new ();