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