dashdemux: expose all streams

always expose all streams instead of only exposing one of each type.

This is more aligned with gstreamer's way of working. Allows the user
to select the stream that it wants to use by linking its pad and leaving
the unused ones as unlinked.
This commit is contained in:
Thiago Santos 2013-12-02 17:31:41 -03:00
parent 7f5422c06d
commit 08636f3bab
3 changed files with 60 additions and 216 deletions

View file

@ -650,43 +650,20 @@ static gboolean
gst_dash_demux_setup_mpdparser_streams (GstDashDemux * demux, gst_dash_demux_setup_mpdparser_streams (GstDashDemux * demux,
GstMpdClient * client) GstMpdClient * client)
{ {
GList *listLang = NULL;
guint i, nb_audio;
gchar *lang;
gboolean has_streams = FALSE; gboolean has_streams = FALSE;
GList *adapt_sets, *iter;
if (!gst_mpd_client_setup_streaming (client, GST_STREAM_VIDEO, "")) adapt_sets = gst_mpd_client_get_adaptation_sets (client);
GST_INFO_OBJECT (demux, "No video adaptation set found"); for (iter = adapt_sets; iter; iter = g_list_next (iter)) {
else GstAdaptationSetNode *adapt_set_node = iter->data;
gst_mpd_client_setup_streaming (client, adapt_set_node);
has_streams = TRUE; has_streams = TRUE;
nb_audio =
gst_mpdparser_get_list_and_nb_of_audio_language (client, &listLang);
if (nb_audio == 0)
nb_audio = 1;
GST_INFO_OBJECT (demux, "Number of languages is=%d", nb_audio);
for (i = 0; i < nb_audio; i++) {
lang = (gchar *) g_list_nth_data (listLang, i);
GST_INFO ("nb adaptation set: %i",
gst_mpdparser_get_nb_adaptationSet (client));
if (!gst_mpd_client_setup_streaming (client, GST_STREAM_AUDIO, lang))
GST_INFO_OBJECT (demux, "No audio adaptation set found");
else
has_streams = TRUE;
if (gst_mpdparser_get_nb_adaptationSet (client) > nb_audio) {
if (!gst_mpd_client_setup_streaming (client,
GST_STREAM_APPLICATION, lang)) {
GST_INFO_OBJECT (demux, "No application adaptation set found");
} else {
has_streams = TRUE;
}
}
} }
if (!has_streams) { if (!has_streams) {
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, ("Manifest has no playable " GST_ELEMENT_ERROR (demux, STREAM, DEMUX, ("Manifest has no playable "
"streams"), ("No streams could be activated from the manifest")); "streams"), ("No streams could be activated from the manifest"));
} }
return has_streams; return has_streams;
} }

View file

