dashdemux: create src pads for subtitle streams.
authorChris Bass <floobleflam@gmail.com>
Tue, 18 Aug 2015 13:16:11 +0000 (14:16 +0100)
committerSebastian Dröge <sebastian@centricular.com>
Fri, 25 Sep 2015 22:50:55 +0000 (00:50 +0200)
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

ext/dash/gstdashdemux.c
ext/dash/gstdashdemux.h
ext/dash/gstmpdparser.c
ext/dash/gstmpdparser.h

index 20d6764..9091753 100644 (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;
 }
 
index ca2af31..3d01a0b 100644 (file)
@@ -99,6 +99,7 @@ struct _GstDashDemux
 
   gint n_audio_streams;
   gint n_video_streams;
+  gint n_subtitle_streams;
 };
 
 struct _GstDashDemuxClass
index bb9d7b0..80148e0 100644 (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
index 36569b5..6e29d22 100644 (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);