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_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,
@ -377,6 +383,8 @@ gst_dash_demux_class_init (GstDashDemuxClass * klass)
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));
@ -535,11 +543,11 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
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);
@ -771,6 +779,15 @@ gst_dash_demux_create_pad (GstDashDemux * demux, GstActiveStream * stream)
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;
@ -814,7 +831,6 @@ gst_dash_demux_get_video_input_caps (GstDashDemux * demux,
GstActiveStream * stream)
{
guint width = 0, height = 0;
const gchar *mimeType = NULL;
GstCaps *caps = 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);
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);
@ -843,7 +858,6 @@ gst_dash_demux_get_audio_input_caps (GstDashDemux * demux,
GstActiveStream * stream)
{
guint rate = 0, channels = 0;
const gchar *mimeType;
GstCaps *caps = 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);
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);
}
@ -873,18 +886,15 @@ static GstCaps *
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;
}

View file

@ -99,6 +99,7 @@ struct _GstDashDemux
gint n_audio_streams;
gint n_video_streams;
gint n_subtitle_streams;
};
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);
}
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)
{
@ -5271,10 +5292,11 @@ 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)
@ -5285,7 +5307,16 @@ gst_mpd_client_get_stream_mimeType (GstActiveStream * stream)
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

View file

@ -569,6 +569,7 @@ gboolean gst_mpdparser_get_chunk_by_index (GstMpdClient *client, guint indexStre
/* 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);
@ -580,8 +581,8 @@ GstFlowReturn gst_mpd_client_advance_segment (GstMpdClient * client, GstActiveSt
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);