gst_plugins_base/gst-libs/gst/tag/gsttagdemux.c
changeset 8 4a7fac7dd34a
parent 0 0e761a78d257
child 30 7e817e7e631c
--- a/gst_plugins_base/gst-libs/gst/tag/gsttagdemux.c	Fri Mar 19 09:35:09 2010 +0200
+++ b/gst_plugins_base/gst-libs/gst/tag/gsttagdemux.c	Fri Apr 16 15:15:52 2010 +0300
@@ -75,11 +75,7 @@
 #include "gsttagdemux.h"
 
 #include <gst/base/gsttypefindhelper.h>
-#ifndef __SYMBIAN32__
 #include <gst/gst-i18n-plugin.h>
-#else
-#include "gst/gst-i18n-plugin.h"
-#endif
 #include <string.h>
 
 typedef enum
@@ -115,6 +111,8 @@
   GstSegment segment;
   gboolean need_newseg;
   gboolean newseg_update;
+
+  GList *pending_events;
 };
 
 /* Require at least 8kB of data before we attempt typefind. 
@@ -166,6 +164,27 @@
 static void gst_tag_demux_init (GstTagDemux * obj, GstTagDemuxClass * klass);
 
 static gpointer parent_class;   /* NULL */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GType
+gst_tag_demux_result_get_type (void)
+{
+  static GType etype = 0;
+  if (etype == 0) {
+    static const GEnumValue values[] = {
+      {GST_TAG_DEMUX_RESULT_BROKEN_TAG, "GST_TAG_DEMUX_RESULT_BROKEN_TAG",
+          "broken-tag"},
+      {GST_TAG_DEMUX_RESULT_AGAIN, "GST_TAG_DEMUX_RESULT_AGAIN", "again"},
+      {GST_TAG_DEMUX_RESULT_OK, "GST_TAG_DEMUX_RESULT_OK", "ok"},
+      {0, NULL, NULL}
+    };
+    etype = g_enum_register_static ("GstTagDemuxResult", values);
+  }
+  return etype;
+}
 
 /* Cannot use boilerplate macros here because we want the abstract flag */
 #ifdef __SYMBIAN32__
@@ -258,6 +277,11 @@
   gst_segment_init (&tagdemux->priv->segment, GST_FORMAT_UNDEFINED);
   tagdemux->priv->need_newseg = TRUE;
   tagdemux->priv->newseg_update = FALSE;
+
+  g_list_foreach (tagdemux->priv->pending_events,
+      (GFunc) gst_mini_object_unref, NULL);
+  g_list_free (tagdemux->priv->pending_events);
+  tagdemux->priv->pending_events = NULL;
 }
 
 static void
@@ -423,8 +447,6 @@
     need_sub = TRUE;
   }
 
-  g_assert (out_size > 0);
-
   if (need_sub == TRUE) {
     if (out_size != GST_BUFFER_SIZE (buf) || !gst_buffer_is_writable (buf)) {
       GstBuffer *sub;
@@ -656,6 +678,8 @@
           return GST_FLOW_UNEXPECTED;
       }
       if (outbuf) {
+        GList *events;
+
         if (G_UNLIKELY (demux->priv->srcpad == NULL)) {
           gst_buffer_unref (outbuf);
           return GST_FLOW_ERROR;
@@ -670,7 +694,20 @@
           demux->priv->need_newseg = FALSE;
         }
 
-        /* Send pending tag event */
+        /* send any pending events we cached */
+        GST_OBJECT_LOCK (demux);
+        events = demux->priv->pending_events;
+        demux->priv->pending_events = NULL;
+        GST_OBJECT_UNLOCK (demux);
+
+        while (events != NULL) {
+          GST_DEBUG_OBJECT (demux->priv->srcpad, "sending cached %s event: %"
+              GST_PTR_FORMAT, GST_EVENT_TYPE_NAME (events->data), events->data);
+          gst_pad_push_event (demux->priv->srcpad, GST_EVENT (events->data));
+          events = g_list_delete_link (events, events);
+        }
+
+        /* Send our own pending tag event */
         if (demux->priv->send_tag_event) {
           gst_tag_demux_send_tag_event (demux);
           demux->priv->send_tag_event = FALSE;
@@ -728,7 +765,18 @@
       break;
     }
     default:
-      ret = gst_pad_event_default (pad, event);
+      if (demux->priv->need_newseg) {
+        /* Cache all events if we have a pending segment, so they don't get
+         * lost (esp. tag events) */
+        GST_INFO_OBJECT (demux, "caching event: %" GST_PTR_FORMAT, event);
+        GST_OBJECT_LOCK (demux);
+        demux->priv->pending_events =
+            g_list_append (demux->priv->pending_events, event);
+        GST_OBJECT_UNLOCK (demux);
+        ret = TRUE;
+      } else {
+        ret = gst_pad_event_default (pad, event);
+      }
       break;
   }
 
@@ -829,12 +877,14 @@
       break;
     }
     default:
-      /* FIXME: shouldn't we pass unknown and unhandled events upstream? */
+      res = gst_pad_push_event (tagdemux->priv->sinkpad, event);
+      event = NULL;
       break;
   }
 
   gst_object_unref (tagdemux);
-  gst_event_unref (event);
+  if (event)
+    gst_event_unref (event);
   return res;
 }
 
@@ -1159,6 +1209,13 @@
     demux->priv->send_tag_event = TRUE;
   }
 
+  if (demux->priv->upstream_size <=
+      demux->priv->strip_start + demux->priv->strip_end) {
+    /* There was no data (probably due to a truncated file) */
+    GST_DEBUG_OBJECT (demux, "No data in file");
+    return FALSE;
+  }
+
   /* 3 - Do typefinding on data */
   caps = gst_type_find_helper_get_range (GST_OBJECT (demux),
       (GstTypeFindHelperGetRangeFunction) gst_tag_demux_read_range,
@@ -1269,7 +1326,7 @@
   {
     GST_DEBUG_OBJECT (demux, "attempted read beyond end of file");
     if (*buffer != NULL) {
-      gst_buffer_unref (buffer);
+      gst_buffer_unref (*buffer);
       *buffer = NULL;
     }
     return GST_FLOW_UNEXPECTED;