gst/matroska/: Handle return values from pull_range in a more granular way to properl...
authorWim Taymans <wim.taymans@gmail.com>
Thu, 6 Mar 2008 19:47:48 +0000 (19:47 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 6 Mar 2008 19:47:48 +0000 (19:47 +0000)
Original commit message from CVS:
* gst/matroska/ebml-read.c: (gst_ebml_read_peek_bytes),
(gst_ebml_read_pull_bytes), (gst_ebml_read_element_id),
(gst_ebml_read_element_length), (gst_ebml_peek_id),
(gst_ebml_read_skip), (gst_ebml_read_buffer),
(gst_ebml_read_bytes), (gst_ebml_read_uint), (gst_ebml_read_sint),
(gst_ebml_read_float), (gst_ebml_read_ascii), (gst_ebml_read_utf8),
(gst_ebml_read_date), (gst_ebml_read_master),
(gst_ebml_read_binary), (gst_ebml_read_header):
* gst/matroska/ebml-read.h:
* gst/matroska/matroska-demux.c:
(gst_matroska_demux_combine_flows), (gst_matroska_demux_reset),
(gst_matroska_demux_read_track_encodings),
(gst_matroska_demux_add_stream),
(gst_matroska_demux_handle_src_query),
(gst_matroska_demux_handle_seek_event),
(gst_matroska_demux_init_stream),
(gst_matroska_demux_parse_tracks),
(gst_matroska_demux_parse_index_cuetrack),
(gst_matroska_demux_parse_index_pointentry),
(gst_matroska_demux_parse_index), (gst_matroska_demux_parse_info),
(gst_matroska_demux_parse_metadata_id_simple_tag),
(gst_matroska_demux_parse_metadata_id_tag),
(gst_matroska_demux_parse_metadata),
(gst_matroska_demux_sync_streams),
(gst_matroska_demux_push_hdr_buf),
(gst_matroska_demux_push_flac_codec_priv_data),
(gst_matroska_demux_push_xiph_codec_priv_data),
(gst_matroska_demux_add_wvpk_header),
(gst_matroska_demux_check_subtitle_buffer),
(gst_matroska_demux_parse_blockgroup_or_simpleblock),
(gst_matroska_demux_parse_cluster),
(gst_matroska_demux_parse_contents_seekentry),
(gst_matroska_demux_parse_contents),
(gst_matroska_demux_loop_stream_parse_id),
(gst_matroska_demux_loop_stream), (gst_matroska_demux_loop):
* gst/matroska/matroska-demux.h:
* gst/matroska/matroska-ids.h:
Handle return values from pull_range in a more granular way to properly
shut down on seeks.
Combine return values from push.
Implement proper error handling.
Prepare for handling seeking correctly.

ChangeLog
common
gst/matroska/ebml-read.c
gst/matroska/ebml-read.h
gst/matroska/matroska-demux.c
gst/matroska/matroska-demux.h
gst/matroska/matroska-ids.h

index 2d02f73..ac7ae58 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,48 @@
+2008-03-06  Wim Taymans  <wim.taymans@collabora.co.uk>
+
+       * gst/matroska/ebml-read.c: (gst_ebml_read_peek_bytes),
+       (gst_ebml_read_pull_bytes), (gst_ebml_read_element_id),
+       (gst_ebml_read_element_length), (gst_ebml_peek_id),
+       (gst_ebml_read_skip), (gst_ebml_read_buffer),
+       (gst_ebml_read_bytes), (gst_ebml_read_uint), (gst_ebml_read_sint),
+       (gst_ebml_read_float), (gst_ebml_read_ascii), (gst_ebml_read_utf8),
+       (gst_ebml_read_date), (gst_ebml_read_master),
+       (gst_ebml_read_binary), (gst_ebml_read_header):
+       * gst/matroska/ebml-read.h:
+       * gst/matroska/matroska-demux.c:
+       (gst_matroska_demux_combine_flows), (gst_matroska_demux_reset),
+       (gst_matroska_demux_read_track_encodings),
+       (gst_matroska_demux_add_stream),
+       (gst_matroska_demux_handle_src_query),
+       (gst_matroska_demux_handle_seek_event),
+       (gst_matroska_demux_init_stream),
+       (gst_matroska_demux_parse_tracks),
+       (gst_matroska_demux_parse_index_cuetrack),
+       (gst_matroska_demux_parse_index_pointentry),
+       (gst_matroska_demux_parse_index), (gst_matroska_demux_parse_info),
+       (gst_matroska_demux_parse_metadata_id_simple_tag),
+       (gst_matroska_demux_parse_metadata_id_tag),
+       (gst_matroska_demux_parse_metadata),
+       (gst_matroska_demux_sync_streams),
+       (gst_matroska_demux_push_hdr_buf),
+       (gst_matroska_demux_push_flac_codec_priv_data),
+       (gst_matroska_demux_push_xiph_codec_priv_data),
+       (gst_matroska_demux_add_wvpk_header),
+       (gst_matroska_demux_check_subtitle_buffer),
+       (gst_matroska_demux_parse_blockgroup_or_simpleblock),
+       (gst_matroska_demux_parse_cluster),
+       (gst_matroska_demux_parse_contents_seekentry),
+       (gst_matroska_demux_parse_contents),
+       (gst_matroska_demux_loop_stream_parse_id),
+       (gst_matroska_demux_loop_stream), (gst_matroska_demux_loop):
+       * gst/matroska/matroska-demux.h:
+       * gst/matroska/matroska-ids.h:
+       Handle return values from pull_range in a more granular way to properly
+       shut down on seeks.
+       Combine return values from push.
+       Implement proper error handling.
+       Prepare for handling seeking correctly.
+
 2008-03-03  Jan Schmidt  <jan.schmidt@sun.com>
 
        * gst/matroska/ebml-read.c:
diff --git a/common b/common
index 081a00a..e02bd43 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 081a00a5e25d069b15bb7f6092c8f951462cd8eb
+Subproject commit e02bd43fe6b9e45536eccbf5b7a5f9eae62030fd
index 9c5ae4a..5335c55 100644 (file)
@@ -162,7 +162,7 @@ gst_ebml_read_element_level_up (GstEbmlRead * ebml)
 /*
  * Calls pull_range for (offset,size) without advancing our offset
  */
-static gboolean
+static GstFlowReturn
 gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
     guint8 ** bytes)
 {
@@ -182,29 +182,37 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
       if (bytes)
         *bytes =
             GST_BUFFER_DATA (ebml->cached_buffer) + ebml->offset - cache_offset;
-      return TRUE;
+      return GST_FLOW_OK;
     }
+    /* not enough data in the cache, free cache and get a new one */
     gst_buffer_unref (ebml->cached_buffer);
     ebml->cached_buffer = NULL;
   }
 
-  if (gst_pad_pull_range (ebml->sinkpad, ebml->offset, MAX (size, 64 * 1024),
-          &ebml->cached_buffer) == GST_FLOW_OK &&
-      GST_BUFFER_SIZE (ebml->cached_buffer) >= size) {
+  /* refill the cache */
+  ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, MAX (size, 64 * 1024),
+      &ebml->cached_buffer);
+  if (ret != GST_FLOW_OK) {
+    ebml->cached_buffer = NULL;
+    return ret;
+  }
+
+  if (GST_BUFFER_SIZE (ebml->cached_buffer) >= size) {
     if (p_buf)
       *p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size);
     if (bytes)
       *bytes = GST_BUFFER_DATA (ebml->cached_buffer);
-    return TRUE;
+    return GST_FLOW_OK;
   }
 
+  /* FIXME, seems silly to require this */
   if (!p_buf)
-    return FALSE;
+    return GST_FLOW_ERROR;
 
   ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, size, p_buf);
   if (ret != GST_FLOW_OK) {
     GST_DEBUG ("pull_range returned %d", ret);
-    return FALSE;
+    return ret;
   }
 
   if (GST_BUFFER_SIZE (*p_buf) < size) {
@@ -215,27 +223,30 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
     *p_buf = NULL;
     if (bytes)
       *bytes = NULL;
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
 
   if (bytes)
     *bytes = GST_BUFFER_DATA (*p_buf);
 
-  return TRUE;
+  return GST_FLOW_OK;
 }
 
 /*
  * Calls pull_range for (offset,size) and advances our offset by size
  */
-static gboolean
+static GstFlowReturn
 gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
     guint8 ** bytes)
 {
-  if (!gst_ebml_read_peek_bytes (ebml, size, p_buf, bytes))
-    return FALSE;
+  GstFlowReturn ret;
+
+  ret = gst_ebml_read_peek_bytes (ebml, size, p_buf, bytes);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   ebml->offset += size;
-  return TRUE;
+  return GST_FLOW_OK;
 }
 
 /*
@@ -243,16 +254,18 @@ gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
  * Return: FALSE on error.
  */
 
-static gboolean
+static GstFlowReturn
 gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
 {
   guint8 *buf;
   gint len_mask = 0x80, read = 1, n = 1;
   guint32 total;
   guint8 b;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf))
-    return FALSE;
+  ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   b = GST_READ_UINT8 (buf);
 
@@ -268,11 +281,12 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
         ("Invalid EBML ID size tag (0x%x) at position %" G_GUINT64_FORMAT
             " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
 
-  if (!gst_ebml_read_peek_bytes (ebml, read, NULL, &buf))
-    return FALSE;
+  ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   while (n < read) {
     b = GST_READ_UINT8 (buf + n);
@@ -287,7 +301,7 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
     *level_up = gst_ebml_read_element_level_up (ebml);
 
   ebml->offset += read;
-  return TRUE;
+  return GST_FLOW_OK;
 }
 
 /*
@@ -295,16 +309,19 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
  * Return: the number of bytes read or -1 on error.
  */
 
-static gint
-gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
+static GstFlowReturn
+gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length,
+    gint * rread)
 {
+  GstFlowReturn ret;
   guint8 *buf;
   gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
   guint64 total;
   guint8 b;
 
-  if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf))
-    return -1;
+  ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   b = GST_READ_UINT8 (buf);
 
@@ -320,14 +337,15 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
         ("Invalid EBML length size tag (0x%x) at position %" G_GUINT64_FORMAT
             " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
-    return -1;
+    return GST_FLOW_ERROR;
   }
 
   if ((total &= (len_mask - 1)) == len_mask - 1)
     num_ffs++;
 
-  if (!gst_ebml_read_peek_bytes (ebml, read, NULL, &buf))
-    return -1;
+  ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   while (n < read) {
     guint8 b = GST_READ_UINT8 (buf + n);
@@ -343,9 +361,12 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
   else
     *length = total;
 
+  if (rread)
+    *rread = read;
+
   ebml->offset += read;
 
-  return read;
+  return GST_FLOW_OK;
 }
 
 /*
@@ -354,20 +375,21 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
  * next element lies higher than the previous one.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_peek_id (GstEbmlRead * ebml, guint * level_up, guint32 * id)
 {
   guint64 off;
+  GstFlowReturn ret;
 
   g_assert (level_up);
 
   off = ebml->offset;           /* save offset */
 
-  if (!gst_ebml_read_element_id (ebml, id, level_up))
-    return FALSE;
+  if ((ret = gst_ebml_read_element_id (ebml, id, level_up)) != GST_FLOW_OK)
+    return ret;
 
   ebml->offset = off;           /* restore offset */
