gst/matroska/: Set DISCONT flag on first buffer after a discontinuity.
authorTim-Philipp Müller <tim@centricular.net>
Thu, 20 Apr 2006 13:23:40 +0000 (13:23 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Thu, 20 Apr 2006 13:23:40 +0000 (13:23 +0000)
Original commit message from CVS:
* gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream),
(gst_matroskademux_do_index_seek),
(gst_matroska_demux_handle_seek_event),
(gst_matroska_demux_parse_blockgroup_or_simpleblock):
* gst/matroska/matroska-ids.h:
Set DISCONT flag on first buffer after a discontinuity.
Fix newsegment events sent when seeking and honour KEY_UNIT
seek flag. Create pad with bogus caps if we don't recognise
the stream codec id.
* gst/matroska/matroska-demux.h:
Fix GObject macros.

ChangeLog
gst/matroska/matroska-demux.c
gst/matroska/matroska-demux.h
gst/matroska/matroska-ids.h

index ef83d1cc030842fa12164a2159f35b15c6083be7..daaf793357db57788ee23c47467cce111314c2f8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2006-04-20  Tim-Philipp Müller  <tim at centricular dot net>
+
+       * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream),
+       (gst_matroskademux_do_index_seek),
+       (gst_matroska_demux_handle_seek_event),
+       (gst_matroska_demux_parse_blockgroup_or_simpleblock):
+       * gst/matroska/matroska-ids.h:
+         Set DISCONT flag on first buffer after a discontinuity.
+         Fix newsegment events sent when seeking and honour KEY_UNIT
+         seek flag. Create pad with bogus caps if we don't recognise
+         the stream codec id.
+
+       * gst/matroska/matroska-demux.h:
+         Fix GObject macros.
+
 2006-04-20  Tim-Philipp Müller  <tim at centricular dot net>
 
        Patch by: Mark Nauwelaerts  <manauw at skynet dot be>
index f342781303b0a84132a0cbc38e4e85f2ff151124..1d4248ad40a54641b784cded1c2944be2423a0c4 100644 (file)
@@ -315,6 +315,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
   context->type = 0;            /* no type yet */
   context->default_duration = 0;
   context->pos = 0;
+  context->set_discont = TRUE;
   demux->num_streams++;
 
   /* start with the master */
@@ -908,9 +909,29 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         GST_TAG_LANGUAGE_CODE, context->language, NULL);
   }
 
+  if (caps == NULL) {
+    GST_WARNING_OBJECT (demux, "could not determine caps for stream with "
+        "codec_id='%s'", context->codec_id);
+    switch (context->type) {
+      case GST_MATROSKA_TRACK_TYPE_VIDEO:
+        caps = gst_caps_new_simple ("video/x-unknown", NULL);
+        break;
+      case GST_MATROSKA_TRACK_TYPE_AUDIO:
+        caps = gst_caps_new_simple ("audio/x-unknown", NULL);
+        break;
+      case GST_MATROSKA_TRACK_TYPE_SUBTITLE:
+        caps = gst_caps_new_simple ("application/x-subtitle-unknown", NULL);
+        break;
+      case GST_MATROSKA_TRACK_TYPE_COMPLEX:
+      default:
+        caps = gst_caps_new_simple ("application/x-matroska-unknown", NULL);
+        break;
+    }
+  }
+
   /* the pad in here */
   context->pad = gst_pad_new_from_template (templ, padname);
-  context->caps = caps ? caps : gst_caps_new_empty ();
+  context->caps = caps;
 
   gst_pad_set_event_function (context->pad,
       GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_event));
@@ -919,20 +940,13 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
   gst_pad_set_query_function (context->pad,
       GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_query));
 