@ -139,17 +139,6 @@ static GstClockTime gst_mpd_client_get_segment_duration (GstMpdClient * client,
static GstDateTime *gst_mpd_client_get_availability_start_time (GstMpdClient * static GstDateTime *gst_mpd_client_get_availability_start_time (GstMpdClient *
client); client);
/* Adaptation Set */
static GstAdaptationSetNode
* gst_mpdparser_get_first_adapt_set_with_mimeType (GList * AdaptationSets,
const gchar * mimeType);
static GstAdaptationSetNode
* gst_mpdparser_get_adapt_set_with_mimeType_and_idx (GList * AdaptationSets,
const gchar * mimeType, gint idx);
static GstAdaptationSetNode
* gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang (GList *
AdaptationSets, const gchar * mimeType, const gchar * lang);
/* Representation */ /* Representation */
static GstRepresentationNode *gst_mpdparser_get_lowest_representation (GList * static GstRepresentationNode *gst_mpdparser_get_lowest_representation (GList *
Representations); Representations);
@ -1931,114 +1920,25 @@ strncmp_ext (const char *s1, const char *s2)
} }
/* navigation functions */ /* navigation functions */
static GstAdaptationSetNode * static GstStreamMimeType
gst_mpdparser_get_first_adapt_set_with_mimeType (GList * AdaptationSets, gst_mpdparser_representation_get_mimetype (GstAdaptationSetNode * adapt_set,
const gchar * mimeType) GstRepresentationNode * rep)
{ {
GList *list; gchar *mime = NULL;
GstAdaptationSetNode *adapt_set; if (rep->RepresentationBase)
mime = rep->RepresentationBase->mimeType;
if (AdaptationSets == NULL) if (mime == NULL && adapt_set->RepresentationBase) {
return NULL; mime = adapt_set->RepresentationBase->mimeType;
for (list = g_list_first (AdaptationSets); list; list = g_list_next (list)) {
adapt_set = (GstAdaptationSetNode *) list->data;
if (adapt_set) {
gchar *this_mimeType = NULL;
GstRepresentationNode *rep;
rep =
gst_mpdparser_get_lowest_representation (adapt_set->Representations);
if (rep->RepresentationBase)
this_mimeType = rep->RepresentationBase->mimeType;
if (!this_mimeType && adapt_set->RepresentationBase) {
this_mimeType = adapt_set->RepresentationBase->mimeType;
}
GST_DEBUG ("Looking for mime type %s -> %s", mimeType, this_mimeType);
if (strncmp_ext (this_mimeType, mimeType) == 0)
return adapt_set;
}
} }
return NULL; if (strncmp_ext (mime, "audio"))
} return GST_STREAM_AUDIO;
if (strncmp_ext (mime, "video"))
return GST_STREAM_VIDEO;
if (strncmp_ext (mime, "application"))
return GST_STREAM_APPLICATION;
/* if idx < 0, returns the highest adaptation set with the given mimeType return GST_STREAM_UNKNOWN;
* if idx >= 0, returns the highest adaptation set with the given mimeType and an index <= idx
*/
static GstAdaptationSetNode *
gst_mpdparser_get_adapt_set_with_mimeType_and_idx (GList * AdaptationSets,
const gchar * mimeType, gint idx)
{
GList *list;
GstAdaptationSetNode *adapt_set, *selected = NULL;
gint i = 0;
if (AdaptationSets == NULL)
return NULL;
/* FIXME Use ContentComponent to determine if this adaptation set contains
* the content type we're looking for. */
for (list = g_list_first (AdaptationSets); list; list = g_list_next (list)) {
adapt_set = (GstAdaptationSetNode *) list->data;
if (adapt_set) {
gchar *this_mimeType = NULL;
GstRepresentationNode *rep;
rep =
gst_mpdparser_get_lowest_representation (adapt_set->Representations);
if (rep->RepresentationBase)
this_mimeType = rep->RepresentationBase->mimeType;
if (!this_mimeType && adapt_set->RepresentationBase)
this_mimeType = adapt_set->RepresentationBase->mimeType;
GST_DEBUG ("Looking for mime type %s -> %i: %s", mimeType, i,
this_mimeType);
if (strncmp_ext (this_mimeType, mimeType) == 0) {
if (idx < 0 || i <= idx)
selected = adapt_set;
i++;
}
}
}
return selected;
}
static GstAdaptationSetNode *
gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang (GList *
AdaptationSets, const gchar * mimeType, const gchar * lang)
{
GList *list;
GstAdaptationSetNode *adapt_set;
if (AdaptationSets == NULL)
return NULL;
for (list = g_list_first (AdaptationSets); list; list = g_list_next (list)) {
adapt_set = (GstAdaptationSetNode *) list->data;
if (adapt_set) {
GstRepresentationNode *rep;
gchar *this_lang = adapt_set->lang;
gchar *this_mimeType = NULL;
rep =
gst_mpdparser_get_lowest_representation (adapt_set->Representations);
#ifndef GST_DISABLE_GST_DEBUG
if (rep && rep->BaseURLs) {
GstBaseURL *url = rep->BaseURLs->data;
GST_DEBUG ("%s", url->baseURL);
}
#endif
if (rep->RepresentationBase)
this_mimeType = rep->RepresentationBase->mimeType;
if (!this_mimeType && adapt_set->RepresentationBase) {
this_mimeType = adapt_set->RepresentationBase->mimeType;
}
GST_DEBUG ("Looking for mime type %s -> %s", mimeType, this_mimeType);
if (strncmp_ext (this_mimeType, mimeType) == 0
&& strncmp_ext (this_lang, lang) == 0)
return adapt_set;
}
}
return NULL;
} }
static GstRepresentationNode * static GstRepresentationNode *
@ -3394,80 +3294,40 @@ no_mem:
return FALSE; return FALSE;
} }
gboolean static GList *
gst_mpd_client_setup_streaming (GstMpdClient * client, gst_mpd_client_get_adaptation_sets_for_period (GstMpdClient * client,
GstStreamMimeType mimeType, const gchar * lang) GstStreamPeriod * period)
{
g_return_val_if_fail (period != NULL, NULL);
return period->period->AdaptationSets;
}
GList *
gst_mpd_client_get_adaptation_sets (GstMpdClient * client)
{ {
GstActiveStream *stream;
GstStreamPeriod *stream_period; GstStreamPeriod *stream_period;
GstAdaptationSetNode *adapt_set;
GstRepresentationNode *representation;
GList *rep_list = NULL;
stream_period = gst_mpdparser_get_stream_period (client); stream_period = gst_mpdparser_get_stream_period (client);
if (stream_period == NULL || stream_period->period == NULL) { if (stream_period == NULL || stream_period->period == NULL) {
GST_DEBUG ("No more Period nodes in the MPD file, terminating..."); GST_DEBUG ("No more Period nodes in the MPD file, terminating...");
return FALSE; return NULL;
} }
switch (mimeType) { return gst_mpd_client_get_adaptation_sets_for_period (client, stream_period);
case GST_STREAM_VIDEO: }
/* select the adaptation set for the video pipeline */
adapt_set = gboolean
gst_mpdparser_get_adapt_set_with_mimeType_and_idx gst_mpd_client_setup_streaming (GstMpdClient * client,
(stream_period->period->AdaptationSets, "video", 0); GstAdaptationSetNode * adapt_set)
if (!adapt_set) { {
GST_INFO ("No video adaptation set found"); GstRepresentationNode *representation;
return FALSE; GList *rep_list = NULL;
} GstActiveStream *stream;
/* retrive the list of representations */
rep_list = adapt_set->Representations; rep_list = adapt_set->Representations;
if (!rep_list) { if (!rep_list) {
GST_WARNING ("Can not retrieve any representation, aborting..."); GST_WARNING ("Can not retrieve any representation, aborting...");
return FALSE; return FALSE;
}
break;
case GST_STREAM_AUDIO:
adapt_set =
gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang
(stream_period->period->AdaptationSets, "audio", lang);
/* if we did not found the requested audio language, get the first one */
if (!adapt_set)
adapt_set =
gst_mpdparser_get_first_adapt_set_with_mimeType
(stream_period->period->AdaptationSets, "audio");
if (!adapt_set) {
GST_INFO ("No audio adaptation set found");
return FALSE;
}
rep_list = adapt_set->Representations;
if (!rep_list) {
GST_WARNING ("Can not retrieve any representation, aborting...");
return FALSE;
}
break;
case GST_STREAM_APPLICATION:
adapt_set =
gst_mpdparser_get_first_adapt_set_with_mimeType_and_lang
(stream_period->period->AdaptationSets, "application", lang);
/* if we did not found the requested subtitles language, get the first one */
if (!adapt_set)
adapt_set =
gst_mpdparser_get_first_adapt_set_with_mimeType
(stream_period->period->AdaptationSets, "application");
if (!adapt_set) {
GST_INFO ("No application adaptation set found");
return FALSE;
}
rep_list = adapt_set->Representations;
if (!rep_list) {
GST_WARNING ("Can not retrieve any representation, aborting...");
return FALSE;
}
break;
default:
GST_WARNING ("Unsupported mimeType %d", mimeType);
return FALSE;
} }
stream = g_slice_new0 (GstActiveStream); stream = g_slice_new0 (GstActiveStream);
@ -3476,10 +3336,8 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
return FALSE; return FALSE;
} }
gst_mpdparser_init_active_stream_segments (stream); gst_mpdparser_init_active_stream_segments (stream);
client->active_streams = g_list_append (client->active_streams, stream);
stream->baseURL_idx = 0; stream->baseURL_idx = 0;
stream->mimeType = mimeType;
stream->cur_adapt_set = adapt_set; stream->cur_adapt_set = adapt_set;
GST_DEBUG ("0. Current stream %p", stream); GST_DEBUG ("0. Current stream %p", stream);
@ -3508,12 +3366,19 @@ gst_mpd_client_setup_streaming (GstMpdClient * client,
GST_WARNING ("No valid representation in the MPD file, aborting..."); GST_WARNING ("No valid representation in the MPD file, aborting...");
return FALSE; return FALSE;
} }
stream->mimeType =
gst_mpdparser_representation_get_mimetype (adapt_set, representation);
if (stream->mimeType == GST_STREAM_UNKNOWN) {
g_slice_free (GstActiveStream, stream);
return FALSE;
}
client->active_streams = g_list_append (client->active_streams, stream);
if (!gst_mpd_client_setup_representation (client, stream, representation)) if (!gst_mpd_client_setup_representation (client, stream, representation))
return FALSE; return FALSE;
GST_INFO ("Successfully setup the download pipeline for mimeType %d", GST_INFO ("Successfully setup the download pipeline for mimeType %d",
mimeType); stream->mimeType);
return TRUE; return TRUE;
} }

