gst_plugins_base/gst-libs/gst/tag/gsttagdemux.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer Base Class for Tag Demuxing
       
     2  * Copyright (C) 2005 Jan Schmidt <thaytan@mad.scientist.com>
       
     3  * Copyright (C) 2006-2007 Tim-Philipp Müller <tim centricular net>
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Library General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Library General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Library General Public
       
    16  * License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 /**
       
    22  * SECTION:gsttagdemux
       
    23  * @see_also: GstApeDemux, GstID3Demux
       
    24  * @short_description: Base class for demuxing tags that are in chunks
       
    25  *                     directly at the beginning or at the end of a file
       
    26  * 
       
    27  * <refsect2>
       
    28  * <para>
       
    29  * Provides a base class for demuxing tags at the beginning or end of a
       
    30  * stream and handles things like typefinding, querying, seeking, and
       
    31  * different modes of operation (chain-based, pull_range-based, and providing
       
    32  * downstream elements with random access if upstream supports that). The tag
       
    33  * is stripped from the output, and all offsets are adjusted for the tag
       
    34  * sizes, so that to the downstream element the stream will appear as if
       
    35  * there was no tag at all. Also, once the tag has been parsed, GstTagDemux
       
    36  * will try to determine the media type of the resulting stream and add a
       
    37  * source pad with the appropriate caps in order to facilitate auto-plugging.
       
    38  * </para>
       
    39  * <title>Deriving from GstTagDemux</title>
       
    40  * <para>
       
    41  * Subclasses have to do four things:
       
    42  * <itemizedlist>
       
    43  *  <listitem><para>
       
    44  *  In their base init function, they must add a pad template for the sink
       
    45  *  pad to the element class, describing the media type they can parse in
       
    46  *  the caps of the pad template.
       
    47  *  </para></listitem>
       
    48  *  <listitem><para>
       
    49  *  In their class init function, they must override
       
    50  *  GST_TAG_DEMUX_CLASS(demux_klass)->identify_tag with their own identify
       
    51  *  function.
       
    52  *  </para></listitem>
       
    53  *  <listitem><para>
       
    54  *  In their class init function, they must override
       
    55  *  GST_TAG_DEMUX_CLASS(demux_klass)->parse_tag with their own parse
       
    56  *  function.
       
    57  *  </para></listitem>
       
    58  *  <listitem><para>
       
    59  *  In their class init function, they must also set
       
    60  *  GST_TAG_DEMUX_CLASS(demux_klass)->min_start_size and/or 
       
    61  *  GST_TAG_DEMUX_CLASS(demux_klass)->min_end_size to the minimum size required
       
    62  *  for the identify function to decide whether the stream has a supported tag
       
    63  *  or not. A class parsing ID3v1 tags, for example, would set min_end_size to
       
    64  *  128 bytes.
       
    65  *  </para></listitem>
       
    66  * </itemizedlist>
       
    67  * </para>
       
    68  * </refsect2>
       
    69  */
       
    70 
       
    71 #ifdef HAVE_CONFIG_H
       
    72 #include "config.h"
       
    73 #endif
       
    74 
       
    75 #include "gsttagdemux.h"
       
    76 
       
    77 #include <gst/base/gsttypefindhelper.h>
       
    78 #ifndef __SYMBIAN32__
       
    79 #include <gst/gst-i18n-plugin.h>
       
    80 #else
       
    81 #include "gst/gst-i18n-plugin.h"
       
    82 #endif
       
    83 #include <string.h>
       
    84 
       
    85 typedef enum
       
    86 {
       
    87   GST_TAG_DEMUX_READ_START_TAG,
       
    88   GST_TAG_DEMUX_TYPEFINDING,
       
    89   GST_TAG_DEMUX_STREAMING
       
    90 } GstTagDemuxState;
       
    91 
       
    92 struct _GstTagDemuxPrivate
       
    93 {
       
    94   GstPad *srcpad;
       
    95   GstPad *sinkpad;
       
    96 
       
    97   /* Number of bytes to remove from the
       
    98    * start of file (tag at beginning) */
       
    99   guint strip_start;
       
   100 
       
   101   /* Number of bytes to remove from the
       
   102    * end of file (tag at end) */
       
   103   guint strip_end;
       
   104 
       
   105   gint64 upstream_size;
       
   106 
       
   107   GstTagDemuxState state;
       
   108   GstBuffer *collect;
       
   109   GstCaps *src_caps;
       
   110 
       
   111   GstTagList *event_tags;
       
   112   GstTagList *parsed_tags;
       
   113   gboolean send_tag_event;
       
   114 
       
   115   GstSegment segment;
       
   116   gboolean need_newseg;
       
   117   gboolean newseg_update;
       
   118 };
       
   119 
       
   120 /* Require at least 8kB of data before we attempt typefind. 
       
   121  * Seems a decent value based on test files
       
   122  * 40kB is massive overkill for the maximum, I think, but it 
       
   123  * doesn't do any harm (tpm: increased to 64kB after watching
       
   124  * typefinding fail on a wavpack file that needed 42kB to succeed) */
       
   125 #define TYPE_FIND_MIN_SIZE 8192
       
   126 #define TYPE_FIND_MAX_SIZE 65536
       
   127 
       
   128 GST_DEBUG_CATEGORY_STATIC (tagdemux_debug);
       
   129 #define GST_CAT_DEFAULT (tagdemux_debug)
       
   130 
       
   131 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
       
   132     GST_PAD_SRC,
       
   133     GST_PAD_SOMETIMES,
       
   134     GST_STATIC_CAPS ("ANY")
       
   135     );
       
   136 
       
   137 static void gst_tag_demux_dispose (GObject * object);
       
   138 
       
   139 static GstFlowReturn gst_tag_demux_chain (GstPad * pad, GstBuffer * buf);
       
   140 static gboolean gst_tag_demux_sink_event (GstPad * pad, GstEvent * event);
       
   141 
       
   142 static gboolean gst_tag_demux_src_activate_pull (GstPad * pad, gboolean active);
       
   143 static GstFlowReturn gst_tag_demux_read_range (GstTagDemux * tagdemux,
       
   144     guint64 offset, guint length, GstBuffer ** buffer);
       
   145 
       
   146 static gboolean gst_tag_demux_src_checkgetrange (GstPad * srcpad);
       
   147 static GstFlowReturn gst_tag_demux_src_getrange (GstPad * srcpad,
       
   148     guint64 offset, guint length, GstBuffer ** buffer);
       
   149 
       
   150 static gboolean gst_tag_demux_add_srcpad (GstTagDemux * tagdemux,
       
   151     GstCaps * new_caps);
       
   152 static gboolean gst_tag_demux_remove_srcpad (GstTagDemux * tagdemux);
       
   153 
       
   154 static gboolean gst_tag_demux_srcpad_event (GstPad * pad, GstEvent * event);
       
   155 static gboolean gst_tag_demux_sink_activate (GstPad * sinkpad);
       
   156 static GstStateChangeReturn gst_tag_demux_change_state (GstElement * element,
       
   157     GstStateChange transition);
       
   158 static gboolean gst_tag_demux_pad_query (GstPad * pad, GstQuery * query);
       
   159 static const GstQueryType *gst_tag_demux_get_query_types (GstPad * pad);
       
   160 static gboolean gst_tag_demux_get_upstream_size (GstTagDemux * tagdemux);
       
   161 static void gst_tag_demux_send_tag_event (GstTagDemux * tagdemux);
       
   162 static gboolean gst_tag_demux_send_new_segment (GstTagDemux * tagdemux);
       
   163 
       
   164 static void gst_tag_demux_base_init (gpointer g_class);
       
   165 static void gst_tag_demux_class_init (gpointer g_class, gpointer d);
       
   166 static void gst_tag_demux_init (GstTagDemux * obj, GstTagDemuxClass * klass);
       
   167 
       
   168 static gpointer parent_class;   /* NULL */
       
   169 
       
   170 /* Cannot use boilerplate macros here because we want the abstract flag */
       
   171 #ifdef __SYMBIAN32__
       
   172 EXPORT_C
       
   173 #endif
       
   174 
       
   175 GType
       
   176 gst_tag_demux_get_type (void)
       
   177 {
       
   178   static GType object_type;     /* 0 */
       
   179 
       
   180   if (object_type == 0) {
       
   181     static const GTypeInfo object_info = {
       
   182       sizeof (GstTagDemuxClass),
       
   183       gst_tag_demux_base_init,
       
   184       NULL,                     /* base_finalize */
       
   185       gst_tag_demux_class_init,
       
   186       NULL,                     /* class_finalize */
       
   187       NULL,                     /* class_data */
       
   188       sizeof (GstTagDemux),
       
   189       0,                        /* n_preallocs */
       
   190       (GInstanceInitFunc) gst_tag_demux_init
       
   191     };
       
   192 
       
   193     object_type = g_type_register_static (GST_TYPE_ELEMENT,
       
   194         "GstTagDemux", &object_info, G_TYPE_FLAG_ABSTRACT);
       
   195   }
       
   196 
       
   197   return object_type;
       
   198 }
       
   199 
       
   200 static void
       
   201 gst_tag_demux_base_init (gpointer klass)
       
   202 {
       
   203   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
       
   204 
       
   205   gst_element_class_add_pad_template (element_class,
       
   206       gst_static_pad_template_get (&src_factory));
       
   207 
       
   208   GST_DEBUG_CATEGORY_INIT (tagdemux_debug, "tagdemux", 0,
       
   209       "tag demux base class");
       
   210 }
       
   211 
       
   212 static void
       
   213 gst_tag_demux_class_init (gpointer klass, gpointer d)
       
   214 {
       
   215   GstTagDemuxClass *tagdemux_class = GST_TAG_DEMUX_CLASS (klass);
       
   216   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
       
   217   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
       
   218 
       
   219   parent_class = g_type_class_peek_parent (klass);
       
   220 
       
   221   gobject_class->dispose = gst_tag_demux_dispose;
       
   222 
       
   223   element_class->change_state = GST_DEBUG_FUNCPTR (gst_tag_demux_change_state);
       
   224 
       
   225   g_type_class_add_private (klass, sizeof (GstTagDemuxPrivate));
       
   226 
       
   227   /* subclasses must set at least one of these */
       
   228   tagdemux_class->min_start_size = 0;
       
   229   tagdemux_class->min_end_size = 0;
       
   230 }
       
   231 
       
   232 static void
       
   233 gst_tag_demux_reset (GstTagDemux * tagdemux)
       
   234 {
       
   235   GstBuffer **buffer_p = &tagdemux->priv->collect;
       
   236   GstCaps **caps_p = &tagdemux->priv->src_caps;
       
   237 
       
   238   tagdemux->priv->strip_start = 0;
       
   239   tagdemux->priv->strip_end = 0;
       
   240   tagdemux->priv->upstream_size = -1;
       
   241   tagdemux->priv->state = GST_TAG_DEMUX_READ_START_TAG;
       
   242   tagdemux->priv->send_tag_event = FALSE;
       
   243 
       
   244   gst_buffer_replace (buffer_p, NULL);
       
   245   gst_caps_replace (caps_p, NULL);
       
   246 
       
   247   gst_tag_demux_remove_srcpad (tagdemux);
       
   248 
       
   249   if (tagdemux->priv->event_tags) {
       
   250     gst_tag_list_free (tagdemux->priv->event_tags);
       
   251     tagdemux->priv->event_tags = NULL;
       
   252   }
       
   253   if (tagdemux->priv->parsed_tags) {
       
   254     gst_tag_list_free (tagdemux->priv->parsed_tags);
       
   255     tagdemux->priv->parsed_tags = NULL;
       
   256   }
       
   257 
       
   258   gst_segment_init (&tagdemux->priv->segment, GST_FORMAT_UNDEFINED);
       
   259   tagdemux->priv->need_newseg = TRUE;
       
   260   tagdemux->priv->newseg_update = FALSE;
       
   261 }
       
   262 
       
   263 static void
       
   264 gst_tag_demux_init (GstTagDemux * demux, GstTagDemuxClass * gclass)
       
   265 {
       
   266   GstElementClass *element_klass = GST_ELEMENT_CLASS (gclass);
       
   267   GstPadTemplate *tmpl;
       
   268 
       
   269   demux->priv = g_type_instance_get_private ((GTypeInstance *) demux,
       
   270       GST_TYPE_TAG_DEMUX);
       
   271 
       
   272   tmpl = gst_element_class_get_pad_template (element_klass, "sink");
       
   273   if (tmpl) {
       
   274     demux->priv->sinkpad = gst_pad_new_from_template (tmpl, "sink");
       
   275 
       
   276     gst_pad_set_activate_function (demux->priv->sinkpad,
       
   277         GST_DEBUG_FUNCPTR (gst_tag_demux_sink_activate));
       
   278     gst_pad_set_event_function (demux->priv->sinkpad,
       
   279         GST_DEBUG_FUNCPTR (gst_tag_demux_sink_event));
       
   280     gst_pad_set_chain_function (demux->priv->sinkpad,
       
   281         GST_DEBUG_FUNCPTR (gst_tag_demux_chain));
       
   282     gst_element_add_pad (GST_ELEMENT (demux), demux->priv->sinkpad);
       
   283   }
       
   284 
       
   285   gst_tag_demux_reset (demux);
       
   286 }
       
   287 
       
   288 static void
       
   289 gst_tag_demux_dispose (GObject * object)
       
   290 {
       
   291   GstTagDemux *tagdemux = GST_TAG_DEMUX (object);
       
   292 
       
   293   gst_tag_demux_reset (tagdemux);
       
   294 
       
   295   G_OBJECT_CLASS (parent_class)->dispose (object);
       
   296 }
       
   297 
       
   298 static gboolean
       
   299 gst_tag_demux_add_srcpad (GstTagDemux * tagdemux, GstCaps * new_caps)
       
   300 {
       
   301   GstPad *srcpad = NULL;
       
   302 
       
   303   if (tagdemux->priv->src_caps == NULL ||
       
   304       !gst_caps_is_equal (new_caps, tagdemux->priv->src_caps)) {
       
   305 
       
   306     gst_caps_replace (&tagdemux->priv->src_caps, new_caps);
       
   307 
       
   308     if (tagdemux->priv->srcpad != NULL) {
       
   309       GST_DEBUG_OBJECT (tagdemux, "Changing src pad caps to %" GST_PTR_FORMAT,
       
   310           tagdemux->priv->src_caps);
       
   311 
       
   312       gst_pad_set_caps (tagdemux->priv->srcpad, tagdemux->priv->src_caps);
       
   313     }
       
   314   } else {
       
   315     /* Caps never changed */
       
   316   }
       
   317 
       
   318   if (tagdemux->priv->srcpad == NULL) {
       
   319     srcpad = tagdemux->priv->srcpad =
       
   320         gst_pad_new_from_template (gst_element_class_get_pad_template
       
   321         (GST_ELEMENT_GET_CLASS (tagdemux), "src"), "src");
       
   322     g_return_val_if_fail (tagdemux->priv->srcpad != NULL, FALSE);
       
   323 
       
   324     gst_pad_set_query_type_function (tagdemux->priv->srcpad,
       
   325         GST_DEBUG_FUNCPTR (gst_tag_demux_get_query_types));
       
   326     gst_pad_set_query_function (tagdemux->priv->srcpad,
       
   327         GST_DEBUG_FUNCPTR (gst_tag_demux_pad_query));
       
   328     gst_pad_set_event_function (tagdemux->priv->srcpad,
       
   329         GST_DEBUG_FUNCPTR (gst_tag_demux_srcpad_event));
       
   330     gst_pad_set_activatepull_function (tagdemux->priv->srcpad,
       
   331         GST_DEBUG_FUNCPTR (gst_tag_demux_src_activate_pull));
       
   332     gst_pad_set_checkgetrange_function (tagdemux->priv->srcpad,
       
   333         GST_DEBUG_FUNCPTR (gst_tag_demux_src_checkgetrange));
       
   334     gst_pad_set_getrange_function (tagdemux->priv->srcpad,
       
   335         GST_DEBUG_FUNCPTR (gst_tag_demux_src_getrange));
       
   336 
       
   337     gst_pad_use_fixed_caps (tagdemux->priv->srcpad);
       
   338 
       
   339     if (tagdemux->priv->src_caps)
       
   340       gst_pad_set_caps (tagdemux->priv->srcpad, tagdemux->priv->src_caps);
       
   341 
       
   342     GST_DEBUG_OBJECT (tagdemux, "Adding src pad with caps %" GST_PTR_FORMAT,
       
   343         tagdemux->priv->src_caps);
       
   344 
       
   345     gst_object_ref (tagdemux->priv->srcpad);
       
   346     gst_pad_set_active (tagdemux->priv->srcpad, TRUE);
       
   347     if (!gst_element_add_pad (GST_ELEMENT (tagdemux), tagdemux->priv->srcpad))
       
   348       return FALSE;
       
   349     gst_element_no_more_pads (GST_ELEMENT (tagdemux));
       
   350   }
       
   351 
       
   352   return TRUE;
       
   353 }
       
   354 
       
   355 static gboolean
       
   356 gst_tag_demux_remove_srcpad (GstTagDemux * demux)
       
   357 {
       
   358   gboolean res = TRUE;
       
   359 
       
   360   if (demux->priv->srcpad != NULL) {
       
   361     GST_DEBUG_OBJECT (demux, "Removing src pad");
       
   362     res = gst_element_remove_pad (GST_ELEMENT (demux), demux->priv->srcpad);
       
   363     g_return_val_if_fail (res != FALSE, FALSE);
       
   364     gst_object_unref (demux->priv->srcpad);
       
   365     demux->priv->srcpad = NULL;
       
   366   }
       
   367 
       
   368   return res;
       
   369 };
       
   370 
       
   371 /* will return FALSE if buffer is beyond end of data; will return TRUE
       
   372  * if buffer was trimmed successfully or didn't need trimming, but may
       
   373  * also return TRUE and set *buf_ref to NULL if the buffer was before
       
   374  * the start of the data */
       
   375 static gboolean
       
   376 gst_tag_demux_trim_buffer (GstTagDemux * tagdemux, GstBuffer ** buf_ref)
       
   377 {
       
   378   GstBuffer *buf = *buf_ref;
       
   379 
       
   380   guint trim_start = 0;
       
   381   guint out_size = GST_BUFFER_SIZE (buf);
       
   382   guint64 out_offset = GST_BUFFER_OFFSET (buf);
       
   383   gboolean need_sub = FALSE;
       
   384 
       
   385   /* Adjust offset and length */
       
   386   if (!GST_BUFFER_OFFSET_IS_VALID (buf)) {
       
   387     /* Can't change anything without an offset */
       
   388     return TRUE;
       
   389   }
       
   390 
       
   391   /* If the buffer crosses the tag at the end of file, trim it */
       
   392   if (tagdemux->priv->strip_end > 0) {
       
   393     if (gst_tag_demux_get_upstream_size (tagdemux)) {
       
   394       guint64 v1tag_offset =
       
   395           tagdemux->priv->upstream_size - tagdemux->priv->strip_end;
       
   396 
       
   397       if (out_offset >= v1tag_offset) {
       
   398         GST_DEBUG_OBJECT (tagdemux, "Buffer is past the end of the data");
       
   399         goto no_out_buffer_end;
       
   400       }
       
   401 
       
   402       if (out_offset + out_size > v1tag_offset) {
       
   403         out_size = v1tag_offset - out_offset;
       
   404         need_sub = TRUE;
       
   405       }
       
   406     }
       
   407   }
       
   408 
       
   409   if (tagdemux->priv->strip_start > 0) {
       
   410     /* If the buffer crosses the tag at the start of file, trim it */
       
   411     if (out_offset <= tagdemux->priv->strip_start) {
       
   412       if (out_offset + out_size <= tagdemux->priv->strip_start) {
       
   413         GST_DEBUG_OBJECT (tagdemux, "Buffer is before the start of the data");
       
   414         goto no_out_buffer_start;
       
   415       }
       
   416 
       
   417       trim_start = tagdemux->priv->strip_start - out_offset;
       
   418       out_size -= trim_start;
       
   419       out_offset = 0;
       
   420     } else {
       
   421       out_offset -= tagdemux->priv->strip_start;
       
   422     }
       
   423     need_sub = TRUE;
       
   424   }
       
   425 
       
   426   g_assert (out_size > 0);
       
   427 
       
   428   if (need_sub == TRUE) {
       
   429     if (out_size != GST_BUFFER_SIZE (buf) || !gst_buffer_is_writable (buf)) {
       
   430       GstBuffer *sub;
       
   431 
       
   432       GST_DEBUG_OBJECT (tagdemux, "Sub-buffering to trim size %d offset %"
       
   433           G_GINT64_FORMAT " to %d offset %" G_GINT64_FORMAT,
       
   434           GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf), out_size, out_offset);
       
   435 
       
   436       sub = gst_buffer_create_sub (buf, trim_start, out_size);
       
   437       g_return_val_if_fail (sub != NULL, FALSE);
       
   438       gst_buffer_unref (buf);
       
   439       *buf_ref = buf = sub;
       
   440     } else {
       
   441       GST_DEBUG_OBJECT (tagdemux, "Adjusting buffer from size %d offset %"
       
   442           G_GINT64_FORMAT " to %d offset %" G_GINT64_FORMAT,
       
   443           GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf), out_size, out_offset);
       
   444     }
       
   445 
       
   446     GST_BUFFER_OFFSET (buf) = out_offset;
       
   447     GST_BUFFER_OFFSET_END (buf) = out_offset + out_size;
       
   448     gst_buffer_set_caps (buf, tagdemux->priv->src_caps);
       
   449   }
       
   450 
       
   451   return TRUE;
       
   452 
       
   453 no_out_buffer_end:
       
   454   {
       
   455     gst_buffer_unref (buf);
       
   456     *buf_ref = NULL;
       
   457     return FALSE;
       
   458   }
       
   459 no_out_buffer_start:
       
   460   {
       
   461     gst_buffer_unref (buf);
       
   462     *buf_ref = NULL;
       
   463     return TRUE;
       
   464   }
       
   465 }
       
   466 
       
   467 static void
       
   468 gst_tag_demux_chain_parse_tag (GstTagDemux * demux, GstBuffer * collect)
       
   469 {
       
   470   GstTagDemuxResult parse_ret;
       
   471   GstTagDemuxClass *klass;
       
   472   guint tagsize = 0;
       
   473   guint available;
       
   474 
       
   475   g_assert (gst_buffer_is_metadata_writable (collect));
       
   476 
       
   477   klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux));
       
   478 
       
   479   /* If we receive a buffer that's from the middle of the file, 
       
   480    * we can't read tags so move to typefinding */
       
   481   if (GST_BUFFER_OFFSET_IS_VALID (collect) && GST_BUFFER_OFFSET (collect) != 0) {
       
   482     GST_DEBUG_OBJECT (demux, "Received buffer from non-zero offset %"
       
   483         G_GINT64_FORMAT ". Can't read tags", GST_BUFFER_OFFSET (collect));
       
   484     demux->priv->state = GST_TAG_DEMUX_TYPEFINDING;
       
   485     return;
       
   486   }
       
   487 
       
   488   g_assert (klass->identify_tag != NULL);
       
   489   g_assert (klass->parse_tag != NULL);
       
   490 
       
   491   available = GST_BUFFER_SIZE (collect);
       
   492 
       
   493   if (available < klass->min_start_size) {
       
   494     GST_DEBUG_OBJECT (demux, "Only %u bytes available, but %u needed "
       
   495         "to identify tag", available, klass->min_start_size);
       
   496     return;                     /* wait for more data */
       
   497   }
       
   498 
       
   499   if (!klass->identify_tag (demux, collect, TRUE, &tagsize)) {
       
   500     GST_DEBUG_OBJECT (demux, "Could not identify start tag");
       
   501     demux->priv->state = GST_TAG_DEMUX_TYPEFINDING;
       
   502     return;
       
   503   }
       
   504 
       
   505   /* need to set offset of first buffer to 0 or trimming won't work */
       
   506   if (!GST_BUFFER_OFFSET_IS_VALID (collect)) {
       
   507     GST_WARNING_OBJECT (demux, "Fixing up first buffer without offset");
       
   508     GST_BUFFER_OFFSET (collect) = 0;
       
   509   }
       
   510 
       
   511   GST_DEBUG_OBJECT (demux, "Identified tag, size = %u bytes", tagsize);
       
   512 
       
   513   do {
       
   514     GstTagList *tags = NULL;
       
   515     guint newsize, saved_size;
       
   516 
       
   517     demux->priv->strip_start = tagsize;
       
   518 
       
   519     if (available < tagsize) {
       
   520       GST_DEBUG_OBJECT (demux, "Only %u bytes available, but %u needed "
       
   521           "to parse tag", available, tagsize);
       
   522       return;                   /* wait for more data */
       
   523     }
       
   524 
       
   525     saved_size = GST_BUFFER_SIZE (collect);
       
   526     GST_BUFFER_SIZE (collect) = tagsize;
       
   527     newsize = tagsize;
       
   528 
       
   529     parse_ret = klass->parse_tag (demux, collect, TRUE, &newsize, &tags);
       
   530 
       
   531     GST_BUFFER_SIZE (collect) = saved_size;
       
   532 
       
   533     switch (parse_ret) {
       
   534       case GST_TAG_DEMUX_RESULT_OK:
       
   535         demux->priv->strip_start = newsize;
       
   536         demux->priv->parsed_tags = tags;
       
   537         GST_DEBUG_OBJECT (demux, "Read start tag of size %u", newsize);
       
   538         break;
       
   539       case GST_TAG_DEMUX_RESULT_BROKEN_TAG:
       
   540         demux->priv->strip_start = newsize;
       
   541         demux->priv->parsed_tags = tags;
       
   542         GST_WARNING_OBJECT (demux, "Ignoring broken start tag of size %d",
       
   543             demux->priv->strip_start);
       
   544         break;
       
   545       case GST_TAG_DEMUX_RESULT_AGAIN:
       
   546         GST_DEBUG_OBJECT (demux, "Re-parse, this time with %u bytes", newsize);
       
   547         g_assert (newsize != tagsize);
       
   548         tagsize = newsize;
       
   549         break;
       
   550     }
       
   551   } while (parse_ret == GST_TAG_DEMUX_RESULT_AGAIN);
       
   552 
       
   553   GST_LOG_OBJECT (demux, "Parsed tag. Proceeding to typefinding");
       
   554   demux->priv->state = GST_TAG_DEMUX_TYPEFINDING;
       
   555   demux->priv->send_tag_event = TRUE;
       
   556 }
       
   557 
       
   558 static GstFlowReturn
       
   559 gst_tag_demux_chain (GstPad * pad, GstBuffer * buf)
       
   560 {
       
   561   GstTagDemux *demux;
       
   562 
       
   563   demux = GST_TAG_DEMUX (GST_PAD_PARENT (pad));
       
   564 
       
   565   /* Update our segment last_stop info */
       
   566   if (demux->priv->segment.format == GST_FORMAT_BYTES) {
       
   567     if (GST_BUFFER_OFFSET_IS_VALID (buf))
       
   568       demux->priv->segment.last_stop = GST_BUFFER_OFFSET (buf);
       
   569     demux->priv->segment.last_stop += GST_BUFFER_SIZE (buf);
       
   570   } else if (demux->priv->segment.format == GST_FORMAT_TIME) {
       
   571     if (GST_BUFFER_TIMESTAMP_IS_VALID (buf))
       
   572       demux->priv->segment.last_stop = GST_BUFFER_TIMESTAMP (buf);
       
   573     if (GST_BUFFER_DURATION_IS_VALID (buf))
       
   574       demux->priv->segment.last_stop += GST_BUFFER_DURATION (buf);
       
   575   }
       
   576 
       
   577   if (demux->priv->collect == NULL) {
       
   578     demux->priv->collect = buf;
       
   579   } else {
       
   580     demux->priv->collect = gst_buffer_join (demux->priv->collect, buf);
       
   581   }
       
   582   buf = NULL;
       
   583 
       
   584   switch (demux->priv->state) {
       
   585     case GST_TAG_DEMUX_READ_START_TAG:
       
   586       demux->priv->collect =
       
   587           gst_buffer_make_metadata_writable (demux->priv->collect);
       
   588       gst_tag_demux_chain_parse_tag (demux, demux->priv->collect);
       
   589       if (demux->priv->state != GST_TAG_DEMUX_TYPEFINDING)
       
   590         break;
       
   591       /* Fall-through */
       
   592     case GST_TAG_DEMUX_TYPEFINDING:{
       
   593       GstTypeFindProbability probability = 0;
       
   594       GstBuffer *typefind_buf = NULL;
       
   595       GstCaps *caps;
       
   596 
       
   597       if (GST_BUFFER_SIZE (demux->priv->collect) <
       
   598           TYPE_FIND_MIN_SIZE + demux->priv->strip_start)
       
   599         break;                  /* Go get more data first */
       
   600 
       
   601       GST_DEBUG_OBJECT (demux, "Typefinding with size %d",
       
   602           GST_BUFFER_SIZE (demux->priv->collect));
       
   603 
       
   604       /* Trim the buffer and adjust offset for typefinding */
       
   605       typefind_buf = demux->priv->collect;
       
   606       gst_buffer_ref (typefind_buf);
       
   607       if (!gst_tag_demux_trim_buffer (demux, &typefind_buf))
       
   608         return GST_FLOW_UNEXPECTED;
       
   609 
       
   610       if (typefind_buf == NULL)
       
   611         break;                  /* Still need more data */
       
   612 
       
   613       caps = gst_type_find_helper_for_buffer (GST_OBJECT (demux),
       
   614           typefind_buf, &probability);
       
   615 
       
   616       if (caps == NULL) {
       
   617         if (GST_BUFFER_SIZE (typefind_buf) < TYPE_FIND_MAX_SIZE) {
       
   618           /* Just break for more data */
       
   619           gst_buffer_unref (typefind_buf);
       
   620           return GST_FLOW_OK;
       
   621         }
       
   622 
       
   623         /* We failed typefind */
       
   624         GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL),
       
   625             ("Could not detect type for contents within tag"));
       
   626         gst_buffer_unref (typefind_buf);
       
   627         gst_buffer_unref (demux->priv->collect);
       
   628         demux->priv->collect = NULL;
       
   629         return GST_FLOW_ERROR;
       
   630       }
       
   631       gst_buffer_unref (typefind_buf);
       
   632 
       
   633       GST_DEBUG_OBJECT (demux, "Found type %" GST_PTR_FORMAT " with a "
       
   634           "probability of %u", caps, probability);
       
   635 
       
   636       if (!gst_tag_demux_add_srcpad (demux, caps)) {
       
   637         GST_DEBUG_OBJECT (demux, "Failed to add srcpad");
       
   638         gst_caps_unref (caps);
       
   639         goto error;
       
   640       }
       
   641       gst_caps_unref (caps);
       
   642 
       
   643       /* Move onto streaming and fall-through to push out existing
       
   644        * data */
       
   645       demux->priv->state = GST_TAG_DEMUX_STREAMING;
       
   646       /* fall-through */
       
   647     }
       
   648     case GST_TAG_DEMUX_STREAMING:{
       
   649       GstBuffer *outbuf = NULL;
       
   650 
       
   651       /* Trim the buffer and adjust offset */
       
   652       if (demux->priv->collect) {
       
   653         outbuf = demux->priv->collect;
       
   654         demux->priv->collect = NULL;
       
   655         if (!gst_tag_demux_trim_buffer (demux, &outbuf))
       
   656           return GST_FLOW_UNEXPECTED;
       
   657       }
       
   658       if (outbuf) {
       
   659         if (G_UNLIKELY (demux->priv->srcpad == NULL)) {
       
   660           gst_buffer_unref (outbuf);
       
   661           return GST_FLOW_ERROR;
       
   662         }
       
   663 
       
   664         /* Might need a new segment before the buffer */
       
   665         if (demux->priv->need_newseg) {
       
   666           if (!gst_tag_demux_send_new_segment (demux)) {
       
   667             GST_WARNING_OBJECT (demux, "Downstream did not handle newsegment "
       
   668                 "event as it should");
       
   669           }
       
   670           demux->priv->need_newseg = FALSE;
       
   671         }
       
   672 
       
   673         /* Send pending tag event */
       
   674         if (demux->priv->send_tag_event) {
       
   675           gst_tag_demux_send_tag_event (demux);
       
   676           demux->priv->send_tag_event = FALSE;
       
   677         }
       
   678 
       
   679         /* Ensure the caps are set correctly */
       
   680         outbuf = gst_buffer_make_metadata_writable (outbuf);
       
   681         gst_buffer_set_caps (outbuf, GST_PAD_CAPS (demux->priv->srcpad));
       
   682 
       
   683         GST_LOG_OBJECT (demux, "Pushing buffer %p", outbuf);
       
   684 
       
   685         return gst_pad_push (demux->priv->srcpad, outbuf);
       
   686       }
       
   687     }
       
   688   }
       
   689   return GST_FLOW_OK;
       
   690 
       
   691 error:
       
   692   GST_DEBUG_OBJECT (demux, "error in chain function");
       
   693 
       
   694   return GST_FLOW_ERROR;
       
   695 }
       
   696 
       
   697 static gboolean
       
   698 gst_tag_demux_sink_event (GstPad * pad, GstEvent * event)
       
   699 {
       
   700   GstTagDemux *demux;
       
   701   gboolean ret;
       
   702 
       
   703   demux = GST_TAG_DEMUX (gst_pad_get_parent (pad));
       
   704 
       
   705   switch (GST_EVENT_TYPE (event)) {
       
   706     case GST_EVENT_EOS:
       
   707       if (demux->priv->srcpad == NULL) {
       
   708         GST_WARNING_OBJECT (demux, "EOS before we found a type");
       
   709         GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
       
   710       }
       
   711       ret = gst_pad_event_default (pad, event);
       
   712       break;
       
   713     case GST_EVENT_NEWSEGMENT:{
       
   714       gboolean update;
       
   715       gdouble rate, arate;
       
   716       GstFormat format;
       
   717       gint64 start, stop, position;
       
   718 
       
   719       gst_event_parse_new_segment_full (event, &update, &rate, &arate,
       
   720           &format, &start, &stop, &position);
       
   721 
       
   722       gst_segment_set_newsegment_full (&demux->priv->segment, update, rate,
       
   723           arate, format, start, stop, position);
       
   724       demux->priv->newseg_update = update;
       
   725       demux->priv->need_newseg = TRUE;
       
   726       gst_event_unref (event);
       
   727       ret = TRUE;
       
   728       break;
       
   729     }
       
   730     default:
       
   731       ret = gst_pad_event_default (pad, event);
       
   732       break;
       
   733   }
       
   734 
       
   735   gst_object_unref (demux);
       
   736   return ret;
       
   737 }
       
   738 
       
   739 static gboolean
       
   740 gst_tag_demux_get_upstream_size (GstTagDemux * tagdemux)
       
   741 {
       
   742   GstFormat format;
       
   743   gint64 len;
       
   744 
       
   745   /* Short-cut if we already queried upstream */
       
   746   if (tagdemux->priv->upstream_size > 0)
       
   747     return TRUE;
       
   748 
       
   749   format = GST_FORMAT_BYTES;
       
   750   if (!gst_pad_query_peer_duration (tagdemux->priv->sinkpad, &format, &len) ||
       
   751       len <= 0) {
       
   752     return FALSE;
       
   753   }
       
   754 
       
   755   tagdemux->priv->upstream_size = len;
       
   756   return TRUE;
       
   757 }
       
   758 
       
   759 static gboolean
       
   760 gst_tag_demux_srcpad_event (GstPad * pad, GstEvent * event)
       
   761 {
       
   762   GstTagDemux *tagdemux;
       
   763   gboolean res = FALSE;
       
   764 
       
   765   tagdemux = GST_TAG_DEMUX (gst_pad_get_parent (pad));
       
   766 
       
   767   /* Handle SEEK events, with adjusted byte offsets and sizes. */
       
   768 
       
   769   switch (GST_EVENT_TYPE (event)) {
       
   770     case GST_EVENT_SEEK:
       
   771     {
       
   772       gdouble rate;
       
   773       GstFormat format;
       
   774       GstSeekType cur_type, stop_type;
       
   775       GstSeekFlags flags;
       
   776       gint64 cur, stop;
       
   777 
       
   778       gst_event_parse_seek (event, &rate, &format, &flags,
       
   779           &cur_type, &cur, &stop_type, &stop);
       
   780 
       
   781       if (format == GST_FORMAT_BYTES &&
       
   782           tagdemux->priv->state == GST_TAG_DEMUX_STREAMING &&
       
   783           gst_pad_is_linked (tagdemux->priv->sinkpad)) {
       
   784         GstEvent *upstream;
       
   785 
       
   786         switch (cur_type) {
       
   787           case GST_SEEK_TYPE_SET:
       
   788             if (cur == -1)
       
   789               cur = 0;
       
   790             cur += tagdemux->priv->strip_start;
       
   791             break;
       
   792           case GST_SEEK_TYPE_CUR:
       
   793             break;
       
   794           case GST_SEEK_TYPE_END:
       
   795             /* Adjust the seek to be relative to the start of any end tag
       
   796              * (note: 10 bytes before end is represented by stop=-10) */
       
   797             if (cur > 0)
       
   798               cur = 0;
       
   799             cur -= tagdemux->priv->strip_end;
       
   800             break;
       
   801           case GST_SEEK_TYPE_NONE:
       
   802           default:
       
   803             break;
       
   804         }
       
   805         switch (stop_type) {
       
   806           case GST_SEEK_TYPE_SET:
       
   807             if (stop != -1) {
       
   808               /* -1 means the end of the file, pass it upstream intact */
       
   809               stop += tagdemux->priv->strip_start;
       
   810             }
       
   811             break;
       
   812           case GST_SEEK_TYPE_CUR:
       
   813             break;
       
   814           case GST_SEEK_TYPE_END:
       
   815             /* Adjust the seek to be relative to the start of any end tag
       
   816              * (note: 10 bytes before end is represented by stop=-10) */
       
   817             if (stop > 0)
       
   818               stop = 0;
       
   819             stop -= tagdemux->priv->strip_end;
       
   820             break;
       
   821           case GST_SEEK_TYPE_NONE:
       
   822           default:
       
   823             break;
       
   824         }
       
   825         upstream = gst_event_new_seek (rate, format, flags,
       
   826             cur_type, cur, stop_type, stop);
       
   827         res = gst_pad_push_event (tagdemux->priv->sinkpad, upstream);
       
   828       }
       
   829       break;
       
   830     }
       
   831     default:
       
   832       /* FIXME: shouldn't we pass unknown and unhandled events upstream? */
       
   833       break;
       
   834   }
       
   835 
       
   836   gst_object_unref (tagdemux);
       
   837   gst_event_unref (event);
       
   838   return res;
       
   839 }
       
   840 
       
   841 /* Read and interpret any end tag when activating in pull_range.
       
   842  * Returns FALSE if pad activation should fail. */
       
   843 static gboolean
       
   844 gst_tag_demux_pull_end_tag (GstTagDemux * demux, GstTagList ** tags)
       
   845 {
       
   846   GstTagDemuxResult parse_ret;
       
   847   GstTagDemuxClass *klass;
       
   848   GstFlowReturn flow_ret;
       
   849   GstTagList *new_tags = NULL;
       
   850   GstBuffer *buffer = NULL;
       
   851   gboolean have_tag;
       
   852   gboolean res = FALSE;
       
   853   guint64 offset;
       
   854   guint tagsize;
       
   855 
       
   856   klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux));
       
   857 
       
   858   g_assert (klass->identify_tag != NULL);
       
   859   g_assert (klass->parse_tag != NULL);
       
   860 
       
   861   if (klass->min_end_size == 0) {
       
   862     GST_DEBUG_OBJECT (demux, "Not looking for tag at the end");
       
   863     return TRUE;
       
   864   }
       
   865 
       
   866   if (demux->priv->upstream_size < klass->min_end_size) {
       
   867     GST_DEBUG_OBJECT (demux, "File too small");
       
   868     return TRUE;
       
   869   }
       
   870 
       
   871   /* Pull enough to identify the tag and retrieve its total size */
       
   872   offset = demux->priv->upstream_size - klass->min_end_size;
       
   873 
       
   874   flow_ret = gst_pad_pull_range (demux->priv->sinkpad, offset,
       
   875       klass->min_end_size, &buffer);
       
   876 
       
   877   if (flow_ret != GST_FLOW_OK) {
       
   878     GST_DEBUG_OBJECT (demux, "Could not read tag header from end of file, "
       
   879         "ret = %s", gst_flow_get_name (flow_ret));
       
   880     goto done;
       
   881   }
       
   882 
       
   883   if (GST_BUFFER_SIZE (buffer) < klass->min_end_size) {
       
   884     GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file "
       
   885         "(required: %u bytes)", GST_BUFFER_SIZE (buffer), klass->min_end_size);
       
   886     goto done;
       
   887   }
       
   888 
       
   889   have_tag = klass->identify_tag (demux, buffer, FALSE, &tagsize);
       
   890 
       
   891   if (!have_tag) {
       
   892     GST_DEBUG_OBJECT (demux, "Could not find tag at end");
       
   893     goto done;
       
   894   }
       
   895 
       
   896   /* Now pull the entire tag */
       
   897   do {
       
   898     guint newsize, saved_size;
       
   899 
       
   900     GST_DEBUG_OBJECT (demux, "Identified tag at end, size=%u bytes", tagsize);
       
   901 
       
   902     demux->priv->strip_end = tagsize;
       
   903 
       
   904     g_assert (tagsize >= klass->min_end_size);
       
   905 
       
   906     /* Get buffer that's exactly the requested size */
       
   907     if (GST_BUFFER_SIZE (buffer) != tagsize) {
       
   908       gst_buffer_unref (buffer);
       
   909       buffer = NULL;
       
   910 
       
   911       offset = demux->priv->upstream_size - tagsize;
       
   912 
       
   913       flow_ret = gst_pad_pull_range (demux->priv->sinkpad, offset,
       
   914           tagsize, &buffer);
       
   915 
       
   916       if (flow_ret != GST_FLOW_OK) {
       
   917         GST_DEBUG_OBJECT (demux, "Could not read data from end of file at "
       
   918             "offset %" G_GUINT64_FORMAT ". ret = %s", offset,
       
   919             gst_flow_get_name (flow_ret));
       
   920         goto done;
       
   921       }
       
   922 
       
   923       if (GST_BUFFER_SIZE (buffer) < tagsize) {
       
   924         GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file",
       
   925             GST_BUFFER_SIZE (buffer));
       
   926         goto done;
       
   927       }
       
   928     }
       
   929 
       
   930     GST_BUFFER_OFFSET (buffer) = offset;
       
   931 
       
   932     saved_size = GST_BUFFER_SIZE (buffer);
       
   933     GST_BUFFER_SIZE (buffer) = tagsize;
       
   934     newsize = tagsize;
       
   935 
       
   936     parse_ret = klass->parse_tag (demux, buffer, FALSE, &newsize, &new_tags);
       
   937 
       
   938     GST_BUFFER_SIZE (buffer) = saved_size;
       
   939 
       
   940     switch (parse_ret) {
       
   941       case GST_TAG_DEMUX_RESULT_OK:
       
   942         res = TRUE;
       
   943         demux->priv->strip_end = newsize;
       
   944         GST_DEBUG_OBJECT (demux, "Read tag at end, size %d",
       
   945             demux->priv->strip_end);
       
   946         break;
       
   947       case GST_TAG_DEMUX_RESULT_BROKEN_TAG:
       
   948         res = TRUE;
       
   949         demux->priv->strip_end = newsize;
       
   950         GST_WARNING_OBJECT (demux, "Ignoring broken tag at end, size %d",
       
   951             demux->priv->strip_end);
       
   952         break;
       
   953       case GST_TAG_DEMUX_RESULT_AGAIN:
       
   954         GST_DEBUG_OBJECT (demux, "Re-parse, this time with %d bytes", newsize);
       
   955         g_assert (newsize != tagsize);
       
   956         tagsize = newsize;
       
   957         break;
       
   958     }
       
   959   } while (parse_ret == GST_TAG_DEMUX_RESULT_AGAIN);
       
   960 
       
   961   *tags = new_tags;
       
   962   new_tags = NULL;
       
   963 
       
   964 done:
       
   965   if (new_tags)
       
   966     gst_tag_list_free (new_tags);
       
   967   if (buffer)
       
   968     gst_buffer_unref (buffer);
       
   969   return res;
       
   970 }
       
   971 
       
   972 /* Read and interpret any tag at the start when activating in
       
   973  * pull_range. Returns FALSE if pad activation should fail. */
       
   974 static gboolean
       
   975 gst_tag_demux_pull_start_tag (GstTagDemux * demux, GstTagList ** tags)
       
   976 {
       
   977   GstTagDemuxResult parse_ret;
       
   978   GstTagDemuxClass *klass;
       
   979   GstFlowReturn flow_ret;
       
   980   GstTagList *new_tags = NULL;
       
   981   GstBuffer *buffer = NULL;
       
   982   gboolean have_tag;
       
   983   gboolean res = FALSE;
       
   984   guint req, tagsize;
       
   985 
       
   986   klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux));
       
   987 
       
   988   g_assert (klass->identify_tag != NULL);
       
   989   g_assert (klass->parse_tag != NULL);
       
   990 
       
   991   if (klass->min_start_size == 0) {
       
   992     GST_DEBUG_OBJECT (demux, "Not looking for tag at the beginning");
       
   993     return TRUE;
       
   994   }
       
   995 
       
   996   /* Handle tag at start. Try with 4kB to start with */
       
   997   req = MAX (klass->min_start_size, 4096);
       
   998 
       
   999   /* Pull enough to identify the tag and retrieve its total size */
       
  1000   flow_ret = gst_pad_pull_range (demux->priv->sinkpad, 0, req, &buffer);
       
  1001   if (flow_ret != GST_FLOW_OK) {
       
  1002     GST_DEBUG_OBJECT (demux, "Could not read data from start of file ret=%s",
       
  1003         gst_flow_get_name (flow_ret));
       
  1004     goto done;
       
  1005   }
       
  1006 
       
  1007   if (GST_BUFFER_SIZE (buffer) < klass->min_start_size) {
       
  1008     GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file - "
       
  1009         "no tag in this file", GST_BUFFER_SIZE (buffer));
       
  1010     goto done;
       
  1011   }
       
  1012 
       
  1013   have_tag = klass->identify_tag (demux, buffer, TRUE, &tagsize);
       
  1014 
       
  1015   if (!have_tag) {
       
  1016     GST_DEBUG_OBJECT (demux, "Could not find start tag");
       
  1017     res = TRUE;
       
  1018     goto done;
       
  1019   }
       
  1020 
       
  1021   GST_DEBUG_OBJECT (demux, "Identified start tag, size = %u bytes", tagsize);
       
  1022 
       
  1023   do {
       
  1024     guint newsize, saved_size;
       
  1025 
       
  1026     demux->priv->strip_start = tagsize;
       
  1027 
       
  1028     /* Now pull the entire tag */
       
  1029     g_assert (tagsize >= klass->min_start_size);
       
  1030 
       
  1031     if (GST_BUFFER_SIZE (buffer) < tagsize) {
       
  1032       gst_buffer_unref (buffer);
       
  1033       buffer = NULL;
       
  1034 
       
  1035       flow_ret = gst_pad_pull_range (demux->priv->sinkpad, 0, tagsize, &buffer);
       
  1036       if (flow_ret != GST_FLOW_OK) {
       
  1037         GST_DEBUG_OBJECT (demux, "Could not read data from start of file, "
       
  1038             "ret = %s", gst_flow_get_name (flow_ret));
       
  1039         goto done;
       
  1040       }
       
  1041 
       
  1042       if (GST_BUFFER_SIZE (buffer) < tagsize) {
       
  1043         GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file",
       
  1044             GST_BUFFER_SIZE (buffer));
       
  1045         GST_ELEMENT_ERROR (demux, STREAM, DECODE,
       
  1046             (_("Failed to read tag: not enough data")), (NULL));
       
  1047         goto done;
       
  1048       }
       
  1049     }
       
  1050 
       
  1051     saved_size = GST_BUFFER_SIZE (buffer);
       
  1052     GST_BUFFER_SIZE (buffer) = tagsize;
       
  1053     newsize = tagsize;
       
  1054     parse_ret = klass->parse_tag (demux, buffer, TRUE, &newsize, &new_tags);
       
  1055 
       
  1056     GST_BUFFER_SIZE (buffer) = saved_size;
       
  1057 
       
  1058     switch (parse_ret) {
       
  1059       case GST_TAG_DEMUX_RESULT_OK:
       
  1060         res = TRUE;
       
  1061         demux->priv->strip_start = newsize;
       
  1062         GST_DEBUG_OBJECT (demux, "Read start tag of size %d", newsize);
       
  1063         break;
       
  1064       case GST_TAG_DEMUX_RESULT_BROKEN_TAG:
       
  1065         res = TRUE;
       
  1066         demux->priv->strip_start = newsize;
       
  1067         GST_WARNING_OBJECT (demux, "Ignoring broken start tag of size %d",
       
  1068             demux->priv->strip_start);
       
  1069         break;
       
  1070       case GST_TAG_DEMUX_RESULT_AGAIN:
       
  1071         GST_DEBUG_OBJECT (demux, "Re-parse, this time with %d bytes", newsize);
       
  1072         g_assert (newsize != tagsize);
       
  1073         tagsize = newsize;
       
  1074         break;
       
  1075     }
       
  1076   } while (parse_ret == GST_TAG_DEMUX_RESULT_AGAIN);
       
  1077 
       
  1078   *tags = new_tags;
       
  1079   new_tags = NULL;
       
  1080 
       
  1081 done:
       
  1082   if (new_tags)
       
  1083     gst_tag_list_free (new_tags);
       
  1084   if (buffer)
       
  1085     gst_buffer_unref (buffer);
       
  1086   return res;
       
  1087 }
       
  1088 
       
  1089 /* This function operates similarly to gst_type_find_element_activate
       
  1090  * in the typefind element
       
  1091  * 1. try to activate in pull mode. if not, switch to push and succeed.
       
  1092  * 2. try to read tags in pull mode
       
  1093  * 3. typefind the contents
       
  1094  * 4. deactivate pull mode.
       
  1095  * 5. if we didn't find any caps, fail.
       
  1096  * 6. Add the srcpad
       
  1097  * 7. if the sink pad is activated, we are in pull mode. succeed.
       
  1098  *    otherwise activate both pads in push mode and succeed.
       
  1099  */
       
  1100 static gboolean
       
  1101 gst_tag_demux_sink_activate (GstPad * sinkpad)
       
  1102 {
       
  1103   GstTypeFindProbability probability = 0;
       
  1104   GstTagDemuxClass *klass;
       
  1105   GstTagDemux *demux;
       
  1106   GstTagList *start_tags = NULL;
       
  1107   GstTagList *end_tags = NULL;
       
  1108   gboolean e_tag_ok, s_tag_ok;
       
  1109   gboolean ret = FALSE;
       
  1110   GstCaps *caps = NULL;
       
  1111 
       
  1112   demux = GST_TAG_DEMUX (GST_PAD_PARENT (sinkpad));
       
  1113   klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux));
       
  1114 
       
  1115   /* 1: */
       
  1116   /* If we can activate pull_range upstream, then read any end and start
       
  1117    * tags, otherwise activate in push mode and the chain function will 
       
  1118    * collect buffers, read the start tag and output a buffer to end
       
  1119    * preroll.
       
  1120    */
       
  1121   if (!gst_pad_check_pull_range (sinkpad) ||
       
  1122       !gst_pad_activate_pull (sinkpad, TRUE)) {
       
  1123     GST_DEBUG_OBJECT (demux, "No pull mode. Changing to push, but won't be "
       
  1124         "able to read end tags");
       
  1125     demux->priv->state = GST_TAG_DEMUX_READ_START_TAG;
       
  1126     return gst_pad_activate_push (sinkpad, TRUE);
       
  1127   }
       
  1128 
       
  1129   /* Look for tags at start and end of file */
       
  1130   GST_DEBUG_OBJECT (demux, "Activated pull mode. Looking for tags");
       
  1131   if (!gst_tag_demux_get_upstream_size (demux))
       
  1132     return FALSE;
       
  1133 
       
  1134   demux->priv->strip_start = 0;
       
  1135   demux->priv->strip_end = 0;
       
  1136 
       
  1137   s_tag_ok = gst_tag_demux_pull_start_tag (demux, &start_tags);
       
  1138   e_tag_ok = gst_tag_demux_pull_end_tag (demux, &end_tags);
       
  1139 
       
  1140   if (klass->merge_tags != NULL) {
       
  1141     demux->priv->parsed_tags = klass->merge_tags (demux, start_tags, end_tags);
       
  1142   } else {
       
  1143     /* we merge in REPLACE mode, so put the less important tags first, which
       
  1144      * we'll just assume is the end tag (subclasses may change this behaviour
       
  1145      * or make it configurable by overriding the merge_tags vfunc) */
       
  1146     demux->priv->parsed_tags =
       
  1147         gst_tag_list_merge (end_tags, start_tags, GST_TAG_MERGE_REPLACE);
       
  1148   }
       
  1149 
       
  1150   if (start_tags)
       
  1151     gst_tag_list_free (start_tags);
       
  1152   if (end_tags)
       
  1153     gst_tag_list_free (end_tags);
       
  1154 
       
  1155   if (!e_tag_ok && !s_tag_ok)
       
  1156     return FALSE;
       
  1157 
       
  1158   if (demux->priv->parsed_tags != NULL) {
       
  1159     demux->priv->send_tag_event = TRUE;
       
  1160   }
       
  1161 
       
  1162   /* 3 - Do typefinding on data */
       
  1163   caps = gst_type_find_helper_get_range (GST_OBJECT (demux),
       
  1164       (GstTypeFindHelperGetRangeFunction) gst_tag_demux_read_range,
       
  1165       demux->priv->upstream_size
       
  1166       - (demux->priv->strip_start + demux->priv->strip_end), &probability);
       
  1167 
       
  1168   GST_DEBUG_OBJECT (demux, "Found type %" GST_PTR_FORMAT " with a "
       
  1169       "probability of %u", caps, probability);
       
  1170 
       
  1171   /* 4 - Deactivate pull mode */
       
  1172   if (!gst_pad_activate_pull (sinkpad, FALSE)) {
       
  1173     if (caps)
       
  1174       gst_caps_unref (caps);
       
  1175     GST_DEBUG_OBJECT (demux, "Could not deactivate sinkpad after reading tags");
       
  1176     return FALSE;
       
  1177   }
       
  1178 
       
  1179   /* 5 - If we didn't find the caps, fail */
       
  1180   if (caps == NULL) {
       
  1181     GST_DEBUG_OBJECT (demux, "Could not detect type of contents");
       
  1182     GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
       
  1183     goto done_activate;
       
  1184   }
       
  1185 
       
  1186   /* tag reading and typefinding were already done, don't do them again in
       
  1187    * the chain function if we end up in push mode */
       
  1188   demux->priv->state = GST_TAG_DEMUX_STREAMING;
       
  1189 
       
  1190   /* 6 Add the srcpad for output now we know caps. */
       
  1191   if (!gst_tag_demux_add_srcpad (demux, caps)) {
       
  1192     GST_DEBUG_OBJECT (demux, "Could not add source pad");
       
  1193     goto done_activate;
       
  1194   }
       
  1195 
       
  1196   /* 7 - if the sinkpad is active, it was done by downstream so we're 
       
  1197    * done, otherwise switch to push */
       
  1198   ret = TRUE;
       
  1199   if (!gst_pad_is_active (sinkpad)) {
       
  1200     ret = gst_pad_activate_push (demux->priv->srcpad, TRUE);
       
  1201     ret &= gst_pad_activate_push (sinkpad, TRUE);
       
  1202   }
       
  1203 
       
  1204 done_activate:
       
  1205 
       
  1206   if (caps)
       
  1207     gst_caps_unref (caps);
       
  1208 
       
  1209   return ret;
       
  1210 }
       
  1211 
       
  1212 static gboolean
       
  1213 gst_tag_demux_src_activate_pull (GstPad * pad, gboolean active)
       
  1214 {
       
  1215   GstTagDemux *demux = GST_TAG_DEMUX (GST_PAD_PARENT (pad));
       
  1216 
       
  1217   return gst_pad_activate_pull (demux->priv->sinkpad, active);
       
  1218 }
       
  1219 
       
  1220 static gboolean
       
  1221 gst_tag_demux_src_checkgetrange (GstPad * srcpad)
       
  1222 {
       
  1223   GstTagDemux *demux = GST_TAG_DEMUX (GST_PAD_PARENT (srcpad));
       
  1224 
       
  1225   return gst_pad_check_pull_range (demux->priv->sinkpad);
       
  1226 }
       
  1227 
       
  1228 static GstFlowReturn
       
  1229 gst_tag_demux_read_range (GstTagDemux * demux,
       
  1230     guint64 offset, guint length, GstBuffer ** buffer)
       
  1231 {
       
  1232   GstFlowReturn ret;
       
  1233   guint64 in_offset;
       
  1234   guint in_length;
       
  1235 
       
  1236   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
       
  1237 
       
  1238   /* Adjust offset and length of the request to trim off tag information. 
       
  1239    * For the returned buffer, adjust the output offset to match what downstream
       
  1240    * should see */
       
  1241   in_offset = offset + demux->priv->strip_start;
       
  1242 
       
  1243   if (!gst_tag_demux_get_upstream_size (demux))
       
  1244     return GST_FLOW_ERROR;
       
  1245 
       
  1246   if (in_offset + length >= demux->priv->upstream_size - demux->priv->strip_end) {
       
  1247     if (in_offset + demux->priv->strip_end >= demux->priv->upstream_size)
       
  1248       return GST_FLOW_UNEXPECTED;
       
  1249     in_length = demux->priv->upstream_size - demux->priv->strip_end - in_offset;
       
  1250   } else {
       
  1251     in_length = length;
       
  1252   }
       
  1253 
       
  1254   ret = gst_pad_pull_range (demux->priv->sinkpad, in_offset, in_length, buffer);
       
  1255 
       
  1256   if (ret == GST_FLOW_OK && *buffer) {
       
  1257     if (!gst_tag_demux_trim_buffer (demux, buffer))
       
  1258       goto read_beyond_end;
       
  1259 
       
  1260     /* this should only happen in streaming mode */
       
  1261     g_assert (*buffer != NULL);
       
  1262 
       
  1263     gst_buffer_set_caps (*buffer, demux->priv->src_caps);
       
  1264   }
       
  1265 
       
  1266   return ret;
       
  1267 
       
  1268 read_beyond_end:
       
  1269   {
       
  1270     GST_DEBUG_OBJECT (demux, "attempted read beyond end of file");
       
  1271     if (*buffer != NULL) {
       
  1272       gst_buffer_unref (buffer);
       
  1273       *buffer = NULL;
       
  1274     }
       
  1275     return GST_FLOW_UNEXPECTED;
       
  1276   }
       
  1277 }
       
  1278 
       
  1279 static GstFlowReturn
       
  1280 gst_tag_demux_src_getrange (GstPad * srcpad,
       
  1281     guint64 offset, guint length, GstBuffer ** buffer)
       
  1282 {
       
  1283   GstTagDemux *demux = GST_TAG_DEMUX (GST_PAD_PARENT (srcpad));
       
  1284 
       
  1285   if (demux->priv->send_tag_event) {
       
  1286     gst_tag_demux_send_tag_event (demux);
       
  1287     demux->priv->send_tag_event = FALSE;
       
  1288   }
       
  1289 
       
  1290   return gst_tag_demux_read_range (demux, offset, length, buffer);
       
  1291 }
       
  1292 
       
  1293 static GstStateChangeReturn
       
  1294 gst_tag_demux_change_state (GstElement * element, GstStateChange transition)
       
  1295 {
       
  1296   GstStateChangeReturn ret;
       
  1297   GstTagDemux *demux = GST_TAG_DEMUX (element);
       
  1298 
       
  1299   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
  1300 
       
  1301   switch (transition) {
       
  1302     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
  1303       gst_tag_demux_reset (demux);
       
  1304       break;
       
  1305     default:
       
  1306       break;
       
  1307   }
       
  1308   return ret;
       
  1309 }
       
  1310 
       
  1311 static gboolean
       
  1312 gst_tag_demux_pad_query (GstPad * pad, GstQuery * query)
       
  1313 {
       
  1314   /* For a position or duration query, adjust the returned
       
  1315    * bytes to strip off the end and start areas */
       
  1316 
       
  1317   GstTagDemux *demux = GST_TAG_DEMUX (GST_PAD_PARENT (pad));
       
  1318   GstPad *peer = NULL;
       
  1319   GstFormat format;
       
  1320   gint64 result;
       
  1321 
       
  1322   if ((peer = gst_pad_get_peer (demux->priv->sinkpad)) == NULL)
       
  1323     return FALSE;
       
  1324 
       
  1325   if (!gst_pad_query (peer, query)) {
       
  1326     gst_object_unref (peer);
       
  1327     return FALSE;
       
  1328   }
       
  1329 
       
  1330   gst_object_unref (peer);
       
  1331 
       
  1332   switch (GST_QUERY_TYPE (query)) {
       
  1333     case GST_QUERY_POSITION:
       
  1334     {
       
  1335       gst_query_parse_position (query, &format, &result);
       
  1336       if (format == GST_FORMAT_BYTES) {
       
  1337         result -= demux->priv->strip_start;
       
  1338         gst_query_set_position (query, format, result);
       
  1339       }
       
  1340       break;
       
  1341     }
       
  1342     case GST_QUERY_DURATION:
       
  1343     {
       
  1344       gst_query_parse_duration (query, &format, &result);
       
  1345       if (format == GST_FORMAT_BYTES) {
       
  1346         result -= demux->priv->strip_start + demux->priv->strip_end;
       
  1347         gst_query_set_duration (query, format, result);
       
  1348       }
       
  1349       break;
       
  1350     }
       
  1351     default:
       
  1352       break;
       
  1353   }
       
  1354 
       
  1355   return TRUE;
       
  1356 }
       
  1357 
       
  1358 static const GstQueryType *
       
  1359 gst_tag_demux_get_query_types (GstPad * pad)
       
  1360 {
       
  1361   static const GstQueryType types[] = {
       
  1362     GST_QUERY_POSITION,
       
  1363     GST_QUERY_DURATION,
       
  1364     0
       
  1365   };
       
  1366 
       
  1367   return types;
       
  1368 }
       
  1369 
       
  1370 static void
       
  1371 gst_tag_demux_send_tag_event (GstTagDemux * demux)
       
  1372 {
       
  1373   /* FIXME: what's the correct merge mode? Docs need to tell... */
       
  1374   GstTagList *merged = gst_tag_list_merge (demux->priv->event_tags,
       
  1375       demux->priv->parsed_tags, GST_TAG_MERGE_KEEP);
       
  1376 
       
  1377   if (demux->priv->parsed_tags)
       
  1378     gst_element_post_message (GST_ELEMENT (demux),
       
  1379         gst_message_new_tag (GST_OBJECT (demux),
       
  1380             gst_tag_list_copy (demux->priv->parsed_tags)));
       
  1381 
       
  1382   if (merged) {
       
  1383     GstEvent *event = gst_event_new_tag (merged);
       
  1384 
       
  1385     GST_EVENT_TIMESTAMP (event) = 0;
       
  1386     GST_DEBUG_OBJECT (demux, "Sending tag event on src pad");
       
  1387     gst_pad_push_event (demux->priv->srcpad, event);
       
  1388   }
       
  1389 }
       
  1390 
       
  1391 static gboolean
       
  1392 gst_tag_demux_send_new_segment (GstTagDemux * tagdemux)
       
  1393 {
       
  1394   GstEvent *event;
       
  1395   gint64 start, stop, position;
       
  1396   GstSegment *seg = &tagdemux->priv->segment;
       
  1397 
       
  1398   if (seg->format == GST_FORMAT_UNDEFINED) {
       
  1399     GST_LOG_OBJECT (tagdemux,
       
  1400         "No new segment received before first buffer. Using default");
       
  1401     gst_segment_set_newsegment (seg, FALSE, 1.0,
       
  1402         GST_FORMAT_BYTES, tagdemux->priv->strip_start, -1,
       
  1403         tagdemux->priv->strip_start);
       
  1404   }
       
  1405 
       
  1406   /* Can't adjust segments in non-BYTES formats */
       
  1407   if (tagdemux->priv->segment.format != GST_FORMAT_BYTES) {
       
  1408     event = gst_event_new_new_segment_full (tagdemux->priv->newseg_update,
       
  1409         seg->rate, seg->applied_rate, seg->format, seg->start,
       
  1410         seg->stop, seg->time);
       
  1411     return gst_pad_push_event (tagdemux->priv->srcpad, event);
       
  1412   }
       
  1413 
       
  1414   start = seg->start;
       
  1415   stop = seg->stop;
       
  1416   position = seg->time;
       
  1417 
       
  1418   g_return_val_if_fail (start != -1, FALSE);
       
  1419   g_return_val_if_fail (position != -1, FALSE);
       
  1420 
       
  1421   if (tagdemux->priv->strip_end > 0) {
       
  1422     if (gst_tag_demux_get_upstream_size (tagdemux)) {
       
  1423       guint64 v1tag_offset =
       
  1424           tagdemux->priv->upstream_size - tagdemux->priv->strip_end;
       
  1425 
       
  1426       if (start >= v1tag_offset) {
       
  1427         /* Segment is completely within the end tag, output an open-ended
       
  1428          * segment, even though all the buffers will get trimmed away */
       
  1429         start = v1tag_offset;
       
  1430         stop = -1;
       
  1431       }
       
  1432 
       
  1433       if (stop != -1 && stop >= v1tag_offset) {
       
  1434         GST_DEBUG_OBJECT (tagdemux,
       
  1435             "Segment crosses the end tag. Trimming end");
       
  1436         stop = v1tag_offset;
       
  1437       }
       
  1438     }
       
  1439   }
       
  1440 
       
  1441   if (tagdemux->priv->strip_start > 0) {
       
  1442     if (start > tagdemux->priv->strip_start)
       
  1443       start -= tagdemux->priv->strip_start;
       
  1444     else
       
  1445       start = 0;
       
  1446 
       
  1447     if (position > tagdemux->priv->strip_start)
       
  1448       position -= tagdemux->priv->strip_start;
       
  1449     else
       
  1450       position = 0;
       
  1451 
       
  1452     if (stop != -1) {
       
  1453       if (stop > tagdemux->priv->strip_start)
       
  1454         stop -= tagdemux->priv->strip_start;
       
  1455       else
       
  1456         stop = 0;
       
  1457     }
       
  1458   }
       
  1459 
       
  1460   GST_DEBUG_OBJECT (tagdemux,
       
  1461       "Sending new segment update %d, rate %g, format %d, "
       
  1462       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
       
  1463       G_GINT64_FORMAT, tagdemux->priv->newseg_update, seg->rate, seg->format,
       
  1464       start, stop, position);
       
  1465 
       
  1466   event = gst_event_new_new_segment_full (tagdemux->priv->newseg_update,
       
  1467       seg->rate, seg->applied_rate, seg->format, start, stop, position);
       
  1468   return gst_pad_push_event (tagdemux->priv->srcpad, event);
       
  1469 }