gst/avi/gstavidemux.*: Proper aggregation of each stream's GstFlowReturn in order...
authorEdward Hervey <bilboed@bilboed.com>
Mon, 3 Jul 2006 15:28:48 +0000 (15:28 +0000)
committerEdward Hervey <bilboed@bilboed.com>
Mon, 3 Jul 2006 15:28:48 +0000 (15:28 +0000)
Original commit message from CVS:
* gst/avi/gstavidemux.c: (gst_avi_demux_reset),
(gst_avi_demux_read_subindexes), (gst_avi_demux_parse_stream),
(gst_avi_demux_handle_seek), (gst_avi_demux_aggregated_flow),
(gst_avi_demux_process_next_entry), (push_tag_lists),
(gst_avi_demux_stream_data), (gst_avi_demux_loop):
* gst/avi/gstavidemux.h:
Proper aggregation of each stream's GstFlowReturn in order to figure out
whether the task should stop or not.
Don't send inline events before pushing out a NEW_SEGMENT, more
specifically for GST_TAG_EVENT.
Change a GST_ERROR to a GST_WARNING for a non-fatal situation in reading
sub-indexes.

ChangeLog
common
gst/avi/gstavidemux.c
gst/avi/gstavidemux.h

index 5777915..289874b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2006-07-03  Edward Hervey  <edward@fluendo.com>
+
+       * gst/avi/gstavidemux.c: (gst_avi_demux_reset),
+       (gst_avi_demux_read_subindexes), (gst_avi_demux_parse_stream),
+       (gst_avi_demux_handle_seek), (gst_avi_demux_aggregated_flow),
+       (gst_avi_demux_process_next_entry), (push_tag_lists),
+       (gst_avi_demux_stream_data), (gst_avi_demux_loop):
+       * gst/avi/gstavidemux.h:
+       Proper aggregation of each stream's GstFlowReturn in order to figure out
+       whether the task should stop or not.
+       Don't send inline events before pushing out a NEW_SEGMENT, more
+       specifically for GST_TAG_EVENT.
+       Change a GST_ERROR to a GST_WARNING for a non-fatal situation in reading
+       sub-indexes.
+
 2006-06-30  Tim-Philipp Müller  <tim at centricular dot net>
 
        Patch by: Brian Cameron  <brian dot cameron at sun dot com>
diff --git a/common b/common
index 123195d..dd173e2 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 123195d3bbcc0b6e1cf867d3a180685f8766a0be
+Subproject commit dd173e2720ac21e4a47c97705d7ff32271a0ee66
index 392ce79..886a6b2 100644 (file)
@@ -206,6 +206,10 @@ gst_avi_demux_reset (GstAviDemux * avi)
       gst_buffer_unref (avi->stream[i].extradata);
     if (avi->stream[i].pad)
       gst_element_remove_pad (GST_ELEMENT (avi), avi->stream[i].pad);
+    if (avi->stream[i].taglist) {
+      gst_tag_list_free (avi->stream[i].taglist);
+      avi->stream[i].taglist = NULL;
+    }
   }
   memset (&avi->stream, 0, sizeof (avi->stream));
 
@@ -228,6 +232,8 @@ gst_avi_demux_reset (GstAviDemux * avi)
     gst_event_unref (avi->seek_event);
   avi->seek_event = NULL;
 
+  avi->got_tags = FALSE;
+
   gst_segment_init (&avi->segment, GST_FORMAT_TIME);
 }
 
