dashdemux: create src pads for subtitle streams.

Create src pads for Representations that contain timed-text subtitles,
both when the subtitles are encapsulated in ISO BMFF (i.e., the
Representation has mimeType "application/mp4") and when they are
unencapsulated (i.e., the Representation has mimeType
"application/ttml+xml").

https://bugzilla.gnome.org/show_bug.cgi?id=747774
This commit is contained in:
Chris Bass 2015-08-18 14:16:11 +01:00 committed by Sebastian Dröge
parent bed2c6820f
commit 69f86e51b2
4 changed files with 65 additions and 22 deletions

View file

@ -167,6 +167,12 @@ GST_STATIC_PAD_TEMPLATE ("audio_%02u",
GST_PAD_SOMETIMES, GST_PAD_SOMETIMES,
GST_STATIC_CAPS_ANY); 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", static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
@ -377,6 +383,8 @@ gst_dash_demux_class_init (GstDashDemuxClass * klass)
gst_static_pad_template_get (&gst_dash_demux_audiosrc_template)); gst_static_pad_template_get (&gst_dash_demux_audiosrc_template));
gst_element_class_add_pad_template (gstelement_class, gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_dash_demux_videosrc_template)); 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_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sinktemplate)); gst_static_pad_template_get (&sinktemplate));
@ -535,11 +543,11 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
active_stream = gst_mpdparser_get_active_stream_by_index (demux->client, i); active_stream = gst_mpdparser_get_active_stream_by_index (demux->client, i);
if (active_stream == NULL) if (active_stream == NULL)
continue; continue;
/* TODO: support 'application' mimeType */
if (active_stream->mimeType == GST_STREAM_APPLICATION)
continue;
srcpad = gst_dash_demux_create_pad (demux, active_stream); srcpad = gst_dash_demux_create_pad (demux, active_stream);
if (srcpad == NULL)
continue;
caps = gst_dash_demux_get_input_caps (demux, active_stream); caps = gst_dash_demux_get_input_caps (demux, active_stream);
GST_LOG_OBJECT (demux, "Creating stream %d %" GST_PTR_FORMAT, i, caps); GST_LOG_OBJECT (demux, "Creating stream %d %" GST_PTR_FORMAT, i, caps);
@ -771,6 +779,15 @@ gst_dash_demux_create_pad (GstDashDemux * demux, GstActiveStream * stream)
name = g_strdup_printf ("video_%02u", demux->n_video_streams++); name = g_strdup_printf ("video_%02u", demux->n_video_streams++);
tmpl = gst_static_pad_template_get (&gst_dash_demux_videosrc_template); tmpl = gst_static_pad_template_get (&gst_dash_demux_videosrc_template);
break; 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: default:
g_assert_not_reached (); g_assert_not_reached ();
return NULL; return NULL;
@ -814,7 +831,6 @@ gst_dash_demux_get_video_input_caps (GstDashDemux * demux,
GstActiveStream * stream) GstActiveStream * stream)
{ {
guint width = 0, height = 0; guint width = 0, height = 0;
const gchar *mimeType = NULL;
GstCaps *caps = NULL; GstCaps *caps = NULL;
if (stream == NULL) if (stream == NULL)
@ -825,11 +841,10 @@ gst_dash_demux_get_video_input_caps (GstDashDemux * demux,
width = gst_mpd_client_get_video_stream_width (stream); width = gst_mpd_client_get_video_stream_width (stream);
height = gst_mpd_client_get_video_stream_height (stream); height = gst_mpd_client_get_video_stream_height (stream);
} }
mimeType = gst_mpd_client_get_stream_mimeType (stream); caps = gst_mpd_client_get_stream_caps (stream);
if (mimeType == NULL) if (caps == NULL)
return NULL; return NULL;
caps = gst_caps_from_string (mimeType);
if (width > 0 && height > 0) { if (width > 0 && height > 0) {
gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height", gst_caps_set_simple (caps, "width", G_TYPE_INT, width, "height",
G_TYPE_INT, height, NULL); G_TYPE_INT, height, NULL);
@ -843,7 +858,6 @@ gst_dash_demux_get_audio_input_caps (GstDashDemux * demux,
GstActiveStream * stream) GstActiveStream * stream)
{ {
guint rate = 0, channels = 0; guint rate = 0, channels = 0;
const gchar *mimeType;
GstCaps *caps = NULL; GstCaps *caps = NULL;
if (stream == NULL) if (stream == NULL)
@ -854,11 +868,10 @@ gst_dash_demux_get_audio_input_caps (GstDashDemux * demux,
channels = gst_mpd_client_get_audio_stream_num_channels (stream); channels = gst_mpd_client_get_audio_stream_num_channels (stream);
rate = gst_mpd_client_get_audio_stream_rate (stream); rate = gst_mpd_client_get_audio_stream_rate (stream);
} }
mimeType = gst_mpd_client_get_stream_mimeType (stream); caps = gst_mpd_client_get_stream_caps (stream);
if (mimeType == NULL) if (caps == NULL)
return NULL; return NULL;
caps = gst_caps_from_string (mimeType);
if (rate > 0) { if (rate > 0) {
gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate, NULL); gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate, NULL);
} }
@ -873,18 +886,15 @@ static GstCaps *
gst_dash_demux_get_application_input_caps (GstDashDemux * demux, gst_dash_demux_get_application_input_caps (GstDashDemux * demux,
GstActiveStream * stream) GstActiveStream * stream)
{ {
const gchar *mimeType;
GstCaps *caps = NULL; GstCaps *caps = NULL;
if (stream == NULL) if (stream == NULL)
return NULL; return NULL;
mimeType = gst_mpd_client_get_stream_mimeType (stream); caps = gst_mpd_client_get_stream_caps (stream);
if (mimeType == NULL) if (caps == NULL)
return NULL; return NULL;
caps = gst_caps_from_string (mimeType);
return caps; return caps;
} }

