qtdemux: unselect instead of ignoring disabled track, detect chapter track
authorMatej Knopp <matej.knopp@gmail.com>
Thu, 11 Jul 2013 14:13:05 +0000 (16:13 +0200)
committerSebastian Dröge <slomo@circular-chaos.org>
Fri, 12 Jul 2013 09:45:33 +0000 (11:45 +0200)
https://bugzilla.gnome.org/show_bug.cgi?id=704007

gst/isomp4/qtdemux.c
gst/isomp4/qtdemux.h
gst/isomp4/qtdemux_fourcc.h
gst/isomp4/qtdemux_types.c

index ca5f9d5..b530c25 100644 (file)
@@ -351,6 +351,8 @@ struct _QtDemuxStream
   guint32 def_sample_duration;
   guint32 def_sample_size;
   guint32 def_sample_flags;
+
+  gboolean disabled;
 };
 
 enum QtDemuxState
@@ -1813,6 +1815,7 @@ gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
     qtdemux->duration = 0;
     qtdemux->mfra_offset = 0;
     qtdemux->moof_offset = 0;
+    qtdemux->chapters_track_id = 0;
   }
   qtdemux->offset = 0;
   gst_adapter_clear (qtdemux->adapter);
@@ -4094,8 +4097,9 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
   /* gap events for subtitle streams */
   for (i = 0; i < qtdemux->n_streams; i++) {
     stream = qtdemux->streams[i];
-    if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
-        || stream->subtype == FOURCC_sbtl) {
+    if (stream->pad && (stream->subtype == FOURCC_subp
+            || stream->subtype == FOURCC_text
+            || stream->subtype == FOURCC_sbtl)) {
       /* send one second gap events until the stream catches up */
       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
@@ -5672,11 +5676,16 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
     if (stream->new_stream) {
       gchar *stream_id;
+      GstEvent *event;
 
       stream->new_stream = FALSE;
       stream_id =
           gst_pad_create_stream_id_printf (stream->pad,
           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
+      event = gst_event_new_stream_start (stream_id);
+      if (stream->disabled) {
+        gst_event_set_stream_flags (event, GST_STREAM_FLAG_UNSELECT);
+      }
       gst_pad_push_event (stream->pad, gst_event_new_stream_start (stream_id));
       g_free (stream_id);
     }
@@ -6909,6 +6918,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
   GNode *wave;
   GNode *esds;
   GNode *pasp;
+  GNode *tref;
+
   QtDemuxStream *stream = NULL;
   GstTagList *list = NULL;
   gchar *codec = NULL;
@@ -6928,9 +6939,6 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
     goto corrupt_file;
 
-  if ((tkhd_flags & 1) == 0)
-    goto track_disabled;
-
   /* pick between 64 or 32 bits */
   value_size = tkhd_version == 1 ? 8 : 4;
   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
@@ -6950,6 +6958,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
     }
   }
 
+  if ((tkhd_flags & 1) == 0)
+    stream->disabled = TRUE;
+
   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
       tkhd_version, tkhd_flags, stream->track_id);
 
@@ -6999,6 +7010,21 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
     goto corrupt_file;
 
+  if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
+    /* chapters track reference */
+    GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
+    if (chap) {
+      gsize length = GST_READ_UINT32_BE (chap->data);
+      if (qtdemux->chapters_track_id)
+        GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
+
+      if (length >= 12) {
+        qtdemux->chapters_track_id =
+            GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
+      }
+    }
+  }
+
   /* fragmented files may have bogus duration in moov */
   if (!qtdemux->fragmented &&
       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
@@ -8126,7 +8152,6 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
 
 /* ERRORS */
 skip_track:
-track_disabled:
   {
     GST_INFO_OBJECT (qtdemux, "skip disabled track");
     g_free (stream);
@@ -8363,6 +8388,13 @@ qtdemux_expose_streams (GstQTDemux * qtdemux)
     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
         i, stream->track_id, GST_FOURCC_ARGS (stream->fourcc));
 
+    if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
+        stream->track_id == qtdemux->chapters_track_id) {
+      /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
+         so that it doesn't look like a subtitle track */
+      continue;
+    }
+
     /* now we have all info and can expose */
     list = stream->pending_tags;
     stream->pending_tags = NULL;
index efc6ffa..7a527e3 100644 (file)
@@ -121,6 +121,8 @@ struct _GstQTDemux {
   gboolean exposed;
   gboolean mss_mode; /* flag to indicate that we're working with a smoothstreaming fragment */
   guint64 fragment_start;
+    
+  gint64 chapters_track_id;
 };
 
 struct _GstQTDemuxClass {
index 077b54b..9e66072 100644 (file)
@@ -240,6 +240,9 @@ G_BEGIN_DECLS
 /* MPEG DASH */
 #define FOURCC_tfdt     GST_MAKE_FOURCC('t','f','d','t')
 
+/* Chapters reference */
+#define FOURCC_chap     GST_MAKE_FOURCC('c','h','a','p')
+
 G_END_DECLS
 
 #endif /* __GST_QTDEMUX_FOURCC_H__ */
index c676734..92e1814 100644 (file)
@@ -172,6 +172,7 @@ static const QtNodeType qt_node_types[] = {
   {FOURCC_ovc1, "ovc1", 0},
   {FOURCC_owma, "owma", 0},
   {FOURCC_tfdt, "Track fragment decode time", 0, qtdemux_dump_tfdt},
+  {FOURCC_chap, "Chapter Reference"},
   {0, "unknown", 0,},
 };