@@ -968,7 +974,7 @@ gst_avi_demux_read_subindexes (GstAviDemux * avi,
         continue;
       else if (tag != GST_MAKE_FOURCC ('i', 'x', '0' + stream->num / 10,
               '0' + stream->num % 10)) {
-        GST_ERROR_OBJECT (GST_ELEMENT (avi),
+        GST_WARNING_OBJECT (GST_ELEMENT (avi),
             "Not an ix## chunk (%" GST_FOURCC_FORMAT ")",
             GST_FOURCC_ARGS (tag));
         gst_buffer_unref (buf);
@@ -1202,11 +1208,13 @@ gst_avi_demux_parse_stream (GstElement * element, GstBuffer * buf)
       GST_PAD_NAME (pad), caps);
 
   if (codec_name) {
-    GstTagList *list = gst_tag_list_new ();
+    if (!stream->taglist)
+      stream->taglist = gst_tag_list_new ();
+
+    avi->got_tags = TRUE;
 
-    gst_tag_list_add (list, GST_TAG_MERGE_APPEND, tag_name, codec_name, NULL);
-    gst_element_found_tags_for_pad (GST_ELEMENT (avi), pad, list);
-    g_free (codec_name);
+    gst_tag_list_add (stream->taglist, GST_TAG_MERGE_APPEND, tag_name,
+        codec_name, NULL);
   }
 
   return TRUE;
@@ -2342,6 +2350,7 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, gboolean update)
   GstClockTime start_time;
   gboolean flush, keyframe;
   gst_avi_index_entry *entry;
+  guint i;
 
   /* FIXME: if we seek in an openDML file, we will have multiple
    * primary levels. Seeking in between those will cause havoc. */
@@ -2393,6 +2402,9 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, gboolean update)
   if (flush) {
     gst_avi_demux_push_event (avi, gst_event_new_flush_stop ());
     gst_pad_push_event (avi->sinkpad, gst_event_new_flush_stop ());
+    for (i = 0; i < avi->num_streams; i++) {
+      avi->stream[i].last_flow = GST_FLOW_OK;
+    }
   }
 
   if (avi->segment.flags & GST_SEEK_FLAG_SEGMENT) {
@@ -2458,26 +2470,40 @@ gst_avi_demux_invert (avi_stream_context * stream, GstBuffer * buf)
   return buf;
 }
 