-  if (caps) {
-    GST_LOG ("Adding pad '%s' with caps %" GST_PTR_FORMAT, padname, caps);
-    if (gst_caps_is_fixed (caps)) {
-      gst_pad_use_fixed_caps (context->pad);
-      gst_pad_set_caps (context->pad, context->caps);
-      gst_pad_set_active (context->pad, TRUE);
-      gst_element_add_pad (GST_ELEMENT (demux), context->pad);
-    } else {
-      g_warning ("FIXME: non-fixed caps: %s", gst_caps_to_string (caps));
-    }
-  } else {
-    /* FIXME: are we leaking the pad here? can this even happen? */
-    GST_LOG ("Not adding pad '%s' with empty caps", padname);
-  }
+  GST_INFO_OBJECT (demux, "Adding pad '%s' with caps %" GST_PTR_FORMAT,
+      padname, caps);
+
+  gst_pad_use_fixed_caps (context->pad);
+  gst_pad_set_caps (context->pad, context->caps);
+  gst_pad_set_active (context->pad, TRUE);
+  gst_element_add_pad (GST_ELEMENT (demux), context->pad);
 
   /* tags */
   if (list) {
@@ -1014,21 +1028,41 @@ gst_matroska_demux_handle_src_query (GstPad * pad, GstQuery * query)
 
 
 static GstMatroskaIndex *
-gst_matroskademux_do_index_seek (GstMatroskaDemux * demux, guint64 seek_pos)
+gst_matroskademux_do_index_seek (GstMatroskaDemux * demux, gint64 seek_pos,
+    gint64 segment_stop, gboolean keyunit)
 {
-  guint entry = demux->num_indexes - 1;
+  guint entry;
   guint n = 0;
 
   if (!demux->num_indexes)
     return NULL;
 
-  while (n < demux->num_indexes - 1) {
-    if ((demux->index[n].time <= seek_pos) &&
-        (demux->index[n + 1].time > seek_pos)) {
-      entry = n;
-      break;
+  if (keyunit) {
+    /* find index entry closest to the requested position */
+    entry = 0;
+    for (n = 0; n < demux->num_indexes; ++n) {
+      gdouble d_entry, d_this;
+
+      d_entry = fabs ((gdouble) demux->index[entry].time - (gdouble) seek_pos);
+      d_this = fabs ((gdouble) demux->index[n].time - (gdouble) seek_pos);
+
+      if (d_this < d_entry &&
+          (demux->index[n].time < segment_stop || segment_stop == -1)) {
+        entry = n;
+      }
+    }
+  } else {
+    /* find index entry at or before the requested position */
+    entry = demux->num_indexes - 1;
+
+    while (n < demux->num_indexes - 1) {
+      if ((demux->index[n].time <= seek_pos) &&
+          (demux->index[n + 1].time > seek_pos)) {
+        entry = n;
+        break;
+      }
+      n++;
     }
-    n++;
   }
 
   return &demux->index[entry];
@@ -1080,7 +1114,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
   GstSeekType cur_type, stop_type;
   GstFormat format;
   GstEvent *newsegment_event;
-  gboolean flush;
+  gboolean flush, keyunit;
   gdouble rate;
   gint64 cur, stop;
   gint64 segment_start, segment_stop;
@@ -1104,7 +1138,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
   /* check sanity before we start flushing and all that */
   if (cur_type == GST_SEEK_TYPE_SET) {
     GST_OBJECT_LOCK (demux);
-    if (!gst_matroskademux_do_index_seek (demux, cur)) {
+    if (!gst_matroskademux_do_index_seek (demux, cur, -1, FALSE)) {
       GST_DEBUG ("No matching seek entry in index");
       GST_OBJECT_UNLOCK (demux);
       return FALSE;
@@ -1114,6 +1148,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
   }
 
   flush = !!(flags & GST_SEEK_FLAG_FLUSH);
+  keyunit = !!(flags & GST_SEEK_FLAG_KEY_UNIT);
 
   if (flush) {
     GST_DEBUG ("Starting flush");
@@ -1156,7 +1191,9 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
   GST_DEBUG ("New segment positions: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
       GST_TIME_ARGS (segment_start), GST_TIME_ARGS (segment_stop));
 
-  entry = gst_matroskademux_do_index_seek (demux, segment_start);
+  entry = gst_matroskademux_do_index_seek (demux, segment_start,
+      segment_stop, keyunit);
+
   if (!entry) {
     GST_DEBUG ("No matching seek entry in index");
     goto seek_error;
@@ -1173,6 +1210,12 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
   GST_DEBUG ("Seeked to offset %" G_GUINT64_FORMAT, entry->pos +
       demux->ebml_segment_start);
 
+  if (keyunit) {
+    GST_DEBUG ("seek to key unit, adjusting segment start to %"
+        GST_TIME_FORMAT, GST_TIME_ARGS (entry->time));
+    segment_start = entry->time;
+  }
+
   GST_DEBUG ("Committing new seek segment");
 
   demux->segment_rate = rate;
@@ -1192,9 +1235,8 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
     gst_element_post_message (GST_ELEMENT (demux), msg);
   }
 
-  /* FIXME: should be demux->segment_start, not entry->time */
   newsegment_event = gst_event_new_new_segment (FALSE, rate,
-      GST_FORMAT_TIME, entry->time, segment_stop, entry->time);
+      GST_FORMAT_TIME, segment_start, segment_stop, segment_start);
 
   GST_DEBUG ("Stopping flush");
   if (flush) {
@@ -1204,8 +1246,10 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
 
   /* send newsegment event to all source pads and update the time */
   gst_matroska_demux_send_event (demux, newsegment_event);
-  for (i = 0; i < demux->num_streams; i++)
+  for (i = 0; i < demux->num_streams; i++) {
     demux->src[i]->pos = entry->time;
+    demux->src[i]->set_discont = TRUE;
+  }
   demux->pos = entry->time;
 
   /* restart our task since it might have been stopped when we did the
@@ -2363,6 +2407,11 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
           GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT);
       }
 
+      if (stream->set_discont) {
+        GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DISCONT);
+        stream->set_discont = FALSE;
+      }
+
       GST_DEBUG ("Pushing data of size %d for stream %d, time=%"
           GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT,
           GST_BUFFER_SIZE (sub), stream_num,
index 14401a58942c33eb78cdce0847719d05ce382f67..49b073bb158fa290c25e3295c627f8ececa30bf2 100644 (file)
@@ -34,10 +34,10 @@ G_BEGIN_DECLS
 #define GST_MATROSKA_DEMUX(obj) \
   (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MATROSKA_DEMUX, GstMatroskaDemux))
 #define GST_MATROSKA_DEMUX_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MATROSKA_DEMUX, GstMatroskaDemux))
+  (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MATROSKA_DEMUX, GstMatroskaDemuxClass))
 #define GST_IS_MATROSKA_DEMUX(obj) \
   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MATROSKA_DEMUX))
-#define GST_IS_MATROSKA_DEMUX_CLASS(obj) \
+#define GST_IS_MATROSKA_DEMUX_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MATROSKA_DEMUX))
 
 #define GST_MATROSKA_DEMUX_MAX_STREAMS 64       
index 71dfc634379c5cc0e6063092790fd8c39c81d774..c8c6d37179f5b8dfe321b271779b6657d854ec9c 100644 (file)
@@ -243,6 +243,8 @@ typedef struct _GstMatroskaTrackContext {
   GstMatroskaTrackFlags flags;
   guint64       default_duration;
   guint64       pos;
+
+  gboolean      set_discont; /* TRUE = set DISCONT flag on next buffer */
 } GstMatroskaTrackContext;
 
 typedef struct _GstMatroskaTrackVideoContext {