-  return TRUE;
+  return ret;
 }
 
 /*
@@ -408,100 +430,111 @@ gst_ebml_read_seek (GstEbmlRead * ebml, guint64 offset)
  * Skip the next element.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_skip (GstEbmlRead * ebml)
 {
   guint64 length;
   guint32 id;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_element_id (ebml, &id, NULL))
-    return FALSE;
+  ret = gst_ebml_read_element_id (ebml, &id, NULL);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
-  if (gst_ebml_read_element_length (ebml, &length) < 0)
-    return FALSE;
+  ret = gst_ebml_read_element_length (ebml, &length, NULL);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   ebml->offset += length;
-  return TRUE;
+  return ret;
 }
 
 /*
  * Read the next element as a GstBuffer (binary).
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf)
 {
   guint64 length;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_element_id (ebml, id, NULL))
-    return FALSE;
+  ret = gst_ebml_read_element_id (ebml, id, NULL);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
-  if (gst_ebml_read_element_length (ebml, &length) < 0)
-    return FALSE;
+  ret = gst_ebml_read_element_length (ebml, &length, NULL);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   if (length == 0) {
     *buf = gst_buffer_new ();
-    return TRUE;
+    return GST_FLOW_OK;
   }
 
   *buf = NULL;
-  if (!gst_ebml_read_pull_bytes (ebml, (guint) length, buf, NULL))
-    return FALSE;
+  ret = gst_ebml_read_pull_bytes (ebml, (guint) length, buf, NULL);
 
-  return TRUE;
+  return ret;
 }
 
 /*
  * Read the next element, return a pointer to it and its size.
  */
 
-static gboolean
+static GstFlowReturn
 gst_ebml_read_bytes (GstEbmlRead * ebml, guint32 * id, guint8 ** data,
     guint * size)
 {
   guint64 length;
+  GstFlowReturn ret;
 
   *size = 0;
 
-  if (!gst_ebml_read_element_id (ebml, id, NULL))
-    return FALSE;
+  ret = gst_ebml_read_element_id (ebml, id, NULL);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
-  if (gst_ebml_read_element_length (ebml, &length) < 0)
-    return FALSE;
+  ret = gst_ebml_read_element_length (ebml, &length, NULL);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   if (length == 0) {
     *data = NULL;
-    return TRUE;
+    return ret;
   }
 
   *data = NULL;
-  if (!gst_ebml_read_pull_bytes (ebml, (guint) length, NULL, data))
-    return FALSE;
+  ret = gst_ebml_read_pull_bytes (ebml, (guint) length, NULL, data);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   *size = (guint) length;
 
-  return TRUE;
+  return ret;
 }
 
 /*
  * Read the next element as an unsigned int.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
 {
   guint8 *data;
   guint size;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_bytes (ebml, id, &data, &size))
-    return FALSE;
+  ret = gst_ebml_read_bytes (ebml, id, &data, &size);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   if (size < 1 || size > 8) {
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
         ("Invalid integer element size %d at position %" G_GUINT64_FORMAT
             " (0x%" G_GINT64_MODIFIER "x)",
             size, ebml->offset - size, ebml->offset - size));
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
   *num = 0;
   while (size > 0) {
@@ -510,29 +543,31 @@ gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
     data++;
   }
 
-  return TRUE;
+  return ret;
 }
 
 /*
  * Read the next element as a signed int.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
 {
   guint8 *data;
   guint size;
   gboolean negative = 0;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_bytes (ebml, id, &data, &size))
-    return FALSE;
+  ret = gst_ebml_read_bytes (ebml, id, &data, &size);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   if (size < 1 || size > 8) {
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
         ("Invalid integer element size %d at position %" G_GUINT64_FORMAT
             " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
             ebml->offset - size));
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
 
   *num = 0;
@@ -554,34 +589,36 @@ gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
     *num = 0 - *num;
   }
 
-  return TRUE;
+  return ret;
 }
 
 /*
  * Read the next element as a float.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
 {
   guint8 *data;
   guint size;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_bytes (ebml, id, &data, &size))
-    return FALSE;
+  ret = gst_ebml_read_bytes (ebml, id, &data, &size);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   if (size != 4 && size != 8 && size != 10) {
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
         ("Invalid float element size %d at position %" G_GUINT64_FORMAT
             " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
             ebml->offset - size));
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
 
   if (size == 10) {
     GST_ELEMENT_ERROR (ebml, CORE, NOT_IMPLEMENTED, (NULL),
         ("FIXME! 10-byte floats unimplemented"));
-    return FALSE;
+    return GST_FLOW_NOT_SUPPORTED;
   }
 
   if (size == 4) {
@@ -612,43 +649,47 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
     *num = d;
   }
 
-  return TRUE;
+  return ret;
 }
 
 /*
  * Read the next element as an ASCII string.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_ascii (GstEbmlRead * ebml, guint32 * id, gchar ** str)
 {
   guint8 *data;
   guint size;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_bytes (ebml, id, &data, &size))
-    return FALSE;
+  ret = gst_ebml_read_bytes (ebml, id, &data, &size);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   *str = g_malloc (size + 1);
   memcpy (*str, data, size);
   (*str)[size] = '\0';
 
-  return TRUE;
+  return ret;
 }
 
 /*
  * Read the next element as a UTF-8 string.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str)
 {
-  gboolean ret;
+  GstFlowReturn ret;
 
 #ifndef GST_DISABLE_GST_DEBUG
   guint64 oldoff = ebml->offset;
 #endif
 
   ret = gst_ebml_read_ascii (ebml, id, str);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   if (str != NULL && *str != NULL && **str != '\0' &&
       !g_utf8_validate (*str, -1, NULL)) {
@@ -663,14 +704,19 @@ gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str)
  * Returns the seconds since the unix epoch.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date)
 {
   gint64 ebml_date;
-  gboolean res = gst_ebml_read_sint (ebml, id, &ebml_date);
+  GstFlowReturn ret;
+
+  ret = gst_ebml_read_sint (ebml, id, &ebml_date);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   *date = (ebml_date / GST_SECOND) + GST_EBML_DATE_OFFSET;
-  return res;
+
+  return ret;
 }
 
 /*
@@ -678,17 +724,20 @@ gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date)
  * are supposed to be sub-elements which can be read separately.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id)
 {
   GstEbmlLevel *level;
   guint64 length;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_element_id (ebml, id, NULL))
-    return FALSE;
+  ret = gst_ebml_read_element_id (ebml, id, NULL);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
-  if (gst_ebml_read_element_length (ebml, &length) < 0)
-    return FALSE;
+  ret = gst_ebml_read_element_length (ebml, &length, NULL);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   /* remember level */
   level = g_new (GstEbmlLevel, 1);
@@ -696,39 +745,42 @@ gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id)
   level->length = length;
   ebml->level = g_list_append (ebml->level, level);
 
-  return TRUE;
+  return GST_FLOW_OK;
 }
 
 /*
  * Read the next element as binary data.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_binary (GstEbmlRead * ebml,
     guint32 * id, guint8 ** binary, guint64 * length)
 {
   guint8 *data;
   guint size;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_bytes (ebml, id, &data, &size))
-    return FALSE;
+  ret = gst_ebml_read_bytes (ebml, id, &data, &size);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   *length = size;
   *binary = g_memdup (data, size);
 
-  return TRUE;
+  return GST_FLOW_OK;
 }
 
 /*
  * Read an EBML header.
  */
 
-gboolean
+GstFlowReturn
 gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
 {
   /* this function is the first to be called */
   guint32 id;
   guint level_up;
+  GstFlowReturn ret;
 
   /* default init */
   if (doctype)
@@ -736,21 +788,24 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
   if (version)
     *version = 1;
 
-  if (!gst_ebml_peek_id (ebml, &level_up, &id))
-    return FALSE;
+  ret = gst_ebml_peek_id (ebml, &level_up, &id);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   GST_DEBUG_OBJECT (ebml, "id: %08x", GST_READ_UINT32_BE (&id));
 
   if (level_up != 0 || id != GST_EBML_ID_HEADER) {
     GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
-  if (!gst_ebml_read_master (ebml, &id))
-    return FALSE;
+  ret = gst_ebml_read_master (ebml, &id);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   while (TRUE) {
-    if (!gst_ebml_peek_id (ebml, &level_up, &id))
-      return FALSE;
+    ret = gst_ebml_peek_id (ebml, &level_up, &id);
+    if (ret != GST_FLOW_OK)
+      return ret;
 
     /* end-of-header */
     if (level_up)
@@ -761,11 +816,14 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
       case GST_EBML_ID_EBMLREADVERSION:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num))
-          return FALSE;
+        ret = gst_ebml_read_uint (ebml, &id, &num);
+        if (ret != GST_FLOW_OK)
+          return ret;
         g_assert (id == GST_EBML_ID_EBMLREADVERSION);
-        if (num != GST_EBML_VERSION)
-          return FALSE;
+        if (num != GST_EBML_VERSION) {
+          GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
+          return GST_FLOW_ERROR;
+        }
         break;
       }
 
@@ -773,11 +831,14 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
       case GST_EBML_ID_EBMLMAXSIZELENGTH:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num))
-          return FALSE;
+        ret = gst_ebml_read_uint (ebml, &id, &num);
+        if (ret != GST_FLOW_OK)
+          return ret;
         g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH);
-        if (num != sizeof (guint64))
-          return FALSE;
+        if (num != sizeof (guint64)) {
+          GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
+          return GST_FLOW_ERROR;
+        }
         break;
       }
 
@@ -785,19 +846,23 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
       case GST_EBML_ID_EBMLMAXIDLENGTH:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num))
-          return FALSE;
+        ret = gst_ebml_read_uint (ebml, &id, &num);
+        if (ret != GST_FLOW_OK)
+          return ret;
         g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH);
-        if (num != sizeof (guint32))
-          return FALSE;
+        if (num != sizeof (guint32)) {
+          GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
+          return GST_FLOW_ERROR;
+        }
         break;
       }
 
       case GST_EBML_ID_DOCTYPE:{
         gchar *text;
 
-        if (!gst_ebml_read_ascii (ebml, &id, &text))
-          return FALSE;
+        ret = gst_ebml_read_ascii (ebml, &id, &text);
+        if (ret != GST_FLOW_OK)
+          return ret;
         g_assert (id == GST_EBML_ID_DOCTYPE);
         if (doctype) {
           if (doctype)
@@ -811,8 +876,9 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
       case GST_EBML_ID_DOCTYPEREADVERSION:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num))
-          return FALSE;
+        ret = gst_ebml_read_uint (ebml, &id, &num);
+        if (ret != GST_FLOW_OK)
+          return ret;
         g_assert (id == GST_EBML_ID_DOCTYPEREADVERSION);
         if (version)
           *version = num;
@@ -827,11 +893,12 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
       case GST_EBML_ID_VOID:
       case GST_EBML_ID_EBMLVERSION:
       case GST_EBML_ID_DOCTYPEVERSION:
-        if (!gst_ebml_read_skip (ebml))
-          return FALSE;
+        ret = gst_ebml_read_skip (ebml);
+        if (ret != GST_FLOW_OK)
+          return ret;
         break;
     }
   }
 
-  return TRUE;
+  return GST_FLOW_OK;
 }
index f990ee5..54782b2 100644 (file)
@@ -59,58 +59,58 @@ typedef struct _GstEbmlReadClass {
   GstElementClass parent;
 } GstEbmlReadClass;
 
-GType    gst_ebml_read_get_type     (void);
+GType    gst_ebml_read_get_type          (void);
 