-static gboolean
-gst_avi_demux_all_source_pads_unlinked (GstAviDemux * avi)
+/*
+  Returns the aggregated GstFlowReturn.
+*/
+
+static GstFlowReturn
+gst_avi_demux_aggregated_flow (GstAviDemux * avi)
 {
   gint i;
+  GstFlowReturn res = GST_FLOW_OK;
+  gboolean haveok = FALSE;
 
-  for (i = 0; i < avi->num_streams; ++i) {
-    if (gst_pad_is_linked (avi->stream[i].pad))
-      return FALSE;
-    /* ignore unlinked state if we haven't tried to push on this pad yet */
-    if (avi->stream[i].last_flow == GST_FLOW_OK)
-      return FALSE;
+  for (i = 0; i < avi->num_streams; i++) {
+    GstFlowReturn last = avi->stream[i].last_flow;
+
+    GST_LOG_OBJECT (avi, "stream %d , flow : %s", i, gst_flow_get_name (last));
+    if (last == GST_FLOW_OK)
+      haveok = TRUE;
+    else if (last < res) {
+      res = last;
+    }
   }
 
-  return TRUE;
+  if (!GST_FLOW_IS_FATAL (res) && res != GST_FLOW_WRONG_STATE && haveok)
+    res = GST_FLOW_OK;
+
+  GST_DEBUG_OBJECT (avi, "Returning aggregated value of %s",
+      gst_flow_get_name (res));
+  return res;
 }
 
 static GstFlowReturn
 gst_avi_demux_process_next_entry (GstAviDemux * avi)
 {
-  GstFlowReturn res;
+  GstFlowReturn res = GST_FLOW_OK;
   gboolean processed = FALSE;
 
   do {
@@ -2485,6 +2511,7 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
     if (avi->current_entry >= avi->index_size) {
       GST_LOG_OBJECT (avi, "Handled last index entry, setting EOS (%d > %d)",
           avi->current_entry, avi->index_size);
+      avi->stream[0].last_flow = GST_FLOW_UNEXPECTED;
       goto eos;
     } else {
       GstBuffer *buf;
@@ -2497,6 +2524,8 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
         continue;
       }
 
+      stream = &avi->stream[entry->stream_nr];
+
       if ((entry->flags & GST_RIFF_IF_KEYFRAME)
           && GST_CLOCK_TIME_IS_VALID (entry->ts)
           && GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
@@ -2504,11 +2533,10 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
         GST_LOG_OBJECT (avi, "Found keyframe after segment,"
             " setting EOS (%" GST_TIME_FORMAT " > %" GST_TIME_FORMAT ")",
             GST_TIME_ARGS (entry->ts), GST_TIME_ARGS (avi->segment.stop));
-        goto eos;
+        res = stream->last_flow = GST_FLOW_UNEXPECTED;
+        goto beach;
       }
 
-      stream = &avi->stream[entry->stream_nr];
-
       if (entry->size == 0 || !stream->pad) {
         GST_DEBUG_OBJECT (avi, "Skipping entry %d (%d, %p)",
             avi->current_entry - 1, entry->size, stream->pad);
@@ -2517,14 +2545,16 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
 
       if ((res = gst_pad_pull_range (avi->sinkpad, entry->offset +
                   avi->index_offset, entry->size, &buf)) != GST_FLOW_OK) {
-        return res;
+        stream->last_flow = res;
+        goto beach;
       }
 
       if (GST_BUFFER_SIZE (buf) < entry->size) {
         GST_WARNING_OBJECT (avi, "Short read at offset %" G_GUINT64_FORMAT
             ", only got %d/%d bytes (truncated file?)", entry->offset +
             avi->index_offset, GST_BUFFER_SIZE (buf), entry->size);
-        goto eos;
+        res = stream->last_flow = GST_FLOW_UNEXPECTED;
+        goto beach;
       }
 
       if (stream->strh->fcc_handler == GST_MAKE_FOURCC ('D', 'I', 'B', ' ')) {
@@ -2545,7 +2575,7 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
       if (res != GST_FLOW_OK && res != GST_FLOW_NOT_LINKED) {
         GST_DEBUG_OBJECT (avi, "Flow on pad %s: %s",
             GST_PAD_NAME (stream->pad), gst_flow_get_name (res));
-        return res;
+        goto beach;
       }
       processed = TRUE;
 
@@ -2555,7 +2585,9 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi)
     }
   } while (!processed);
 
-  return GST_FLOW_OK;
+beach:
+  GST_DEBUG_OBJECT (avi, "returning %s", gst_flow_get_name (res));
+  return res;
 
 eos:
   {
@@ -2563,6 +2595,23 @@ eos:
   }
 }
 
+static void
+push_tag_lists (GstAviDemux * avi)
+{
+  guint i;
+
+  if (!avi->got_tags)
+    return;
+
+  for (i = 0; i < avi->num_streams; i++)
+    if (avi->stream[i].pad && avi->stream[i].taglist) {
+      gst_element_found_tags_for_pad (GST_ELEMENT (avi), avi->stream[i].pad,
+          avi->stream[i].taglist);
+      avi->stream[i].taglist = NULL;
+    }
+  avi->got_tags = FALSE;
+}
+
 /*
  * Read data.
  */
@@ -2641,7 +2690,7 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
 static void
 gst_avi_demux_loop (GstPad * pad)
 {
-  GstFlowReturn res;
+  GstFlowReturn res = GST_FLOW_OK;
   GstAviDemux *avi = GST_AVI_DEMUX (GST_PAD_PARENT (pad));
 
   switch (avi->state) {
@@ -2656,24 +2705,25 @@ gst_avi_demux_loop (GstPad * pad)
       avi->state = GST_AVI_DEMUX_MOVI;
       break;
     case GST_AVI_DEMUX_MOVI:
-      if (avi->seek_event) {
+      if (G_UNLIKELY (avi->seek_event)) {
         gst_avi_demux_push_event (avi, avi->seek_event);
         avi->seek_event = NULL;
       }
-      if ((res = gst_avi_demux_stream_data (avi)) != GST_FLOW_OK) {
-        GST_DEBUG_OBJECT (avi, "stream_data flow: %s", gst_flow_get_name (res));
-        goto pause;
-      }
+      if (G_UNLIKELY (avi->got_tags))
+        push_tag_lists (avi);
+      res = gst_avi_demux_stream_data (avi);
       break;
     default:
       g_assert_not_reached ();
   }
 
-  if (gst_avi_demux_all_source_pads_unlinked (avi)) {
-    GST_DEBUG_OBJECT (avi, "all source pads unlinked, pausing");
-    res = GST_FLOW_NOT_LINKED;
+  GST_DEBUG_OBJECT (avi, "res:%s", gst_flow_get_name (res));
+
+  /* Get Aggregated flow return */
+
+  if ((res != GST_FLOW_OK)
+      && ((res = gst_avi_demux_aggregated_flow (avi)) != GST_FLOW_OK))
     goto pause;
-  }
 
   return;
 
index 0cb26de..0ea5123 100644 (file)
@@ -90,6 +90,8 @@ typedef struct {
   GstClockTime   idx_duration;
 
   guint64       *indexes;
+
+  GstTagList   *taglist;
 } avi_stream_context;
 
 typedef enum {
@@ -127,6 +129,8 @@ typedef struct _GstAviDemux {
   GstSegment    segment;
   GstEvent      *seek_event;
 
+  gboolean     got_tags;
+
 } GstAviDemux;
 
 typedef struct _GstAviDemuxClass {