View file

@ -99,6 +99,7 @@ struct _GstDashDemux
gint n_audio_streams; gint n_audio_streams;
gint n_video_streams; gint n_video_streams;
gint n_subtitle_streams;
}; };
struct _GstDashDemuxClass struct _GstDashDemuxClass

View file

@ -5256,6 +5256,27 @@ gst_mpdparser_get_active_stream_by_index (GstMpdClient * client,
return g_list_nth_data (client->active_streams, stream_idx); 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 * static const gchar *
gst_mpdparser_mimetype_to_caps (const gchar * mimeType) gst_mpdparser_mimetype_to_caps (const gchar * mimeType)
{ {
@ -5271,10 +5292,11 @@ gst_mpdparser_mimetype_to_caps (const gchar * mimeType)
return mimeType; return mimeType;
} }
const gchar * GstCaps *
gst_mpd_client_get_stream_mimeType (GstActiveStream * stream) 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 if (stream == NULL || stream->cur_adapt_set == NULL
|| stream->cur_representation == NULL) || stream->cur_representation == NULL)
@ -5285,7 +5307,16 @@ gst_mpd_client_get_stream_mimeType (GstActiveStream * stream)
mimeType = stream->cur_adapt_set->RepresentationBase->mimeType; 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 gboolean

View file

@ -569,6 +569,7 @@ gboolean gst_mpdparser_get_chunk_by_index (GstMpdClient *client, guint indexStre
/* Active stream */ /* Active stream */
guint gst_mpdparser_get_nb_active_stream (GstMpdClient *client); guint gst_mpdparser_get_nb_active_stream (GstMpdClient *client);
GstActiveStream *gst_mpdparser_get_active_stream_by_index (GstMpdClient *client, guint stream_idx); GstActiveStream *gst_mpdparser_get_active_stream_by_index (GstMpdClient *client, guint stream_idx);
gboolean gst_mpd_client_active_stream_contains_subtitles (GstActiveStream * stream);
/* AdaptationSet */ /* AdaptationSet */
guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client); guint gst_mpdparser_get_nb_adaptationSet (GstMpdClient *client);
@ -580,8 +581,8 @@ GstFlowReturn gst_mpd_client_advance_segment (GstMpdClient * client, GstActiveSt
void gst_mpd_client_seek_to_first_segment (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); 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) */ /* Get audio/video stream parameters (caps, width, height, rate, number of channels) */
const gchar *gst_mpd_client_get_stream_mimeType (GstActiveStream * stream); GstCaps * gst_mpd_client_get_stream_caps (GstActiveStream * stream);
gboolean gst_mpd_client_get_bitstream_switching_flag (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_width (GstActiveStream * stream);
guint gst_mpd_client_get_video_stream_height (GstActiveStream * stream); guint gst_mpd_client_get_video_stream_height (GstActiveStream * stream);