GST_PAD_SOMETIMES,
GST_STATIC_CAPS_ANY);
+static GstStaticPadTemplate gst_dash_demux_subtitlesrc_template =
+GST_STATIC_PAD_TEMPLATE ("subtitle_%02u",
+ GST_PAD_SRC,
+ GST_PAD_SOMETIMES,
+ GST_STATIC_CAPS_ANY);
+
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
gst_static_pad_template_get (&gst_dash_demux_audiosrc_template));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_dash_demux_videosrc_template));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&gst_dash_demux_subtitlesrc_template));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sinktemplate));
active_stream = gst_mpdparser_get_active_stream_by_index (demux->client, i);
if (active_stream == NULL)
continue;
- /* TODO: support 'application' mimeType */
- if (active_stream->mimeType == GST_STREAM_APPLICATION)
- continue;
srcpad = gst_dash_demux_create_pad (demux, active_stream);
+ if (srcpad == NULL)
+ continue;
+
caps = gst_dash_demux_get_input_caps (demux, active_stream);
GST_LOG_OBJECT (demux, "Creating stream %d %" GST_PTR_FORMAT, i, caps);
name = g_strdup_printf ("video_%02u", demux->n_video_streams++);
tmpl = gst_static_pad_template_get (&gst_dash_demux_videosrc_template);
break;
+ case GST_STREAM_APPLICATION:
+ if (gst_mpd_client_active_stream_contains_subtitles (stream)) {
+ name = g_strdup_printf ("subtitle_%02u", demux->n_subtitle_streams++);
+ tmpl =
+ gst_static_pad_template_get (&gst_dash_demux_subtitlesrc_template);
+ } else {
+ return NULL;
+ }
+ break;
default:
g_assert_not_reached ();
return NULL;
GstActiveStream * stream)
{
guint width = 0, height = 0;
- const gchar *mimeType = NULL;
GstCaps *caps = NULL;
if (stream == NULL)
width = gst_mpd_client_get_video_stream_width (stream);
height = gst_mpd_client_get_video_stream_height (stream);
}
- mimeType = gst_mpd_client_get_stream_mimeType (stream);
- if (mimeType == NULL)
+ caps = gst_mpd_client_get_stream_caps (stream);
+ if (caps == NULL)
return NULL;
- caps = gst_caps_from_string (mimeType);
if (width > 0 && height > 0) {
gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height",
G_TYPE_INT, height, NULL);
GstActiveStream * stream)
{
guint rate = 0, channels = 0;
- const gchar *mimeType;
GstCaps *caps = NULL;
if (stream == NULL)
channels = gst_mpd_client_get_audio_stream_num_channels (stream);
rate = gst_mpd_client_get_audio_stream_rate (stream);
}
- mimeType = gst_mpd_client_get_stream_mimeType (stream);
- if (mimeType == NULL)
+ caps = gst_mpd_client_get_stream_caps (stream);
+ if (caps == NULL)
return NULL;
- caps = gst_caps_from_string (mimeType);
if (rate > 0) {
gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate, NULL);
}
gst_dash_demux_get_application_input_caps (GstDashDemux * demux,
GstActiveStream * stream)
{
- const gchar *mimeType;
GstCaps *caps = NULL;
if (stream == NULL)
return NULL;
- mimeType = gst_mpd_client_get_stream_mimeType (stream);
- if (mimeType == NULL)
+ caps = gst_mpd_client_get_stream_caps (stream);
+ if (caps == NULL)
return NULL;
- caps = gst_caps_from_string (mimeType);
-
return caps;
}
return g_list_nth_data (client->active_streams, stream_idx);
}
+gboolean
+gst_mpd_client_active_stream_contains_subtitles (GstActiveStream * stream)
+{
+ const gchar *mimeType;
+ const gchar *adapt_set_codecs;
+ const gchar *rep_codecs;
+
+ mimeType = stream->cur_representation->RepresentationBase->mimeType;
+ if (!mimeType)
+ mimeType = stream->cur_adapt_set->RepresentationBase->mimeType;
+
+ if (g_strcmp0 (mimeType, "application/ttml+xml") == 0)
+ return TRUE;
+
+ adapt_set_codecs = stream->cur_adapt_set->RepresentationBase->codecs;
+ rep_codecs = stream->cur_representation->RepresentationBase->codecs;
+
+ return (adapt_set_codecs && g_str_has_prefix (adapt_set_codecs, "stpp"))
+ || (rep_codecs && g_str_has_prefix (rep_codecs, "stpp"));
+}
+
static const gchar *
gst_mpdparser_mimetype_to_caps (const gchar * mimeType)
{
return mimeType;
}
-const gchar *
-gst_mpd_client_get_stream_mimeType (GstActiveStream * stream)
+GstCaps *
+gst_mpd_client_get_stream_caps (GstActiveStream * stream)
{
- const gchar *mimeType;
+ const gchar *mimeType, *caps_string;
+ GstCaps *ret = NULL;
if (stream == NULL || stream->cur_adapt_set == NULL
|| stream->cur_representation == NULL)
mimeType = stream->cur_adapt_set->RepresentationBase->mimeType;
}
- return gst_mpdparser_mimetype_to_caps (mimeType);
+ caps_string = gst_mpdparser_mimetype_to_caps (mimeType);
+
+ if ((g_strcmp0 (caps_string, "application/mp4") == 0)
+ && gst_mpd_client_active_stream_contains_subtitles (stream))
+ caps_string = "video/quicktime";
+
+ if (caps_string)
+ ret = gst_caps_from_string (caps_string);
+
+ return ret;
}
gboolean
/* 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);
void gst_mpd_client_seek_to_first_segment (GstMpdClient * client);
GstDateTime *gst_mpd_client_get_next_segment_availability_end_time (GstMpdClient * client, GstActiveStream * stream);
-/* Get audio/video stream parameters (mimeType, width, height, rate, number of channels) */
-const gchar *gst_mpd_client_get_stream_mimeType (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);