-gboolean gst_ebml_peek_id           (GstEbmlRead *ebml,
-                                     guint       *level_up,
-                                     guint32     *id);
+GstFlowReturn gst_ebml_peek_id           (GstEbmlRead *ebml,
+                                          guint       *level_up,
+                                          guint32     *id);
 
-gboolean gst_ebml_read_seek         (GstEbmlRead *ebml,
-                                     guint64      offset);
+GstFlowReturn gst_ebml_read_seek         (GstEbmlRead *ebml,
+                                          guint64      offset);
 
-gint64   gst_ebml_read_get_length   (GstEbmlRead *ebml);
+gint64        gst_ebml_read_get_length   (GstEbmlRead *ebml);
 
-gboolean gst_ebml_read_skip         (GstEbmlRead *ebml);
+GstFlowReturn gst_ebml_read_skip         (GstEbmlRead *ebml);
 
-gboolean gst_ebml_read_buffer       (GstEbmlRead *ebml,
-                                     guint32     *id,
-                                     GstBuffer  **buf);
+GstFlowReturn gst_ebml_read_buffer       (GstEbmlRead *ebml,
+                                          guint32     *id,
+                                          GstBuffer  **buf);
 
-gboolean gst_ebml_read_uint         (GstEbmlRead *ebml,
-                                     guint32     *id,
-                                     guint64     *num);
+GstFlowReturn gst_ebml_read_uint         (GstEbmlRead *ebml,
+                                          guint32     *id,
+                                          guint64     *num);
 
-gboolean gst_ebml_read_sint         (GstEbmlRead *ebml,
-                                     guint32     *id,
-                                     gint64      *num);
+GstFlowReturn gst_ebml_read_sint         (GstEbmlRead *ebml,
+                                          guint32     *id,
+                                          gint64      *num);
 
-gboolean gst_ebml_read_float        (GstEbmlRead *ebml,
-                                     guint32     *id,
-                                     gdouble     *num);
+GstFlowReturn gst_ebml_read_float        (GstEbmlRead *ebml,
+                                          guint32     *id,
+                                          gdouble     *num);
 
-gboolean gst_ebml_read_ascii        (GstEbmlRead *ebml,
-                                     guint32     *id,
-                                     gchar      **str);
+GstFlowReturn gst_ebml_read_ascii        (GstEbmlRead *ebml,
+                                          guint32     *id,
+                                          gchar      **str);
 
-gboolean gst_ebml_read_utf8         (GstEbmlRead *ebml,
-                                     guint32     *id,
-                                     gchar      **str);
+GstFlowReturn gst_ebml_read_utf8         (GstEbmlRead *ebml,
+                                          guint32     *id,
+                                          gchar      **str);
 
-gboolean gst_ebml_read_date         (GstEbmlRead *ebml,
-                                     guint32     *id,
-                                     gint64      *date);
+GstFlowReturn gst_ebml_read_date         (GstEbmlRead *ebml,
+                                          guint32     *id,
+                                          gint64      *date);
 
-gboolean gst_ebml_read_master       (GstEbmlRead *ebml,
-                                     guint32     *id);
+GstFlowReturn gst_ebml_read_master       (GstEbmlRead *ebml,
+                                          guint32     *id);
 
-gboolean gst_ebml_read_binary       (GstEbmlRead *ebml,
-                                     guint32     *id,
-                                     guint8     **binary,
-                                     guint64     *length);
+GstFlowReturn gst_ebml_read_binary       (GstEbmlRead *ebml,
+                                          guint32     *id,
+                                          guint8     **binary,
+                                          guint64     *length);
 
-gboolean gst_ebml_read_header       (GstEbmlRead *read,
-                                     gchar      **doctype,
-                                     guint       *version);
+GstFlowReturn gst_ebml_read_header       (GstEbmlRead *read,
+                                          gchar      **doctype,
+                                          guint       *version);
 
 G_END_DECLS
 
index 5fe16e3..039678b 100644 (file)
@@ -242,6 +242,42 @@ gst_matroska_track_free (GstMatroskaTrackContext * track)
   g_free (track);
 }
 
+/*
+ * Returns the aggregated GstFlowReturn.
+ */
+static GstFlowReturn
+gst_matroska_demux_combine_flows (GstMatroskaDemux * demux,
+    GstMatroskaTrackContext * track, GstFlowReturn ret)
+{
+  guint i;
+
+  /* store the value */
+  track->last_flow = ret;
+
+  /* any other error that is not-linked can be returned right away */
+  if (ret != GST_FLOW_NOT_LINKED)
+    goto done;
+
+  /* only return NOT_LINKED if all other pads returned NOT_LINKED */
+  for (i = 0; i < GST_MATROSKA_DEMUX_MAX_STREAMS; i++) {
+    GstMatroskaTrackContext *ostream = demux->src[i];
+
+    if (ostream == NULL)
+      continue;
+
+    ret = ostream->last_flow;
+    /* some other return value (must be SUCCESS but we can return
+     * other values as well) */
+    if (ret != GST_FLOW_NOT_LINKED)
+      goto done;
+  }
+  /* if we get here, all other pads were unlinked and we return
+   * NOT_LINKED then */
+done:
+  GST_LOG_OBJECT (demux, "combined return %s", gst_flow_get_name (ret));
+  return ret;
+}
+
 static void
 gst_matroska_demux_reset (GstElement * element)
 {
@@ -281,18 +317,12 @@ gst_matroska_demux_reset (GstElement * element)
   /* reset timers */
   demux->clock = NULL;
   demux->time_scale = 1000000;
-  demux->duration = 0;
-  demux->pos = 0;
   demux->created = G_MININT64;
 
   demux->metadata_parsed = FALSE;
   demux->index_parsed = FALSE;
 
-  demux->segment_rate = 1.0;
-  demux->segment_start = GST_CLOCK_TIME_NONE;
-  demux->segment_stop = GST_CLOCK_TIME_NONE;
-  demux->segment_play = FALSE;
-  demux->seek_pending = FALSE;
+  gst_segment_init (&demux->segment, GST_FORMAT_TIME);
 }
 
 static gint
@@ -325,22 +355,21 @@ gst_matroska_demux_encoding_cmp (gconstpointer a, gconstpointer b)
   return (gint) enc_b->order - (gint) enc_a->order;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
     GstMatroskaDemux * demux, GstMatroskaTrackContext * context)
 {
-  gboolean res = TRUE;
+  GstFlowReturn ret;
   guint32 id;
 
-  if (!gst_ebml_read_master (ebml, &id))
-    return FALSE;
+  if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+    return ret;
 
   context->encodings =
       g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1);
 
