gst_plugins_good/gst/wavparse/gstwavparse.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    20  */
    20  */
    21 
    21 
    22 /**
    22 /**
    23  * SECTION:element-wavparse
    23  * SECTION:element-wavparse
    24  *
    24  *
       
    25  * <refsect2>
       
    26  * <para>
    25  * Parse a .wav file into raw or compressed audio.
    27  * Parse a .wav file into raw or compressed audio.
    26  *
    28  * </para>
    27  * Wavparse supports both push and pull mode operations, making it possible to
    29  * <para>
    28  * stream from a network source.
    30  * This element currently only supports pull based scheduling.
    29  *
    31  * </para>
    30  * <refsect2>
       
    31  * <title>Example launch line</title>
    32  * <title>Example launch line</title>
    32  * |[
    33  * <para>
       
    34  * <programlisting>
    33  * gst-launch filesrc location=sine.wav ! wavparse ! audioconvert ! alsasink
    35  * gst-launch filesrc location=sine.wav ! wavparse ! audioconvert ! alsasink
    34  * ]| Read a wav file and output to the soundcard using the ALSA element. The
    36  * </programlisting>
       
    37  * Read a wav file and output to the soundcard using the ALSA element. The
    35  * wav file is assumed to contain raw uncompressed samples.
    38  * wav file is assumed to contain raw uncompressed samples.
    36  * |[
    39  * </para>
       
    40  * <para>
       
    41  * <programlisting>
    37  * gst-launch gnomevfssrc location=http://www.example.org/sine.wav ! queue ! wavparse ! audioconvert ! alsasink
    42  * gst-launch gnomevfssrc location=http://www.example.org/sine.wav ! queue ! wavparse ! audioconvert ! alsasink
    38  * ]| Stream data from a network url.
    43  * </programlisting>
       
    44  * Stream data from
       
    45  * </para>
    39  * </refsect2>
    46  * </refsect2>
    40  *
    47  *
    41  * Last reviewed on 2007-02-14 (0.10.6)
    48  * Last reviewed on 2006-03-03 (0.10.3)
    42  */
       
    43 
       
    44 /*
       
    45  * TODO:
       
    46  * http://replaygain.hydrogenaudio.org/file_format_wav.html
       
    47  */
    49  */
    48 
    50 
    49 #ifdef HAVE_CONFIG_H
    51 #ifdef HAVE_CONFIG_H
    50 #include "config.h"
    52 #include "config.h"
    51 #endif
    53 #endif
    52 #include <string.h>
    54 
    53 #include <math.h>
    55 #include "string.h"
    54 
       
    55 #include "gstwavparse.h"
    56 #include "gstwavparse.h"
    56 #include "gst/riff/riff-ids.h"
    57 #include <gst/riff/riff-ids.h>
    57 #include "gst/riff/riff-media.h"
    58 #include <gst/riff/riff-media.h>
       
    59 #include <gst/riff/riff-read.h>
       
    60 
       
    61 #ifndef __SYMBIAN32__
    58 #include <gst/gst-i18n-plugin.h>
    62 #include <gst/gst-i18n-plugin.h>
       
    63 #else
       
    64 #include "gst/gst-i18n-plugin.h"
       
    65 #endif
       
    66 
       
    67 #ifdef __SYMBIAN32__
       
    68 #include <gst/gstinfo.h>
       
    69 #endif
       
    70 
       
    71 #ifndef G_MAXUINT32
       
    72 #define G_MAXUINT32 0xffffffff
       
    73 #endif
    59 
    74 
    60 GST_DEBUG_CATEGORY_STATIC (wavparse_debug);
    75 GST_DEBUG_CATEGORY_STATIC (wavparse_debug);
    61 #define GST_CAT_DEFAULT (wavparse_debug)
    76 #define GST_CAT_DEFAULT (wavparse_debug)
    62 
    77 
       
    78 static void gst_wavparse_base_init (gpointer g_class);
       
    79 static void gst_wavparse_class_init (GstWavParseClass * klass);
       
    80 static void gst_wavparse_init (GstWavParse * wavparse);
    63 static void gst_wavparse_dispose (GObject * object);
    81 static void gst_wavparse_dispose (GObject * object);
    64 
    82 
    65 static gboolean gst_wavparse_sink_activate (GstPad * sinkpad);
    83 static gboolean gst_wavparse_sink_activate (GstPad * sinkpad);
    66 static gboolean gst_wavparse_sink_activate_pull (GstPad * sinkpad,
    84 static gboolean gst_wavparse_sink_activate_pull (GstPad * sinkpad,
    67     gboolean active);
    85     gboolean active);
    68 static gboolean gst_wavparse_send_event (GstElement * element,
    86 static gboolean gst_wavparse_send_event (GstElement * element,
    69     GstEvent * event);
    87     GstEvent * event);
       
    88 static GstFlowReturn gst_wavparse_chain (GstPad * pad, GstBuffer * buf);
    70 static GstStateChangeReturn gst_wavparse_change_state (GstElement * element,
    89 static GstStateChangeReturn gst_wavparse_change_state (GstElement * element,
    71     GstStateChange transition);
    90     GstStateChange transition);
    72 
    91 
       
    92 static gboolean gst_wavparse_pad_query (GstPad * pad, GstQuery * query);
    73 static const GstQueryType *gst_wavparse_get_query_types (GstPad * pad);
    93 static const GstQueryType *gst_wavparse_get_query_types (GstPad * pad);
    74 static gboolean gst_wavparse_pad_query (GstPad * pad, GstQuery * query);
       
    75 static gboolean gst_wavparse_pad_convert (GstPad * pad,
    94 static gboolean gst_wavparse_pad_convert (GstPad * pad,
    76     GstFormat src_format,
    95     GstFormat src_format,
    77     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
    96     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
    78 
    97 
    79 static GstFlowReturn gst_wavparse_chain (GstPad * pad, GstBuffer * buf);
       
    80 static gboolean gst_wavparse_sink_event (GstPad * pad, GstEvent * event);
       
    81 static void gst_wavparse_loop (GstPad * pad);
    98 static void gst_wavparse_loop (GstPad * pad);
    82 static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstEvent * event);
    99 static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstEvent * event);
       
   100 static void gst_wavparse_get_property (GObject * object, guint prop_id,
       
   101     GValue * value, GParamSpec * pspec);
    83 
   102 
    84 static const GstElementDetails gst_wavparse_details =
   103 static const GstElementDetails gst_wavparse_details =
    85 GST_ELEMENT_DETAILS ("WAV audio demuxer",
   104 GST_ELEMENT_DETAILS ("WAV audio demuxer",
    86     "Codec/Demuxer/Audio",
   105     "Codec/Demuxer/Audio",
    87     "Parse a .wav file into raw audio",
   106     "Parse a .wav file into raw audio",
    88     "Erik Walthinsen <omega@cse.ogi.edu>");
   107     "Erik Walthinsen <omega@cse.ogi.edu>");
    89 
   108 
    90 static GstStaticPadTemplate sink_template_factory =
   109 static GstStaticPadTemplate sink_template_factory =
    91 GST_STATIC_PAD_TEMPLATE ("wavparse_sink",
   110 //GST_STATIC_PAD_TEMPLATE ("wavparse_sink",
       
   111 GST_STATIC_PAD_TEMPLATE ("sink", 
    92     GST_PAD_SINK,
   112     GST_PAD_SINK,
    93     GST_PAD_ALWAYS,
   113     GST_PAD_ALWAYS,
    94     GST_STATIC_CAPS ("audio/x-wav")
   114     GST_STATIC_CAPS ("audio/x-wav")
    95     );
   115     );
    96 
   116 
    97 #define DEBUG_INIT(bla) \
   117 /* the pad is marked a sometimes and is added to the element when the
    98   GST_DEBUG_CATEGORY_INIT (wavparse_debug, "wavparse", 0, "WAV parser");
   118  * exact type is known. This makes it much easier for a static autoplugger
    99 
   119  * to connect the right decoder when needed.
   100 GST_BOILERPLATE_FULL (GstWavParse, gst_wavparse, GstElement,
   120  */
   101     GST_TYPE_ELEMENT, DEBUG_INIT);
   121 static GstStaticPadTemplate src_template_factory =
       
   122  //   GST_STATIC_PAD_TEMPLATE ("wavparse_src",
       
   123     GST_STATIC_PAD_TEMPLATE ("src",
       
   124     GST_PAD_SRC,
       
   125     GST_PAD_SOMETIMES,
       
   126     GST_STATIC_CAPS ("audio/x-raw-int, "
       
   127         "endianness = (int) little_endian, "
       
   128         "signed = (boolean) { true, false }, "
       
   129         "width = (int) { 8, 16, 24, 32 }, "
       
   130         "depth = (int) { 8, 16, 24, 32 }, "
       
   131         "rate = (int) [ 8000, 96000 ], "
       
   132         "channels = (int) [ 1, 8 ]; "
       
   133         "audio/mpeg, "
       
   134         "mpegversion = (int) 1, "
       
   135         "layer = (int) [ 1, 3 ], "
       
   136         "rate = (int) [ 8000, 48000 ], "
       
   137         "channels = (int) [ 1, 2 ]; "
       
   138         "audio/x-alaw, "
       
   139         "rate = (int) [ 8000, 48000 ], "
       
   140         "channels = (int) [ 1, 2 ]; "
       
   141         "audio/x-mulaw, "
       
   142         "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ];"
       
   143         "audio/x-adpcm, "
       
   144         "layout = (string) microsoft, "
       
   145         "block_align = (int) [ 1, 8192 ], "
       
   146         "rate = (int) [ 8000, 48000 ], "
       
   147         "channels = (int) [ 1, 2 ]; "
       
   148         "audio/x-adpcm, "
       
   149         "layout = (string) dvi, "
       
   150         "block_align = (int) [ 1, 8192 ], "
       
   151         "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ];"
       
   152         "audio/x-vnd.sony.atrac3;"
       
   153         "audio/x-dts;" "audio/x-wma, " "wmaversion = (int) [ 1, 2 ]")
       
   154     );
       
   155 
       
   156 
       
   157 static GstElementClass *parent_class = NULL;
       
   158 
       
   159 GType
       
   160 gst_wavparse_get_type (void)
       
   161 {
       
   162   static GType wavparse_type = 0;
       
   163 
       
   164   if (!wavparse_type) {
       
   165     static const GTypeInfo wavparse_info = {
       
   166       sizeof (GstWavParseClass),
       
   167       gst_wavparse_base_init,
       
   168       NULL,
       
   169       (GClassInitFunc) gst_wavparse_class_init,
       
   170       NULL,
       
   171       NULL,
       
   172       sizeof (GstWavParse),
       
   173       0,
       
   174       (GInstanceInitFunc) gst_wavparse_init,
       
   175     };
       
   176 
       
   177     wavparse_type =
       
   178         g_type_register_static (GST_TYPE_ELEMENT, "GstWavParse",
       
   179         &wavparse_info, 0);
       
   180   }
       
   181   return wavparse_type;
       
   182 }
       
   183 
   102 
   184 
   103 static void
   185 static void
   104 gst_wavparse_base_init (gpointer g_class)
   186 gst_wavparse_base_init (gpointer g_class)
   105 {
   187 {
   106   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
   188   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
   107   GstPadTemplate *src_template;
   189 
   108 
   190   /* register src pads */
   109   /* register pads */
       
   110   gst_element_class_add_pad_template (element_class,
   191   gst_element_class_add_pad_template (element_class,
   111       gst_static_pad_template_get (&sink_template_factory));
   192       gst_static_pad_template_get (&sink_template_factory));
   112 
   193   gst_element_class_add_pad_template (element_class,
   113   src_template = gst_pad_template_new ("wavparse_src", GST_PAD_SRC,
   194       gst_static_pad_template_get (&src_template_factory));
   114       GST_PAD_SOMETIMES, gst_riff_create_audio_template_caps ());
       
   115   gst_element_class_add_pad_template (element_class, src_template);
       
   116   gst_object_unref (src_template);
       
   117 
       
   118   gst_element_class_set_details (element_class, &gst_wavparse_details);
   195   gst_element_class_set_details (element_class, &gst_wavparse_details);
   119 }
   196 }
   120 
   197 
   121 static void
   198 static void
   122 gst_wavparse_class_init (GstWavParseClass * klass)
   199 gst_wavparse_class_init (GstWavParseClass * klass)
   127   gstelement_class = (GstElementClass *) klass;
   204   gstelement_class = (GstElementClass *) klass;
   128   object_class = (GObjectClass *) klass;
   205   object_class = (GObjectClass *) klass;
   129 
   206 
   130   parent_class = g_type_class_peek_parent (klass);
   207   parent_class = g_type_class_peek_parent (klass);
   131 
   208 
       
   209   object_class->get_property = gst_wavparse_get_property;
   132   object_class->dispose = gst_wavparse_dispose;
   210   object_class->dispose = gst_wavparse_dispose;
   133 
   211 
   134   gstelement_class->change_state = gst_wavparse_change_state;
   212   gstelement_class->change_state = gst_wavparse_change_state;
   135   gstelement_class->send_event = gst_wavparse_send_event;
   213   gstelement_class->send_event = gst_wavparse_send_event;
   136 }
   214 }
   137 
   215 
       
   216 
   138 static void
   217 static void
   139 gst_wavparse_reset (GstWavParse * wav)
   218 gst_wavparse_dispose (GObject * object)
   140 {
   219 {
   141   wav->state = GST_WAVPARSE_START;
   220 	#ifndef __SYMBIAN32__
   142 
   221   GST_DEBUG("WAV: Dispose\n");
   143   /* These will all be set correctly in the fmt chunk */
   222   #endif
   144   wav->depth = 0;
   223   GstWavParse *wav = GST_WAVPARSE (object);
   145   wav->rate = 0;
   224   #ifdef __SYMBIAN32__
   146   wav->width = 0;
   225   GST_DEBUG("WAV: Dispose\n");
   147   wav->channels = 0;
   226 	#endif
   148   wav->blockalign = 0;
   227 
   149   wav->bps = 0;
       
   150   wav->fact = 0;
       
   151   wav->offset = 0;
       
   152   wav->end_offset = 0;
       
   153   wav->dataleft = 0;
       
   154   wav->datasize = 0;
       
   155   wav->datastart = 0;
       
   156   wav->duration = 0;
       
   157   wav->got_fmt = FALSE;
       
   158   wav->first = TRUE;
       
   159 
       
   160   if (wav->seek_event)
       
   161     gst_event_unref (wav->seek_event);
       
   162   wav->seek_event = NULL;
       
   163   if (wav->adapter) {
   228   if (wav->adapter) {
   164     gst_adapter_clear (wav->adapter);
       
   165     g_object_unref (wav->adapter);
   229     g_object_unref (wav->adapter);
   166     wav->adapter = NULL;
   230     wav->adapter = NULL;
   167   }
   231   }
   168   if (wav->tags)
   232 
   169     gst_tag_list_free (wav->tags);
   233   G_OBJECT_CLASS (parent_class)->dispose (object);
   170   wav->tags = NULL;
   234 }
   171 }
   235 
   172 
   236 
   173 static void
   237 static void
   174 gst_wavparse_dispose (GObject * object)
   238 gst_wavparse_reset (GstWavParse * wavparse)
   175 {
   239 {
   176   GstWavParse *wav = GST_WAVPARSE (object);
   240   wavparse->state = GST_WAVPARSE_START;
   177 
   241 
   178   GST_DEBUG_OBJECT (wav, "WAV: Dispose");
   242   /* These will all be set correctly in the fmt chunk */
   179   gst_wavparse_reset (wav);
   243   wavparse->depth = 0;
   180 
   244   wavparse->rate = 0;
   181   G_OBJECT_CLASS (parent_class)->dispose (object);
   245   wavparse->width = 0;
       
   246   wavparse->channels = 0;
       
   247   wavparse->blockalign = 0;
       
   248   wavparse->bps = 0;
       
   249   wavparse->offset = 0;
       
   250   wavparse->end_offset = 0;
       
   251   wavparse->dataleft = 0;
       
   252   wavparse->datasize = 0;
       
   253   wavparse->datastart = 0;
       
   254   wavparse->got_fmt = FALSE;
       
   255   wavparse->first = TRUE;
       
   256 
       
   257   if (wavparse->seek_event)
       
   258     gst_event_unref (wavparse->seek_event);
       
   259   wavparse->seek_event = NULL;
       
   260 
       
   261   /* we keep the segment info in time */
       
   262   gst_segment_init (&wavparse->segment, GST_FORMAT_TIME);
   182 }
   263 }
   183 
   264 
   184 static void
   265 static void
   185 gst_wavparse_init (GstWavParse * wavparse, GstWavParseClass * g_class)
   266 gst_wavparse_init (GstWavParse * wavparse)
   186 {
   267 {
   187   gst_wavparse_reset (wavparse);
   268   gst_wavparse_reset (wavparse);
   188 
   269 
   189   /* sink */
   270   /* sink */
   190   wavparse->sinkpad =
   271   wavparse->sinkpad =
   193       GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate));
   274       GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate));
   194   gst_pad_set_activatepull_function (wavparse->sinkpad,
   275   gst_pad_set_activatepull_function (wavparse->sinkpad,
   195       GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate_pull));
   276       GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate_pull));
   196   gst_pad_set_chain_function (wavparse->sinkpad,
   277   gst_pad_set_chain_function (wavparse->sinkpad,
   197       GST_DEBUG_FUNCPTR (gst_wavparse_chain));
   278       GST_DEBUG_FUNCPTR (gst_wavparse_chain));
   198   gst_pad_set_event_function (wavparse->sinkpad,
   279   gst_element_add_pad (GST_ELEMENT (wavparse), wavparse->sinkpad);
   199       GST_DEBUG_FUNCPTR (gst_wavparse_sink_event));
       
   200   gst_element_add_pad (GST_ELEMENT_CAST (wavparse), wavparse->sinkpad);
       
   201 
   280 
   202   /* src, will be created later */
   281   /* src, will be created later */
   203   wavparse->srcpad = NULL;
   282   wavparse->srcpad = NULL;
   204 }
   283 }
   205 
   284 
   206 static void
   285 static void
   207 gst_wavparse_destroy_sourcepad (GstWavParse * wavparse)
   286 gst_wavparse_destroy_sourcepad (GstWavParse * wavparse)
   208 {
   287 {
   209   if (wavparse->srcpad) {
   288   if (wavparse->srcpad) {
   210     gst_element_remove_pad (GST_ELEMENT_CAST (wavparse), wavparse->srcpad);
   289     gst_element_remove_pad (GST_ELEMENT (wavparse), wavparse->srcpad);
   211     wavparse->srcpad = NULL;
   290     wavparse->srcpad = NULL;
   212   }
   291   }
   213 }
   292 }
   214 
   293 
   215 static void
   294 static void
   216 gst_wavparse_create_sourcepad (GstWavParse * wavparse)
   295 gst_wavparse_create_sourcepad (GstWavParse * wavparse)
   217 {
   296 {
   218   GstElementClass *klass = GST_ELEMENT_GET_CLASS (wavparse);
       
   219   GstPadTemplate *src_template;
       
   220 
       
   221   /* destroy previous one */
   297   /* destroy previous one */
   222   gst_wavparse_destroy_sourcepad (wavparse);
   298   gst_wavparse_destroy_sourcepad (wavparse);
   223 
   299 
   224   /* source */
   300   /* source */
   225   src_template = gst_element_class_get_pad_template (klass, "wavparse_src");
   301   wavparse->srcpad =
   226   wavparse->srcpad = gst_pad_new_from_template (src_template, "src");
   302       gst_pad_new_from_static_template (&src_template_factory, "src");
   227   gst_pad_use_fixed_caps (wavparse->srcpad);
   303   gst_pad_use_fixed_caps (wavparse->srcpad);
   228   gst_pad_set_query_type_function (wavparse->srcpad,
   304   gst_pad_set_query_type_function (wavparse->srcpad,
   229       GST_DEBUG_FUNCPTR (gst_wavparse_get_query_types));
   305       GST_DEBUG_FUNCPTR (gst_wavparse_get_query_types));
   230   gst_pad_set_query_function (wavparse->srcpad,
   306   gst_pad_set_query_function (wavparse->srcpad,
   231       GST_DEBUG_FUNCPTR (gst_wavparse_pad_query));
   307       GST_DEBUG_FUNCPTR (gst_wavparse_pad_query));
   233       GST_DEBUG_FUNCPTR (gst_wavparse_srcpad_event));
   309       GST_DEBUG_FUNCPTR (gst_wavparse_srcpad_event));
   234 
   310 
   235   GST_DEBUG_OBJECT (wavparse, "srcpad created");
   311   GST_DEBUG_OBJECT (wavparse, "srcpad created");
   236 }
   312 }
   237 
   313 
   238 /* Compute (value * nom) % denom, avoiding overflow.  This can be used
   314 static void
   239  * to perform ceiling or rounding division together with
   315 gst_wavparse_get_property (GObject * object,
   240  * gst_util_uint64_scale[_int]. */
   316     guint prop_id, GValue * value, GParamSpec * pspec)
   241 #define uint64_scale_modulo(val, nom, denom) \
   317 {
   242   ((val % denom) * (nom % denom) % denom)
   318   GstWavParse *wavparse;
   243 
   319 
   244 /* Like gst_util_uint64_scale, but performs ceiling division. */
   320   wavparse = GST_WAVPARSE (object);
   245 static guint64
   321 
   246 uint64_ceiling_scale_int (guint64 val, gint num, gint denom)
   322   switch (prop_id) {
   247 {
   323     default:
   248   guint64 result = gst_util_uint64_scale_int (val, num, denom);
   324       break;
   249 
   325   }
   250   if (uint64_scale_modulo (val, num, denom) == 0)
   326 }
   251     return result;
   327 
   252   else
   328 
   253     return result + 1;
   329 
   254 }
       
   255 
       
   256 /* Like gst_util_uint64_scale, but performs ceiling division. */
       
   257 static guint64
       
   258 uint64_ceiling_scale (guint64 val, guint64 num, guint64 denom)
       
   259 {
       
   260   guint64 result = gst_util_uint64_scale (val, num, denom);
       
   261 
       
   262   if (uint64_scale_modulo (val, num, denom) == 0)
       
   263     return result;
       
   264   else
       
   265     return result + 1;
       
   266 }
       
   267 
       
   268 
       
   269 /* FIXME: why is that not in use? */
       
   270 #if 0
   330 #if 0
   271 static void
   331 static void
   272 gst_wavparse_parse_adtl (GstWavParse * wavparse, int len)
   332 gst_wavparse_parse_adtl (GstWavParse * wavparse, int len)
   273 {
   333 {
   274   guint32 got_bytes;
   334   guint32 got_bytes;
   519 gst_wavparse_fmt (GstWavParse * wav)
   579 gst_wavparse_fmt (GstWavParse * wav)
   520 {
   580 {
   521   gst_riff_strf_auds *header = NULL;
   581   gst_riff_strf_auds *header = NULL;
   522   GstCaps *caps;
   582   GstCaps *caps;
   523 
   583 
   524   if (!gst_riff_read_strf_auds (wav, &header))
   584   if (!gst_riff_read_strf_auds (wav, &header)) {
   525     goto no_fmt;
   585     g_warning ("Not fmt");
       
   586     return FALSE;
       
   587   }
   526 
   588 
   527   wav->format = header->format;
   589   wav->format = header->format;
   528   wav->rate = header->rate;
   590   wav->rate = header->rate;
   529   wav->channels = header->channels;
   591   wav->channels = header->channels;
   530   if (wav->channels == 0)
   592   if (wav->channels == 0) {
   531     goto no_channels;
   593     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
   532 
   594         ("Stream claims to contain zero channels - invalid data"));
       
   595     g_free (header);
       
   596     return FALSE;
       
   597   }
   533   wav->blockalign = header->blockalign;
   598   wav->blockalign = header->blockalign;
   534   wav->width = (header->blockalign * 8) / header->channels;
   599   wav->width = (header->blockalign * 8) / header->channels;
   535   wav->depth = header->size;
   600   wav->depth = header->size;
   536   wav->bps = header->av_bps;
   601   wav->bps = header->av_bps;
   537   if (wav->bps <= 0)
   602   if (wav->bps <= 0) {
   538     goto no_bps;
       
   539 
       
   540   /* Note: gst_riff_create_audio_caps might need to fix values in
       
   541    * the header header depending on the format, so call it first */
       
   542   caps = gst_riff_create_audio_caps (header->format, NULL, header, NULL);
       
   543   g_free (header);
       
   544 
       
   545   if (caps == NULL)
       
   546     goto no_caps;
       
   547 
       
   548   gst_wavparse_create_sourcepad (wav);
       
   549   gst_pad_use_fixed_caps (wav->srcpad);
       
   550   gst_pad_set_active (wav->srcpad, TRUE);
       
   551   gst_pad_set_caps (wav->srcpad, caps);
       
   552   gst_caps_free (caps);
       
   553   gst_element_add_pad (GST_ELEMENT_CAST (wav), wav->srcpad);
       
   554   gst_element_no_more_pads (GST_ELEMENT_CAST (wav));
       
   555 
       
   556   GST_DEBUG ("frequency %d, channels %d", wav->rate, wav->channels);
       
   557 
       
   558   return TRUE;
       
   559 
       
   560   /* ERRORS */
       
   561 no_fmt:
       
   562   {
       
   563     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
       
   564         ("No FMT tag found"));
       
   565     return FALSE;
       
   566   }
       
   567 no_channels:
       
   568   {
       
   569     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
       
   570         ("Stream claims to contain zero channels - invalid data"));
       
   571     g_free (header);
       
   572     return FALSE;
       
   573   }
       
   574 no_bps:
       
   575   {
       
   576     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
   603     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
   577         ("Stream claims to bitrate of <= zero - invalid data"));
   604         ("Stream claims to bitrate of <= zero - invalid data"));
   578     g_free (header);
   605     g_free (header);
   579     return FALSE;
   606     return FALSE;
   580   }
   607   }
   581 no_caps:
   608 
   582   {
   609   /* Note: gst_riff_create_audio_caps might nedd to fix values in
       
   610    * the header header depending on the format, so call it first */
       
   611   caps = gst_riff_create_audio_caps (header->format, NULL, header, NULL);
       
   612 
       
   613   g_free (header);
       
   614 
       
   615   if (caps) {
       
   616     gst_wavparse_create_sourcepad (wav);
       
   617     gst_pad_use_fixed_caps (wav->srcpad);
       
   618     gst_pad_set_active (wav->srcpad, TRUE);
       
   619     gst_pad_set_caps (wav->srcpad, caps);
       
   620     gst_caps_free (caps);
       
   621     gst_element_add_pad (GST_ELEMENT (wav), wav->srcpad);
       
   622     gst_element_no_more_pads (GST_ELEMENT (wav));
       
   623     GST_DEBUG ("frequency %d, channels %d", wav->rate, wav->channels);
       
   624   } else {
   583     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
   625     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
   584     return FALSE;
   626     return FALSE;
   585   }
   627   }
       
   628 
       
   629   return TRUE;
   586 }
   630 }
   587 
   631 
   588 static gboolean
   632 static gboolean
   589 gst_wavparse_other (GstWavParse * wav)
   633 gst_wavparse_other (GstWavParse * wav)
   590 {
   634 {
   665           length = file_length - wav->datastart;
   709           length = file_length - wav->datastart;
   666           GST_DEBUG_OBJECT (wav, "datalength %lld", length);
   710           GST_DEBUG_OBJECT (wav, "datalength %lld", length);
   667         }
   711         }
   668       }
   712       }
   669       wav->datasize = (guint64) length;
   713       wav->datasize = (guint64) length;
   670       GST_DEBUG_OBJECT (wav, "datasize = %ld", length)
   714       break;
   671           break;
       
   672 
   715 
   673     case GST_RIFF_TAG_cue:
   716     case GST_RIFF_TAG_cue:
   674       if (!gst_riff_read_skip (wav)) {
   717       if (!gst_riff_read_skip (wav)) {
   675         GST_WARNING_OBJECT (wav, "could not read skip");
   718         GST_WARNING_OBJECT (wav, "could not read skip");
   676         return FALSE;
   719         return FALSE;
   687   return TRUE;
   730   return TRUE;
   688 }
   731 }
   689 #endif
   732 #endif
   690 
   733 
   691 
   734 
       
   735 
   692 static gboolean
   736 static gboolean
   693 gst_wavparse_parse_file_header (GstElement * element, GstBuffer * buf)
   737 gst_wavparse_parse_file_header (GstElement * element, GstBuffer * buf)
   694 {
   738 {
   695   guint32 doctype;
   739   guint32 doctype;
   696 
   740   
   697   if (!gst_riff_parse_file_header (element, buf, &doctype))
   741   if (!gst_riff_parse_file_header (element, buf, &doctype))
   698     return FALSE;
   742    return FALSE;
   699 
   743 
   700   if (doctype != GST_RIFF_RIFF_WAVE)
   744   if (doctype != GST_RIFF_RIFF_WAVE)
   701     goto not_wav;
   745     goto not_wav;
   702 
   746 
   703   return TRUE;
   747   return TRUE;
   704 
   748 
   705   /* ERRORS */
   749   /* ERRORS */
   706 not_wav:
   750 not_wav:
       
   751 
   707   {
   752   {
   708     GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL),
   753     GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL),
   709         ("File is not a WAVE file: %" GST_FOURCC_FORMAT,
   754         ("File is not an WAVE file: %" GST_FOURCC_FORMAT,
   710             GST_FOURCC_ARGS (doctype)));
   755             GST_FOURCC_ARGS (doctype)));
   711     return FALSE;
   756     return FALSE;
   712   }
   757   }
   713 }
   758 }
   714 
   759 
   716 gst_wavparse_stream_init (GstWavParse * wav)
   761 gst_wavparse_stream_init (GstWavParse * wav)
   717 {
   762 {
   718   GstFlowReturn res;
   763   GstFlowReturn res;
   719   GstBuffer *buf = NULL;
   764   GstBuffer *buf = NULL;
   720 
   765 
       
   766   
   721   if ((res = gst_pad_pull_range (wav->sinkpad,
   767   if ((res = gst_pad_pull_range (wav->sinkpad,
   722               wav->offset, 12, &buf)) != GST_FLOW_OK)
   768               wav->offset, 12, &buf)) != GST_FLOW_OK)
       
   769       {
       
   770  
   723     return res;
   771     return res;
   724   else if (!gst_wavparse_parse_file_header (GST_ELEMENT_CAST (wav), buf))
   772       }
       
   773   else if (!gst_wavparse_parse_file_header (GST_ELEMENT (wav), buf))
   725     return GST_FLOW_ERROR;
   774     return GST_FLOW_ERROR;
   726 
   775 
   727   wav->offset += 12;
   776   wav->offset += 12;
   728 
   777 
   729   return GST_FLOW_OK;
   778   return GST_FLOW_OK;
   730 }
   779 }
   731 
   780 
   732 static gboolean
   781 /* This function is used to perform seeks on the element in 
   733 gst_wavparse_time_to_bytepos (GstWavParse * wav, gint64 ts, gint64 * bytepos)
   782  * pull mode.
   734 {
       
   735   /* -1 always maps to -1 */
       
   736   if (ts == -1) {
       
   737     *bytepos = -1;
       
   738     return TRUE;
       
   739   }
       
   740 
       
   741   /* 0 always maps to 0 */
       
   742   if (ts == 0) {
       
   743     *bytepos = 0;
       
   744     return TRUE;
       
   745   }
       
   746 
       
   747   if (wav->bps > 0) {
       
   748     *bytepos = uint64_ceiling_scale (ts, (guint64) wav->bps, GST_SECOND);
       
   749     return TRUE;
       
   750   } else if (wav->fact) {
       
   751     guint64 bps =
       
   752         gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
       
   753     *bytepos = uint64_ceiling_scale (ts, bps, GST_SECOND);
       
   754     return TRUE;
       
   755   }
       
   756 
       
   757   return FALSE;
       
   758 }
       
   759 
       
   760 /* This function is used to perform seeks on the element.
       
   761  *
   783  *
   762  * It also works when event is NULL, in which case it will just
   784  * It also works when event is NULL, in which case it will just
   763  * start from the last configured segment. This technique is
   785  * start from the last configured segment. This technique is
   764  * used when activating the element and to perform the seek in
   786  * used when activating the element and to perform the seek in
   765  * READY.
   787  * READY.
   767 static gboolean
   789 static gboolean
   768 gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event)
   790 gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event)
   769 {
   791 {
   770   gboolean res;
   792   gboolean res;
   771   gdouble rate;
   793   gdouble rate;
   772   GstFormat format, bformat;
   794   GstEvent *newsegment;
       
   795   GstFormat format;
   773   GstSeekFlags flags;
   796   GstSeekFlags flags;
   774   GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
   797   GstSeekType cur_type, stop_type;
   775   gint64 cur, stop, upstream_size;
   798   gint64 cur, stop;
   776   gboolean flush;
   799   gboolean flush;
   777   gboolean update;
   800   gboolean update;
   778   GstSegment seeksegment = { 0, };
   801   GstSegment seeksegment;
   779   gint64 last_stop;
       
   780 
   802 
   781   if (event) {
   803   if (event) {
   782     GST_DEBUG_OBJECT (wav, "doing seek with event");
   804     GST_DEBUG_OBJECT (wav, "doing seek with event");
   783 
   805 
   784     gst_event_parse_seek (event, &rate, &format, &flags,
   806     gst_event_parse_seek (event, &rate, &format, &flags,
   785         &cur_type, &cur, &stop_type, &stop);
   807         &cur_type, &cur, &stop_type, &stop);
   786 
   808 
   787     /* no negative rates yet */
   809     /* we have to have a format as the segment format. Try to convert
   788     if (rate < 0.0)
   810      * if not. */
   789       goto negative_rate;
   811     if (format != GST_FORMAT_TIME) {
   790 
   812       GstFormat fmt;
   791     if (format != wav->segment.format) {
   813 
   792       GST_INFO_OBJECT (wav, "converting seek-event from %s to %s",
   814       fmt = GST_FORMAT_TIME;
   793           gst_format_get_name (format),
       
   794           gst_format_get_name (wav->segment.format));
       
   795       res = TRUE;
   815       res = TRUE;
   796       if (cur_type != GST_SEEK_TYPE_NONE)
   816       if (cur_type != GST_SEEK_TYPE_NONE)
   797         res =
   817         res = gst_pad_query_convert (wav->srcpad, format, cur, &fmt, &cur);
   798             gst_pad_query_convert (wav->srcpad, format, cur,
       
   799             &wav->segment.format, &cur);
       
   800       if (res && stop_type != GST_SEEK_TYPE_NONE)
   818       if (res && stop_type != GST_SEEK_TYPE_NONE)
   801         res =
   819         res = gst_pad_query_convert (wav->srcpad, format, stop, &fmt, &stop);
   802             gst_pad_query_convert (wav->srcpad, format, stop,
       
   803             &wav->segment.format, &stop);
       
   804       if (!res)
   820       if (!res)
   805         goto no_format;
   821         goto no_format;
   806 
   822 
   807       format = wav->segment.format;
   823       format = fmt;
   808     }
   824     }
   809   } else {
   825   } else {
   810     GST_DEBUG_OBJECT (wav, "doing seek without event");
   826     GST_DEBUG_OBJECT (wav, "doing seek without event");
   811     flags = 0;
   827     flags = 0;
   812     rate = 1.0;
   828   }
   813     cur_type = GST_SEEK_TYPE_SET;
   829 
   814     stop_type = GST_SEEK_TYPE_SET;
       
   815   }
       
   816 
       
   817   /* in push mode, we must delegate to upstream */
       
   818   if (wav->streaming) {
       
   819     gboolean res = FALSE;
       
   820 
       
   821     /* if streaming not yet started; only prepare initial newsegment */
       
   822     if (!event || wav->state != GST_WAVPARSE_DATA) {
       
   823       if (wav->start_segment)
       
   824         gst_event_unref (wav->start_segment);
       
   825       wav->start_segment =
       
   826           gst_event_new_new_segment (FALSE, wav->segment.rate,
       
   827           wav->segment.format, wav->segment.last_stop, wav->segment.duration,
       
   828           wav->segment.last_stop);
       
   829       res = TRUE;
       
   830     } else {
       
   831       /* convert seek positions to byte positions in data sections */
       
   832       if (format == GST_FORMAT_TIME) {
       
   833         /* should not fail */
       
   834         if (!gst_wavparse_time_to_bytepos (wav, cur, &cur))
       
   835           goto no_position;
       
   836         if (!gst_wavparse_time_to_bytepos (wav, stop, &stop))
       
   837           goto no_position;
       
   838       }
       
   839       /* mind sample boundary and header */
       
   840       if (cur >= 0) {
       
   841         cur -= (cur % wav->bytes_per_sample);
       
   842         cur += wav->datastart;
       
   843       }
       
   844       if (stop >= 0) {
       
   845         stop -= (stop % wav->bytes_per_sample);
       
   846         stop += wav->datastart;
       
   847       }
       
   848       GST_DEBUG_OBJECT (wav, "Pushing BYTE seek rate %g, "
       
   849           "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur,
       
   850           stop);
       
   851       /* BYTE seek event */
       
   852       event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur,
       
   853           stop_type, stop);
       
   854       res = gst_pad_push_event (wav->sinkpad, event);
       
   855     }
       
   856     return res;
       
   857   }
       
   858 
       
   859   /* get flush flag */
       
   860   flush = flags & GST_SEEK_FLAG_FLUSH;
   830   flush = flags & GST_SEEK_FLAG_FLUSH;
   861 
   831 
   862   /* now we need to make sure the streaming thread is stopped. We do this by
   832   if (flush && wav->srcpad) {
   863    * either sending a FLUSH_START event downstream which will cause the
   833     GST_DEBUG_OBJECT (wav, "sending flush start");
   864    * streaming thread to stop with a WRONG_STATE.
   834     gst_pad_push_event (wav->srcpad, gst_event_new_flush_start ());
   865    * For a non-flushing seek we simply pause the task, which will happen as soon
       
   866    * as it completes one iteration (and thus might block when the sink is
       
   867    * blocking in preroll). */
       
   868   if (flush) {
       
   869     if (wav->srcpad) {
       
   870       GST_DEBUG_OBJECT (wav, "sending flush start");
       
   871       gst_pad_push_event (wav->srcpad, gst_event_new_flush_start ());
       
   872     }
       
   873   } else {
   835   } else {
   874     gst_pad_pause_task (wav->sinkpad);
   836     gst_pad_pause_task (wav->sinkpad);
   875   }
   837   }
   876 
   838 
   877   /* we should now be able to grab the streaming thread because we stopped it
       
   878    * with the above flush/pause code */
       
   879   GST_PAD_STREAM_LOCK (wav->sinkpad);
   839   GST_PAD_STREAM_LOCK (wav->sinkpad);
   880 
       
   881   /* save current position */
       
   882   last_stop = wav->segment.last_stop;
       
   883 
       
   884   GST_DEBUG_OBJECT (wav, "stopped streaming at %" G_GINT64_FORMAT, last_stop);
       
   885 
   840 
   886   /* copy segment, we need this because we still need the old
   841   /* copy segment, we need this because we still need the old
   887    * segment when we close the current segment. */
   842    * segment when we close the current segment. */
   888   memcpy (&seeksegment, &wav->segment, sizeof (GstSegment));
   843   memcpy (&seeksegment, &wav->segment, sizeof (GstSegment));
   889 
   844 
   890   /* configure the seek parameters in the seeksegment. We will then have the
       
   891    * right values in the segment to perform the seek */
       
   892   if (event) {
   845   if (event) {
   893     GST_DEBUG_OBJECT (wav, "configuring seek");
   846     GST_DEBUG_OBJECT (wav, "configuring seek");
   894     gst_segment_set_seek (&seeksegment, rate, format, flags,
   847     gst_segment_set_seek (&seeksegment, rate, format, flags,
   895         cur_type, cur, stop_type, stop, &update);
   848         cur_type, cur, stop_type, stop, &update);
   896   }
   849   }
   897 
   850 
   898   /* figure out the last position we need to play. If it's configured (stop !=
       
   899    * -1), use that, else we play until the total duration of the file */
       
   900   if ((stop = seeksegment.stop) == -1)
   851   if ((stop = seeksegment.stop) == -1)
   901     stop = seeksegment.duration;
   852     stop = seeksegment.duration;
   902 
   853 
   903   GST_DEBUG_OBJECT (wav, "cur_type =%d", cur_type);
   854   if (cur_type != GST_SEEK_TYPE_NONE) {
   904   if ((cur_type != GST_SEEK_TYPE_NONE)) {
   855     wav->offset =
   905     /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and
   856         gst_util_uint64_scale_int (seeksegment.last_stop, wav->bps, GST_SECOND);
   906      * we can just copy the last_stop. If not, we use the bps to convert TIME to
   857     wav->offset -= wav->offset % wav->bytes_per_sample;
   907      * bytes. */
       
   908     if (!gst_wavparse_time_to_bytepos (wav, seeksegment.last_stop,
       
   909             (gint64 *) & wav->offset))
       
   910       wav->offset = seeksegment.last_stop;
       
   911     GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);
       
   912     wav->offset -= (wav->offset % wav->bytes_per_sample);
       
   913     GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);
       
   914     wav->offset += wav->datastart;
   858     wav->offset += wav->datastart;
   915     GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);
   859   }
       
   860 
       
   861   if (stop != -1) {
       
   862     wav->end_offset = gst_util_uint64_scale_int (stop, wav->bps, GST_SECOND);
       
   863     wav->end_offset +=
       
   864         wav->bytes_per_sample - (wav->end_offset % wav->bytes_per_sample);
       
   865     wav->end_offset += wav->datastart;
   916   } else {
   866   } else {
   917     GST_LOG_OBJECT (wav, "continue from offset=%" G_GUINT64_FORMAT,
   867     wav->end_offset = wav->datasize + wav->datastart;
   918         wav->offset);
   868   }
   919   }
       
   920 
       
   921   if (stop_type != GST_SEEK_TYPE_NONE) {
       
   922     if (!gst_wavparse_time_to_bytepos (wav, stop, (gint64 *) & wav->end_offset))
       
   923       wav->end_offset = stop;
       
   924     GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);
       
   925     wav->end_offset -= (wav->end_offset % wav->bytes_per_sample);
       
   926     GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);
       
   927     wav->end_offset += wav->datastart;
       
   928     GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);
       
   929   } else {
       
   930     GST_LOG_OBJECT (wav, "continue to end_offset=%" G_GUINT64_FORMAT,
       
   931         wav->end_offset);
       
   932   }
       
   933 
       
   934   /* make sure filesize is not exceeded due to rounding errors or so,
       
   935    * same precaution as in _stream_headers */
       
   936   bformat = GST_FORMAT_BYTES;
       
   937   if (gst_pad_query_peer_duration (wav->sinkpad, &bformat, &upstream_size))
       
   938     wav->end_offset = MIN (wav->end_offset, upstream_size);
       
   939 
       
   940   /* this is the range of bytes we will use for playback */
       
   941   wav->offset = MIN (wav->offset, wav->end_offset);
   869   wav->offset = MIN (wav->offset, wav->end_offset);
   942   wav->dataleft = wav->end_offset - wav->offset;
   870   wav->dataleft = wav->end_offset - wav->offset;
   943 
   871 
   944   GST_DEBUG_OBJECT (wav,
   872   GST_DEBUG_OBJECT (wav,
   945       "seek: rate %lf, offset %" G_GUINT64_FORMAT ", end %" G_GUINT64_FORMAT
   873       "seek: offset %" G_GUINT64_FORMAT ", end %" G_GUINT64_FORMAT ", segment %"
   946       ", segment %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate, wav->offset,
   874       GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, wav->offset, wav->end_offset,
   947       wav->end_offset, GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (stop));
   875       GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (stop));
   948 
   876 
   949   /* prepare for streaming again */
   877   /* prepare for streaming again */
   950   if (wav->srcpad) {
   878   if (wav->srcpad) {
   951     if (flush) {
   879     if (flush) {
   952       /* if we sent a FLUSH_START, we now send a FLUSH_STOP */
       
   953       GST_DEBUG_OBJECT (wav, "sending flush stop");
   880       GST_DEBUG_OBJECT (wav, "sending flush stop");
   954       gst_pad_push_event (wav->srcpad, gst_event_new_flush_stop ());
   881       gst_pad_push_event (wav->srcpad, gst_event_new_flush_stop ());
   955     } else if (wav->segment_running) {
   882     } else if (wav->segment_running) {
   956       /* we are running the current segment and doing a non-flushing seek,
   883       /* we are running the current segment and doing a non-flushing seek,
   957        * close the segment first based on the previous last_stop. */
   884        * close the segment first based on the last_stop. */
   958       GST_DEBUG_OBJECT (wav, "closing running segment %" G_GINT64_FORMAT
   885       GST_DEBUG_OBJECT (wav, "closing running segment %" G_GINT64_FORMAT
   959           " to %" G_GINT64_FORMAT, wav->segment.accum, wav->segment.last_stop);
   886           " to %" G_GINT64_FORMAT, wav->segment.start, wav->segment.last_stop);
   960 
   887 
   961       /* queue the segment for sending in the stream thread */
   888       gst_pad_push_event (wav->srcpad,
   962       if (wav->close_segment)
   889           gst_event_new_new_segment (TRUE,
   963         gst_event_unref (wav->close_segment);
   890               wav->segment.rate, wav->segment.format,
   964       wav->close_segment = gst_event_new_new_segment (TRUE,
   891               wav->segment.start, wav->segment.last_stop, wav->segment.time));
   965           wav->segment.rate, wav->segment.format,
   892     }
   966           wav->segment.accum, wav->segment.last_stop, wav->segment.accum);
   893   }
   967 
   894 
   968       /* keep track of our last_stop */
       
   969       seeksegment.accum = wav->segment.last_stop;
       
   970     }
       
   971   }
       
   972 
       
   973   /* now we did the seek and can activate the new segment values */
       
   974   memcpy (&wav->segment, &seeksegment, sizeof (GstSegment));
   895   memcpy (&wav->segment, &seeksegment, sizeof (GstSegment));
   975 
   896 
   976   /* if we're doing a segment seek, post a SEGMENT_START message */
       
   977   if (wav->segment.flags & GST_SEEK_FLAG_SEGMENT) {
   897   if (wav->segment.flags & GST_SEEK_FLAG_SEGMENT) {
   978     gst_element_post_message (GST_ELEMENT_CAST (wav),
   898     gst_element_post_message (GST_ELEMENT (wav),
   979         gst_message_new_segment_start (GST_OBJECT_CAST (wav),
   899         gst_message_new_segment_start (GST_OBJECT (wav),
   980             wav->segment.format, wav->segment.last_stop));
   900             wav->segment.format, wav->segment.last_stop));
   981   }
   901   }
   982 
   902 
   983   /* now create the newsegment */
   903   /* now send the newsegment */
   984   GST_DEBUG_OBJECT (wav, "Creating newsegment from %" G_GINT64_FORMAT
   904   GST_DEBUG_OBJECT (wav, "Sending newsegment from %" G_GINT64_FORMAT
   985       " to %" G_GINT64_FORMAT, wav->segment.last_stop, stop);
   905       " to %" G_GINT64_FORMAT, wav->segment.start, stop);
   986 
   906 
   987   /* store the newsegment event so it can be sent from the streaming thread. */
   907   newsegment =
   988   if (wav->start_segment)
       
   989     gst_event_unref (wav->start_segment);
       
   990   wav->start_segment =
       
   991       gst_event_new_new_segment (FALSE, wav->segment.rate,
   908       gst_event_new_new_segment (FALSE, wav->segment.rate,
   992       wav->segment.format, wav->segment.last_stop, stop,
   909       wav->segment.format, wav->segment.last_stop, stop, wav->segment.time);
   993       wav->segment.last_stop);
   910 
   994 
   911   if (wav->srcpad) {
   995   /* mark discont if we are going to stream from another position. */
   912     gst_pad_push_event (wav->srcpad, newsegment);
   996   if (last_stop != wav->segment.last_stop) {
   913   } else {
   997     GST_DEBUG_OBJECT (wav, "mark DISCONT, we did a seek to another position");
   914     /* send later when we actually create the source pad */
   998     wav->discont = TRUE;
   915     g_assert (wav->newsegment == NULL);
   999   }
   916     wav->newsegment = newsegment;
  1000 
   917   }
  1001   /* and start the streaming task again */
   918 
  1002   wav->segment_running = TRUE;
   919   wav->segment_running = TRUE;
  1003   if (!wav->streaming) {
   920   if (!wav->streaming) {
  1004     gst_pad_start_task (wav->sinkpad, (GstTaskFunction) gst_wavparse_loop,
   921     gst_pad_start_task (wav->sinkpad, (GstTaskFunction) gst_wavparse_loop,
  1005         wav->sinkpad);
   922         wav->sinkpad);
  1006   }
   923   }
  1008   GST_PAD_STREAM_UNLOCK (wav->sinkpad);
   925   GST_PAD_STREAM_UNLOCK (wav->sinkpad);
  1009 
   926 
  1010   return TRUE;
   927   return TRUE;
  1011 
   928 
  1012   /* ERRORS */
   929   /* ERRORS */
  1013 negative_rate:
       
  1014   {
       
  1015     GST_DEBUG_OBJECT (wav, "negative playback rates are not supported yet.");
       
  1016     return FALSE;
       
  1017   }
       
  1018 no_format:
   930 no_format:
  1019   {
   931   {
  1020     GST_DEBUG_OBJECT (wav, "unsupported format given, seek aborted.");
   932     GST_DEBUG_OBJECT (wav, "unsupported format given, seek aborted.");
  1021     return FALSE;
       
  1022   }
       
  1023 no_position:
       
  1024   {
       
  1025     GST_DEBUG_OBJECT (wav,
       
  1026         "Could not determine byte position for desired time");
       
  1027     return FALSE;
   933     return FALSE;
  1028   }
   934   }
  1029 }
   935 }
  1030 
   936 
  1031 /*
   937 /*
  1032  * gst_wavparse_peek_chunk_info:
   938  * gst_wavparse_peek_chunk_info:
  1033  * @wav Wavparse object
   939  * @wav Wavparse object
  1034  * @tag holder for tag
   940  * @tag holder for tag
  1035  * @size holder for tag size
   941  * @size holder for tag size
       
   942  *                         
       
   943  * Peek next chunk info (tag and size)                         
  1036  *
   944  *
  1037  * Peek next chunk info (tag and size)
   945  * Returns: %TRUE when one chunk info has been got from the adapter
  1038  *
       
  1039  * Returns: %TRUE when the chunk info (header) is available
       
  1040  */
   946  */
  1041 static gboolean
   947 static gboolean
  1042 gst_wavparse_peek_chunk_info (GstWavParse * wav, guint32 * tag, guint32 * size)
   948 gst_wavparse_peek_chunk_info (GstWavParse * wav, guint32 * tag, guint32 * size)
  1043 {
   949 {
  1044   const guint8 *data = NULL;
   950   const guint8 *data = NULL;
  1045 
   951 
  1046   if (gst_adapter_available (wav->adapter) < 8)
   952   if (gst_adapter_available (wav->adapter) < 8) {
  1047     return FALSE;
   953     return FALSE;
  1048 
   954   }
       
   955 
       
   956   GST_DEBUG ("Next chunk size is %d bytes", *size);
  1049   data = gst_adapter_peek (wav->adapter, 8);
   957   data = gst_adapter_peek (wav->adapter, 8);
  1050   *tag = GST_READ_UINT32_LE (data);
   958   *tag = GST_READ_UINT32_LE (data);
  1051   *size = GST_READ_UINT32_LE (data + 4);
   959   *size = GST_READ_UINT32_LE (data + 4);
  1052 
       
  1053   GST_DEBUG ("Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
       
  1054       GST_FOURCC_ARGS (*tag));
       
  1055 
   960 
  1056   return TRUE;
   961   return TRUE;
  1057 }
   962 }
  1058 
   963 
  1059 /*
   964 /*
  1062  * @tag holder for tag
   967  * @tag holder for tag
  1063  * @size holder for tag size
   968  * @size holder for tag size
  1064  *
   969  *
  1065  * Peek enough data for one full chunk
   970  * Peek enough data for one full chunk
  1066  *
   971  *
  1067  * Returns: %TRUE when the full chunk is available
   972  * Returns: %TRUE when one chunk has been got
  1068  */
   973  */
  1069 static gboolean
   974 static gboolean
  1070 gst_wavparse_peek_chunk (GstWavParse * wav, guint32 * tag, guint32 * size)
   975 gst_wavparse_peek_chunk (GstWavParse * wav, guint32 * tag, guint32 * size)
  1071 {
   976 {
  1072   guint32 peek_size = 0;
   977   guint32 peek_size = 0;
  1073   guint available;
   978 
  1074 
   979   gst_wavparse_peek_chunk_info (wav, tag, size);
  1075   if (!gst_wavparse_peek_chunk_info (wav, tag, size))
       
  1076     return FALSE;
       
  1077 
       
  1078   GST_DEBUG ("Need to peek chunk of %d bytes", *size);
   980   GST_DEBUG ("Need to peek chunk of %d bytes", *size);
  1079   peek_size = (*size + 1) & ~1;
   981   peek_size = (*size + 1) & ~1;
  1080 
   982 
  1081   available = gst_adapter_available (wav->adapter);
   983   if (gst_adapter_available (wav->adapter) >= (8 + peek_size)) {
  1082   if (available >= (8 + peek_size)) {
       
  1083     return TRUE;
   984     return TRUE;
  1084   } else {
   985   } else {
  1085     GST_LOG ("but only %u bytes available now", available);
       
  1086     return FALSE;
   986     return FALSE;
  1087   }
   987   }
  1088 }
   988 }
  1089 
   989 
  1090 /*
       
  1091  * gst_wavparse_calculate_duration:
       
  1092  * @wav: wavparse object
       
  1093  *
       
  1094  * Calculate duration on demand and store in @wav. Prefer bps, but use fact as a
       
  1095  * fallback.
       
  1096  *
       
  1097  * Returns: %TRUE if duration is available.
       
  1098  */
       
  1099 static gboolean
   990 static gboolean
  1100 gst_wavparse_calculate_duration (GstWavParse * wav)
   991 gst_wavparse_get_upstream_size (GstWavParse * wav, gint64 * len)
  1101 {
   992 {
  1102   if (wav->duration > 0)
   993   gboolean res = FALSE;
  1103     return TRUE;
   994   GstFormat fmt = GST_FORMAT_BYTES;
  1104 
   995   GstPad *peer;
  1105   if (wav->bps > 0) {
   996 
  1106     GST_INFO_OBJECT (wav, "Got datasize %" G_GUINT64_FORMAT, wav->datasize);
   997   if ((peer = gst_pad_get_peer (wav->sinkpad))) {
  1107     wav->duration =
   998     res = gst_pad_query_duration (peer, &fmt, len);
  1108         uint64_ceiling_scale (wav->datasize, GST_SECOND, (guint64) wav->bps);
   999     gst_object_unref (peer);
  1109     GST_INFO_OBJECT (wav, "Got duration (bps) %" GST_TIME_FORMAT,
  1000   }
  1110         GST_TIME_ARGS (wav->duration));
  1001 
  1111     return TRUE;
  1002   return res;
  1112   } else if (wav->fact) {
       
  1113     wav->duration = uint64_ceiling_scale_int (GST_SECOND, wav->fact, wav->rate);
       
  1114     GST_INFO_OBJECT (wav, "Got duration (fact) %" GST_TIME_FORMAT,
       
  1115         GST_TIME_ARGS (wav->duration));
       
  1116     return TRUE;
       
  1117   }
       
  1118   return FALSE;
       
  1119 }
       
  1120 
       
  1121 static void
       
  1122 gst_waveparse_ignore_chunk (GstWavParse * wav, GstBuffer * buf, guint32 tag,
       
  1123     guint32 size)
       
  1124 {
       
  1125   guint flush;
       
  1126 
       
  1127   if (wav->streaming) {
       
  1128     if (!gst_wavparse_peek_chunk (wav, &tag, &size))
       
  1129       return;
       
  1130   }
       
  1131   GST_DEBUG_OBJECT (wav, "Ignoring tag %" GST_FOURCC_FORMAT,
       
  1132       GST_FOURCC_ARGS (tag));
       
  1133   flush = 8 + ((size + 1) & ~1);
       
  1134   wav->offset += flush;
       
  1135   if (wav->streaming) {
       
  1136     gst_adapter_flush (wav->adapter, flush);
       
  1137   } else {
       
  1138     gst_buffer_unref (buf);
       
  1139   }
       
  1140 }
  1003 }
  1141 
  1004 
  1142 static GstFlowReturn
  1005 static GstFlowReturn
  1143 gst_wavparse_stream_headers (GstWavParse * wav)
  1006 gst_wavparse_stream_headers (GstWavParse * wav)
  1144 {
  1007 {
  1146   GstBuffer *buf;
  1009   GstBuffer *buf;
  1147   gst_riff_strf_auds *header = NULL;
  1010   gst_riff_strf_auds *header = NULL;
  1148   guint32 tag, size;
  1011   guint32 tag, size;
  1149   gboolean gotdata = FALSE;
  1012   gboolean gotdata = FALSE;
  1150   GstCaps *caps;
  1013   GstCaps *caps;
       
  1014   gint64 duration;
  1151   gchar *codec_name = NULL;
  1015   gchar *codec_name = NULL;
  1152   GstEvent **event_p;
  1016   GstEvent **event_p;
  1153   GstFormat bformat;
  1017 
  1154   gint64 upstream_size = 0;
  1018   
  1155 
  1019   if (!wav->got_fmt) {
  1156   /* search for "_fmt" chunk, which should be first */
       
  1157   while (!wav->got_fmt) {
       
  1158     GstBuffer *extra;
  1020     GstBuffer *extra;
  1159 
  1021 
  1160     /* The header starts with a 'fmt ' tag */
  1022     /* The header start with a 'fmt ' tag */
       
  1023 
  1161     if (wav->streaming) {
  1024     if (wav->streaming) {
  1162       if (!gst_wavparse_peek_chunk (wav, &tag, &size))
  1025       if (!gst_wavparse_peek_chunk (wav, &tag, &size))
  1163         return GST_FLOW_OK;
  1026         return GST_FLOW_OK;
  1164 
  1027 
       
  1028       buf = gst_buffer_new ();
       
  1029       gst_buffer_ref (buf);
  1165       gst_adapter_flush (wav->adapter, 8);
  1030       gst_adapter_flush (wav->adapter, 8);
  1166       wav->offset += 8;
  1031       wav->offset += 8;
  1167 
  1032       GST_BUFFER_DATA (buf) = (guint8 *) gst_adapter_peek (wav->adapter, size);
  1168       buf = gst_adapter_take_buffer (wav->adapter, size);
  1033       GST_BUFFER_SIZE (buf) = size;
       
  1034 
  1169     } else {
  1035     } else {
  1170       if ((res = gst_riff_read_chunk (GST_ELEMENT_CAST (wav), wav->sinkpad,
  1036       if ((res = gst_riff_read_chunk (GST_ELEMENT (wav), wav->sinkpad,
  1171                   &wav->offset, &tag, &buf)) != GST_FLOW_OK)
  1037                   &wav->offset, &tag, &buf)) != GST_FLOW_OK)
  1172         return res;
  1038         return res;
  1173     }
  1039     }
  1174 
  1040 
  1175     if (tag == GST_RIFF_TAG_JUNK || tag == GST_RIFF_TAG_bext ||
       
  1176         tag == GST_RIFF_TAG_BEXT || tag == GST_RIFF_TAG_LIST) {
       
  1177       GST_DEBUG_OBJECT (wav, "skipping %" GST_FOURCC_FORMAT " chunk",
       
  1178           GST_FOURCC_ARGS (tag));
       
  1179       gst_buffer_unref (buf);
       
  1180       buf = NULL;
       
  1181       continue;
       
  1182     }
       
  1183 
       
  1184     if (tag != GST_RIFF_TAG_fmt)
  1041     if (tag != GST_RIFF_TAG_fmt)
  1185       goto invalid_wav;
  1042       goto invalid_wav;
  1186 
  1043 
  1187     if (!(gst_riff_parse_strf_auds (GST_ELEMENT_CAST (wav), buf, &header,
  1044     if (!(gst_riff_parse_strf_auds (GST_ELEMENT (wav), buf, &header, &extra)))
  1188                 &extra)))
       
  1189       goto parse_header_error;
  1045       goto parse_header_error;
  1190 
  1046 
  1191     buf = NULL;                 /* parse_strf_auds() took ownership of buffer */
  1047     if (wav->streaming) {
  1192 
  1048       gst_adapter_flush (wav->adapter, size);
  1193     /* do sanity checks of header fields */
  1049       wav->offset += size;
  1194     if (header->channels == 0)
  1050       GST_BUFFER_DATA (buf) = NULL;
  1195       goto no_channels;
  1051       gst_buffer_unref (buf);
  1196     if (header->rate == 0)
  1052     }
  1197       goto no_rate;
  1053 
  1198 
  1054     /* Note: gst_riff_create_audio_caps might nedd to fix values in
  1199     GST_DEBUG_OBJECT (wav, "creating the caps");
       
  1200 
       
  1201     /* Note: gst_riff_create_audio_caps might need to fix values in
       
  1202      * the header header depending on the format, so call it first */
  1055      * the header header depending on the format, so call it first */
  1203     caps = gst_riff_create_audio_caps (header->format, NULL, header, extra,
  1056     caps =
       
  1057         gst_riff_create_audio_caps (header->format, NULL, header, extra,
  1204         NULL, &codec_name);
  1058         NULL, &codec_name);
  1205 
  1059 
  1206     if (extra)
  1060     if (extra)
  1207       gst_buffer_unref (extra);
  1061       gst_buffer_unref (extra);
  1208 
  1062 
  1209     if (!caps)
       
  1210       goto unknown_format;
       
  1211 
       
  1212     /* do more sanity checks of header fields
       
  1213      * (these can be sanitized by gst_riff_create_audio_caps()
       
  1214      */
       
  1215     wav->format = header->format;
  1063     wav->format = header->format;
  1216     wav->rate = header->rate;
  1064     wav->rate = header->rate;
  1217     wav->channels = header->channels;
  1065     wav->channels = header->channels;
       
  1066 
       
  1067     if (wav->channels == 0)
       
  1068       goto no_channels;
       
  1069 
  1218     wav->blockalign = header->blockalign;
  1070     wav->blockalign = header->blockalign;
       
  1071     wav->width = (header->blockalign * 8) / header->channels;
  1219     wav->depth = header->size;
  1072     wav->depth = header->size;
  1220     wav->av_bps = header->av_bps;
  1073     wav->bps = header->av_bps;
  1221     wav->vbr = FALSE;
  1074 
  1222 
  1075     if (wav->bps <= 0)
  1223     g_free (header);
  1076       goto no_bitrate;
  1224     header = NULL;
  1077 
  1225 
       
  1226     /* do format specific handling */
       
  1227     switch (wav->format) {
       
  1228       case GST_RIFF_WAVE_FORMAT_MPEGL12:
       
  1229       case GST_RIFF_WAVE_FORMAT_MPEGL3:
       
  1230       {
       
  1231         /* Note: workaround for mp2/mp3 embedded in wav, that relies on the
       
  1232          * bitrate inside the mpeg stream */
       
  1233         GST_INFO ("resetting bps from %d to 0 for mp2/3", wav->av_bps);
       
  1234         wav->bps = 0;
       
  1235         break;
       
  1236       }
       
  1237       case GST_RIFF_WAVE_FORMAT_PCM:
       
  1238         if (wav->blockalign > wav->channels * (guint) ceil (wav->depth / 8.0))
       
  1239           goto invalid_blockalign;
       
  1240         /* fall through */
       
  1241       default:
       
  1242         if (wav->av_bps > wav->blockalign * wav->rate)
       
  1243           goto invalid_bps;
       
  1244         /* use the configured bps */
       
  1245         wav->bps = wav->av_bps;
       
  1246         break;
       
  1247     }
       
  1248 
       
  1249     wav->width = (wav->blockalign * 8) / wav->channels;
       
  1250     wav->bytes_per_sample = wav->channels * wav->width / 8;
  1078     wav->bytes_per_sample = wav->channels * wav->width / 8;
  1251 
       
  1252     if (wav->bytes_per_sample <= 0)
  1079     if (wav->bytes_per_sample <= 0)
  1253       goto no_bytes_per_sample;
  1080       goto no_bytes_per_sample;
       
  1081 
       
  1082     g_free (header);
       
  1083 
       
  1084     if (!caps)
       
  1085       goto unknown_format;
  1254 
  1086 
  1255     GST_DEBUG_OBJECT (wav, "blockalign = %u", (guint) wav->blockalign);
  1087     GST_DEBUG_OBJECT (wav, "blockalign = %u", (guint) wav->blockalign);
  1256     GST_DEBUG_OBJECT (wav, "width      = %u", (guint) wav->width);
  1088     GST_DEBUG_OBJECT (wav, "width      = %u", (guint) wav->width);
  1257     GST_DEBUG_OBJECT (wav, "depth      = %u", (guint) wav->depth);
  1089     GST_DEBUG_OBJECT (wav, "depth      = %u", (guint) wav->depth);
  1258     GST_DEBUG_OBJECT (wav, "av_bps     = %u", (guint) wav->av_bps);
       
  1259     GST_DEBUG_OBJECT (wav, "frequency  = %u", (guint) wav->rate);
       
  1260     GST_DEBUG_OBJECT (wav, "channels   = %u", (guint) wav->channels);
       
  1261     GST_DEBUG_OBJECT (wav, "bytes_per_sample = %u", wav->bytes_per_sample);
       
  1262 
       
  1263     /* bps can be 0 when we don't have a valid bitrate (mostly for compressed
       
  1264      * formats). This will make the element output a BYTE format segment and
       
  1265      * will not timestamp the outgoing buffers.
       
  1266      */
       
  1267     GST_DEBUG_OBJECT (wav, "bps        = %u", (guint) wav->bps);
  1090     GST_DEBUG_OBJECT (wav, "bps        = %u", (guint) wav->bps);
  1268 
       
  1269     GST_DEBUG_OBJECT (wav, "caps = %" GST_PTR_FORMAT, caps);
       
  1270 
  1091 
  1271     /* create pad later so we can sniff the first few bytes
  1092     /* create pad later so we can sniff the first few bytes
  1272      * of the real data and correct our caps if necessary */
  1093      * of the real data and correct our caps if necessary */
  1273     gst_caps_replace (&wav->caps, caps);
  1094     gst_caps_replace (&wav->caps, caps);
  1274     gst_caps_replace (&caps, NULL);
  1095     gst_caps_replace (&caps, NULL);
  1283 
  1104 
  1284       g_free (codec_name);
  1105       g_free (codec_name);
  1285       codec_name = NULL;
  1106       codec_name = NULL;
  1286     }
  1107     }
  1287 
  1108 
  1288   }
  1109     GST_DEBUG_OBJECT (wav, "frequency %d, channels %d", wav->rate,
  1289 
  1110         wav->channels);
  1290   bformat = GST_FORMAT_BYTES;
  1111   }
  1291   gst_pad_query_peer_duration (wav->sinkpad, &bformat, &upstream_size);
       
  1292   GST_DEBUG_OBJECT (wav, "upstream size %" G_GUINT64_FORMAT, upstream_size);
       
  1293 
  1112 
  1294   /* loop headers until we get data */
  1113   /* loop headers until we get data */
  1295   while (!gotdata) {
  1114   while (!gotdata) {
  1296     if (wav->streaming) {
  1115     if (wav->streaming) {
  1297       if (!gst_wavparse_peek_chunk_info (wav, &tag, &size))
  1116       if (!gst_wavparse_peek_chunk_info (wav, &tag, &size))
  1303         goto header_read_error;
  1122         goto header_read_error;
  1304       tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
  1123       tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
  1305       size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
  1124       size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
  1306     }
  1125     }
  1307 
  1126 
  1308     GST_INFO_OBJECT (wav,
  1127     /*
  1309         "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
  1128        wav is a st00pid format, we don't know for sure where data starts.
  1310         GST_FOURCC_ARGS (tag), wav->offset);
  1129        So we have to go bit by bit until we find the 'data' header
  1311 
       
  1312     /* wav is a st00pid format, we don't know for sure where data starts.
       
  1313      * So we have to go bit by bit until we find the 'data' header
       
  1314      */
  1130      */
       
  1131 
  1315     switch (tag) {
  1132     switch (tag) {
       
  1133         /* TODO : Implement the various cases */
  1316       case GST_RIFF_TAG_data:{
  1134       case GST_RIFF_TAG_data:{
       
  1135         gint64 upstream_size;
       
  1136 
  1317         GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %d", size);
  1137         GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %d", size);
       
  1138         gotdata = TRUE;
  1318         if (wav->streaming) {
  1139         if (wav->streaming) {
  1319           gst_adapter_flush (wav->adapter, 8);
  1140           gst_adapter_flush (wav->adapter, 8);
  1320           gotdata = TRUE;
       
  1321         } else {
  1141         } else {
  1322           gst_buffer_unref (buf);
  1142           gst_buffer_unref (buf);
  1323         }
  1143         }
  1324         wav->offset += 8;
  1144         wav->offset += 8;
  1325         wav->datastart = wav->offset;
  1145         wav->datastart = wav->offset;
  1326         /* file might be truncated */
  1146         /* file might be truncated */
  1327         if (upstream_size) {
  1147         if (gst_wavparse_get_upstream_size (wav, &upstream_size)) {
  1328           size = MIN (size, (upstream_size - wav->datastart));
  1148           size = MIN (size, (upstream_size - wav->datastart));
  1329         }
  1149         }
  1330         wav->datasize = (guint64) size;
  1150         wav->datasize = size;
  1331         wav->dataleft = (guint64) size;
  1151         wav->dataleft = size;
  1332         wav->end_offset = size + wav->datastart;
  1152         wav->end_offset = size + wav->datastart;
  1333         if (!wav->streaming) {
       
  1334           /* We will continue parsing tags 'till end */
       
  1335           wav->offset += size;
       
  1336         }
       
  1337         GST_DEBUG_OBJECT (wav, "datasize = %d", size);
       
  1338         break;
       
  1339       }
       
  1340       case GST_RIFF_TAG_fact:{
       
  1341         if (wav->format != GST_RIFF_WAVE_FORMAT_MPEGL12 &&
       
  1342             wav->format != GST_RIFF_WAVE_FORMAT_MPEGL3) {
       
  1343           const guint data_size = 4;
       
  1344 
       
  1345           /* number of samples (for compressed formats) */
       
  1346           if (wav->streaming) {
       
  1347             const guint8 *data = NULL;
       
  1348 
       
  1349             if (gst_adapter_available (wav->adapter) < 8 + data_size) {
       
  1350               return GST_FLOW_OK;
       
  1351             }
       
  1352             gst_adapter_flush (wav->adapter, 8);
       
  1353             data = gst_adapter_peek (wav->adapter, data_size);
       
  1354             wav->fact = GST_READ_UINT32_LE (data);
       
  1355             gst_adapter_flush (wav->adapter, data_size);
       
  1356           } else {
       
  1357             gst_buffer_unref (buf);
       
  1358             if ((res =
       
  1359                     gst_pad_pull_range (wav->sinkpad, wav->offset + 8,
       
  1360                         data_size, &buf)) != GST_FLOW_OK)
       
  1361               goto header_read_error;
       
  1362             wav->fact = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
       
  1363             gst_buffer_unref (buf);
       
  1364           }
       
  1365           GST_DEBUG_OBJECT (wav, "have fact %u", wav->fact);
       
  1366           wav->offset += 8 + data_size;
       
  1367           break;
       
  1368         } else {
       
  1369           gst_waveparse_ignore_chunk (wav, buf, tag, size);
       
  1370         }
       
  1371         break;
       
  1372       }
       
  1373       case GST_RIFF_TAG_acid:{
       
  1374         const gst_riff_acid *acid = NULL;
       
  1375         const guint data_size = sizeof (gst_riff_acid);
       
  1376 
       
  1377         if (wav->streaming) {
       
  1378           if (gst_adapter_available (wav->adapter) < 8 + data_size) {
       
  1379             return GST_FLOW_OK;
       
  1380           }
       
  1381           gst_adapter_flush (wav->adapter, 8);
       
  1382           acid = (const gst_riff_acid *) gst_adapter_peek (wav->adapter,
       
  1383               data_size);
       
  1384         } else {
       
  1385           gst_buffer_unref (buf);
       
  1386           if ((res =
       
  1387                   gst_pad_pull_range (wav->sinkpad, wav->offset + 8,
       
  1388                       data_size, &buf)) != GST_FLOW_OK)
       
  1389             goto header_read_error;
       
  1390           acid = (const gst_riff_acid *) GST_BUFFER_DATA (buf);
       
  1391         }
       
  1392         GST_INFO_OBJECT (wav, "Have acid chunk");
       
  1393         /* send data as tags */
       
  1394         if (!wav->tags)
       
  1395           wav->tags = gst_tag_list_new ();
       
  1396         gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
       
  1397             GST_TAG_BEATS_PER_MINUTE, acid->tempo, NULL);
       
  1398 
       
  1399         if (wav->streaming) {
       
  1400           gst_adapter_flush (wav->adapter, data_size);
       
  1401         } else {
       
  1402           gst_buffer_unref (buf);
       
  1403           wav->offset += 8 + data_size;
       
  1404         }
       
  1405         break;
       
  1406       }
       
  1407         /* FIXME: all list tags after data are ignored in streaming mode */
       
  1408       case GST_RIFF_TAG_LIST:{
       
  1409         guint32 ltag;
       
  1410 
       
  1411         if (wav->streaming) {
       
  1412           const guint8 *data = NULL;
       
  1413 
       
  1414           if (gst_adapter_available (wav->adapter) < 12) {
       
  1415             return GST_FLOW_OK;
       
  1416           }
       
  1417           data = gst_adapter_peek (wav->adapter, 12);
       
  1418           ltag = GST_READ_UINT32_LE (data + 8);
       
  1419         } else {
       
  1420           gst_buffer_unref (buf);
       
  1421           if ((res =
       
  1422                   gst_pad_pull_range (wav->sinkpad, wav->offset, 12,
       
  1423                       &buf)) != GST_FLOW_OK)
       
  1424             goto header_read_error;
       
  1425           ltag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 8);
       
  1426         }
       
  1427         switch (ltag) {
       
  1428           case GST_RIFF_LIST_INFO:{
       
  1429             const guint data_size = size - 4;
       
  1430             GstTagList *new;
       
  1431 
       
  1432             GST_INFO_OBJECT (wav, "Have LIST chunk INFO size %u", data_size);
       
  1433             if (wav->streaming) {
       
  1434               gst_adapter_flush (wav->adapter, 12);
       
  1435               if (gst_adapter_available (wav->adapter) < data_size) {
       
  1436                 return GST_FLOW_OK;
       
  1437               }
       
  1438               gst_buffer_unref (buf);
       
  1439               if (data_size > 0)
       
  1440                 buf = gst_adapter_take_buffer (wav->adapter, data_size);
       
  1441             } else {
       
  1442               wav->offset += 12;
       
  1443               gst_buffer_unref (buf);
       
  1444               if (data_size > 0) {
       
  1445                 if ((res =
       
  1446                         gst_pad_pull_range (wav->sinkpad, wav->offset,
       
  1447                             data_size, &buf)) != GST_FLOW_OK)
       
  1448                   goto header_read_error;
       
  1449               }
       
  1450             }
       
  1451             if (data_size > 0) {
       
  1452               /* parse tags */
       
  1453               gst_riff_parse_info (GST_ELEMENT (wav), buf, &new);
       
  1454               if (new) {
       
  1455                 GstTagList *old = wav->tags;
       
  1456                 wav->tags =
       
  1457                     gst_tag_list_merge (old, new, GST_TAG_MERGE_REPLACE);
       
  1458                 if (old)
       
  1459                   gst_tag_list_free (old);
       
  1460                 gst_tag_list_free (new);
       
  1461               }
       
  1462               if (wav->streaming) {
       
  1463                 gst_adapter_flush (wav->adapter, data_size);
       
  1464               } else {
       
  1465                 gst_buffer_unref (buf);
       
  1466                 wav->offset += data_size;
       
  1467               }
       
  1468             }
       
  1469             break;
       
  1470           }
       
  1471           default:
       
  1472             GST_INFO_OBJECT (wav, "Ignoring LIST chunk %" GST_FOURCC_FORMAT,
       
  1473                 GST_FOURCC_ARGS (ltag));
       
  1474             gst_waveparse_ignore_chunk (wav, buf, tag, size);
       
  1475             break;
       
  1476         }
       
  1477         break;
  1153         break;
  1478       }
  1154       }
  1479       default:
  1155       default:
  1480         gst_waveparse_ignore_chunk (wav, buf, tag, size);
  1156         if (wav->streaming) {
  1481     }
  1157           if (!gst_wavparse_peek_chunk (wav, &tag, &size))
  1482 
  1158             return GST_FLOW_OK;
  1483     if (upstream_size && (wav->offset >= upstream_size)) {
  1159         }
  1484       /* Now we are gone through the whole file */
  1160         GST_DEBUG_OBJECT (wav, "Ignoring tag %" GST_FOURCC_FORMAT,
  1485       gotdata = TRUE;
  1161             GST_FOURCC_ARGS (tag));
       
  1162         wav->offset += 8 + ((size + 1) & ~1);
       
  1163         if (wav->streaming) {
       
  1164           gst_adapter_flush (wav->adapter, 8 + ((size + 1) & ~1));
       
  1165         } else {
       
  1166           gst_buffer_unref (buf);
       
  1167         }
  1486     }
  1168     }
  1487   }
  1169   }
  1488 
  1170 
  1489   GST_DEBUG_OBJECT (wav, "Finished parsing headers");
  1171   GST_DEBUG_OBJECT (wav, "Finished parsing headers");
  1490 
  1172 
  1491   if (wav->bps <= 0 && wav->fact) {
  1173   duration = gst_util_uint64_scale_int (wav->datasize, GST_SECOND, wav->bps);
  1492 #if 0
  1174   GST_DEBUG_OBJECT (wav, "Got duration %" GST_TIME_FORMAT,
  1493     /* not a good idea, as for embedded mp2/mp3 we set bps to 0 earlier */
  1175       GST_TIME_ARGS (duration));
  1494     wav->bps =
  1176   gst_segment_set_duration (&wav->segment, GST_FORMAT_TIME, duration);
  1495         (guint32) gst_util_uint64_scale ((guint64) wav->rate, wav->datasize,
       
  1496         (guint64) wav->fact);
       
  1497     GST_INFO_OBJECT (wav, "calculated bps : %d, enabling VBR", wav->bps);
       
  1498 #endif
       
  1499     wav->vbr = TRUE;
       
  1500   }
       
  1501 
       
  1502   if (gst_wavparse_calculate_duration (wav)) {
       
  1503     gst_segment_init (&wav->segment, GST_FORMAT_TIME);
       
  1504     gst_segment_set_duration (&wav->segment, GST_FORMAT_TIME, wav->duration);
       
  1505   } else {
       
  1506     /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
       
  1507     gst_segment_init (&wav->segment, GST_FORMAT_BYTES);
       
  1508     gst_segment_set_duration (&wav->segment, GST_FORMAT_BYTES, wav->datasize);
       
  1509   }
       
  1510 
  1177 
  1511   /* now we have all the info to perform a pending seek if any, if no
  1178   /* now we have all the info to perform a pending seek if any, if no
  1512    * event, this will still do the right thing and it will also send
  1179    * event, this will still do the right thing and it will also send
  1513    * the right newsegment event downstream. */
  1180    * the right newsegment event downstream. */
  1514   gst_wavparse_perform_seek (wav, wav->seek_event);
  1181   gst_wavparse_perform_seek (wav, wav->seek_event);
  1515   /* remove pending event */
  1182   /* remove pending event */
  1516   event_p = &wav->seek_event;
  1183   event_p = &wav->seek_event;
  1517   gst_event_replace (event_p, NULL);
  1184   gst_event_replace (event_p, NULL);
  1518 
  1185 
  1519   /* we just started, we are discont */
       
  1520   wav->discont = TRUE;
       
  1521 
       
  1522   wav->state = GST_WAVPARSE_DATA;
  1186   wav->state = GST_WAVPARSE_DATA;
  1523 
  1187 
  1524   return GST_FLOW_OK;
  1188   return GST_FLOW_OK;
  1525 
  1189 
  1526   /* ERROR */
  1190   /* ERROR */
  1527 invalid_wav:
  1191 invalid_wav:
  1528   {
  1192   {
  1529     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
  1193     GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
  1530         ("Invalid WAV header (no fmt at start): %"
  1194         ("Invalid WAV header (no fmt at start): %"
  1531             GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
  1195             GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
  1532     g_free (codec_name);
  1196     g_free (codec_name);
       
  1197 
  1533     return GST_FLOW_ERROR;
  1198     return GST_FLOW_ERROR;
  1534   }
  1199   }
  1535 parse_header_error:
  1200 parse_header_error:
  1536   {
  1201   {
  1537     GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
  1202     GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
  1538         ("Couldn't parse audio header"));
  1203         ("Couldn't parse audio header"));
       
  1204     gst_buffer_unref (buf);
  1539     g_free (codec_name);
  1205     g_free (codec_name);
       
  1206  
  1540     return GST_FLOW_ERROR;
  1207     return GST_FLOW_ERROR;
  1541   }
  1208   }
  1542 no_channels:
  1209 no_channels:
  1543   {
  1210   {
  1544     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
  1211     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
  1545         ("Stream claims to contain no channels - invalid data"));
  1212         ("Stream claims to contain no channels - invalid data"));
  1546     g_free (header);
  1213     g_free (header);
  1547     g_free (codec_name);
  1214     g_free (codec_name);
  1548     return GST_FLOW_ERROR;
  1215     return GST_FLOW_ERROR;
  1549   }
  1216   }
  1550 no_rate:
  1217 no_bitrate:
  1551   {
  1218   {
  1552     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
  1219     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
  1553         ("Stream with sample_rate == 0 - invalid data"));
  1220         ("Stream claims to have a bitrate of <= zero - invalid data"));
  1554     g_free (header);
  1221     g_free (header);
  1555     g_free (codec_name);
  1222     g_free (codec_name);
  1556     return GST_FLOW_ERROR;
  1223     return GST_FLOW_ERROR;
  1557   }
  1224   }
  1558 invalid_blockalign:
       
  1559   {
       
  1560     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
       
  1561         ("Stream claims blockalign = %u, which is more than %u - invalid data",
       
  1562             wav->blockalign, wav->channels * (guint) ceil (wav->depth / 8.0)));
       
  1563     g_free (codec_name);
       
  1564     return GST_FLOW_ERROR;
       
  1565   }
       
  1566 invalid_bps:
       
  1567   {
       
  1568     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
       
  1569         ("Stream claims av_bsp = %u, which is more than %u - invalid data",
       
  1570             wav->av_bps, wav->blockalign * wav->rate));
       
  1571     g_free (codec_name);
       
  1572     return GST_FLOW_ERROR;
       
  1573   }
       
  1574 no_bytes_per_sample:
  1225 no_bytes_per_sample:
  1575   {
  1226   {
  1576     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
  1227     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
  1577         ("Could not caluclate bytes per sample - invalid data"));
  1228         ("could not caluclate bytes per sample - invalid data"));
       
  1229     g_free (header);
  1578     g_free (codec_name);
  1230     g_free (codec_name);
  1579     return GST_FLOW_ERROR;
  1231     return GST_FLOW_ERROR;
  1580   }
  1232   }
  1581 unknown_format:
  1233 unknown_format:
  1582   {
  1234   {
  1583     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
  1235     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
  1584         ("No caps found for format 0x%x, %d channels, %d Hz",
  1236         ("No caps found for format 0x%x, %d channels, %d Hz",
  1585             wav->format, wav->channels, wav->rate));
  1237             wav->format, wav->channels, wav->rate));
  1586     g_free (header);
       
  1587     g_free (codec_name);
  1238     g_free (codec_name);
  1588     return GST_FLOW_ERROR;
  1239     return GST_FLOW_ERROR;
  1589   }
  1240   }
  1590 header_read_error:
  1241 header_read_error:
  1591   {
  1242   {
  1592     GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
  1243     GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL), ("Couldn't read in header"));
  1593         ("Couldn't read in header %d (%s)", res, gst_flow_get_name (res)));
       
  1594     g_free (codec_name);
  1244     g_free (codec_name);
  1595     return GST_FLOW_ERROR;
  1245     return GST_FLOW_ERROR;
  1596   }
  1246   }
  1597 }
  1247 }
  1598 
  1248 
  1599 /*
  1249 
       
  1250 /*                       
  1600  * Read WAV file tag when streaming
  1251  * Read WAV file tag when streaming
  1601  */
  1252  */
  1602 static GstFlowReturn
  1253 static GstFlowReturn
  1603 gst_wavparse_parse_stream_init (GstWavParse * wav)
  1254 gst_wavparse_parse_stream_init (GstWavParse * wav)
  1604 {
  1255 {
  1605   if (gst_adapter_available (wav->adapter) >= 12) {
  1256   if (gst_adapter_available (wav->adapter) >= 12) {
  1606     GstBuffer *tmp;
  1257     GstBuffer *tmp = gst_buffer_new ();
  1607 
  1258 
  1608     /* _take flushes the data */
  1259     /* _take flushes the data */
  1609     tmp = gst_adapter_take_buffer (wav->adapter, 12);
  1260     GST_BUFFER_DATA (tmp) = gst_adapter_take (wav->adapter, 12);
       
  1261     GST_BUFFER_SIZE (tmp) = 12;
  1610 
  1262 
  1611     GST_DEBUG ("Parsing wav header");
  1263     GST_DEBUG ("Parsing wav header");
  1612     if (!gst_wavparse_parse_file_header (GST_ELEMENT_CAST (wav), tmp))
  1264     if (!gst_wavparse_parse_file_header (GST_ELEMENT (wav), tmp)) {
  1613       return GST_FLOW_ERROR;
  1265       return GST_FLOW_ERROR;
       
  1266     }
  1614 
  1267 
  1615     wav->offset += 12;
  1268     wav->offset += 12;
  1616     /* Go to next state */
  1269     /* Go to next state */
  1617     wav->state = GST_WAVPARSE_HEADER;
  1270     wav->state = GST_WAVPARSE_HEADER;
  1618   }
  1271   }
  1667 gst_wavparse_add_src_pad (GstWavParse * wav, GstBuffer * buf)
  1320 gst_wavparse_add_src_pad (GstWavParse * wav, GstBuffer * buf)
  1668 {
  1321 {
  1669   GstStructure *s;
  1322   GstStructure *s;
  1670   const guint8 dts_marker[] = { 0xFF, 0x1F, 0x00, 0xE8, 0xF1, 0x07 };
  1323   const guint8 dts_marker[] = { 0xFF, 0x1F, 0x00, 0xE8, 0xF1, 0x07 };
  1671 
  1324 
  1672   GST_DEBUG_OBJECT (wav, "adding src pad");
  1325   
  1673 
  1326   s = gst_caps_get_structure (wav->caps, 0);
  1674   if (wav->caps) {
  1327   if (gst_structure_has_name (s, "audio/x-raw-int") &&
  1675     s = gst_caps_get_structure (wav->caps, 0);
  1328       GST_BUFFER_SIZE (buf) > 6 &&
  1676     if (s && gst_structure_has_name (s, "audio/x-raw-int") && buf &&
  1329       memcmp (GST_BUFFER_DATA (buf), dts_marker, 6) == 0) {
  1677         GST_BUFFER_SIZE (buf) > 6 &&
  1330 
  1678         memcmp (GST_BUFFER_DATA (buf), dts_marker, 6) == 0) {
  1331     GST_WARNING_OBJECT (wav, "Found DTS marker in file marked as raw PCM");
  1679 
  1332     gst_caps_unref (wav->caps);
  1680       GST_WARNING_OBJECT (wav, "Found DTS marker in file marked as raw PCM");
  1333     wav->caps = gst_caps_from_string ("audio/x-dts");
  1681       gst_caps_unref (wav->caps);
  1334 
  1682       wav->caps = gst_caps_from_string ("audio/x-dts");
  1335     gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
  1683 
  1336         GST_TAG_AUDIO_CODEC, "dts", NULL);
  1684       gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
  1337   
  1685           GST_TAG_AUDIO_CODEC, "dts", NULL);
       
  1686     }
       
  1687   }
  1338   }
  1688 
  1339 
  1689   gst_wavparse_create_sourcepad (wav);
  1340   gst_wavparse_create_sourcepad (wav);
  1690   gst_pad_set_active (wav->srcpad, TRUE);
  1341   gst_pad_set_active (wav->srcpad, TRUE);
  1691   gst_pad_set_caps (wav->srcpad, wav->caps);
  1342   gst_pad_set_caps (wav->srcpad, wav->caps);
  1692   gst_caps_replace (&wav->caps, NULL);
  1343   gst_caps_replace (&wav->caps, NULL);
  1693 
  1344 
  1694   gst_element_add_pad (GST_ELEMENT_CAST (wav), wav->srcpad);
  1345   gst_element_add_pad (GST_ELEMENT (wav), wav->srcpad);
  1695   gst_element_no_more_pads (GST_ELEMENT_CAST (wav));
  1346    
  1696 
  1347 
  1697   if (wav->close_segment) {
  1348   gst_element_no_more_pads (GST_ELEMENT (wav));
  1698     GST_DEBUG_OBJECT (wav, "Send close segment event on newpad");
  1349 
  1699     gst_pad_push_event (wav->srcpad, wav->close_segment);
  1350   GST_DEBUG_OBJECT (wav, "Send newsegment event on newpad");
  1700     wav->close_segment = NULL;
  1351   gst_pad_push_event (wav->srcpad, wav->newsegment);
  1701   }
  1352   wav->newsegment = NULL;
  1702   if (wav->start_segment) {
  1353 
  1703     GST_DEBUG_OBJECT (wav, "Send start segment event on newpad");
  1354   
  1704     gst_pad_push_event (wav->srcpad, wav->start_segment);
       
  1705     wav->start_segment = NULL;
       
  1706   }
       
  1707 
       
  1708   if (wav->tags) {
  1355   if (wav->tags) {
  1709     gst_element_found_tags_for_pad (GST_ELEMENT_CAST (wav), wav->srcpad,
  1356     gst_element_found_tags_for_pad (GST_ELEMENT (wav), wav->srcpad, wav->tags);
  1710         wav->tags);
       
  1711     wav->tags = NULL;
  1357     wav->tags = NULL;
  1712   }
  1358   }
       
  1359 
  1713 }
  1360 }
  1714 
  1361 
  1715 #define MAX_BUFFER_SIZE 4096
  1362 #define MAX_BUFFER_SIZE 4096
  1716 
  1363 
  1717 static GstFlowReturn
  1364 static GstFlowReturn
  1718 gst_wavparse_stream_data (GstWavParse * wav)
  1365 gst_wavparse_stream_data (GstWavParse * wav)
  1719 {
  1366 {
  1720   GstBuffer *buf = NULL;
  1367   GstBuffer *buf = NULL;
  1721   GstFlowReturn res = GST_FLOW_OK;
  1368   GstFlowReturn res = GST_FLOW_OK;
  1722   guint64 desired, obtained;
  1369   guint64 desired, obtained;
  1723   GstClockTime timestamp, next_timestamp, duration;
  1370   GstClockTime timestamp, next_timestamp;
  1724   guint64 pos, nextpos;
  1371   guint64 pos, nextpos;
  1725 
  1372 
       
  1373  
  1726 iterate_adapter:
  1374 iterate_adapter:
  1727   GST_LOG_OBJECT (wav,
  1375   GST_LOG_OBJECT (wav,
  1728       "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
  1376       "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
  1729       G_GINT64_FORMAT, wav->offset, wav->end_offset, wav->dataleft);
  1377       G_GINT64_FORMAT, wav->offset, wav->end_offset, wav->dataleft);
  1730 
  1378 
  1734 
  1382 
  1735   /* scale the amount of data by the segment rate so we get equal
  1383   /* scale the amount of data by the segment rate so we get equal
  1736    * amounts of data regardless of the playback rate */
  1384    * amounts of data regardless of the playback rate */
  1737   desired =
  1385   desired =
  1738       MIN (gst_guint64_to_gdouble (wav->dataleft),
  1386       MIN (gst_guint64_to_gdouble (wav->dataleft),
  1739       MAX_BUFFER_SIZE * wav->segment.abs_rate);
  1387       MAX_BUFFER_SIZE * ABS (wav->segment.rate));
  1740 
       
  1741   if (desired >= wav->blockalign && wav->blockalign > 0)
  1388   if (desired >= wav->blockalign && wav->blockalign > 0)
  1742     desired -= (desired % wav->blockalign);
  1389     desired -= (desired % wav->blockalign);
  1743 
  1390 
       
  1391   
  1744   GST_LOG_OBJECT (wav, "Fetching %" G_GINT64_FORMAT " bytes of data "
  1392   GST_LOG_OBJECT (wav, "Fetching %" G_GINT64_FORMAT " bytes of data "
  1745       "from the sinkpad", desired);
  1393       "from the sinkpad", desired);
  1746 
  1394 
  1747   if (wav->streaming) {
  1395   if (wav->streaming) {
  1748     guint avail = gst_adapter_available (wav->adapter);
  1396     guint avail = gst_adapter_available (wav->adapter);
  1749     guint extra;
  1397      
  1750 
       
  1751     /* flush some bytes if evil upstream sends segment that starts
       
  1752      * before data or does is not send sample aligned segment */
       
  1753     if (G_LIKELY (wav->offset >= wav->datastart)) {
       
  1754       extra = (wav->offset - wav->datastart) % wav->bytes_per_sample;
       
  1755     } else {
       
  1756       extra = wav->datastart - wav->offset;
       
  1757     }
       
  1758 
       
  1759     if (G_UNLIKELY (extra)) {
       
  1760       extra = wav->bytes_per_sample - extra;
       
  1761       if (extra <= avail) {
       
  1762         GST_DEBUG_OBJECT (wav, "flushing %d bytes to sample boundary", extra);
       
  1763         gst_adapter_flush (wav->adapter, extra);
       
  1764         wav->offset += extra;
       
  1765         wav->dataleft -= extra;
       
  1766         goto iterate_adapter;
       
  1767       } else {
       
  1768         GST_DEBUG_OBJECT (wav, "flushing %d bytes", avail);
       
  1769         gst_adapter_clear (wav->adapter);
       
  1770         wav->offset += avail;
       
  1771         wav->dataleft -= avail;
       
  1772         return GST_FLOW_OK;
       
  1773       }
       
  1774     }
       
  1775 
       
  1776     if (avail < desired) {
  1398     if (avail < desired) {
       
  1399    
  1777       GST_LOG_OBJECT (wav, "Got only %d bytes of data from the sinkpad", avail);
  1400       GST_LOG_OBJECT (wav, "Got only %d bytes of data from the sinkpad", avail);
  1778       return GST_FLOW_OK;
  1401       return GST_FLOW_OK;
  1779     }
  1402     }
  1780 
  1403 
  1781     buf = gst_adapter_take_buffer (wav->adapter, desired);
  1404     buf = gst_buffer_new ();
       
  1405     GST_BUFFER_DATA (buf) = gst_adapter_take (wav->adapter, desired);
       
  1406     GST_BUFFER_SIZE (buf) = desired;
       
  1407 
       
  1408     
  1782   } else {
  1409   } else {
  1783     if ((res = gst_pad_pull_range (wav->sinkpad, wav->offset,
  1410     if ((res = gst_pad_pull_range (wav->sinkpad, wav->offset,
  1784                 desired, &buf)) != GST_FLOW_OK)
  1411                 desired, &buf)) != GST_FLOW_OK)
       
  1412         {
       
  1413    
  1785       goto pull_error;
  1414       goto pull_error;
       
  1415         }
       
  1416 
  1786   }
  1417   }
  1787 
  1418 
  1788   /* first chunk of data? create the source pad. We do this only here so
  1419   /* first chunk of data? create the source pad. We do this only here so
  1789    * we can detect broken .wav files with dts disguised as raw PCM (sigh) */
  1420    * we can detect broken .wav files with dts disguised as raw PCM (sigh) */
  1790   if (G_UNLIKELY (wav->first)) {
  1421   if (G_UNLIKELY (wav->first)) {
  1791     wav->first = FALSE;
  1422     wav->first = FALSE;
  1792     /* this will also push the segment events */
  1423 
  1793     gst_wavparse_add_src_pad (wav, buf);
  1424     gst_wavparse_add_src_pad (wav, buf);
  1794   } else {
       
  1795     /* If we have a pending close/start segment, send it now. */
       
  1796     if (G_UNLIKELY (wav->close_segment != NULL)) {
       
  1797       gst_pad_push_event (wav->srcpad, wav->close_segment);
       
  1798       wav->close_segment = NULL;
       
  1799     }
       
  1800     if (G_UNLIKELY (wav->start_segment != NULL)) {
       
  1801       gst_pad_push_event (wav->srcpad, wav->start_segment);
       
  1802       wav->start_segment = NULL;
       
  1803     }
       
  1804   }
  1425   }
  1805 
  1426 
  1806   obtained = GST_BUFFER_SIZE (buf);
  1427   obtained = GST_BUFFER_SIZE (buf);
  1807 
  1428 
  1808   /* our positions in bytes */
  1429   /* our positions */
  1809   pos = wav->offset - wav->datastart;
  1430   pos = wav->offset - wav->datastart;
  1810   nextpos = pos + obtained;
  1431   nextpos = pos + obtained;
  1811 
  1432 
  1812   /* update offsets, does not overflow. */
  1433   /* update offsets, does not overflow. */
  1813   GST_BUFFER_OFFSET (buf) = pos / wav->bytes_per_sample;
  1434   GST_BUFFER_OFFSET (buf) = pos / wav->bytes_per_sample;
  1814   GST_BUFFER_OFFSET_END (buf) = nextpos / wav->bytes_per_sample;
  1435   GST_BUFFER_OFFSET_END (buf) = nextpos / wav->bytes_per_sample;
  1815 
  1436 
  1816   if (wav->bps > 0) {
  1437   /* and timestamps, be carefull for overflows */
  1817     /* and timestamps if we have a bitrate, be careful for overflows */
  1438   timestamp = gst_util_uint64_scale_int (pos, GST_SECOND, wav->bps);
  1818     timestamp = uint64_ceiling_scale (pos, GST_SECOND, (guint64) wav->bps);
  1439   next_timestamp = gst_util_uint64_scale_int (nextpos, GST_SECOND, wav->bps);
  1819     next_timestamp =
       
  1820         uint64_ceiling_scale (nextpos, GST_SECOND, (guint64) wav->bps);
       
  1821     duration = next_timestamp - timestamp;
       
  1822 
       
  1823     /* update current running segment position */
       
  1824     gst_segment_set_last_stop (&wav->segment, GST_FORMAT_TIME, next_timestamp);
       
  1825   } else if (wav->fact) {
       
  1826     guint64 bps =
       
  1827         gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
       
  1828     /* and timestamps if we have a bitrate, be careful for overflows */
       
  1829     timestamp = uint64_ceiling_scale (pos, GST_SECOND, bps);
       
  1830     next_timestamp = uint64_ceiling_scale (nextpos, GST_SECOND, bps);
       
  1831     duration = next_timestamp - timestamp;
       
  1832   } else {
       
  1833     /* no bitrate, all we know is that the first sample has timestamp 0, all
       
  1834      * other positions and durations have unknown timestamp. */
       
  1835     if (pos == 0)
       
  1836       timestamp = 0;
       
  1837     else
       
  1838       timestamp = GST_CLOCK_TIME_NONE;
       
  1839     duration = GST_CLOCK_TIME_NONE;
       
  1840     /* update current running segment position with byte offset */
       
  1841     gst_segment_set_last_stop (&wav->segment, GST_FORMAT_BYTES, nextpos);
       
  1842   }
       
  1843   if ((pos > 0) && wav->vbr) {
       
  1844     /* don't set timestamps for VBR files if it's not the first buffer */
       
  1845     timestamp = GST_CLOCK_TIME_NONE;
       
  1846     duration = GST_CLOCK_TIME_NONE;
       
  1847   }
       
  1848   if (wav->discont) {
       
  1849     GST_DEBUG_OBJECT (wav, "marking DISCONT");
       
  1850     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
       
  1851     wav->discont = FALSE;
       
  1852   }
       
  1853 
  1440 
  1854   GST_BUFFER_TIMESTAMP (buf) = timestamp;
  1441   GST_BUFFER_TIMESTAMP (buf) = timestamp;
  1855   GST_BUFFER_DURATION (buf) = duration;
  1442   GST_BUFFER_DURATION (buf) = next_timestamp - timestamp;
       
  1443 
       
  1444   /* update current running segment position */
       
  1445   gst_segment_set_last_stop (&wav->segment, GST_FORMAT_TIME, next_timestamp);
  1856 
  1446 
  1857   /* don't forget to set the caps on the buffer */
  1447   /* don't forget to set the caps on the buffer */
  1858   gst_buffer_set_caps (buf, GST_PAD_CAPS (wav->srcpad));
  1448   gst_buffer_set_caps (buf, GST_PAD_CAPS (wav->srcpad));
  1859 
  1449 
  1860   GST_LOG_OBJECT (wav,
  1450   GST_LOG_OBJECT (wav,
  1861       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
  1451       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
  1862       ", size:%u", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration),
  1452       ", size:%u", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
  1863       GST_BUFFER_SIZE (buf));
  1453       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_SIZE (buf));
  1864 
  1454   
       
  1455      
  1865   if ((res = gst_pad_push (wav->srcpad, buf)) != GST_FLOW_OK)
  1456   if ((res = gst_pad_push (wav->srcpad, buf)) != GST_FLOW_OK)
       
  1457       {
       
  1458 
  1866     goto push_error;
  1459     goto push_error;
  1867 
  1460       }
       
  1461  
       
  1462     
  1868   if (obtained < wav->dataleft) {
  1463   if (obtained < wav->dataleft) {
  1869     wav->offset += obtained;
       
  1870     wav->dataleft -= obtained;
  1464     wav->dataleft -= obtained;
  1871   } else {
  1465   } else {
  1872     wav->offset += wav->dataleft;
       
  1873     wav->dataleft = 0;
  1466     wav->dataleft = 0;
  1874   }
  1467   }
  1875 
  1468   wav->offset += obtained;
  1876   /* Iterate until need more data, so adapter size won't grow */
  1469   /* Iterate until need more data, so adapter size won't grow */
  1877   if (wav->streaming) {
  1470   if (wav->streaming) {
  1878     GST_LOG_OBJECT (wav,
  1471     GST_LOG_OBJECT (wav,
  1879         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, wav->offset,
  1472         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, wav->offset,
  1880         wav->end_offset);
  1473         wav->end_offset);
       
  1474     
  1881     goto iterate_adapter;
  1475     goto iterate_adapter;
  1882   }
  1476   }
       
  1477 
  1883   return res;
  1478   return res;
  1884 
  1479 
  1885   /* ERROR */
  1480   /* ERROR */
  1886 found_eos:
  1481 found_eos:
  1887   {
  1482   {
       
  1483 
  1888     GST_DEBUG_OBJECT (wav, "found EOS");
  1484     GST_DEBUG_OBJECT (wav, "found EOS");
  1889     return GST_FLOW_UNEXPECTED;
  1485     /* we completed the segment */
       
  1486     wav->segment_running = FALSE;
       
  1487     if (wav->segment.flags & GST_SEEK_FLAG_SEGMENT) {
       
  1488       GstClockTime stop;
       
  1489 
       
  1490       if ((stop = wav->segment.stop) == -1)
       
  1491         stop = wav->segment.duration;
       
  1492 
       
  1493       gst_element_post_message (GST_ELEMENT (wav),
       
  1494           gst_message_new_segment_done (GST_OBJECT (wav), GST_FORMAT_TIME,
       
  1495               stop));
       
  1496 
       
  1497     } else {
       
  1498       gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
       
  1499  
       
  1500     }
       
  1501     return GST_FLOW_WRONG_STATE;
  1890   }
  1502   }
  1891 pull_error:
  1503 pull_error:
  1892   {
  1504   {
  1893     /* check if we got EOS */
  1505      
  1894     if (res == GST_FLOW_UNEXPECTED)
  1506     GST_DEBUG_OBJECT (wav, "Error getting %" G_GINT64_FORMAT " bytes from the "
  1895       goto found_eos;
       
  1896 
       
  1897     GST_WARNING_OBJECT (wav,
       
  1898         "Error getting %" G_GINT64_FORMAT " bytes from the "
       
  1899         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, wav->dataleft);
  1507         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, wav->dataleft);
  1900     return res;
  1508     return res;
  1901   }
  1509   }
  1902 push_error:
  1510 push_error:
  1903   {
  1511   {
  1904     GST_INFO_OBJECT (wav,
  1512       
  1905         "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
  1513     GST_DEBUG_OBJECT (wav, "Error pushing on srcpad");
  1906         GST_DEBUG_PAD_NAME (wav->srcpad), gst_flow_get_name (res),
       
  1907         gst_pad_is_linked (wav->srcpad));
       
  1908     return res;
  1514     return res;
  1909   }
  1515   }
  1910 }
  1516 }
  1911 
  1517 
  1912 static void
  1518 static void
  1917 
  1523 
  1918   GST_LOG_OBJECT (wav, "process data");
  1524   GST_LOG_OBJECT (wav, "process data");
  1919 
  1525 
  1920   switch (wav->state) {
  1526   switch (wav->state) {
  1921     case GST_WAVPARSE_START:
  1527     case GST_WAVPARSE_START:
  1922       GST_INFO_OBJECT (wav, "GST_WAVPARSE_START");
  1528       GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_START");
  1923       if ((ret = gst_wavparse_stream_init (wav)) != GST_FLOW_OK)
  1529       if ((ret = gst_wavparse_stream_init (wav)) != GST_FLOW_OK)
  1924         goto pause;
  1530         goto pause;
  1925 
  1531       
  1926       wav->state = GST_WAVPARSE_HEADER;
  1532       wav->state = GST_WAVPARSE_HEADER;
  1927       /* fall-through */
  1533       /* fall-through */
  1928 
  1534 
  1929     case GST_WAVPARSE_HEADER:
  1535     case GST_WAVPARSE_HEADER:
  1930       GST_INFO_OBJECT (wav, "GST_WAVPARSE_HEADER");
  1536       GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_HEADER");
  1931       if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
  1537       if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
  1932         goto pause;
  1538         goto pause;
  1933 
  1539 
  1934       wav->state = GST_WAVPARSE_DATA;
  1540       wav->state = GST_WAVPARSE_DATA;
  1935       GST_INFO_OBJECT (wav, "GST_WAVPARSE_DATA");
       
  1936       /* fall-through */
  1541       /* fall-through */
  1937 
  1542 
  1938     case GST_WAVPARSE_DATA:
  1543     case GST_WAVPARSE_DATA:
  1939       if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
  1544       if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
       
  1545           {
       
  1546 
  1940         goto pause;
  1547         goto pause;
  1941       break;
  1548           }
       
  1549  
       
  1550         break;
  1942     default:
  1551     default:
  1943       g_assert_not_reached ();
  1552       g_assert_not_reached ();
  1944   }
  1553   }
       
  1554  
  1945   return;
  1555   return;
  1946 
  1556 
  1947   /* ERRORS */
  1557   /* ERRORS */
  1948 pause:
  1558 pause:
  1949   {
  1559   GST_LOG_OBJECT (wav, "pausing task %d", ret);
  1950     const gchar *reason = gst_flow_get_name (ret);
  1560   gst_pad_pause_task (wav->sinkpad);
  1951 
  1561   if (GST_FLOW_IS_FATAL (ret)) {
  1952     GST_DEBUG_OBJECT (wav, "pausing task, reason %s", reason);
  1562 
  1953     wav->segment_running = FALSE;
  1563      
  1954     gst_pad_pause_task (pad);
  1564     /* for fatal errors we post an error message */
  1955 
  1565     GST_ELEMENT_ERROR (wav, STREAM, FAILED,
  1956     if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
  1566         (_("Internal data stream error.")),
  1957       if (ret == GST_FLOW_UNEXPECTED) {
  1567         ("streaming stopped, reason %s", gst_flow_get_name (ret)));
  1958         /* add pad before we perform EOS */
  1568     if (wav->srcpad != NULL)
  1959         if (G_UNLIKELY (wav->first)) {
  1569         {
  1960           wav->first = FALSE;
  1570       gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
  1961           gst_wavparse_add_src_pad (wav, NULL);
  1571            }
  1962         }
  1572   }
  1963         /* perform EOS logic */
  1573   
  1964         if (wav->segment.flags & GST_SEEK_FLAG_SEGMENT) {
       
  1965           GstClockTime stop;
       
  1966 
       
  1967           if ((stop = wav->segment.stop) == -1)
       
  1968             stop = wav->segment.duration;
       
  1969 
       
  1970           gst_element_post_message (GST_ELEMENT_CAST (wav),
       
  1971               gst_message_new_segment_done (GST_OBJECT_CAST (wav),
       
  1972                   wav->segment.format, stop));
       
  1973         } else {
       
  1974           if (wav->srcpad != NULL)
       
  1975             gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
       
  1976         }
       
  1977       } else {
       
  1978         /* for fatal errors we post an error message, post the error
       
  1979          * first so the app knows about the error first. */
       
  1980         GST_ELEMENT_ERROR (wav, STREAM, FAILED,
       
  1981             (_("Internal data flow error.")),
       
  1982             ("streaming task paused, reason %s (%d)", reason, ret));
       
  1983         if (wav->srcpad != NULL)
       
  1984           gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
       
  1985       }
       
  1986     }
       
  1987     return;
       
  1988   }
       
  1989 }
  1574 }
  1990 
  1575 
  1991 static GstFlowReturn
  1576 static GstFlowReturn
  1992 gst_wavparse_chain (GstPad * pad, GstBuffer * buf)
  1577 gst_wavparse_chain (GstPad * pad, GstBuffer * buf)
  1993 {
  1578 {
  1994   GstFlowReturn ret;
  1579   GstFlowReturn ret;
  1995   GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
  1580   GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
  1996 
  1581    GST_LOG_OBJECT (wav, "adapter_push %" G_GINT64_FORMAT " bytes",
  1997   GST_LOG_OBJECT (wav, "adapter_push %u bytes", GST_BUFFER_SIZE (buf));
  1582       GST_BUFFER_SIZE (buf));
  1998 
  1583 
  1999   gst_adapter_push (wav->adapter, buf);
  1584   gst_adapter_push (wav->adapter, buf);
  2000 
       
  2001   switch (wav->state) {
  1585   switch (wav->state) {
  2002     case GST_WAVPARSE_START:
  1586     case GST_WAVPARSE_START:
  2003       GST_INFO_OBJECT (wav, "GST_WAVPARSE_START");
  1587       GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_START");
  2004       if ((ret = gst_wavparse_parse_stream_init (wav)) != GST_FLOW_OK)
  1588       if ((ret = gst_wavparse_parse_stream_init (wav)) != GST_FLOW_OK) 
  2005         goto done;
  1589       {
  2006 
  1590    
  2007       if (wav->state != GST_WAVPARSE_HEADER)
  1591         goto pause;
  2008         break;
  1592 			}
  2009 
  1593 			
  2010       /* otherwise fall-through */
  1594       wav->state = GST_WAVPARSE_HEADER;
       
  1595       /* fall-through */
       
  1596 
  2011     case GST_WAVPARSE_HEADER:
  1597     case GST_WAVPARSE_HEADER:
  2012       GST_INFO_OBJECT (wav, "GST_WAVPARSE_HEADER");
  1598       GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_HEADER");
  2013       if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
  1599       if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
  2014         goto done;
  1600         goto pause;
  2015 
  1601 		
  2016       if (!wav->got_fmt || wav->datastart == 0)
       
  2017         break;
       
  2018 
       
  2019       wav->state = GST_WAVPARSE_DATA;
  1602       wav->state = GST_WAVPARSE_DATA;
  2020       GST_INFO_OBJECT (wav, "GST_WAVPARSE_DATA");
       
  2021 
       
  2022       /* fall-through */
  1603       /* fall-through */
       
  1604 
  2023     case GST_WAVPARSE_DATA:
  1605     case GST_WAVPARSE_DATA:
  2024       if (buf && GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))
       
  2025         wav->discont = TRUE;
       
  2026       if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
  1606       if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
  2027         goto done;
  1607       {
  2028       break;
  1608  
       
  1609         goto pause;
       
  1610       }
       
  1611 
       
  1612       break;
       
  1613 
  2029     default:
  1614     default:
  2030       g_return_val_if_reached (GST_FLOW_ERROR);
  1615       g_assert_not_reached ();
  2031   }
  1616   }
  2032 done:
  1617 	
  2033   return ret;
  1618   return ret;
  2034 }
  1619 
  2035 
  1620 pause:
  2036 static GstFlowReturn
  1621 
  2037 gst_wavparse_flush_data (GstWavParse * wav)
  1622   GST_LOG_OBJECT (wav, "pausing task %d", ret);
  2038 {
  1623   gst_pad_pause_task (wav->sinkpad);
  2039   GstFlowReturn ret = GST_FLOW_OK;
  1624   if (GST_FLOW_IS_FATAL (ret)) {
  2040   guint av;
  1625     /* for fatal errors we post an error message */
  2041 
  1626  
  2042   if ((av = gst_adapter_available (wav->adapter)) > 0) {
  1627     GST_ELEMENT_ERROR (wav, STREAM, FAILED,
  2043     wav->dataleft = av;
  1628         (_("Internal data stream error.")),
  2044     wav->end_offset = wav->offset + av;
  1629         ("streaming stopped, reason %s", gst_flow_get_name (ret)));
  2045     ret = gst_wavparse_stream_data (wav);
  1630     if (wav->srcpad != NULL)
  2046   }
       
  2047 
       
  2048   return ret;
       
  2049 }
       
  2050 
       
  2051 static gboolean
       
  2052 gst_wavparse_sink_event (GstPad * pad, GstEvent * event)
       
  2053 {
       
  2054   GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
       
  2055   gboolean ret = TRUE;
       
  2056 
       
  2057   GST_LOG_OBJECT (wav, "handling %s event", GST_EVENT_TYPE_NAME (event));
       
  2058 
       
  2059   switch (GST_EVENT_TYPE (event)) {
       
  2060     case GST_EVENT_NEWSEGMENT:
       
  2061     {
  1631     {
  2062       GstFormat format;
  1632       gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
  2063       gdouble rate, arate;
  1633   	
  2064       gint64 start, stop, time, offset = 0, end_offset = -1;
  1634   	}
  2065       gboolean update;
       
  2066       GstSegment segment;
       
  2067 
       
  2068       /* some debug output */
       
  2069       gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
       
  2070       gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
       
  2071           &start, &stop, &time);
       
  2072       gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
       
  2073           start, stop, time);
       
  2074       GST_DEBUG_OBJECT (wav,
       
  2075           "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
       
  2076           &segment);
       
  2077 
       
  2078       if (wav->state != GST_WAVPARSE_DATA) {
       
  2079         GST_DEBUG_OBJECT (wav, "still starting, eating event");
       
  2080         goto exit;
       
  2081       }
       
  2082 
       
  2083       /* now we are either committed to TIME or BYTE format,
       
  2084        * and we only expect a BYTE segment, e.g. following a seek */
       
  2085       if (format == GST_FORMAT_BYTES) {
       
  2086         if (start > 0) {
       
  2087           offset = start;
       
  2088           start -= wav->datastart;
       
  2089           start = MAX (start, 0);
       
  2090         }
       
  2091         if (stop > 0) {
       
  2092           end_offset = stop;
       
  2093           stop -= wav->datastart;
       
  2094           stop = MAX (stop, 0);
       
  2095         }
       
  2096         if (wav->segment.format == GST_FORMAT_TIME) {
       
  2097           guint64 bps = wav->bps;
       
  2098 
       
  2099           /* operating in format TIME, so we can convert */
       
  2100           if (!bps && wav->fact)
       
  2101             bps =
       
  2102                 gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
       
  2103           if (bps) {
       
  2104             if (start >= 0)
       
  2105               start =
       
  2106                   uint64_ceiling_scale (start, GST_SECOND, (guint64) wav->bps);
       
  2107             if (stop >= 0)
       
  2108               stop =
       
  2109                   uint64_ceiling_scale (stop, GST_SECOND, (guint64) wav->bps);
       
  2110           }
       
  2111         }
       
  2112       } else {
       
  2113         GST_DEBUG_OBJECT (wav, "unsupported segment format, ignoring");
       
  2114         goto exit;
       
  2115       }
       
  2116 
       
  2117       /* accept upstream's notion of segment and distribute along */
       
  2118       gst_segment_set_newsegment_full (&wav->segment, update, rate, arate,
       
  2119           wav->segment.format, start, stop, start);
       
  2120       /* also store the newsegment event for the streaming thread */
       
  2121       if (wav->start_segment)
       
  2122         gst_event_unref (wav->start_segment);
       
  2123       wav->start_segment =
       
  2124           gst_event_new_new_segment_full (update, rate, arate,
       
  2125           wav->segment.format, start, stop, start);
       
  2126       GST_DEBUG_OBJECT (wav, "Pushing newseg update %d, rate %g, "
       
  2127           "applied rate %g, format %d, start %" G_GINT64_FORMAT ", "
       
  2128           "stop %" G_GINT64_FORMAT, update, rate, arate, wav->segment.format,
       
  2129           start, stop);
       
  2130 
       
  2131       /* stream leftover data in current segment */
       
  2132       gst_wavparse_flush_data (wav);
       
  2133       /* and set up streaming thread for next one */
       
  2134       wav->offset = offset;
       
  2135       wav->end_offset = end_offset;
       
  2136       if (wav->end_offset > 0) {
       
  2137         wav->dataleft = wav->end_offset - wav->offset;
       
  2138       } else {
       
  2139         /* infinity; upstream will EOS when done */
       
  2140         wav->dataleft = G_MAXUINT64;
       
  2141       }
       
  2142     exit:
       
  2143       gst_event_unref (event);
       
  2144       break;
       
  2145     }
       
  2146     case GST_EVENT_EOS:
       
  2147       /* stream leftover data in current segment */
       
  2148       gst_wavparse_flush_data (wav);
       
  2149       /* fall-through */
       
  2150     case GST_EVENT_FLUSH_STOP:
       
  2151       gst_adapter_clear (wav->adapter);
       
  2152       wav->discont = TRUE;
       
  2153       /* fall-through */
       
  2154     default:
       
  2155       ret = gst_pad_event_default (wav->sinkpad, event);
       
  2156       break;
       
  2157   }
  1635   }
  2158 
  1636 
  2159   return ret;
  1637   return ret;
  2160 }
  1638 }
  2161 
  1639 
  2181     GstFormat * dest_format, gint64 * dest_value)
  1659     GstFormat * dest_format, gint64 * dest_value)
  2182 {
  1660 {
  2183   GstWavParse *wavparse;
  1661   GstWavParse *wavparse;
  2184   gboolean res = TRUE;
  1662   gboolean res = TRUE;
  2185 
  1663 
  2186   wavparse = GST_WAVPARSE (GST_PAD_PARENT (pad));
  1664   wavparse = GST_WAVPARSE (gst_pad_get_parent (pad));
  2187 
  1665 
  2188   if (*dest_format == src_format) {
  1666   if (wavparse->bytes_per_sample == 0)
  2189     *dest_value = src_value;
  1667     goto no_bytes_per_sample;
  2190     return TRUE;
  1668 
  2191   }
  1669   if (wavparse->bps == 0)
  2192 
  1670     goto no_bps;
  2193   if ((wavparse->bps == 0) && !wavparse->fact)
       
  2194     goto no_bps_fact;
       
  2195 
       
  2196   GST_INFO_OBJECT (wavparse, "converting value from %s to %s",
       
  2197       gst_format_get_name (src_format), gst_format_get_name (*dest_format));
       
  2198 
  1671 
  2199   switch (src_format) {
  1672   switch (src_format) {
  2200     case GST_FORMAT_BYTES:
  1673     case GST_FORMAT_BYTES:
  2201       switch (*dest_format) {
  1674       switch (*dest_format) {
  2202         case GST_FORMAT_DEFAULT:
  1675         case GST_FORMAT_DEFAULT:
  2203           *dest_value = src_value / wavparse->bytes_per_sample;
  1676           *dest_value = src_value / wavparse->bytes_per_sample;
  2204           /* make sure we end up on a sample boundary */
       
  2205           *dest_value -= *dest_value % wavparse->bytes_per_sample;
       
  2206           break;
  1677           break;
  2207         case GST_FORMAT_TIME:
  1678         case GST_FORMAT_TIME:
  2208           /* src_value + datastart = offset */
  1679           *dest_value =
  2209           GST_INFO_OBJECT (wavparse,
  1680               gst_util_uint64_scale_int (src_value, GST_SECOND, wavparse->bps);
  2210               "src=%" G_GINT64_FORMAT ", offset=%" G_GINT64_FORMAT, src_value,
       
  2211               wavparse->offset);
       
  2212           if (wavparse->bps > 0)
       
  2213             *dest_value = uint64_ceiling_scale (src_value, GST_SECOND,
       
  2214                 (guint64) wavparse->bps);
       
  2215           else if (wavparse->fact) {
       
  2216             guint64 bps = uint64_ceiling_scale_int (wavparse->datasize,
       
  2217                 wavparse->rate, wavparse->fact);
       
  2218 
       
  2219             *dest_value = uint64_ceiling_scale_int (src_value, GST_SECOND, bps);
       
  2220           } else {
       
  2221             res = FALSE;
       
  2222           }
       
  2223           break;
  1681           break;
  2224         default:
  1682         default:
  2225           res = FALSE;
  1683           res = FALSE;
  2226           goto done;
  1684           goto done;
  2227       }
  1685       }
       
  1686       *dest_value -= *dest_value % wavparse->bytes_per_sample;
  2228       break;
  1687       break;
  2229 
  1688 
  2230     case GST_FORMAT_DEFAULT:
  1689     case GST_FORMAT_DEFAULT:
  2231       switch (*dest_format) {
  1690       switch (*dest_format) {
  2232         case GST_FORMAT_BYTES:
  1691         case GST_FORMAT_BYTES:
  2233           *dest_value = src_value * wavparse->bytes_per_sample;
  1692           *dest_value = src_value * wavparse->bytes_per_sample;
  2234           break;
  1693           break;
  2235         case GST_FORMAT_TIME:
  1694         case GST_FORMAT_TIME:
  2236           *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
  1695           *dest_value =
  2237               (guint64) wavparse->rate);
  1696               gst_util_uint64_scale_int (src_value, GST_SECOND, wavparse->rate);
  2238           break;
  1697           break;
  2239         default:
  1698         default:
  2240           res = FALSE;
  1699           res = FALSE;
  2241           goto done;
  1700           goto done;
  2242       }
  1701       }
  2243       break;
  1702       break;
  2244 
  1703 
  2245     case GST_FORMAT_TIME:
  1704     case GST_FORMAT_TIME:
  2246       switch (*dest_format) {
  1705       switch (*dest_format) {
  2247         case GST_FORMAT_BYTES:
  1706         case GST_FORMAT_BYTES:
  2248           if (wavparse->bps > 0)
       
  2249             *dest_value = gst_util_uint64_scale (src_value,
       
  2250                 (guint64) wavparse->bps, GST_SECOND);
       
  2251           else {
       
  2252             guint64 bps = gst_util_uint64_scale_int (wavparse->datasize,
       
  2253                 wavparse->rate, wavparse->fact);
       
  2254 
       
  2255             *dest_value = gst_util_uint64_scale (src_value, bps, GST_SECOND);
       
  2256           }
       
  2257           /* make sure we end up on a sample boundary */
  1707           /* make sure we end up on a sample boundary */
       
  1708           *dest_value =
       
  1709               gst_util_uint64_scale_int (src_value, wavparse->bps, GST_SECOND);
  2258           *dest_value -= *dest_value % wavparse->blockalign;
  1710           *dest_value -= *dest_value % wavparse->blockalign;
  2259           break;
  1711           break;
  2260         case GST_FORMAT_DEFAULT:
  1712         case GST_FORMAT_DEFAULT:
  2261           *dest_value = gst_util_uint64_scale (src_value,
  1713           *dest_value =
  2262               (guint64) wavparse->rate, GST_SECOND);
  1714               gst_util_uint64_scale_int (src_value, wavparse->rate, GST_SECOND);
  2263           break;
  1715           break;
  2264         default:
  1716         default:
  2265           res = FALSE;
  1717           res = FALSE;
  2266           goto done;
  1718           goto done;
  2267       }
  1719       }
  2271       res = FALSE;
  1723       res = FALSE;
  2272       goto done;
  1724       goto done;
  2273   }
  1725   }
  2274 
  1726 
  2275 done:
  1727 done:
       
  1728   gst_object_unref (wavparse);
       
  1729 
  2276   return res;
  1730   return res;
  2277 
  1731 
  2278   /* ERRORS */
  1732   /* ERRORS */
  2279 no_bps_fact:
  1733 no_bytes_per_sample:
  2280   {
  1734   {
  2281     GST_DEBUG_OBJECT (wavparse, "bps 0 or no fact chunk, cannot convert");
  1735     GST_DEBUG_OBJECT (wavparse,
       
  1736         "bytes_per_sample 0, probably an mp3 - channels %d, width %d",
       
  1737         wavparse->channels, wavparse->width);
       
  1738     res = FALSE;
       
  1739     goto done;
       
  1740   }
       
  1741 no_bps:
       
  1742   {
       
  1743     GST_DEBUG_OBJECT (wavparse, "bps 0, cannot convert");
  2282     res = FALSE;
  1744     res = FALSE;
  2283     goto done;
  1745     goto done;
  2284   }
  1746   }
  2285 }
  1747 }
  2286 
  1748 
  2289 {
  1751 {
  2290   static const GstQueryType types[] = {
  1752   static const GstQueryType types[] = {
  2291     GST_QUERY_POSITION,
  1753     GST_QUERY_POSITION,
  2292     GST_QUERY_DURATION,
  1754     GST_QUERY_DURATION,
  2293     GST_QUERY_CONVERT,
  1755     GST_QUERY_CONVERT,
  2294     GST_QUERY_SEEKING,
       
  2295     0
  1756     0
  2296   };
  1757   };
  2297 
  1758 
  2298   return types;
  1759   return types;
  2299 }
  1760 }
  2301 /* handle queries for location and length in requested format */
  1762 /* handle queries for location and length in requested format */
  2302 static gboolean
  1763 static gboolean
  2303 gst_wavparse_pad_query (GstPad * pad, GstQuery * query)
  1764 gst_wavparse_pad_query (GstPad * pad, GstQuery * query)
  2304 {
  1765 {
  2305   gboolean res = TRUE;
  1766   gboolean res = TRUE;
  2306   GstWavParse *wav = GST_WAVPARSE (gst_pad_get_parent (pad));
  1767   GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
  2307 
  1768 
  2308   /* only if we know */
  1769   /* only if we know */
  2309   if (wav->state != GST_WAVPARSE_DATA) {
  1770   if (wav->state != GST_WAVPARSE_DATA)
  2310     gst_object_unref (wav);
       
  2311     return FALSE;
  1771     return FALSE;
  2312   }
       
  2313 
       
  2314   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
       
  2315 
  1772 
  2316   switch (GST_QUERY_TYPE (query)) {
  1773   switch (GST_QUERY_TYPE (query)) {
  2317     case GST_QUERY_POSITION:
  1774     case GST_QUERY_POSITION:
  2318     {
  1775     {
  2319       gint64 curb;
  1776       gint64 curb;
  2320       gint64 cur;
  1777       gint64 cur;
  2321       GstFormat format;
  1778       GstFormat format;
  2322 
  1779       gboolean res = TRUE;
  2323       /* this is not very precise, as we have pushed severla buffer upstream for prerolling */
  1780 
  2324       curb = wav->offset - wav->datastart;
  1781       curb = wav->offset - wav->datastart;
  2325       gst_query_parse_position (query, &format, NULL);
  1782       gst_query_parse_position (query, &format, NULL);
  2326       GST_INFO_OBJECT (wav, "pos query at %" G_GINT64_FORMAT, curb);
       
  2327 
  1783 
  2328       switch (format) {
  1784       switch (format) {
  2329         case GST_FORMAT_TIME:
  1785         case GST_FORMAT_TIME:
  2330           res = gst_wavparse_pad_convert (pad, GST_FORMAT_BYTES, curb,
  1786           res &=
       
  1787               gst_wavparse_pad_convert (pad, GST_FORMAT_BYTES, curb,
  2331               &format, &cur);
  1788               &format, &cur);
  2332           break;
  1789           break;
  2333         default:
  1790         default:
  2334           format = GST_FORMAT_BYTES;
  1791           format = GST_FORMAT_BYTES;
  2335           cur = curb;
  1792           cur = curb;
  2339         gst_query_set_position (query, format, cur);
  1796         gst_query_set_position (query, format, cur);
  2340       break;
  1797       break;
  2341     }
  1798     }
  2342     case GST_QUERY_DURATION:
  1799     case GST_QUERY_DURATION:
  2343     {
  1800     {
  2344       gint64 duration = 0;
  1801       gint64 endb;
       
  1802       gint64 end;
  2345       GstFormat format;
  1803       GstFormat format;
  2346 
  1804       gboolean res = TRUE;
       
  1805 
       
  1806       endb = wav->datasize;
  2347       gst_query_parse_duration (query, &format, NULL);
  1807       gst_query_parse_duration (query, &format, NULL);
  2348 
  1808 
  2349       switch (format) {
  1809       switch (format) {
  2350         case GST_FORMAT_TIME:{
  1810         case GST_FORMAT_TIME:
  2351           if ((res = gst_wavparse_calculate_duration (wav))) {
  1811           res &=
  2352             duration = wav->duration;
  1812               gst_wavparse_pad_convert (pad, GST_FORMAT_BYTES, endb,
  2353           }
  1813               &format, &end);
  2354           break;
  1814           break;
  2355         }
       
  2356         default:
  1815         default:
  2357           format = GST_FORMAT_BYTES;
  1816           format = GST_FORMAT_BYTES;
  2358           duration = wav->datasize;
  1817           end = endb;
  2359           break;
  1818           break;
  2360       }
  1819       }
  2361       gst_query_set_duration (query, format, duration);
  1820       if (res)
       
  1821         gst_query_set_duration (query, format, end);
  2362       break;
  1822       break;
  2363     }
  1823     }
  2364     case GST_QUERY_CONVERT:
  1824     case GST_QUERY_CONVERT:
  2365     {
  1825     {
  2366       gint64 srcvalue, dstvalue;
  1826       gint64 srcvalue, dstvalue;
  2367       GstFormat srcformat, dstformat;
  1827       GstFormat srcformat, dstformat;
  2368 
  1828 
  2369       gst_query_parse_convert (query, &srcformat, &srcvalue,
  1829       gst_query_parse_convert (query, &srcformat, &srcvalue,
  2370           &dstformat, &dstvalue);
  1830           &dstformat, &dstvalue);
  2371       res = gst_wavparse_pad_convert (pad, srcformat, srcvalue,
  1831       res &=
       
  1832           gst_wavparse_pad_convert (pad, srcformat, srcvalue,
  2372           &dstformat, &dstvalue);
  1833           &dstformat, &dstvalue);
  2373       if (res)
  1834       if (res)
  2374         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
  1835         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
  2375       break;
  1836       break;
  2376     }
  1837     }
  2377     case GST_QUERY_SEEKING:{
       
  2378       GstFormat fmt;
       
  2379       gboolean seekable = FALSE;
       
  2380 
       
  2381       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
       
  2382       if (fmt == wav->segment.format) {
       
  2383         if (wav->streaming) {
       
  2384           GstQuery *q;
       
  2385 
       
  2386           q = gst_query_new_seeking (GST_FORMAT_BYTES);
       
  2387           if ((res = gst_pad_peer_query (wav->sinkpad, q))) {
       
  2388             gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
       
  2389             GST_LOG_OBJECT (wav, "upstream BYTE seekable %d", seekable);
       
  2390           }
       
  2391           gst_query_unref (q);
       
  2392         } else {
       
  2393           GST_LOG_OBJECT (wav, "looping => seekable");
       
  2394           seekable = TRUE;
       
  2395           res = TRUE;
       
  2396         }
       
  2397       } else if (fmt == GST_FORMAT_TIME) {
       
  2398         res = TRUE;
       
  2399       }
       
  2400       if (res) {
       
  2401         gst_query_set_seeking (query, fmt, seekable, 0, wav->segment.duration);
       
  2402       }
       
  2403       break;
       
  2404     }
       
  2405     default:
  1838     default:
  2406       res = gst_pad_query_default (pad, query);
  1839       res = gst_pad_query_default (pad, query);
  2407       break;
  1840       break;
  2408   }
  1841   }
  2409   gst_object_unref (wav);
       
  2410   return res;
  1842   return res;
  2411 }
  1843 }
  2412 
  1844 
  2413 static gboolean
  1845 static gboolean
  2414 gst_wavparse_srcpad_event (GstPad * pad, GstEvent * event)
  1846 gst_wavparse_srcpad_event (GstPad * pad, GstEvent * event)
  2415 {
  1847 {
  2416   GstWavParse *wavparse = GST_WAVPARSE (gst_pad_get_parent (pad));
  1848   GstWavParse *wavparse = GST_WAVPARSE (GST_PAD_PARENT (pad));
  2417   gboolean res = FALSE;
  1849   gboolean res = TRUE;
  2418 
  1850 
  2419   GST_DEBUG_OBJECT (wavparse, "%s event", GST_EVENT_TYPE_NAME (event));
  1851   GST_DEBUG_OBJECT (wavparse, "event %d, %s", GST_EVENT_TYPE (event),
       
  1852       GST_EVENT_TYPE_NAME (event));
       
  1853 
       
  1854   /* can only handle events when we are in the data state */
       
  1855   if (wavparse->state != GST_WAVPARSE_DATA)
       
  1856     return FALSE;
  2420 
  1857 
  2421   switch (GST_EVENT_TYPE (event)) {
  1858   switch (GST_EVENT_TYPE (event)) {
  2422     case GST_EVENT_SEEK:
  1859     case GST_EVENT_SEEK:
  2423       /* can only handle events when we are in the data state */
  1860     {
  2424       if (wavparse->state == GST_WAVPARSE_DATA) {
  1861       res = gst_wavparse_perform_seek (wavparse, event);
  2425         res = gst_wavparse_perform_seek (wavparse, event);
  1862       break;
  2426       }
  1863     }
  2427       gst_event_unref (event);
       
  2428       break;
       
  2429     default:
  1864     default:
  2430       res = gst_pad_push_event (wavparse->sinkpad, event);
  1865       res = FALSE;
  2431       break;
  1866       break;
  2432   }
  1867   }
  2433   gst_object_unref (wavparse);
  1868 
       
  1869   gst_event_unref (event);
       
  1870 
  2434   return res;
  1871   return res;
  2435 }
  1872 }
  2436 
  1873 
  2437 static gboolean
  1874 static gboolean
  2438 gst_wavparse_sink_activate (GstPad * sinkpad)
  1875 gst_wavparse_sink_activate (GstPad * sinkpad)
  2439 {
  1876 {
  2440   GstWavParse *wav = GST_WAVPARSE (gst_pad_get_parent (sinkpad));
  1877   GstWavParse *wav = GST_WAVPARSE (gst_pad_get_parent (sinkpad));
  2441   gboolean res;
  1878   gboolean res;
  2442 
       
  2443   if (wav->adapter)
       
  2444     gst_object_unref (wav->adapter);
       
  2445 
  1879 
  2446   if (gst_pad_check_pull_range (sinkpad)) {
  1880   if (gst_pad_check_pull_range (sinkpad)) {
  2447     GST_DEBUG ("going to pull mode");
  1881     GST_DEBUG ("going to pull mode");
  2448     wav->streaming = FALSE;
  1882     wav->streaming = FALSE;
  2449     if (wav->adapter) {
       
  2450       gst_adapter_clear (wav->adapter);
       
  2451       g_object_unref (wav->adapter);
       
  2452     }
       
  2453     wav->adapter = NULL;
  1883     wav->adapter = NULL;
  2454     res = gst_pad_activate_pull (sinkpad, TRUE);
  1884     res = gst_pad_activate_pull (sinkpad, TRUE);
  2455   } else {
  1885   } else {
  2456     GST_DEBUG ("going to push (streaming) mode");
  1886     GST_DEBUG ("going to push (streaming) mode");
  2457     wav->streaming = TRUE;
  1887     wav->streaming = TRUE;
  2458     if (wav->adapter == NULL)
  1888     wav->adapter = gst_adapter_new ();
  2459       wav->adapter = gst_adapter_new ();
       
  2460     res = gst_pad_activate_push (sinkpad, TRUE);
  1889     res = gst_pad_activate_push (sinkpad, TRUE);
  2461   }
  1890   }
  2462   gst_object_unref (wav);
  1891   gst_object_unref (wav);
  2463   return res;
  1892   return res;
  2464 }
  1893 }
  2465 
  1894 
  2466 
  1895 
  2467 static gboolean
  1896 static gboolean
  2468 gst_wavparse_sink_activate_pull (GstPad * sinkpad, gboolean active)
  1897 gst_wavparse_sink_activate_pull (GstPad * sinkpad, gboolean active)
  2469 {
  1898 {
  2470   GstWavParse *wav = GST_WAVPARSE (GST_OBJECT_PARENT (sinkpad));
  1899   GstWavParse *wav = GST_WAVPARSE (gst_pad_get_parent (sinkpad));
       
  1900 
       
  1901   GST_DEBUG_OBJECT (wav, "activating pull");
  2471 
  1902 
  2472   if (active) {
  1903   if (active) {
  2473     /* if we have a scheduler we can start the task */
  1904     /* if we have a scheduler we can start the task */
  2474     wav->segment_running = TRUE;
  1905     wav->segment_running = TRUE;
  2475     return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_wavparse_loop,
  1906     gst_pad_start_task (sinkpad, (GstTaskFunction) gst_wavparse_loop, sinkpad);
  2476         sinkpad);
       
  2477   } else {
  1907   } else {
  2478     wav->segment_running = FALSE;
  1908     gst_pad_stop_task (sinkpad);
  2479     return gst_pad_stop_task (sinkpad);
  1909   }
  2480   }
  1910   gst_object_unref (wav);
  2481 };
  1911 
       
  1912   return TRUE;
       
  1913 }
  2482 
  1914 
  2483 static GstStateChangeReturn
  1915 static GstStateChangeReturn
  2484 gst_wavparse_change_state (GstElement * element, GstStateChange transition)
  1916 gst_wavparse_change_state (GstElement * element, GstStateChange transition)
  2485 {
  1917 {
  2486   GstStateChangeReturn ret;
  1918   GstStateChangeReturn ret;
  2487   GstWavParse *wav = GST_WAVPARSE (element);
  1919   GstWavParse *wav = GST_WAVPARSE (element);
  2488 
  1920 
       
  1921   GST_DEBUG_OBJECT (wav, "changing state %s - %s",
       
  1922       gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
       
  1923       gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
       
  1924 
  2489   switch (transition) {
  1925   switch (transition) {
  2490     case GST_STATE_CHANGE_NULL_TO_READY:
  1926     case GST_STATE_CHANGE_NULL_TO_READY:
  2491       break;
  1927       break;
  2492     case GST_STATE_CHANGE_READY_TO_PAUSED:
  1928     case GST_STATE_CHANGE_READY_TO_PAUSED:
  2493       gst_wavparse_reset (wav);
  1929       gst_wavparse_reset (wav);
  2501   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  1937   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  2502 
  1938 
  2503   switch (transition) {
  1939   switch (transition) {
  2504     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
  1940     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
  2505       break;
  1941       break;
  2506     case GST_STATE_CHANGE_PAUSED_TO_READY:
  1942     case GST_STATE_CHANGE_PAUSED_TO_READY:{
       
  1943       GstEvent **event_p = &wav->seek_event;
       
  1944 
  2507       gst_wavparse_destroy_sourcepad (wav);
  1945       gst_wavparse_destroy_sourcepad (wav);
       
  1946       gst_event_replace (event_p, NULL);
  2508       gst_wavparse_reset (wav);
  1947       gst_wavparse_reset (wav);
  2509       break;
  1948       if (wav->adapter) {
       
  1949         gst_adapter_clear (wav->adapter);
       
  1950       }
       
  1951       break;
       
  1952     }
  2510     case GST_STATE_CHANGE_READY_TO_NULL:
  1953     case GST_STATE_CHANGE_READY_TO_NULL:
  2511       break;
  1954       break;
  2512     default:
  1955     default:
  2513       break;
  1956       break;
  2514   }
  1957   }
  2517 
  1960 
  2518 static gboolean
  1961 static gboolean
  2519 plugin_init (GstPlugin * plugin)
  1962 plugin_init (GstPlugin * plugin)
  2520 {
  1963 {
  2521   gst_riff_init ();
  1964   gst_riff_init ();
       
  1965 
       
  1966   GST_DEBUG_CATEGORY_INIT (wavparse_debug, "wavparse", 0, "WAV parser");
  2522 
  1967 
  2523   return gst_element_register (plugin, "wavparse", GST_RANK_PRIMARY,
  1968   return gst_element_register (plugin, "wavparse", GST_RANK_PRIMARY,
  2524       GST_TYPE_WAVPARSE);
  1969       GST_TYPE_WAVPARSE);
  2525 }
  1970 }
  2526 
  1971 
  2527 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
  1972 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
  2528     GST_VERSION_MINOR,
  1973     GST_VERSION_MINOR,
  2529     "wavparse",
  1974     "wavparse",
  2530     "Parse a .wav file into raw audio",
  1975     "Parse a .wav file into raw audio",
  2531     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
  1976     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
  2532 	
  1977 
  2533 	
  1978 
  2534 EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
  1979 EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
  2535 {
  1980 {
  2536 	return &gst_plugin_desc;
  1981 	return &gst_plugin_desc;
  2537 }
  1982 }
       
  1983