View file

@ -67,6 +67,7 @@ typedef struct _GstMultSegmentBaseType GstMultSegmentBaseType;
typedef enum typedef enum
{ {
GST_STREAM_UNKNOWN,
GST_STREAM_VIDEO, /* video stream (the main one) */ GST_STREAM_VIDEO, /* video stream (the main one) */
GST_STREAM_AUDIO, /* audio stream (optional) */ GST_STREAM_AUDIO, /* audio stream (optional) */
GST_STREAM_APPLICATION /* application stream (optional): for timed text/subtitles */ GST_STREAM_APPLICATION /* application stream (optional): for timed text/subtitles */
@ -482,8 +483,9 @@ gboolean gst_mpd_parse (GstMpdClient *client, const gchar *data, gint size);
/* Streaming management */ /* Streaming management */
gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client); gboolean gst_mpd_client_setup_media_presentation (GstMpdClient *client);
gboolean gst_mpd_client_setup_streaming (GstMpdClient *client, GstStreamMimeType mimeType, const gchar* lang); gboolean gst_mpd_client_setup_streaming (GstMpdClient * client, GstAdaptationSetNode * adapt_set);
gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation); gboolean gst_mpd_client_setup_representation (GstMpdClient *client, GstActiveStream *stream, GstRepresentationNode *representation);
GList * gst_mpd_client_get_adaptation_sets (GstMpdClient * client);
GstClockTime gst_mpd_client_get_next_fragment_duration (GstMpdClient * client, GstActiveStream * stream); 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_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);