-  while (res) {
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
-      res = FALSE;
+  while (ret == GST_FLOW_OK) {
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) {
       break;
     } else if (demux->level_up > 0) {
       demux->level_up--;
@@ -351,14 +380,14 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
       case GST_MATROSKA_ID_CONTENTENCODING:{
         GstMatroskaTrackEncoding enc = { 0, };
 
-        if (!gst_ebml_read_master (ebml, &id)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
           break;
         }
 
-        while (res) {
-          if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
-            res = FALSE;
+        while (ret == GST_FLOW_OK) {
+          if ((ret =
+                  gst_ebml_peek_id (ebml, &demux->level_up,
+                      &id)) != GST_FLOW_OK) {
             break;
           } else if (demux->level_up > 0) {
             demux->level_up--;
@@ -369,8 +398,7 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
             case GST_MATROSKA_ID_CONTENTENCODINGORDER:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               enc.order = num;
@@ -379,8 +407,7 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
             case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               if (num > 7)
@@ -392,8 +419,7 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
             case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               if (num > 1)
@@ -404,15 +430,15 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
             }
             case GST_MATROSKA_ID_CONTENTCOMPRESSION:{
 
-              if (!gst_ebml_read_master (ebml, &id)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
                 break;
               }
 
-              while (res) {
+              while (ret == GST_FLOW_OK) {
 
-                if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
-                  res = FALSE;
+                if ((ret =
+                        gst_ebml_peek_id (ebml, &demux->level_up,
+                            &id)) != GST_FLOW_OK) {
                   break;
                 } else if (demux->level_up > 0) {
                   demux->level_up--;
@@ -423,8 +449,9 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
                   case GST_MATROSKA_ID_CONTENTCOMPALGO:{
                     guint64 num;
 
-                    if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                      res = FALSE;
+                    if ((ret =
+                            gst_ebml_read_uint (ebml, &id,
+                                &num)) != GST_FLOW_OK) {
                       break;
                     }
                     if (num > 3)
@@ -438,8 +465,9 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
                     guint64 size;
 
 
-                    if (!gst_ebml_read_binary (ebml, &id, &data, &size)) {
-                      res = FALSE;
+                    if ((ret =
+                            gst_ebml_read_binary (ebml, &id, &data,
+                                &size)) != GST_FLOW_OK) {
                       break;
                     }
                     enc.comp_settings = data;
@@ -449,8 +477,7 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
                   default:
                     GST_WARNING ("Unknown track compression header entry 0x%x"
                         " - ignoring", id);
-                    if (!gst_ebml_read_skip (ebml))
-                      res = FALSE;
+                    ret = gst_ebml_read_skip (ebml);
                     break;
                 }
 
@@ -468,8 +495,7 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
             default:
               GST_WARNING
                   ("Unknown track encoding header entry 0x%x - ignoring", id);
-              if (!gst_ebml_read_skip (ebml))
-                res = FALSE;
+              ret = gst_ebml_read_skip (ebml);
               break;
           }
 
@@ -486,8 +512,7 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
       default:
         GST_WARNING ("Unknown track encodings header entry 0x%x - ignoring",
             id);
-        if (!gst_ebml_read_skip (ebml))
-          res = FALSE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -500,10 +525,10 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml,
   /* Sort encodings according to their order */
   g_array_sort (context->encodings, gst_matroska_demux_encoding_cmp);
 
-  return res;
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
 {
   GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux);
@@ -512,7 +537,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
   GstPadTemplate *templ = NULL;
   GstCaps *caps = NULL;
   gchar *padname = NULL;
-  gboolean res = TRUE;
+  GstFlowReturn ret;
   guint32 id;
   GstTagList *list = NULL;
   gchar *codec = NULL;
@@ -532,16 +557,16 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
   context->default_duration = 0;
   context->pos = 0;
   context->set_discont = TRUE;
+  context->last_flow = GST_FLOW_OK;
   demux->num_streams++;
 
   /* start with the master */
-  if (!gst_ebml_read_master (ebml, &id))
-    return FALSE;
+  if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+    return ret;
 
   /* try reading the trackentry headers */
-  while (res) {
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
-      res = FALSE;
+  while (ret == GST_FLOW_OK) {
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) {
       break;
     } else if (demux->level_up > 0) {
       demux->level_up--;
@@ -553,20 +578,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TRACKNUMBER:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
         context->num = num;
         break;
       }
-
         /* track UID (unique identifier) */
       case GST_MATROSKA_ID_TRACKUID:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
         context->uid = num;
@@ -577,8 +599,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TRACKTYPE:{
         guint64 track_type;
 
-        if (!gst_ebml_read_uint (ebml, &id, &track_type)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_uint (ebml, &id, &track_type)) != GST_FLOW_OK) {
           break;
         }
 
@@ -621,18 +642,18 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         if (!gst_matroska_track_init_video_context (&context)) {
           GST_WARNING
               ("trackvideo EBML entry in non-video track - ignoring track");
-          res = FALSE;
+          ret = GST_FLOW_ERROR;
           break;
-        } else if (!gst_ebml_read_master (ebml, &id)) {
-          res = FALSE;
+        } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
           break;
         }
         videocontext = (GstMatroskaTrackVideoContext *) context;
         demux->src[demux->num_streams - 1] = context;
 
-        while (res) {
-          if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
-            res = FALSE;
+        while (ret == GST_FLOW_OK) {
+          if ((ret =
+                  gst_ebml_peek_id (ebml, &demux->level_up,
+                      &id)) != GST_FLOW_OK) {
             break;
           } else if (demux->level_up > 0) {
             demux->level_up--;
@@ -644,8 +665,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               context->default_duration = num;
@@ -656,8 +676,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_VIDEOFRAMERATE:{
               gdouble num;
 
-              if (!gst_ebml_read_float (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               if (num != 0.0) {
@@ -672,8 +691,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               videocontext->display_width = num;
@@ -685,8 +703,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               videocontext->display_height = num;
@@ -698,8 +715,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               videocontext->pixel_width = num;
@@ -711,8 +727,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               videocontext->pixel_height = num;
@@ -724,8 +739,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               if (num)
@@ -741,8 +755,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_VIDEOSTEREOMODE:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               if (num != GST_MATROSKA_EYE_MODE_MONO &&
@@ -760,8 +773,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_VIDEOASPECTRATIO:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE &&
@@ -779,8 +791,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               videocontext->fourcc = num;
@@ -793,8 +804,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               /* pass-through */
 
             case GST_EBML_ID_VOID:
-              if (!gst_ebml_read_skip (ebml))
-                res = FALSE;
+              ret = gst_ebml_read_skip (ebml);
               break;
           }
 
@@ -813,18 +823,18 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         if (!gst_matroska_track_init_audio_context (&context)) {
           GST_WARNING
               ("trackaudio EBML entry in non-audio track - ignoring track");
-          res = FALSE;
+          ret = GST_FLOW_ERROR;
           break;
-        } else if (!gst_ebml_read_master (ebml, &id)) {
-          res = FALSE;
+        } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
           break;
         }
         audiocontext = (GstMatroskaTrackAudioContext *) context;
         demux->src[demux->num_streams - 1] = context;
 
-        while (res) {
-          if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
-            res = FALSE;
+        while (ret == GST_FLOW_OK) {
+          if ((ret =
+                  gst_ebml_peek_id (ebml, &demux->level_up,
+                      &id)) != GST_FLOW_OK) {
             break;
           } else if (demux->level_up > 0) {
             demux->level_up--;
@@ -836,8 +846,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{
               gdouble num;
 
-              if (!gst_ebml_read_float (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               audiocontext->samplerate = num;
@@ -848,8 +857,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_AUDIOBITDEPTH:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               audiocontext->bitdepth = num;
@@ -860,8 +868,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
             case GST_MATROSKA_ID_AUDIOCHANNELS:{
               guint64 num;
 
-              if (!gst_ebml_read_uint (ebml, &id, &num)) {
-                res = FALSE;
+              if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
                 break;
               }
               audiocontext->channels = num;
@@ -874,8 +881,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
               /* pass-through */
 
             case GST_EBML_ID_VOID:
-              if (!gst_ebml_read_skip (ebml))
-                res = FALSE;
+              ret = gst_ebml_read_skip (ebml);
               break;
           }
 
@@ -891,8 +897,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_CODECID:{
         gchar *text;
 
-        if (!gst_ebml_read_ascii (ebml, &id, &text)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK) {
           break;
         }
         context->codec_id = text;
@@ -904,8 +909,9 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
         guint8 *data;
         guint64 size;
 
-        if (!gst_ebml_read_binary (ebml, &id, &data, &size)) {
-          res = FALSE;
+        if ((ret =
+                gst_ebml_read_binary (ebml, &id, &data,
+                    &size)) != GST_FLOW_OK) {
           break;
         }
         context->codec_priv = data;
@@ -918,8 +924,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_CODECNAME:{
         gchar *text;
 
-        if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
           break;
         }
         context->codec_name = text;
@@ -930,8 +935,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TRACKNAME:{
         gchar *text;
 
-        if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
           break;
         }
         context->name = text;
@@ -943,8 +947,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TRACKLANGUAGE:{
         gchar *text;
 
-        if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
           break;
         }
 
@@ -961,8 +964,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TRACKFLAGENABLED:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
         if (num)
@@ -976,8 +978,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
         if (num)
@@ -992,8 +993,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TRACKFLAGLACING:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
         if (num)
@@ -1007,8 +1007,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
         context->default_duration = num;
@@ -1016,9 +1015,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       }
 
       case GST_MATROSKA_ID_CONTENTENCODINGS:{
-        if (!gst_matroska_demux_read_track_encodings (ebml, demux, context)) {
-          res = FALSE;
-        }
+        ret = gst_matroska_demux_read_track_encodings (ebml, demux, context);
         break;
       }
 
@@ -1032,8 +1029,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TRACKMINCACHE:
       case GST_MATROSKA_ID_TRACKMAXCACHE:
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          res = FALSE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -1043,8 +1039,8 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
     }
   }
 
-  if (context->type == 0 || context->codec_id == NULL || !res) {
-    if (res)
+  if (context->type == 0 || context->codec_id == NULL || ret != GST_FLOW_OK) {
+    if (ret == GST_FLOW_OK)
       GST_WARNING ("Unknown stream/codec in track entry header");
 
     demux->num_streams--;
@@ -1053,7 +1049,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
       gst_matroska_track_free (context);
     }
 
-    return res;
+    return ret;
   }
 
   /* now create the GStreamer connectivity */
@@ -1179,7 +1175,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
   g_free (padname);
 
   /* tadaah! */
-  return TRUE;
+  return ret;
 }
 
 static const GstQueryType *
@@ -1215,7 +1211,7 @@ gst_matroska_demux_handle_src_query (GstPad * pad, GstQuery * query)
       }
 
       GST_OBJECT_LOCK (demux);
-      gst_query_set_position (query, GST_FORMAT_TIME, demux->pos);
+      gst_query_set_position (query, GST_FORMAT_TIME, demux->segment.last_stop);
       GST_OBJECT_UNLOCK (demux);
 
       res = TRUE;
@@ -1233,7 +1229,7 @@ gst_matroska_demux_handle_src_query (GstPad * pad, GstQuery * query)
       }
 
       GST_OBJECT_LOCK (demux);
-      gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration);
+      gst_query_set_duration (query, GST_FORMAT_TIME, demux->segment.duration);
       GST_OBJECT_UNLOCK (demux);
 
       res = TRUE;
@@ -1404,24 +1400,24 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
   if (cur == GST_CLOCK_TIME_NONE)
     cur = 0;
   if (stop == GST_CLOCK_TIME_NONE)
-    stop = demux->duration;
+    stop = demux->segment.duration;
 
   if (cur_type == GST_SEEK_TYPE_SET)
     segment_start = cur;
   else if (cur_type == GST_SEEK_TYPE_CUR)
-    segment_start = demux->segment_start + cur;
+    segment_start = demux->segment.start + cur;
   else
-    segment_start = demux->segment_start;
+    segment_start = demux->segment.start;
 
   if (stop_type == GST_SEEK_TYPE_SET)
     segment_stop = stop;
   else if (stop_type == GST_SEEK_TYPE_CUR)
-    segment_stop = demux->segment_stop + stop;
+    segment_stop = demux->segment.stop + stop;
   else
-    segment_stop = demux->segment_stop;
+    segment_stop = demux->segment.stop;
 
-  segment_start = CLAMP (segment_start, 0, demux->duration);
-  segment_stop = CLAMP (segment_stop, 0, demux->duration);
+  segment_start = CLAMP (segment_start, 0, demux->segment.duration);
+  segment_stop = CLAMP (segment_stop, 0, demux->segment.duration);
 
   GST_DEBUG ("New segment positions: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
       GST_TIME_ARGS (segment_start), GST_TIME_ARGS (segment_stop));
@@ -1453,42 +1449,48 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
 
   GST_DEBUG ("Committing new seek segment");
 
-  demux->segment_rate = rate;
-  demux->segment_play = !!(flags & GST_SEEK_FLAG_SEGMENT);
+  demux->segment.rate = rate;
+  demux->segment.flags = flags;
 
-  demux->segment_start = segment_start;
-  demux->segment_stop = segment_stop;
+  demux->segment.start = segment_start;
+  demux->segment.stop = segment_stop;
 
   GST_OBJECT_UNLOCK (demux);
 
   /* notify start of new segment */
-  if (demux->segment_play) {
+  if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
     GstMessage *msg;
 
     msg = gst_message_new_segment_start (GST_OBJECT (demux),
-        GST_FORMAT_TIME, demux->segment_start);
+        GST_FORMAT_TIME, demux->segment.start);
     gst_element_post_message (GST_ELEMENT (demux), msg);
   }
 
   newsegment_event = gst_event_new_new_segment (FALSE, rate,
       GST_FORMAT_TIME, segment_start, segment_stop, segment_start);
 
-  GST_DEBUG ("Stopping flush");
   if (flush) {
+    GST_DEBUG ("Stopping flush");
+    gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
     gst_matroska_demux_send_event (demux, gst_event_new_flush_stop ());
+  } else if (demux->segment_running) {
+    /* FIXME, the current segment was still running when we performed the
+     * seek, we need to close the current segment */
+    GST_DEBUG ("Closing currently running segment");
   }
-  gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
 
   /* 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++) {
     demux->src[i]->pos = entry->time;
     demux->src[i]->set_discont = TRUE;
+    demux->src[i]->last_flow = GST_FLOW_OK;
   }
-  demux->pos = entry->time;
+  demux->segment.last_stop = entry->time;
 
   /* restart our task since it might have been stopped when we did the
    * flush. */
+  demux->segment_running = TRUE;
   gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_matroska_demux_loop,
       demux->sinkpad);
 
@@ -1498,14 +1500,14 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
   return TRUE;
 
 seek_error:
-
-  /* FIXME: shouldn't we either make it a real error or start the task
-   * function again so that things can continue from where they left off? */
-  GST_DEBUG ("Got a seek error");
-  GST_OBJECT_UNLOCK (demux);
-  GST_PAD_STREAM_UNLOCK (demux->sinkpad);
-
-  return FALSE;
+  {
+    /* FIXME: shouldn't we either make it a real error or start the task
+     * function again so that things can continue from where they left off? */
+    GST_DEBUG ("Got a seek error");
+    GST_OBJECT_UNLOCK (demux);
+    GST_PAD_STREAM_UNLOCK (demux->sinkpad);
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -1537,38 +1539,39 @@ gst_matroska_demux_handle_src_event (GstPad * pad, GstEvent * event)
   return res;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_init_stream (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
   guint32 id;
   gchar *doctype;
   guint version;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_header (ebml, &doctype, &version))
-    return FALSE;
+  if ((ret = gst_ebml_read_header (ebml, &doctype, &version)) != GST_FLOW_OK)
+    return ret;
 
   if (!doctype || strcmp (doctype, "matroska") != 0) {
     GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
         ("Input is not a matroska stream (doctype=%s)",
             doctype ? doctype : "none"));
     g_free (doctype);
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
   g_free (doctype);
   if (version > 2) {
     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
         ("Demuxer version (2) is too old to read stream version %d", version));
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
 
   /* find segment, must be the next element */
   while (1) {
     guint last_level;
 
-    if (!gst_ebml_peek_id (ebml, &last_level, &id)) {
+    if ((ret = gst_ebml_peek_id (ebml, &last_level, &id)) != GST_FLOW_OK) {
       GST_DEBUG_OBJECT (demux, "gst_ebml_peek_id() failed!");
-      return FALSE;
+      return ret;
     }
 
     if (id == GST_MATROSKA_ID_SEGMENT)
@@ -1578,33 +1581,32 @@ gst_matroska_demux_init_stream (GstMatroskaDemux * demux)
     GST_WARNING ("Expected a Segment ID (0x%x), but received 0x%x!",
         GST_MATROSKA_ID_SEGMENT, id);
 
-    if (!gst_ebml_read_skip (ebml))
-      return FALSE;
+    if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+      return ret;
   }
 
   /* we now have a EBML segment */
-  if (!gst_ebml_read_master (ebml, &id)) {
+  if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) {
     GST_DEBUG_OBJECT (demux, "gst_ebml_read_master() failed!");
-    return FALSE;
+    return ret;
   }
 
   /* seeks are from the beginning of the segment,
    * after the segment ID/length */
   demux->ebml_segment_start = ebml->offset;
 
-  return TRUE;
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean res = TRUE;
+  GstFlowReturn ret = GST_FLOW_OK;
   guint32 id;
 
-  while (res) {
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
-      res = FALSE;
+  while (ret == GST_FLOW_OK) {
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) {
       break;
     } else if (demux->level_up) {
       demux->level_up--;
@@ -1614,8 +1616,7 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux)
     switch (id) {
         /* one track within the "all-tracks" header */
       case GST_MATROSKA_ID_TRACKENTRY:
-        if (!gst_matroska_demux_add_stream (demux))
-          res = FALSE;
+        ret = gst_matroska_demux_add_stream (demux);
         break;
 
       default:
@@ -1623,8 +1624,7 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux)
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          res = FALSE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -1634,26 +1634,26 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux)
     }
   }
 
-  return res;
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
     gboolean prevent_eos, GstMatroskaIndex * idx, guint64 length)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean got_error = FALSE;
   guint32 id;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_master (ebml, &id))
-    return FALSE;
+  if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+    return ret;
 
-  while (!got_error) {
+  while (TRUE) {
     if (prevent_eos && length == ebml->offset)
       break;
 
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
@@ -1666,7 +1666,7 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
       {
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num))
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
           goto error;
 
         idx->track = num;
@@ -1678,7 +1678,7 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
       {
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num))
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK)
           goto error;
 
         idx->pos = num;
@@ -1690,7 +1690,7 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
+        if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
           goto error;
         break;
     }
@@ -1701,26 +1701,26 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux,
     }
   }
 
-  return TRUE;
+  return ret;
 
 error:
   if (demux->level_up)
     demux->level_up--;
 
-  return FALSE;
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux,
     gboolean prevent_eos, guint64 length)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
   GstMatroskaIndex idx;
-  gboolean got_error = FALSE;
   guint32 id;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_master (ebml, &id))
-    return FALSE;
+  if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+    return ret;
 
   /* in the end, we hope to fill one entry with a
    * timestamp, a file position and a tracknum */
@@ -1728,12 +1728,12 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux,
   idx.time = (guint64) - 1;
   idx.track = (guint16) - 1;
 
-  while (!got_error) {
+  while (ret == GST_FLOW_OK) {
     if (prevent_eos && length == ebml->offset)
       break;
 
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
@@ -1746,9 +1746,7 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux,
       {
         guint64 time;
 
-        if (!gst_ebml_read_uint (ebml, &id, &time)) {
-          got_error = TRUE;
-        } else {
+        if ((ret = gst_ebml_read_uint (ebml, &id, &time)) == GST_FLOW_OK) {
           idx.time = time * demux->time_scale;
         }
         break;
@@ -1757,10 +1755,8 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux,
         /* position in the file + track to which it belongs */
       case GST_MATROSKA_ID_CUETRACKPOSITION:
       {
-        if (!gst_matroska_demux_parse_index_cuetrack (demux, prevent_eos, &idx,
-                length)) {
-          got_error = TRUE;
-        }
+        ret = gst_matroska_demux_parse_index_cuetrack (demux, prevent_eos, &idx,
+            length);
         break;
       }
 
@@ -1769,8 +1765,7 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux,
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          got_error = TRUE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -1797,30 +1792,30 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux,
     demux->num_indexes++;
   }
 
-  return (!got_error);
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean got_error = FALSE;
   guint32 id;
   guint64 length = 0;
+  GstFlowReturn ret = GST_FLOW_OK;
 
   if (prevent_eos) {
     length = gst_ebml_read_get_length (ebml);
   }
 
-  while (!got_error) {
+  while (ret == GST_FLOW_OK) {
     /* We're an element that can be seeked to. If we are, then
      * we want to prevent EOS, since that'll kill us. So we cache
      * file size and seek until there, and don't call EOS upon os. */
     if (prevent_eos && length == ebml->offset)
       break;
 
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
@@ -1830,9 +1825,8 @@ gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos)
     switch (id) {
         /* one single index entry ('point') */
       case GST_MATROSKA_ID_POINTENTRY:
-        if (!gst_matroska_demux_parse_index_pointentry (demux, prevent_eos,
-                length))
-          got_error = TRUE;
+        ret = gst_matroska_demux_parse_index_pointentry (demux, prevent_eos,
+            length);
         break;
 
       default:
@@ -1840,8 +1834,7 @@ gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos)
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          got_error = TRUE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -1851,19 +1844,18 @@ gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos)
     }
   }
 
-  return (!got_error);
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean res = TRUE;
+  GstFlowReturn ret = GST_FLOW_OK;
   guint32 id;
 
-  while (res) {
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id)) {
-      res = FALSE;
+  while (ret == GST_FLOW_OK) {
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) {
       break;
     } else if (demux->level_up) {
       demux->level_up--;
@@ -1875,8 +1867,7 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_TIMECODESCALE:{
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
         demux->time_scale = num;
@@ -1887,23 +1878,20 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
         gdouble num;
         GstClockTime dur;
 
-        if (!gst_ebml_read_float (ebml, &id, &num)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) {
           break;
         }
-
         dur = gst_gdouble_to_guint64 (num *
             gst_guint64_to_gdouble (demux->time_scale));
         if (GST_CLOCK_TIME_IS_VALID (dur) && dur <= G_MAXINT64)
-          demux->duration = dur;
+          demux->segment.duration = dur;
         break;
       }
 
       case GST_MATROSKA_ID_WRITINGAPP:{
         gchar *text;
 
-        if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
           break;
         }
         demux->writing_app = text;
@@ -1913,8 +1901,7 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_MUXINGAPP:{
         gchar *text;
 
-        if (!gst_ebml_read_utf8 (ebml, &id, &text)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) {
           break;
         }
         demux->muxing_app = text;
@@ -1924,8 +1911,7 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
       case GST_MATROSKA_ID_DATEUTC:{
         gint64 time;
 
-        if (!gst_ebml_read_date (ebml, &id, &time)) {
-          res = FALSE;
+        if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK) {
           break;
         }
         demux->created = time;
@@ -1934,8 +1920,7 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
 
       case GST_MATROSKA_ID_SEGMENTUID:{
         /* TODO not yet implemented. */
-        if (!gst_ebml_read_skip (ebml))
-          res = FALSE;
+        ret = gst_ebml_read_skip (ebml);
         break;
       }
 
@@ -1944,8 +1929,7 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          res = FALSE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -1955,10 +1939,10 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
     }
   }
 
-  return res;
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
     gboolean prevent_eos, guint64 length, GstTagList ** p_taglist)
 {
@@ -1980,21 +1964,21 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
     GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}
   };
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean got_error = FALSE;
+  GstFlowReturn ret;
   guint32 id;
   gchar *value = NULL;
   gchar *tag = NULL;
 
-  if (!gst_ebml_read_master (ebml, &id))
-    return FALSE;
+  if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+    return ret;
 
-  while (!got_error) {
+  while (ret == GST_FLOW_OK) {
     /* read all sub-entries */
     if (prevent_eos && length == ebml->offset)
       break;
 
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
@@ -2004,14 +1988,14 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
     switch (id) {
       case GST_MATROSKA_ID_TAGNAME:
         g_free (tag);
-        if (!gst_ebml_read_ascii (ebml, &id, &tag))
-          got_error = TRUE;
+        tag = NULL;
+        ret = gst_ebml_read_ascii (ebml, &id, &tag);
         break;
 
       case GST_MATROSKA_ID_TAGSTRING:
         g_free (value);
-        if (!gst_ebml_read_utf8 (ebml, &id, &value))
-          got_error = TRUE;
+        value = NULL;
+        ret = gst_ebml_read_utf8 (ebml, &id, &value);
         break;
 
       default:
@@ -2019,8 +2003,7 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          got_error = TRUE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -2058,27 +2041,27 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux,
   g_free (tag);
   g_free (value);
 
-  return (!got_error);
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux,
     gboolean prevent_eos, guint64 length, GstTagList ** p_taglist)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean got_error = FALSE;
   guint32 id;
+  GstFlowReturn ret;
 
-  if (!gst_ebml_read_master (ebml, &id))
-    return FALSE;
+  if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+    return ret;
 
-  while (!got_error) {
+  while (ret == GST_FLOW_OK) {
     /* read all sub-entries */
     if (prevent_eos && length == ebml->offset)
       break;
 
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
@@ -2087,10 +2070,8 @@ gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux,
 
     switch (id) {
       case GST_MATROSKA_ID_SIMPLETAG:
-        if (!gst_matroska_demux_parse_metadata_id_simple_tag (demux,
-                prevent_eos, length, p_taglist)) {
-          got_error = TRUE;
-        }
+        ret = gst_matroska_demux_parse_metadata_id_simple_tag (demux,
+            prevent_eos, length, p_taglist);
         break;
 
       default:
@@ -2098,8 +2079,7 @@ gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux,
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          got_error = TRUE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -2109,16 +2089,16 @@ gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux,
     }
   }
 
-  return (!got_error);
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux,
     gboolean prevent_eos)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
   GstTagList *taglist = gst_tag_list_new ();
-  gboolean got_error = FALSE;
+  GstFlowReturn ret = GST_FLOW_OK;
   guint64 length = 0;
   guint32 id;
 
@@ -2126,15 +2106,15 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux,
     length = gst_ebml_read_get_length (ebml);
   }
 
-  while (!got_error) {
+  while (ret == GST_FLOW_OK) {
     /* We're an element that can be seeked to. If we are, then
      * we want to prevent EOS, since that'll kill us. So we cache
      * file size and seek until there, and don't call EOS upon os. */
     if (prevent_eos && length == ebml->offset)
       break;
 
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
@@ -2143,10 +2123,8 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux,
 
     switch (id) {
       case GST_MATROSKA_ID_TAG:
-        if (!gst_matroska_demux_parse_metadata_id_tag (demux, prevent_eos,
-                length, &taglist)) {
-          got_error = TRUE;
-        }
+        ret = gst_matroska_demux_parse_metadata_id_tag (demux, prevent_eos,
+            length, &taglist);
         break;
 
       default:
@@ -2154,8 +2132,7 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux,
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          got_error = TRUE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -2171,7 +2148,7 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux,
     gst_tag_list_free (taglist);
   }
 
-  return (!got_error);
+  return ret;
 }
 
 /*
@@ -2245,7 +2222,8 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux)
 {
   gint stream_nr;
 
-  GST_LOG ("Sync to %" GST_TIME_FORMAT, GST_TIME_ARGS (demux->pos));
+  GST_LOG ("Sync to %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (demux->segment.last_stop));
 
   for (stream_nr = 0; stream_nr < demux->num_streams; stream_nr++) {
     GstMatroskaTrackContext *context;
@@ -2258,52 +2236,67 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux)
         stream_nr, GST_TIME_ARGS (context->pos));
 
     /* does it lag? 0.5 seconds is a random treshold... */
-    if (context->pos + (GST_SECOND / 2) < demux->pos) {
+    if (context->pos + (GST_SECOND / 2) < demux->segment.last_stop) {
       GST_DEBUG ("Synchronizing stream %d with others by advancing time "
           "from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, stream_nr,
-          GST_TIME_ARGS (context->pos), GST_TIME_ARGS (demux->pos));
+          GST_TIME_ARGS (context->pos),
+          GST_TIME_ARGS (demux->segment.last_stop));
 
-      context->pos = demux->pos;
+      context->pos = demux->segment.last_stop;
 
       /* advance stream time */
       gst_pad_push_event (context->pad,
-          gst_event_new_new_segment (TRUE, demux->segment_rate,
-              GST_FORMAT_TIME, demux->pos, -1, demux->pos));
+          gst_event_new_new_segment (TRUE, demux->segment.rate,
+              GST_FORMAT_TIME, demux->segment.last_stop, -1,
+              demux->segment.last_stop));
     }
   }
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_push_hdr_buf (GstMatroskaDemux * demux,
     GstMatroskaTrackContext * stream, guint8 * data, guint len)
 {
-  GstFlowReturn flow;
+  GstFlowReturn ret, cret;
   GstBuffer *header_buf = NULL;
 
-  flow = gst_pad_alloc_buffer_and_set_caps (stream->pad,
+  ret = gst_pad_alloc_buffer_and_set_caps (stream->pad,
       GST_BUFFER_OFFSET_NONE, len, stream->caps, &header_buf);
 
-  if (flow == GST_FLOW_OK) {
-    memcpy (GST_BUFFER_DATA (header_buf), data, len);
+  /* we combine but don't use the combined value to check if we have a buffer
+   * or not. The combined value is what we return. */
+  cret = gst_matroska_demux_combine_flows (demux, stream, ret);
+  if (ret != GST_FLOW_OK)
+    goto no_buffer;
 
-    if (stream->set_discont) {
-      GST_BUFFER_FLAG_SET (header_buf, GST_BUFFER_FLAG_DISCONT);
-      stream->set_discont = FALSE;
-    }
+  memcpy (GST_BUFFER_DATA (header_buf), data, len);
 
-    flow = gst_pad_push (stream->pad, header_buf);
+  if (stream->set_discont) {
+    GST_BUFFER_FLAG_SET (header_buf, GST_BUFFER_FLAG_DISCONT);
+    stream->set_discont = FALSE;
   }
 
-  if (flow != GST_FLOW_OK && flow != GST_FLOW_NOT_LINKED)
-    return FALSE;
+  ret = gst_pad_push (stream->pad, header_buf);
 
-  return TRUE;
+  /* combine flows */
+  cret = gst_matroska_demux_combine_flows (demux, stream, ret);
+
+  return cret;
+
+  /* ERRORS */
+no_buffer:
+  {
+    GST_DEBUG_OBJECT (demux, "could not alloc buffer: %s, combined %s",
+        gst_flow_get_name (ret), gst_flow_get_name (cret));
+    return cret;
+  }
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_push_flac_codec_priv_data (GstMatroskaDemux * demux,
     GstMatroskaTrackContext * stream)
 {
+  GstFlowReturn ret;
   guint8 *pdata;
   guint off, len;
 
@@ -2314,16 +2307,17 @@ gst_matroska_demux_push_flac_codec_priv_data (GstMatroskaDemux * demux,
   /* need at least 'fLaC' marker + STREAMINFO metadata block */
   if (stream->codec_priv_size < ((4) + (4 + 34))) {
     GST_WARNING_OBJECT (demux, "not enough codec priv data for flac headers");
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
 
   if (memcmp (pdata, "fLaC", 4) != 0) {
     GST_WARNING_OBJECT (demux, "no flac marker at start of stream headers");
-    return FALSE;
+    return GST_FLOW_ERROR;
   }
 
-  if (!gst_matroska_demux_push_hdr_buf (demux, stream, pdata, 4))
-    return FALSE;
+  ret = gst_matroska_demux_push_hdr_buf (demux, stream, pdata, 4);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   off = 4;                      /* skip fLaC marker */
   while (off < stream->codec_priv_size) {
@@ -2334,19 +2328,20 @@ gst_matroska_demux_push_flac_codec_priv_data (GstMatroskaDemux * demux,
     GST_DEBUG_OBJECT (demux, "header packet: len=%u bytes, flags=0x%02x",
         len, (guint) pdata[off]);
 
-    if (!gst_matroska_demux_push_hdr_buf (demux, stream, pdata + off, len))
-      return FALSE;
+    ret = gst_matroska_demux_push_hdr_buf (demux, stream, pdata + off, len);
+    if (ret != GST_FLOW_OK)
+      return ret;
 
     off += 4 + len;
   }
-
-  return TRUE;
+  return GST_FLOW_OK;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_push_xiph_codec_priv_data (GstMatroskaDemux * demux,
     GstMatroskaTrackContext * stream)
 {
+  GstFlowReturn ret;
   guint8 *p = (guint8 *) stream->codec_priv;
   gint i, offset, length, num_packets;
 
@@ -2363,20 +2358,22 @@ gst_matroska_demux_push_xiph_codec_priv_data (GstMatroskaDemux * demux,
 
     GST_DEBUG_OBJECT (demux, "buffer %d: length=%u bytes", i, (guint) length);
     if (offset + length > stream->codec_priv_size)
-      return FALSE;
+      return GST_FLOW_ERROR;
 
-    if (!gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length))
-      return FALSE;
+    ret = gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length);
+    if (ret != GST_FLOW_OK)
+      return ret;
 
     offset += length;
   }
 
   length = stream->codec_priv_size - offset;
   GST_DEBUG_OBJECT (demux, "buffer %d: length=%u bytes", i, (guint) length);
-  if (!gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length))
-    return FALSE;
+  ret = gst_matroska_demux_push_hdr_buf (demux, stream, p + offset, length);
+  if (ret != GST_FLOW_OK)
+    return ret;
 
-  return TRUE;
+  return GST_FLOW_OK;
 }
 
 static void
@@ -2445,13 +2442,14 @@ gst_matroska_demux_stream_is_wavpack (GstMatroskaTrackContext * stream)
   return FALSE;
 }
 
-static gboolean
-gst_matroska_demux_add_wvpk_header (GstMatroskaTrackContext * stream,
-    gint block_length, GstBuffer ** buf)
+static GstFlowReturn
+gst_matroska_demux_add_wvpk_header (GstMatroskaDemux * demux,
+    GstMatroskaTrackContext * stream, gint block_length, GstBuffer ** buf)
 {
   GstBuffer *newbuf;
   guint8 *data;
   guint newlen;
+  GstFlowReturn ret, cret;
 
   /* we need to reconstruct the header of the wavpack block */
   Wavpack4Header wvh;
@@ -2472,9 +2470,13 @@ gst_matroska_demux_add_wvpk_header (GstMatroskaTrackContext * stream,
 
   /* block_samples, flags and crc are already in the buffer */
   newlen = block_length + sizeof (Wavpack4Header) - 12;
-  if (gst_pad_alloc_buffer_and_set_caps (stream->pad, GST_BUFFER_OFFSET_NONE,
-          newlen, stream->caps, &newbuf) != GST_FLOW_OK) {
-    return TRUE;                /* not an error, pad might not be linked */
+  ret = gst_pad_alloc_buffer_and_set_caps (stream->pad, GST_BUFFER_OFFSET_NONE,
+      newlen, stream->caps, &newbuf);
+  cret = gst_matroska_demux_combine_flows (demux, stream, ret);
+  if (ret != GST_FLOW_OK) {
+    GST_DEBUG_OBJECT (demux, "pad_alloc failed %s, combined %s",
+        gst_flow_get_name (ret), gst_flow_get_name (cret));
+    return cret;
   }
 
   data = GST_BUFFER_DATA (newbuf);
@@ -2492,7 +2494,8 @@ gst_matroska_demux_add_wvpk_header (GstMatroskaTrackContext * stream,
   gst_buffer_copy_metadata (newbuf, *buf, GST_BUFFER_COPY_TIMESTAMPS);
   gst_buffer_unref (*buf);
   *buf = newbuf;
-  return TRUE;
+
+  return cret;
 }
 
 static GstBuffer *
@@ -2559,8 +2562,8 @@ gst_matroska_demux_check_subtitle_buffer (GstMatroskaDemux * demux,
   GST_BUFFER_DATA (newbuf) = (guint8 *) utf8;
   GST_BUFFER_SIZE (newbuf) = strlen (utf8);
   gst_buffer_copy_metadata (newbuf, buf, GST_BUFFER_COPY_TIMESTAMPS);
-
   gst_buffer_unref (buf);
+
   return newbuf;
 }
 
@@ -2654,13 +2657,13 @@ gst_matroska_decode_buffer (GstMatroskaTrackContext * context, GstBuffer * buf)
   return buf;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
     guint64 cluster_time, gboolean is_simpleblock)
 {
   GstMatroskaTrackContext *stream = NULL;
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean got_error = FALSE;
+  GstFlowReturn ret = GST_FLOW_OK;
   gboolean readblock = FALSE;
   guint32 id;
   guint64 block_duration = 0;
@@ -2673,10 +2676,10 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
   gint flags = 0;
   gint64 referenceblock = 0;
 
-  while (!got_error) {
+  while (ret == GST_FLOW_OK) {
     if (!is_simpleblock) {
-      if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-        goto error;
+      if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+        goto done;
 
       if (demux->level_up) {
         demux->level_up--;
@@ -2696,10 +2699,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         guint64 num;
         guint8 *data;
 
-        if (!gst_ebml_read_buffer (ebml, &id, &buf)) {
-          got_error = TRUE;
+        if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
           break;
-        }
 
         data = GST_BUFFER_DATA (buf);
         size = GST_BUFFER_SIZE (buf);
@@ -2708,7 +2709,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
           GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("Data error"));
           gst_buffer_unref (buf);
-          got_error = TRUE;
+          buf = NULL;
+          ret = GST_FLOW_ERROR;
           break;
         }
         data += n;
@@ -2718,6 +2720,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         stream_num = gst_matroska_demux_stream_from_num (demux, num);
         if (size <= 3 || stream_num < 0 || stream_num >= demux->num_streams) {
           gst_buffer_unref (buf);
+          buf = NULL;
           GST_WARNING ("Invalid stream %d or size %u", stream_num, size);
           break;
         }
@@ -2743,7 +2746,9 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
           case 0x2:            /* fixed-size lacing */
           case 0x3:            /* EBML lacing */
             if (size == 0) {
-              got_error = TRUE;
+              GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
+                  ("Invalid lacing size"));
+              ret = GST_FLOW_ERROR;
               break;
             }
             laces = GST_READ_UINT8 (data) + 1;
@@ -2755,10 +2760,12 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
               case 0x1:        /* xiph lacing */  {
                 guint temp, total = 0;
 
-                for (n = 0; !got_error && n < laces - 1; n++) {
+                for (n = 0; ret == GST_FLOW_OK && n < laces - 1; n++) {
                   while (1) {
                     if (size == 0) {
-                      got_error = TRUE;
+                      GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
+                          ("Invalid lacing size"));
+                      ret = GST_FLOW_ERROR;
                       break;
                     }
                     temp = GST_READ_UINT8 (data);
@@ -2785,20 +2792,20 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
                 if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) {
                   GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
                       ("Data error"));
-                  got_error = TRUE;
+                  ret = GST_FLOW_ERROR;
                   break;
                 }
                 data += n;
                 size -= n;
                 total = lace_size[0] = num;
-                for (n = 1; !got_error && n < laces - 1; n++) {
+                for (n = 1; ret == GST_FLOW_OK && n < laces - 1; n++) {
                   gint64 snum;
                   gint r;
 
                   if ((r = gst_matroska_ebmlnum_sint (data, size, &snum)) < 0) {
                     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
                         ("Data error"));
-                    got_error = TRUE;
+                    ret = GST_FLOW_ERROR;
                     break;
                   }
                   data += r;
@@ -2815,16 +2822,12 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         }
 
         if (stream->send_xiph_headers) {
-          if (!gst_matroska_demux_push_xiph_codec_priv_data (demux, stream)) {
-            got_error = TRUE;
-          }
+          ret = gst_matroska_demux_push_xiph_codec_priv_data (demux, stream);
           stream->send_xiph_headers = FALSE;
         }
 
         if (stream->send_flac_headers) {
-          if (!gst_matroska_demux_push_flac_codec_priv_data (demux, stream)) {
-            got_error = TRUE;
-          }
+          ret = gst_matroska_demux_push_flac_codec_priv_data (demux, stream);
           stream->send_flac_headers = FALSE;
         }
 
@@ -2834,7 +2837,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
           stream->send_dvd_event = FALSE;
         }
 
-        if (got_error)
+        if (ret != GST_FLOW_OK)
           break;
 
         readblock = TRUE;
@@ -2842,14 +2845,12 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
       }
 
       case GST_MATROSKA_ID_BLOCKDURATION:{
-        if (!gst_ebml_read_uint (ebml, &id, &block_duration))
-          got_error = TRUE;
+        ret = gst_ebml_read_uint (ebml, &id, &block_duration);
         break;
       }
 
       case GST_MATROSKA_ID_REFERENCEBLOCK:{
-        if (!gst_ebml_read_sint (ebml, &id, &referenceblock))
-          got_error = TRUE;
+        ret = gst_ebml_read_sint (ebml, &id, &referenceblock);
         break;
       }
 
@@ -2858,8 +2859,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          got_error = TRUE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -2881,18 +2881,19 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
     lace_time = GST_CLOCK_TIME_NONE;
   }
 
-  if (referenceblock && readblock && demux->src[stream_num]->set_discont) {
+  stream = demux->src[stream_num];
+
+  if (referenceblock && readblock && stream->set_discont) {
     /* When doing seeks or such, we need to restart on key frames or
        decoders might choke. */
     readblock = FALSE;
     gst_buffer_unref (buf);
+    buf = NULL;
   }
 
-  if (!got_error && readblock) {
+  if (ret == GST_FLOW_OK && readblock) {
     guint64 duration = 0;
 
-    stream = demux->src[stream_num];
-
     if (block_duration) {
       duration = block_duration * demux->time_scale;
     } else if (stream->default_duration) {
@@ -2900,7 +2901,6 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
     }
 
     for (n = 0; n < laces; n++) {
-      GstFlowReturn ret;
       GstBuffer *sub;
 
       if (lace_size[n] == 0)
@@ -2914,15 +2914,15 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
 
       GST_BUFFER_TIMESTAMP (sub) = lace_time;
       if (lace_time != GST_CLOCK_TIME_NONE)
-        demux->pos = lace_time;
+        demux->segment.last_stop = lace_time;
 
-      stream->pos = demux->pos;
+      stream->pos = demux->segment.last_stop;
       gst_matroska_demux_sync_streams (demux);
 
       if (gst_matroska_demux_stream_is_wavpack (stream)) {
-        if (!gst_matroska_demux_add_wvpk_header (stream, lace_size[n], &sub)) {
-          got_error = TRUE;
-        }
+        ret =
+            gst_matroska_demux_add_wvpk_header (demux, stream, lace_size[n],
+            &sub);
       }
 
       /* FIXME: do all laces have the same lenght? */
@@ -2949,8 +2949,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
         stream->set_discont = FALSE;
       }
 
-      GST_DEBUG ("Pushing data of size %d for stream %d, time=%"
-          GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT,
+      GST_DEBUG ("Pushing lace %d, data of size %d for stream %d, time=%"
+          GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n,
           GST_BUFFER_SIZE (sub), stream_num,
           GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)),
           GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
@@ -2963,8 +2963,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
       }
 
       ret = gst_pad_push (stream->pad, sub);
-      if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
-        got_error = TRUE;
+      /* combine flows */
+      ret = gst_matroska_demux_combine_flows (demux, stream, ret);
 
       size -= lace_size[n];
       if (lace_time != GST_CLOCK_TIME_NONE)
@@ -2972,29 +2972,25 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
     }
   }
 
-  if (0) {
-  error:
-    got_error = TRUE;
-  }
-
+done:
   if (readblock)
     gst_buffer_unref (buf);
   g_free (lace_size);
 
-  return (!got_error);
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean got_error = FALSE;
+  GstFlowReturn ret = GST_FLOW_OK;
   guint64 cluster_time = GST_CLOCK_TIME_NONE;
   guint32 id;
 
-  while (!got_error) {
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+  while (ret == GST_FLOW_OK) {
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
@@ -3007,9 +3003,7 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
       {
         guint64 num;
 
-        if (!gst_ebml_read_uint (ebml, &id, &num)) {
-          got_error = TRUE;
-        } else {
+        if ((ret = gst_ebml_read_uint (ebml, &id, &num)) == GST_FLOW_OK) {
           cluster_time = num * demux->time_scale;
         }
         break;
@@ -3017,20 +3011,16 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
 
         /* a group of blocks inside a cluster */
       case GST_MATROSKA_ID_BLOCKGROUP:
-        if (!gst_ebml_read_master (ebml, &id)) {
-          got_error = TRUE;
-        } else {
-          if (!gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
-                  cluster_time, FALSE))
-            got_error = TRUE;
+        if ((ret = gst_ebml_read_master (ebml, &id)) == GST_FLOW_OK) {
+          ret = gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
+              cluster_time, FALSE);
         }
         break;
 
       case GST_MATROSKA_ID_SIMPLEBLOCK:
       {
-        if (!gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
-                cluster_time, TRUE))
-          got_error = TRUE;
+        ret = gst_matroska_demux_parse_blockgroup_or_simpleblock (demux,
+            cluster_time, TRUE);
         break;
       }
 
@@ -3039,8 +3029,7 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          got_error = TRUE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -3050,25 +3039,25 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux)
     }
   }
 
-  return (!got_error);
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
     gboolean * p_run_loop)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean got_error = FALSE;
+  GstFlowReturn ret;
   guint64 seek_pos = (guint64) - 1;
   guint32 seek_id = 0;
   guint32 id;
 
-  if (!gst_ebml_read_master (ebml, &id))
-    return FALSE;
+  if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+    return ret;
 
-  while (!got_error) {
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+  while (ret == GST_FLOW_OK) {
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
@@ -3080,9 +3069,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
       {
         guint64 t;
 
-        if (!gst_ebml_read_uint (ebml, &id, &t)) {
-          got_error = TRUE;
-        } else {
+        if ((ret = gst_ebml_read_uint (ebml, &id, &t)) == GST_FLOW_OK) {
           seek_id = t;
         }
         break;
@@ -3092,9 +3079,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
       {
         guint64 t;
 
-        if (!gst_ebml_read_uint (ebml, &id, &t)) {
-          got_error = TRUE;
-        } else {
+        if ((ret = gst_ebml_read_uint (ebml, &id, &t)) == GST_FLOW_OK) {
           seek_pos = t;
         }
         break;
@@ -3105,8 +3090,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          got_error = TRUE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -3116,13 +3100,13 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
     }
   }
 
-  if (got_error)
-    return FALSE;
+  if (ret != GST_FLOW_OK)
+    return ret;
 
   if (!seek_id || seek_pos == (guint64) - 1) {
     GST_WARNING ("Incomplete seekhead entry (0x%x/%"
         G_GUINT64_FORMAT ")", seek_id, seek_pos);
-    return TRUE;
+    return GST_FLOW_OK;
   }
 
   switch (seek_id) {
@@ -3148,7 +3132,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
 
       /* seek */
       if (!gst_ebml_read_seek (ebml, seek_pos + demux->ebml_segment_start))
-        return FALSE;
+        return GST_FLOW_ERROR;
 
       /* we don't want to lose our seekhead level, so we add
        * a dummy. This is a crude hack. */
@@ -3158,8 +3142,8 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
       ebml->level = g_list_append (ebml->level, level);
 
       /* check ID */
-      if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-        return FALSE;
+      if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+        return ret;
 
       if (id != seek_id) {
         g_warning ("We looked for ID=0x%x but got ID=0x%x (pos=%"
@@ -3171,20 +3155,23 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
       /* read master + parse */
       switch (id) {
         case GST_MATROSKA_ID_CUES:
-          if (!gst_ebml_read_master (ebml, &id))
-            return FALSE;
-          if (!gst_matroska_demux_parse_index (demux, TRUE))
-            return FALSE;
+          if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+            return ret;
+          if ((ret =
+                  gst_matroska_demux_parse_index (demux, TRUE)) != GST_FLOW_OK)
+            return ret;
           if (gst_ebml_read_get_length (ebml) == ebml->offset)
             *p_run_loop = FALSE;
           else
             demux->index_parsed = TRUE;
           break;
         case GST_MATROSKA_ID_TAGS:
-          if (!gst_ebml_read_master (ebml, &id))
-            return FALSE;
-          if (!gst_matroska_demux_parse_metadata (demux, TRUE))
-            return FALSE;
+          if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+            return ret;
+          if ((ret =
+                  gst_matroska_demux_parse_metadata (demux,
+                      TRUE)) != GST_FLOW_OK)
+            return ret;
           if (gst_ebml_read_get_length (ebml) == ebml->offset)
             *p_run_loop = FALSE;
           else
@@ -3219,20 +3206,20 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
       break;
   }
 
-  return (!got_error);
+  return ret;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_parse_contents (GstMatroskaDemux * demux,
     gboolean * p_run_loop)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean got_error = FALSE;
+  GstFlowReturn ret = GST_FLOW_OK;
   guint32 id;
 
-  while (!got_error) {
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+  while (ret == GST_FLOW_OK) {
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
@@ -3242,8 +3229,7 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux,
     switch (id) {
       case GST_MATROSKA_ID_SEEKENTRY:
       {
-        if (!gst_matroska_demux_parse_contents_seekentry (demux, p_run_loop))
-          got_error = TRUE;
+        ret = gst_matroska_demux_parse_contents_seekentry (demux, p_run_loop);
         break;
       }
 
@@ -3252,8 +3238,7 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux,
         /* fall-through */
 
       case GST_EBML_ID_VOID:
-        if (!gst_ebml_read_skip (ebml))
-          got_error = TRUE;
+        ret = gst_ebml_read_skip (ebml);
         break;
     }
 
@@ -3263,32 +3248,33 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux,
     }
   }
 
-  return (!got_error);
+  return ret;
 }
 
 /* returns FALSE on error, otherwise TRUE */
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
     guint32 id, gboolean * p_run_loop)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
+  GstFlowReturn ret;
 
   switch (id) {
       /* stream info */
     case GST_MATROSKA_ID_INFO:
-      if (!gst_ebml_read_master (ebml, &id))
-        return FALSE;
-      if (!gst_matroska_demux_parse_info (demux))
-        return FALSE;
+      if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+        return ret;
+      if ((ret = gst_matroska_demux_parse_info (demux)) != GST_FLOW_OK)
+        return ret;
       break;
 
       /* track info headers */
     case GST_MATROSKA_ID_TRACKS:
     {
-      if (!gst_ebml_read_master (ebml, &id))
-        return FALSE;
-      if (!gst_matroska_demux_parse_tracks (demux))
-        return FALSE;
+      if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+        return ret;
+      if ((ret = gst_matroska_demux_parse_tracks (demux)) != GST_FLOW_OK)
+        return ret;
       break;
     }
 
@@ -3296,13 +3282,14 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
     case GST_MATROSKA_ID_CUES:
     {
       if (!demux->index_parsed) {
-        if (!gst_ebml_read_master (ebml, &id))
-          return FALSE;
-        if (!gst_matroska_demux_parse_index (demux, FALSE))
-          return FALSE;
+        if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+          return ret;
+        if ((ret =
+                gst_matroska_demux_parse_index (demux, FALSE)) != GST_FLOW_OK)
+          return ret;
       } else {
-        if (!gst_ebml_read_skip (ebml))
-          return FALSE;
+        if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+          return ret;
       }
       break;
     }
@@ -3311,13 +3298,15 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
     case GST_MATROSKA_ID_TAGS:
     {
       if (!demux->index_parsed) {
-        if (!gst_ebml_read_master (ebml, &id))
-          return FALSE;
-        if (!gst_matroska_demux_parse_metadata (demux, FALSE))
-          return FALSE;
+        if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+          return ret;
+        if ((ret =
+                gst_matroska_demux_parse_metadata (demux,
+                    FALSE)) != GST_FLOW_OK)
+          return ret;
       } else {
-        if (!gst_ebml_read_skip (ebml))
-          return FALSE;
+        if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+          return ret;
       }
       break;
     }
@@ -3325,10 +3314,12 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
       /* file index (if seekable, seek to Cues/Tags to parse it) */
     case GST_MATROSKA_ID_SEEKHEAD:
     {
-      if (!gst_ebml_read_master (ebml, &id))
-        return FALSE;
-      if (!gst_matroska_demux_parse_contents (demux, p_run_loop))
-        return FALSE;
+      if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+        return ret;
+      if ((ret =
+              gst_matroska_demux_parse_contents (demux,
+                  p_run_loop)) != GST_FLOW_OK)
+        return ret;
       break;
     }
 
@@ -3341,12 +3332,13 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
         gst_matroska_demux_send_event (demux,
             gst_event_new_new_segment (FALSE, 1.0,
                 GST_FORMAT_TIME, 0,
-                (demux->duration > 0) ? demux->duration : -1, 0));
+                (demux->segment.duration > 0) ? demux->segment.duration : -1,
+                0));
         GST_DEBUG_OBJECT (demux, "signaling no more pads");
         gst_element_no_more_pads (GST_ELEMENT (demux));
       } else {
-        if (!gst_ebml_read_master (ebml, &id))
-          return FALSE;
+        if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK)
+          return ret;
 
         /* The idea is that we parse one cluster per loop and
          * then break out of the loop here. In the next call
@@ -3355,8 +3347,8 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
          * actually push a buffer, but we still want to break
          * out of the loop to handle a possible error. We'll
          * get back here if it's recoverable. */
-        if (!gst_matroska_demux_parse_cluster (demux))
-          return FALSE;
+        if ((ret = gst_matroska_demux_parse_cluster (demux)) != GST_FLOW_OK)
+          return ret;
         *p_run_loop = FALSE;
       }
       break;
@@ -3369,43 +3361,40 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux,
 
     case GST_EBML_ID_VOID:
     {
-      if (!gst_ebml_read_skip (ebml))
-        return FALSE;
+      if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK)
+        return ret;
       break;
     }
   }
-
-  return TRUE;
+  return GST_FLOW_OK;
 }
 
-static gboolean
+static GstFlowReturn
 gst_matroska_demux_loop_stream (GstMatroskaDemux * demux)
 {
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean got_error = FALSE;
+  GstFlowReturn ret = GST_FLOW_OK;
   gboolean run_loop = TRUE;
   guint32 id;
 
   /* we've found our segment, start reading the different contents in here */
-  while (run_loop && !got_error) {
-    if (!gst_ebml_peek_id (ebml, &demux->level_up, &id))
-      return FALSE;
+  while (run_loop && ret == GST_FLOW_OK) {
+    if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK)
+      return ret;
 
     if (demux->level_up) {
       demux->level_up--;
       break;
     }
 
-    if (!gst_matroska_demux_loop_stream_parse_id (demux, id, &run_loop))
-      got_error = TRUE;
+    ret = gst_matroska_demux_loop_stream_parse_id (demux, id, &run_loop);
 
     if (demux->level_up) {
       demux->level_up--;
       break;
     }
   }
-
-  return (!got_error);
+  return ret;
 }
 
 static void
@@ -3413,69 +3402,85 @@ gst_matroska_demux_loop (GstPad * pad)
 {
   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad));
   GstEbmlRead *ebml = GST_EBML_READ (demux);
-  gboolean ret;
+  GstFlowReturn ret;
 
   /* first, if we're to start, let's actually get starting */
   if (demux->state == GST_MATROSKA_DEMUX_STATE_START) {
-    if (!gst_matroska_demux_init_stream (demux)) {
+    ret = gst_matroska_demux_init_stream (demux);
+    if (ret != GST_FLOW_OK) {
       GST_WARNING_OBJECT (demux, "init stream failed!");
-      goto eos_and_pause;
+      goto pause;
     }
     demux->state = GST_MATROSKA_DEMUX_STATE_HEADER;
   }
 
   ret = gst_matroska_demux_loop_stream (demux);
+  if (ret != GST_FLOW_OK)
+    goto pause;
 
   /* check if we're at the end of a configured segment */
-  if (GST_CLOCK_TIME_IS_VALID (demux->segment_stop)) {
+  if (GST_CLOCK_TIME_IS_VALID (demux->segment.stop)) {
     guint i;
 
     for (i = 0; i < demux->num_streams; i++) {
-      if (demux->src[i]->pos >= demux->segment_stop) {
+      if (demux->src[i]->pos >= demux->segment.stop) {
         GST_INFO_OBJECT (demux, "Reached end of segment (%" G_GUINT64_FORMAT
-            "-%" G_GUINT64_FORMAT ") on pad %s:%s", demux->segment_start,
-            demux->segment_stop, GST_DEBUG_PAD_NAME (demux->src[i]->pad));
-
-        if (!demux->segment_play)
-          goto eos_and_pause;
-
-        gst_element_post_message (GST_ELEMENT (demux),
-            gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
-                demux->segment_stop));
+            "-%" G_GUINT64_FORMAT ") on pad %s:%s", demux->segment.start,
+            demux->segment.stop, GST_DEBUG_PAD_NAME (demux->src[i]->pad));
+        ret = GST_FLOW_UNEXPECTED;
         goto pause;
       }
     }
   }
 
   if (ebml->offset == gst_ebml_read_get_length (ebml)) {
-    if (demux->segment_play) {
-      GST_LOG ("Reached end of stream and segment, posting message");
-      gst_element_post_message (GST_ELEMENT (demux),
-          gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
-              demux->duration));
-      goto pause;
-    }
-
     GST_LOG ("Reached end of stream, sending EOS");
-    goto eos_and_pause;
-  }
-
-  if (ret == FALSE) {
-    GST_LOG ("Error processing stream, sending EOS");
-    goto eos_and_pause;
+    ret = GST_FLOW_UNEXPECTED;
+    goto pause;
   }
 
   /* all is fine */
   gst_object_unref (demux);
   return;
 
-eos_and_pause:
-  gst_matroska_demux_send_event (demux, gst_event_new_eos ());
-  /* fallthrough */
+  /* ERRORS */
 pause:
-  GST_LOG_OBJECT (demux, "pausing task");
-  gst_pad_pause_task (demux->sinkpad);
-  gst_object_unref (demux);
+  {
+    const gchar *reason = gst_flow_get_name (ret);
+
+    GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
+    demux->segment_running = FALSE;
+    gst_pad_pause_task (demux->sinkpad);
+
+    if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
+      if (ret == GST_FLOW_UNEXPECTED) {
+        /* perform EOS logic */
+        if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
+          gint64 stop;
+
+          /* for segment playback we need to post when (in stream time)
+           * we stopped, this is either stop (when set) or the duration. */
+          if ((stop = demux->segment.stop) == -1)
+            stop = demux->segment.duration;
+
+          GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
+          gst_element_post_message (GST_ELEMENT (demux),
+              gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
+                  stop));
+        } else {
+          /* normal playback, send EOS to all linked pads */
+          GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
+          gst_matroska_demux_send_event (demux, gst_event_new_eos ());
+        }
+      } else {
+        GST_ELEMENT_ERROR (demux, STREAM, FAILED, NULL,
+            ("stream stopped, reason %s", reason));
+        gst_matroska_demux_send_event (demux, gst_event_new_eos ());
+      }
+    }
+    gst_object_unref (demux);
+    return;
+  }
 }
 
 static gboolean
@@ -3490,11 +3495,15 @@ gst_matroska_demux_sink_activate (GstPad * sinkpad)
 static gboolean
 gst_matroska_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
 {
+  GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (GST_PAD_PARENT (sinkpad));
+
   if (active) {
     /* if we have a scheduler we can start the task */
+    demux->segment_running = TRUE;
     gst_pad_start_task (sinkpad, (GstTaskFunction) gst_matroska_demux_loop,
         sinkpad);
   } else {
+    demux->segment_running = FALSE;
     gst_pad_stop_task (sinkpad);
   }
 
index 49b073b..bccec17 100644 (file)
@@ -89,17 +89,9 @@ typedef struct _GstMatroskaDemux {
   /* timescale in the file */
   guint64                  time_scale;
 
-  /* length, position (time, ns) */
-  guint64                  pos;
-  guint64                  duration;
-
-  /* a possible pending seek */
-  gboolean                 seek_pending;
-
-  gdouble                  segment_rate;
-  gint64                   segment_start;
-  gint64                   segment_stop;
-  gboolean                 segment_play;
+  /* keeping track of playback position */
+  GstSegment               segment;
+  gboolean                 segment_running;
 } GstMatroskaDemux;
 
 typedef struct _GstMatroskaDemuxClass {
index 6630dae..760dca8 100644 (file)
@@ -255,6 +255,7 @@ typedef struct _GstMatroskaTrackContext {
   GstPad       *pad;
   GstCaps      *caps;
   guint         index;
+  GstFlowReturn last_flow;
 
   /* some often-used info */
   gchar        *codec_id, *codec_name, *name, *language;