gst_plugins_good/gst/mpegaudioparse/gstmpegaudioparse.c
changeset 27 d43ce56a1534
parent 23 29ecd5cb86b3
child 31 aec498aab1d3
equal deleted inserted replaced
23:29ecd5cb86b3 27:d43ce56a1534
     1 /* GStreamer
       
     2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
       
     3  * Copyright (C) <2006-2007> Jan Schmidt <thaytan@mad.scientist.com>
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Library General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Library General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Library General Public
       
    16  * License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 #ifdef HAVE_CONFIG_H
       
    22 #include "../../config.h"
       
    23 #endif
       
    24 
       
    25 #include <string.h>
       
    26 
       
    27 #include "gstmpegaudioparse.h"
       
    28 
       
    29 GST_DEBUG_CATEGORY_STATIC (mp3parse_debug);
       
    30 #define GST_CAT_DEFAULT mp3parse_debug
       
    31 
       
    32 #define MP3_CHANNEL_MODE_UNKNOWN -1
       
    33 #define MP3_CHANNEL_MODE_STEREO 0
       
    34 #define MP3_CHANNEL_MODE_JOINT_STEREO 1
       
    35 #define MP3_CHANNEL_MODE_DUAL_CHANNEL 2
       
    36 #define MP3_CHANNEL_MODE_MONO 3
       
    37 
       
    38 #define CRC_UNKNOWN -1
       
    39 #define CRC_PROTECTED 0
       
    40 #define CRC_NOT_PROTECTED 1
       
    41 
       
    42 #define XING_FRAMES_FLAG     0x0001
       
    43 #define XING_BYTES_FLAG      0x0002
       
    44 #define XING_TOC_FLAG        0x0004
       
    45 #define XING_VBR_SCALE_FLAG  0x0008
       
    46 
       
    47 #ifndef GST_READ_UINT24_BE
       
    48 #define GST_READ_UINT24_BE(p) (p[2] | (p[1] << 8) | (p[0] << 16))
       
    49 #endif
       
    50 
       
    51 /* Minimum number of consecutive, valid-looking frames to consider
       
    52    for resyncing */
       
    53 #define MIN_RESYNC_FRAMES 3
       
    54 
       
    55 static inline MPEGAudioSeekEntry *
       
    56 mpeg_audio_seek_entry_new ()
       
    57 {
       
    58   return g_slice_new (MPEGAudioSeekEntry);
       
    59 }
       
    60 
       
    61 static inline void
       
    62 mpeg_audio_seek_entry_free (MPEGAudioSeekEntry * entry)
       
    63 {
       
    64   g_slice_free (MPEGAudioSeekEntry, entry);
       
    65 }
       
    66 
       
    67 /* elementfactory information */
       
    68 static GstElementDetails mp3parse_details = {
       
    69   "MPEG1 Audio Parser",
       
    70   "Codec/Parser/Audio",
       
    71   "Parses and frames mpeg1 audio streams (levels 1-3), provides seek",
       
    72   "Jan Schmidt <thaytan@mad.scientist.com>\n"
       
    73       "Erik Walthinsen <omega@cse.ogi.edu>"
       
    74 };
       
    75 
       
    76 static GstStaticPadTemplate mp3_src_template = GST_STATIC_PAD_TEMPLATE ("src",
       
    77     GST_PAD_SRC,
       
    78     GST_PAD_ALWAYS,
       
    79     GST_STATIC_CAPS ("audio/mpeg, "
       
    80         "mpegversion = (int) 1, "
       
    81         "layer = (int) [ 1, 3 ], "
       
    82         "rate = (int) [ 8000, 48000 ], channels = (int) [ 1, 2 ],"
       
    83         "parsed=(boolean) true")
       
    84     );
       
    85 
       
    86 static GstStaticPadTemplate mp3_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
       
    87     GST_PAD_SINK,
       
    88     GST_PAD_ALWAYS,
       
    89     GST_STATIC_CAPS ("audio/mpeg, mpegversion = (int) 1, parsed=(boolean)false")
       
    90     );
       
    91 
       
    92 /* GstMPEGAudioParse signals and args */
       
    93 enum
       
    94 {
       
    95   /* FILL ME */
       
    96   LAST_SIGNAL
       
    97 };
       
    98 
       
    99 enum
       
   100 {
       
   101   ARG_0,
       
   102   ARG_SKIP,
       
   103   ARG_BIT_RATE
       
   104       /* FILL ME */
       
   105 };
       
   106 
       
   107 
       
   108 static void gst_mp3parse_class_init (GstMPEGAudioParseClass * klass);
       
   109 static void gst_mp3parse_base_init (gpointer klass);
       
   110 static void gst_mp3parse_init (GstMPEGAudioParse * mp3parse,
       
   111     GstMPEGAudioParseClass * klass);
       
   112 
       
   113 static gboolean gst_mp3parse_sink_event (GstPad * pad, GstEvent * event);
       
   114 static GstFlowReturn gst_mp3parse_chain (GstPad * pad, GstBuffer * buffer);
       
   115 static gboolean mp3parse_src_query (GstPad * pad, GstQuery * query);
       
   116 static const GstQueryType *mp3parse_get_query_types (GstPad * pad);
       
   117 static gboolean mp3parse_src_event (GstPad * pad, GstEvent * event);
       
   118 
       
   119 static int head_check (GstMPEGAudioParse * mp3parse, unsigned long head);
       
   120 
       
   121 static void gst_mp3parse_dispose (GObject * object);
       
   122 static void gst_mp3parse_set_property (GObject * object, guint prop_id,
       
   123     const GValue * value, GParamSpec * pspec);
       
   124 static void gst_mp3parse_get_property (GObject * object, guint prop_id,
       
   125     GValue * value, GParamSpec * pspec);
       
   126 static GstStateChangeReturn gst_mp3parse_change_state (GstElement * element,
       
   127     GstStateChange transition);
       
   128 static GstFlowReturn
       
   129 gst_mp3parse_handle_data (GstMPEGAudioParse * mp3parse, gboolean at_eos);
       
   130 
       
   131 static gboolean mp3parse_bytepos_to_time (GstMPEGAudioParse * mp3parse,
       
   132     gint64 bytepos, GstClockTime * ts, gboolean from_total_time);
       
   133 static gboolean
       
   134 mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total);
       
   135 static gboolean
       
   136 mp3parse_total_time (GstMPEGAudioParse * mp3parse, GstClockTime * total);
       
   137 
       
   138 GST_BOILERPLATE (GstMPEGAudioParse, gst_mp3parse, GstElement, GST_TYPE_ELEMENT);
       
   139 
       
   140 #define GST_TYPE_MP3_CHANNEL_MODE (gst_mp3_channel_mode_get_type())
       
   141 
       
   142 static const GEnumValue mp3_channel_mode[] = {
       
   143   {MP3_CHANNEL_MODE_UNKNOWN, "Unknown", "unknown"},
       
   144   {MP3_CHANNEL_MODE_MONO, "Mono", "mono"},
       
   145   {MP3_CHANNEL_MODE_DUAL_CHANNEL, "Dual Channel", "dual-channel"},
       
   146   {MP3_CHANNEL_MODE_JOINT_STEREO, "Joint Stereo", "joint-stereo"},
       
   147   {MP3_CHANNEL_MODE_STEREO, "Stereo", "stereo"},
       
   148   {0, NULL, NULL},
       
   149 };
       
   150 
       
   151 static GType
       
   152 gst_mp3_channel_mode_get_type (void)
       
   153 {
       
   154   static GType mp3_channel_mode_type = 0;
       
   155 
       
   156   if (!mp3_channel_mode_type) {
       
   157     mp3_channel_mode_type =
       
   158         g_enum_register_static ("GstMp3ChannelMode", mp3_channel_mode);
       
   159   }
       
   160   return mp3_channel_mode_type;
       
   161 }
       
   162 
       
   163 static const gchar *
       
   164 gst_mp3_channel_mode_get_nick (gint mode)
       
   165 {
       
   166   guint i;
       
   167   for (i = 0; i < G_N_ELEMENTS (mp3_channel_mode); i++) {
       
   168     if (mp3_channel_mode[i].value == mode)
       
   169       return mp3_channel_mode[i].value_nick;
       
   170   }
       
   171   return NULL;
       
   172 }
       
   173 
       
   174 static const guint mp3types_bitrates[2][3][16] = {
       
   175   {
       
   176         {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
       
   177         {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
       
   178         {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
       
   179       },
       
   180   {
       
   181         {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
       
   182         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
       
   183         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
       
   184       },
       
   185 };
       
   186 
       
   187 static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
       
   188 {22050, 24000, 16000},
       
   189 {11025, 12000, 8000}
       
   190 };
       
   191 
       
   192 static inline guint
       
   193 mp3_type_frame_length_from_header (GstMPEGAudioParse * mp3parse, guint32 header,
       
   194     guint * put_version, guint * put_layer, guint * put_channels,
       
   195     guint * put_bitrate, guint * put_samplerate, guint * put_mode,
       
   196     guint * put_crc)
       
   197 {
       
   198   guint length;
       
   199   gulong mode, samplerate, bitrate, layer, channels, padding, crc;
       
   200   gulong version;
       
   201   gint lsf, mpg25;
       
   202 
       
   203   if (header & (1 << 20)) {
       
   204     lsf = (header & (1 << 19)) ? 0 : 1;
       
   205     mpg25 = 0;
       
   206   } else {
       
   207     lsf = 1;
       
   208     mpg25 = 1;
       
   209   }
       
   210 
       
   211   version = 1 + lsf + mpg25;
       
   212 
       
   213   layer = 4 - ((header >> 17) & 0x3);
       
   214 
       
   215   crc = (header >> 16) & 0x1;
       
   216 
       
   217   bitrate = (header >> 12) & 0xF;
       
   218   bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
       
   219   /* The caller has ensured we have a valid header, so bitrate can't be
       
   220      zero here. */
       
   221   g_assert (bitrate != 0);
       
   222 
       
   223   samplerate = (header >> 10) & 0x3;
       
   224   samplerate = mp3types_freqs[lsf + mpg25][samplerate];
       
   225 
       
   226   padding = (header >> 9) & 0x1;
       
   227 
       
   228   mode = (header >> 6) & 0x3;
       
   229   channels = (mode == 3) ? 1 : 2;
       
   230 
       
   231   switch (layer) {
       
   232     case 1:
       
   233       length = 4 * ((bitrate * 12) / samplerate + padding);
       
   234       break;
       
   235     case 2:
       
   236       length = (bitrate * 144) / samplerate + padding;
       
   237       break;
       
   238     default:
       
   239     case 3:
       
   240       length = (bitrate * 144) / (samplerate << lsf) + padding;
       
   241       break;
       
   242   }
       
   243 
       
   244   GST_DEBUG_OBJECT (mp3parse, "Calculated mp3 frame length of %u bytes",
       
   245       length);
       
   246   GST_DEBUG_OBJECT (mp3parse, "samplerate = %lu, bitrate = %lu, version = %lu, "
       
   247       "layer = %lu, channels = %lu, mode = %s", samplerate, bitrate, version,
       
   248       layer, channels, gst_mp3_channel_mode_get_nick (mode));
       
   249 
       
   250   if (put_version)
       
   251     *put_version = version;
       
   252   if (put_layer)
       
   253     *put_layer = layer;
       
   254   if (put_channels)
       
   255     *put_channels = channels;
       
   256   if (put_bitrate)
       
   257     *put_bitrate = bitrate;
       
   258   if (put_samplerate)
       
   259     *put_samplerate = samplerate;
       
   260   if (put_mode)
       
   261     *put_mode = mode;
       
   262   if (put_crc)
       
   263     *put_crc = crc;
       
   264 
       
   265   return length;
       
   266 }
       
   267 
       
   268 static GstCaps *
       
   269 mp3_caps_create (guint version, guint layer, guint channels, guint samplerate)
       
   270 {
       
   271   GstCaps *new;
       
   272 
       
   273   g_assert (version);
       
   274   g_assert (layer);
       
   275   g_assert (samplerate);
       
   276   g_assert (channels);
       
   277 
       
   278   new = gst_caps_new_simple ("audio/mpeg",
       
   279       "mpegversion", G_TYPE_INT, 1,
       
   280       "mpegaudioversion", G_TYPE_INT, version,
       
   281       "layer", G_TYPE_INT, layer,
       
   282       "rate", G_TYPE_INT, samplerate,
       
   283       "channels", G_TYPE_INT, channels, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
       
   284 
       
   285   return new;
       
   286 }
       
   287 
       
   288 static void
       
   289 gst_mp3parse_base_init (gpointer klass)
       
   290 {
       
   291   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
       
   292 
       
   293   gst_element_class_add_pad_template (element_class,
       
   294       gst_static_pad_template_get (&mp3_sink_template));
       
   295   gst_element_class_add_pad_template (element_class,
       
   296       gst_static_pad_template_get (&mp3_src_template));
       
   297 
       
   298   GST_DEBUG_CATEGORY_INIT (mp3parse_debug, "mp3parse", 0, "MPEG Audio Parser");
       
   299 
       
   300   gst_element_class_set_details (element_class, &mp3parse_details);
       
   301 }
       
   302 
       
   303 static void
       
   304 gst_mp3parse_class_init (GstMPEGAudioParseClass * klass)
       
   305 {
       
   306   GObjectClass *gobject_class;
       
   307   GstElementClass *gstelement_class;
       
   308 
       
   309   gobject_class = (GObjectClass *) klass;
       
   310   gstelement_class = (GstElementClass *) klass;
       
   311 
       
   312   parent_class = g_type_class_peek_parent (klass);
       
   313 
       
   314   gobject_class->set_property = gst_mp3parse_set_property;
       
   315   gobject_class->get_property = gst_mp3parse_get_property;
       
   316   gobject_class->dispose = gst_mp3parse_dispose;
       
   317 
       
   318   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SKIP,
       
   319       g_param_spec_int ("skip", "skip", "skip",
       
   320           G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
       
   321   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BIT_RATE,
       
   322       g_param_spec_int ("bitrate", "Bitrate", "Bit Rate",
       
   323           G_MININT, G_MAXINT, 0, G_PARAM_READABLE));
       
   324 
       
   325   gstelement_class->change_state = gst_mp3parse_change_state;
       
   326 
       
   327 /* register tags */
       
   328 #define GST_TAG_CRC    "has-crc"
       
   329 #define GST_TAG_MODE     "channel-mode"
       
   330 
       
   331   gst_tag_register (GST_TAG_CRC, GST_TAG_FLAG_META, G_TYPE_BOOLEAN,
       
   332       "has crc", "Using CRC", NULL);
       
   333   gst_tag_register (GST_TAG_MODE, GST_TAG_FLAG_ENCODED, G_TYPE_STRING,
       
   334       "channel mode", "MPEG audio channel mode", NULL);
       
   335 
       
   336   g_type_class_ref (GST_TYPE_MP3_CHANNEL_MODE);
       
   337 }
       
   338 
       
   339 static void
       
   340 gst_mp3parse_reset (GstMPEGAudioParse * mp3parse)
       
   341 {
       
   342   mp3parse->skip = 0;
       
   343   mp3parse->resyncing = TRUE;
       
   344   mp3parse->next_ts = GST_CLOCK_TIME_NONE;
       
   345   mp3parse->cur_offset = -1;
       
   346 
       
   347   mp3parse->sync_offset = 0;
       
   348   mp3parse->tracked_offset = 0;
       
   349   mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
       
   350   mp3parse->pending_offset = -1;
       
   351 
       
   352   gst_adapter_clear (mp3parse->adapter);
       
   353 
       
   354   mp3parse->rate = mp3parse->channels = mp3parse->layer = -1;
       
   355   mp3parse->version = 1;
       
   356   mp3parse->max_bitreservoir = GST_CLOCK_TIME_NONE;
       
   357 
       
   358   mp3parse->avg_bitrate = 0;
       
   359   mp3parse->bitrate_sum = 0;
       
   360   mp3parse->last_posted_bitrate = 0;
       
   361   mp3parse->frame_count = 0;
       
   362   mp3parse->sent_codec_tag = FALSE;
       
   363 
       
   364   mp3parse->last_posted_crc = CRC_UNKNOWN;
       
   365   mp3parse->last_posted_channel_mode = MP3_CHANNEL_MODE_UNKNOWN;
       
   366 
       
   367   mp3parse->xing_flags = 0;
       
   368   mp3parse->xing_bitrate = 0;
       
   369   mp3parse->xing_frames = 0;
       
   370   mp3parse->xing_total_time = 0;
       
   371   mp3parse->xing_bytes = 0;
       
   372   mp3parse->xing_vbr_scale = 0;
       
   373   memset (mp3parse->xing_seek_table, 0, 100);
       
   374   memset (mp3parse->xing_seek_table_inverse, 0, 256);
       
   375 
       
   376   mp3parse->vbri_bitrate = 0;
       
   377   mp3parse->vbri_frames = 0;
       
   378   mp3parse->vbri_total_time = 0;
       
   379   mp3parse->vbri_bytes = 0;
       
   380   mp3parse->vbri_seek_points = 0;
       
   381   g_free (mp3parse->vbri_seek_table);
       
   382   mp3parse->vbri_seek_table = NULL;
       
   383 
       
   384   if (mp3parse->seek_table) {
       
   385     g_list_foreach (mp3parse->seek_table, (GFunc) mpeg_audio_seek_entry_free,
       
   386         NULL);
       
   387     g_list_free (mp3parse->seek_table);
       
   388     mp3parse->seek_table = NULL;
       
   389   }
       
   390 
       
   391   g_mutex_lock (mp3parse->pending_seeks_lock);
       
   392   if (mp3parse->pending_accurate_seeks) {
       
   393     g_slist_foreach (mp3parse->pending_accurate_seeks, (GFunc) g_free, NULL);
       
   394     g_slist_free (mp3parse->pending_accurate_seeks);
       
   395     mp3parse->pending_accurate_seeks = NULL;
       
   396   }
       
   397   if (mp3parse->pending_nonaccurate_seeks) {
       
   398     g_slist_foreach (mp3parse->pending_nonaccurate_seeks, (GFunc) g_free, NULL);
       
   399     g_slist_free (mp3parse->pending_nonaccurate_seeks);
       
   400     mp3parse->pending_nonaccurate_seeks = NULL;
       
   401   }
       
   402   g_mutex_unlock (mp3parse->pending_seeks_lock);
       
   403 
       
   404   if (mp3parse->pending_segment) {
       
   405     GstEvent **eventp = &mp3parse->pending_segment;
       
   406 
       
   407     gst_event_replace (eventp, NULL);
       
   408   }
       
   409 
       
   410   mp3parse->exact_position = FALSE;
       
   411   gst_segment_init (&mp3parse->segment, GST_FORMAT_TIME);
       
   412 }
       
   413 
       
   414 static void
       
   415 gst_mp3parse_init (GstMPEGAudioParse * mp3parse, GstMPEGAudioParseClass * klass)
       
   416 {
       
   417   mp3parse->sinkpad =
       
   418       gst_pad_new_from_static_template (&mp3_sink_template, "sink");
       
   419   gst_pad_set_event_function (mp3parse->sinkpad, gst_mp3parse_sink_event);
       
   420   gst_pad_set_chain_function (mp3parse->sinkpad, gst_mp3parse_chain);
       
   421   gst_element_add_pad (GST_ELEMENT (mp3parse), mp3parse->sinkpad);
       
   422 
       
   423   mp3parse->srcpad =
       
   424       gst_pad_new_from_static_template (&mp3_src_template, "src");
       
   425   gst_pad_use_fixed_caps (mp3parse->srcpad);
       
   426   gst_pad_set_event_function (mp3parse->srcpad, mp3parse_src_event);
       
   427   gst_pad_set_query_function (mp3parse->srcpad, mp3parse_src_query);
       
   428   gst_pad_set_query_type_function (mp3parse->srcpad, mp3parse_get_query_types);
       
   429   gst_element_add_pad (GST_ELEMENT (mp3parse), mp3parse->srcpad);
       
   430 
       
   431   mp3parse->adapter = gst_adapter_new ();
       
   432   mp3parse->pending_seeks_lock = g_mutex_new ();
       
   433 
       
   434   gst_mp3parse_reset (mp3parse);
       
   435 }
       
   436 
       
   437 static void
       
   438 gst_mp3parse_dispose (GObject * object)
       
   439 {
       
   440   GstMPEGAudioParse *mp3parse = GST_MP3PARSE (object);
       
   441 
       
   442   gst_mp3parse_reset (mp3parse);
       
   443 
       
   444   if (mp3parse->adapter) {
       
   445     g_object_unref (mp3parse->adapter);
       
   446     mp3parse->adapter = NULL;
       
   447   }
       
   448   g_mutex_free (mp3parse->pending_seeks_lock);
       
   449   mp3parse->pending_seeks_lock = NULL;
       
   450 
       
   451   g_list_foreach (mp3parse->pending_events, (GFunc) gst_mini_object_unref,
       
   452       NULL);
       
   453   g_list_free (mp3parse->pending_events);
       
   454   mp3parse->pending_events = NULL;
       
   455 
       
   456   G_OBJECT_CLASS (parent_class)->dispose (object);
       
   457 }
       
   458 
       
   459 static gboolean
       
   460 gst_mp3parse_sink_event (GstPad * pad, GstEvent * event)
       
   461 {
       
   462   gboolean res = TRUE;
       
   463   GstMPEGAudioParse *mp3parse;
       
   464   GstEvent **eventp;
       
   465 
       
   466   mp3parse = GST_MP3PARSE (gst_pad_get_parent (pad));
       
   467 
       
   468   switch (GST_EVENT_TYPE (event)) {
       
   469     case GST_EVENT_NEWSEGMENT:
       
   470     {
       
   471       gdouble rate, applied_rate;
       
   472       GstFormat format;
       
   473       gint64 start, stop, pos;
       
   474       gboolean update;
       
   475       MPEGAudioPendingAccurateSeek *seek = NULL;
       
   476       GSList *node;
       
   477 
       
   478       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
       
   479           &format, &start, &stop, &pos);
       
   480 
       
   481       g_mutex_lock (mp3parse->pending_seeks_lock);
       
   482       if (format == GST_FORMAT_BYTES && mp3parse->pending_accurate_seeks) {
       
   483 
       
   484         for (node = mp3parse->pending_accurate_seeks; node; node = node->next) {
       
   485           MPEGAudioPendingAccurateSeek *tmp = node->data;
       
   486 
       
   487           if (tmp->upstream_start == pos) {
       
   488             seek = tmp;
       
   489             break;
       
   490           }
       
   491         }
       
   492         if (seek) {
       
   493           GstSegment *s = &seek->segment;
       
   494 
       
   495           event =
       
   496               gst_event_new_new_segment_full (FALSE, s->rate, s->applied_rate,
       
   497               GST_FORMAT_TIME, s->start, s->stop, s->last_stop);
       
   498 
       
   499           mp3parse->segment = seek->segment;
       
   500 
       
   501           mp3parse->resyncing = FALSE;
       
   502           mp3parse->cur_offset = pos;
       
   503           mp3parse->next_ts = seek->timestamp_start;
       
   504           mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
       
   505           mp3parse->tracked_offset = 0;
       
   506           mp3parse->sync_offset = 0;
       
   507 
       
   508           gst_event_parse_new_segment_full (event, &update, &rate,
       
   509               &applied_rate, &format, &start, &stop, &pos);
       
   510 
       
   511           GST_DEBUG_OBJECT (mp3parse,
       
   512               "Pushing accurate newseg rate %g, applied rate %g, "
       
   513               "format %d, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT
       
   514               ", pos %" G_GINT64_FORMAT, rate, applied_rate, format, start,
       
   515               stop, pos);
       
   516 
       
   517           g_free (seek);
       
   518           mp3parse->pending_accurate_seeks =
       
   519               g_slist_delete_link (mp3parse->pending_accurate_seeks, node);
       
   520 
       
   521           g_mutex_unlock (mp3parse->pending_seeks_lock);
       
   522           res = gst_pad_push_event (mp3parse->srcpad, event);
       
   523 
       
   524           return res;
       
   525         } else {
       
   526           GST_WARNING_OBJECT (mp3parse,
       
   527               "Accurate seek not possible, didn't get an appropiate upstream segment");
       
   528         }
       
   529       }
       
   530       g_mutex_unlock (mp3parse->pending_seeks_lock);
       
   531 
       
   532       mp3parse->exact_position = FALSE;
       
   533 
       
   534       if (format == GST_FORMAT_BYTES) {
       
   535         GstClockTime seg_start, seg_stop, seg_pos;
       
   536 
       
   537         /* stop time is allowed to be open-ended, but not start & pos */
       
   538         if (!mp3parse_bytepos_to_time (mp3parse, stop, &seg_stop, FALSE))
       
   539           seg_stop = GST_CLOCK_TIME_NONE;
       
   540         if (mp3parse_bytepos_to_time (mp3parse, start, &seg_start, FALSE) &&
       
   541             mp3parse_bytepos_to_time (mp3parse, pos, &seg_pos, FALSE)) {
       
   542           gst_event_unref (event);
       
   543 
       
   544           /* search the pending nonaccurate seeks */
       
   545           g_mutex_lock (mp3parse->pending_seeks_lock);
       
   546           seek = NULL;
       
   547           for (node = mp3parse->pending_nonaccurate_seeks; node;
       
   548               node = node->next) {
       
   549             MPEGAudioPendingAccurateSeek *tmp = node->data;
       
   550 
       
   551             if (tmp->upstream_start == pos) {
       
   552               seek = tmp;
       
   553               break;
       
   554             }
       
   555           }
       
   556 
       
   557           if (seek) {
       
   558             if (seek->segment.stop == -1) {
       
   559               /* corrent the segment end, because non-accurate seeks might make
       
   560                * our streaming end earlier (see bug #603695) */
       
   561               seg_stop = -1;
       
   562             }
       
   563             g_free (seek);
       
   564             mp3parse->pending_nonaccurate_seeks =
       
   565                 g_slist_delete_link (mp3parse->pending_nonaccurate_seeks, node);
       
   566           }
       
   567           g_mutex_unlock (mp3parse->pending_seeks_lock);
       
   568 
       
   569           event = gst_event_new_new_segment_full (update, rate, applied_rate,
       
   570               GST_FORMAT_TIME, seg_start, seg_stop, seg_pos);
       
   571           format = GST_FORMAT_TIME;
       
   572           GST_DEBUG_OBJECT (mp3parse, "Converted incoming segment to TIME. "
       
   573               "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
       
   574               ", pos = %" GST_TIME_FORMAT, GST_TIME_ARGS (seg_start),
       
   575               GST_TIME_ARGS (seg_stop), GST_TIME_ARGS (seg_pos));
       
   576         }
       
   577       }
       
   578 
       
   579       if (format != GST_FORMAT_TIME) {
       
   580         /* Unknown incoming segment format. Output a default open-ended 
       
   581          * TIME segment */
       
   582         gst_event_unref (event);
       
   583         event = gst_event_new_new_segment_full (update, rate, applied_rate,
       
   584             GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0);
       
   585       }
       
   586 
       
   587       mp3parse->resyncing = TRUE;
       
   588       mp3parse->cur_offset = -1;
       
   589       mp3parse->next_ts = GST_CLOCK_TIME_NONE;
       
   590       mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
       
   591       mp3parse->tracked_offset = 0;
       
   592       mp3parse->sync_offset = 0;
       
   593       /* also clear leftover data if clearing so much state */
       
   594       gst_adapter_clear (mp3parse->adapter);
       
   595 
       
   596       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
       
   597           &format, &start, &stop, &pos);
       
   598       GST_DEBUG_OBJECT (mp3parse, "Pushing newseg rate %g, applied rate %g, "
       
   599           "format %d, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT
       
   600           ", pos %" G_GINT64_FORMAT, rate, applied_rate, format, start, stop,
       
   601           pos);
       
   602 
       
   603       gst_segment_set_newsegment_full (&mp3parse->segment, update, rate,
       
   604           applied_rate, format, start, stop, pos);
       
   605 
       
   606       /* save the segment for later, right before we push a new buffer so that
       
   607        * the caps are fixed and the next linked element can receive the segment. */
       
   608       eventp = &mp3parse->pending_segment;
       
   609       gst_event_replace (eventp, event);
       
   610       gst_event_unref (event);
       
   611       res = TRUE;
       
   612       break;
       
   613     }
       
   614     case GST_EVENT_FLUSH_STOP:
       
   615       /* Clear our adapter and set up for a new position */
       
   616       gst_adapter_clear (mp3parse->adapter);
       
   617       eventp = &mp3parse->pending_segment;
       
   618       gst_event_replace (eventp, NULL);
       
   619       res = gst_pad_push_event (mp3parse->srcpad, event);
       
   620       break;
       
   621     case GST_EVENT_EOS:
       
   622       /* If we haven't processed any frames yet, then make sure we process
       
   623          at least whatever's in our adapter */
       
   624       if (mp3parse->frame_count == 0) {
       
   625         gst_mp3parse_handle_data (mp3parse, TRUE);
       
   626 
       
   627         /* If we STILL have zero frames processed, fire an error */
       
   628         if (mp3parse->frame_count == 0) {
       
   629           GST_ELEMENT_ERROR (mp3parse, STREAM, WRONG_TYPE,
       
   630               ("No valid frames found before end of stream"), (NULL));
       
   631         }
       
   632       }
       
   633       /* fall through */
       
   634     default:
       
   635       if (mp3parse->pending_segment &&
       
   636           (GST_EVENT_TYPE (event) != GST_EVENT_EOS) &&
       
   637           (GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_START)) {
       
   638         /* Cache all events except EOS and the ones above if we have
       
   639          * a pending segment */
       
   640         mp3parse->pending_events =
       
   641             g_list_append (mp3parse->pending_events, event);
       
   642       } else {
       
   643         res = gst_pad_push_event (mp3parse->srcpad, event);
       
   644       }
       
   645       break;
       
   646   }
       
   647 
       
   648   gst_object_unref (mp3parse);
       
   649 
       
   650   return res;
       
   651 }
       
   652 
       
   653 static void
       
   654 gst_mp3parse_add_index_entry (GstMPEGAudioParse * mp3parse, guint64 offset,
       
   655     GstClockTime ts)
       
   656 {
       
   657   MPEGAudioSeekEntry *entry, *last;
       
   658 
       
   659   if (G_LIKELY (mp3parse->seek_table != NULL)) {
       
   660     last = mp3parse->seek_table->data;
       
   661 
       
   662     if (last->byte >= offset)
       
   663       return;
       
   664 
       
   665     if (GST_CLOCK_DIFF (last->timestamp, ts) < mp3parse->idx_interval)
       
   666       return;
       
   667   }
       
   668 
       
   669   entry = mpeg_audio_seek_entry_new ();
       
   670   entry->byte = offset;
       
   671   entry->timestamp = ts;
       
   672   mp3parse->seek_table = g_list_prepend (mp3parse->seek_table, entry);
       
   673 
       
   674   GST_LOG_OBJECT (mp3parse, "Adding index entry %" GST_TIME_FORMAT " @ offset "
       
   675       "0x%08" G_GINT64_MODIFIER "x", GST_TIME_ARGS (ts), offset);
       
   676 }
       
   677 
       
   678 /* Prepare a buffer of the indicated size, timestamp it and output */
       
   679 static GstFlowReturn
       
   680 gst_mp3parse_emit_frame (GstMPEGAudioParse * mp3parse, guint size,
       
   681     guint mode, guint crc)
       
   682 {
       
   683   GstBuffer *outbuf;
       
   684   guint bitrate;
       
   685   GstFlowReturn ret = GST_FLOW_OK;
       
   686   GstClockTime push_start;
       
   687   GstTagList *taglist;
       
   688 
       
   689   outbuf = gst_adapter_take_buffer (mp3parse->adapter, size);
       
   690 
       
   691   GST_BUFFER_DURATION (outbuf) =
       
   692       gst_util_uint64_scale (GST_SECOND, mp3parse->spf, mp3parse->rate);
       
   693 
       
   694   GST_BUFFER_OFFSET (outbuf) = mp3parse->cur_offset;
       
   695 
       
   696   /* Check if we have a pending timestamp from an incoming buffer to apply
       
   697    * here */
       
   698   if (GST_CLOCK_TIME_IS_VALID (mp3parse->pending_ts)) {
       
   699     if (mp3parse->tracked_offset >= mp3parse->pending_offset) {
       
   700       /* If the incoming timestamp differs from our expected by more than 
       
   701        * half a frame, then take it instead of our calculated timestamp.
       
   702        * This avoids creating imperfect streams just because of 
       
   703        * quantization in the container timestamping */
       
   704       GstClockTimeDiff diff = mp3parse->next_ts - mp3parse->pending_ts;
       
   705       GstClockTimeDiff thresh = GST_BUFFER_DURATION (outbuf) / 2;
       
   706 
       
   707       if (diff < -thresh || diff > thresh) {
       
   708         GST_DEBUG_OBJECT (mp3parse, "Updating next_ts from %" GST_TIME_FORMAT
       
   709             " to pending ts %" GST_TIME_FORMAT
       
   710             " at offset %" G_GINT64_FORMAT " (pending offset was %"
       
   711             G_GINT64_FORMAT ")", GST_TIME_ARGS (mp3parse->next_ts),
       
   712             GST_TIME_ARGS (mp3parse->pending_ts), mp3parse->tracked_offset,
       
   713             mp3parse->pending_offset);
       
   714         mp3parse->next_ts = mp3parse->pending_ts;
       
   715       }
       
   716       mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
       
   717     }
       
   718   }
       
   719 
       
   720   /* Decide what timestamp we're going to apply */
       
   721   if (GST_CLOCK_TIME_IS_VALID (mp3parse->next_ts)) {
       
   722     GST_BUFFER_TIMESTAMP (outbuf) = mp3parse->next_ts;
       
   723   } else {
       
   724     GstClockTime ts;
       
   725 
       
   726     /* No timestamp yet, convert our offset to a timestamp if we can, or
       
   727      * start at 0 */
       
   728     if (mp3parse_bytepos_to_time (mp3parse, mp3parse->cur_offset, &ts, FALSE) &&
       
   729         GST_CLOCK_TIME_IS_VALID (ts))
       
   730       GST_BUFFER_TIMESTAMP (outbuf) = ts;
       
   731     else {
       
   732       GST_BUFFER_TIMESTAMP (outbuf) = 0;
       
   733     }
       
   734   }
       
   735 
       
   736   if (GST_BUFFER_TIMESTAMP (outbuf) == 0)
       
   737     mp3parse->exact_position = TRUE;
       
   738 
       
   739   if (mp3parse->seekable &&
       
   740       mp3parse->exact_position && GST_BUFFER_TIMESTAMP_IS_VALID (outbuf) &&
       
   741       mp3parse->cur_offset != GST_BUFFER_OFFSET_NONE) {
       
   742     gst_mp3parse_add_index_entry (mp3parse, mp3parse->cur_offset,
       
   743         GST_BUFFER_TIMESTAMP (outbuf));
       
   744   }
       
   745 
       
   746   /* Update our byte offset tracking */
       
   747   if (mp3parse->cur_offset != -1) {
       
   748     mp3parse->cur_offset += size;
       
   749   }
       
   750   mp3parse->tracked_offset += size;
       
   751 
       
   752   if (GST_BUFFER_TIMESTAMP_IS_VALID (outbuf))
       
   753     mp3parse->next_ts =
       
   754         GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf);
       
   755 
       
   756   gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mp3parse->srcpad));
       
   757 
       
   758   /* Post a bitrate tag if we need to before pushing the buffer */
       
   759   if (mp3parse->xing_bitrate != 0)
       
   760     bitrate = mp3parse->xing_bitrate;
       
   761   else if (mp3parse->vbri_bitrate != 0)
       
   762     bitrate = mp3parse->vbri_bitrate;
       
   763   else
       
   764     bitrate = mp3parse->avg_bitrate;
       
   765 
       
   766   /* we will create a taglist (if any of the parameters has changed)
       
   767    * to add the tags that changed */
       
   768   taglist = NULL;
       
   769   if ((mp3parse->last_posted_bitrate / 10000) != (bitrate / 10000)) {
       
   770     taglist = gst_tag_list_new ();
       
   771     mp3parse->last_posted_bitrate = bitrate;
       
   772     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
       
   773         mp3parse->last_posted_bitrate, NULL);
       
   774 
       
   775     /* Post a new duration message if the average bitrate changes that much
       
   776      * so applications can update their cached values
       
   777      */
       
   778     if ((mp3parse->xing_flags & XING_TOC_FLAG) == 0
       
   779         && mp3parse->vbri_total_time == 0) {
       
   780       gst_element_post_message (GST_ELEMENT (mp3parse),
       
   781           gst_message_new_duration (GST_OBJECT (mp3parse), GST_FORMAT_TIME,
       
   782               -1));
       
   783     }
       
   784   }
       
   785 
       
   786   if (mp3parse->last_posted_crc != crc) {
       
   787     gboolean using_crc;
       
   788 
       
   789     if (!taglist) {
       
   790       taglist = gst_tag_list_new ();
       
   791     }
       
   792     mp3parse->last_posted_crc = crc;
       
   793     if (mp3parse->last_posted_crc == CRC_PROTECTED) {
       
   794       using_crc = TRUE;
       
   795     } else {
       
   796       using_crc = FALSE;
       
   797     }
       
   798     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_CRC,
       
   799         using_crc, NULL);
       
   800   }
       
   801 
       
   802   if (mp3parse->last_posted_channel_mode != mode) {
       
   803     if (!taglist) {
       
   804       taglist = gst_tag_list_new ();
       
   805     }
       
   806     mp3parse->last_posted_channel_mode = mode;
       
   807 
       
   808     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MODE,
       
   809         gst_mp3_channel_mode_get_nick (mode), NULL);
       
   810   }
       
   811 
       
   812   /* if the taglist exists, we need to send it */
       
   813   if (taglist) {
       
   814     gst_element_found_tags_for_pad (GST_ELEMENT (mp3parse),
       
   815         mp3parse->srcpad, taglist);
       
   816   }
       
   817 
       
   818   /* We start pushing 9 frames earlier (29 frames for MPEG2) than
       
   819    * segment start to be able to decode the first frame we want.
       
   820    * 9 (29) frames are the theoretical maximum of frames that contain
       
   821    * data for the current frame (bit reservoir).
       
   822    */
       
   823   if (mp3parse->segment.start == 0) {
       
   824     push_start = 0;
       
   825   } else if (GST_CLOCK_TIME_IS_VALID (mp3parse->max_bitreservoir)) {
       
   826     if (GST_CLOCK_TIME_IS_VALID (mp3parse->segment.start) &&
       
   827         mp3parse->segment.start > mp3parse->max_bitreservoir)
       
   828       push_start = mp3parse->segment.start - mp3parse->max_bitreservoir;
       
   829     else
       
   830       push_start = 0;
       
   831   } else {
       
   832     push_start = mp3parse->segment.start;
       
   833   }
       
   834 
       
   835   if (G_UNLIKELY ((GST_CLOCK_TIME_IS_VALID (push_start) &&
       
   836               GST_BUFFER_TIMESTAMP_IS_VALID (outbuf) &&
       
   837               GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf)
       
   838               < push_start))) {
       
   839     GST_DEBUG_OBJECT (mp3parse,
       
   840         "Buffer before configured segment range %" GST_TIME_FORMAT
       
   841         " to %" GST_TIME_FORMAT ", dropping, timestamp %"
       
   842         GST_TIME_FORMAT " duration %" GST_TIME_FORMAT
       
   843         ", offset 0x%08" G_GINT64_MODIFIER "x", GST_TIME_ARGS (push_start),
       
   844         GST_TIME_ARGS (mp3parse->segment.stop),
       
   845         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
       
   846         GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
       
   847         GST_BUFFER_OFFSET (outbuf));
       
   848 
       
   849     gst_buffer_unref (outbuf);
       
   850     ret = GST_FLOW_OK;
       
   851   } else if (G_UNLIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (outbuf) &&
       
   852           GST_CLOCK_TIME_IS_VALID (mp3parse->segment.stop) &&
       
   853           GST_BUFFER_TIMESTAMP (outbuf) >=
       
   854           mp3parse->segment.stop + GST_BUFFER_DURATION (outbuf))) {
       
   855     /* Some mp3 streams have an offset in the timestamps, for which we have to
       
   856      * push the frame *after* the end position in order for the decoder to be
       
   857      * able to decode everything up until the segment.stop position.
       
   858      * That is the reason of the calculated offset */
       
   859     GST_DEBUG_OBJECT (mp3parse,
       
   860         "Buffer after configured segment range %" GST_TIME_FORMAT " to %"
       
   861         GST_TIME_FORMAT ", returning GST_FLOW_UNEXPECTED, timestamp %"
       
   862         GST_TIME_FORMAT " duration %" GST_TIME_FORMAT ", offset 0x%08"
       
   863         G_GINT64_MODIFIER "x", GST_TIME_ARGS (push_start),
       
   864         GST_TIME_ARGS (mp3parse->segment.stop),
       
   865         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
       
   866         GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
       
   867         GST_BUFFER_OFFSET (outbuf));
       
   868 
       
   869     gst_buffer_unref (outbuf);
       
   870     ret = GST_FLOW_UNEXPECTED;
       
   871   } else {
       
   872     GST_DEBUG_OBJECT (mp3parse,
       
   873         "pushing buffer of %d bytes, timestamp %" GST_TIME_FORMAT
       
   874         ", offset 0x%08" G_GINT64_MODIFIER "x", size,
       
   875         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
       
   876         GST_BUFFER_OFFSET (outbuf));
       
   877     mp3parse->segment.last_stop = GST_BUFFER_TIMESTAMP (outbuf);
       
   878     /* push any pending segment now */
       
   879     if (mp3parse->pending_segment) {
       
   880       gst_pad_push_event (mp3parse->srcpad, mp3parse->pending_segment);
       
   881       mp3parse->pending_segment = NULL;
       
   882     }
       
   883     if (mp3parse->pending_events) {
       
   884       GList *l;
       
   885 
       
   886       for (l = mp3parse->pending_events; l != NULL; l = l->next) {
       
   887         gst_pad_push_event (mp3parse->srcpad, GST_EVENT (l->data));
       
   888       }
       
   889       g_list_free (mp3parse->pending_events);
       
   890       mp3parse->pending_events = NULL;
       
   891     }
       
   892 
       
   893     /* set discont if needed */
       
   894     if (mp3parse->discont) {
       
   895       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
       
   896       mp3parse->discont = FALSE;
       
   897     }
       
   898 
       
   899     ret = gst_pad_push (mp3parse->srcpad, outbuf);
       
   900   }
       
   901 
       
   902   return ret;
       
   903 }
       
   904 
       
   905 static void
       
   906 gst_mp3parse_handle_first_frame (GstMPEGAudioParse * mp3parse)
       
   907 {
       
   908   GstTagList *taglist;
       
   909   gchar *codec;
       
   910   const guint32 xing_id = 0x58696e67;   /* 'Xing' in hex */
       
   911   const guint32 info_id = 0x496e666f;   /* 'Info' in hex - found in LAME CBR files */
       
   912   const guint32 vbri_id = 0x56425249;   /* 'VBRI' in hex */
       
   913 
       
   914   gint offset;
       
   915 
       
   916   guint64 avail;
       
   917   gint64 upstream_total_bytes = 0;
       
   918   guint32 read_id;
       
   919   const guint8 *data;
       
   920 
       
   921   /* Output codec tag */
       
   922   if (!mp3parse->sent_codec_tag) {
       
   923     if (mp3parse->layer == 3) {
       
   924       codec = g_strdup_printf ("MPEG %d Audio, Layer %d (MP3)",
       
   925           mp3parse->version, mp3parse->layer);
       
   926     } else {
       
   927       codec = g_strdup_printf ("MPEG %d Audio, Layer %d",
       
   928           mp3parse->version, mp3parse->layer);
       
   929     }
       
   930 
       
   931     taglist = gst_tag_list_new ();
       
   932     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
       
   933         GST_TAG_AUDIO_CODEC, codec, NULL);
       
   934     gst_element_found_tags_for_pad (GST_ELEMENT (mp3parse),
       
   935         mp3parse->srcpad, taglist);
       
   936     g_free (codec);
       
   937 
       
   938     mp3parse->sent_codec_tag = TRUE;
       
   939   }
       
   940   /* end setting the tag */
       
   941 
       
   942   /* Check first frame for Xing info */
       
   943   if (mp3parse->version == 1) { /* MPEG-1 file */
       
   944     if (mp3parse->channels == 1)
       
   945       offset = 0x11;
       
   946     else
       
   947       offset = 0x20;
       
   948   } else {                      /* MPEG-2 header */
       
   949     if (mp3parse->channels == 1)
       
   950       offset = 0x09;
       
   951     else
       
   952       offset = 0x11;
       
   953   }
       
   954   /* Skip the 4 bytes of the MP3 header too */
       
   955   offset += 4;
       
   956 
       
   957   /* Check if we have enough data to read the Xing header */
       
   958   avail = gst_adapter_available (mp3parse->adapter);
       
   959 
       
   960   if (avail < offset + 8)
       
   961     return;
       
   962 
       
   963   data = gst_adapter_peek (mp3parse->adapter, offset + 8);
       
   964   if (data == NULL)
       
   965     return;
       
   966   /* The header starts at the provided offset */
       
   967   data += offset;
       
   968 
       
   969   /* obtain real upstream total bytes */
       
   970   mp3parse_total_bytes (mp3parse, &upstream_total_bytes);
       
   971 
       
   972   read_id = GST_READ_UINT32_BE (data);
       
   973   if (read_id == xing_id || read_id == info_id) {
       
   974     guint32 xing_flags;
       
   975     guint bytes_needed = offset + 8;
       
   976     gint64 total_bytes;
       
   977     GstClockTime total_time;
       
   978 
       
   979     GST_DEBUG_OBJECT (mp3parse, "Found Xing header marker 0x%x", xing_id);
       
   980 
       
   981     /* Read 4 base bytes of flags, big-endian */
       
   982     xing_flags = GST_READ_UINT32_BE (data + 4);
       
   983     if (xing_flags & XING_FRAMES_FLAG)
       
   984       bytes_needed += 4;
       
   985     if (xing_flags & XING_BYTES_FLAG)
       
   986       bytes_needed += 4;
       
   987     if (xing_flags & XING_TOC_FLAG)
       
   988       bytes_needed += 100;
       
   989     if (xing_flags & XING_VBR_SCALE_FLAG)
       
   990       bytes_needed += 4;
       
   991     if (avail < bytes_needed) {
       
   992       GST_DEBUG_OBJECT (mp3parse,
       
   993           "Not enough data to read Xing header (need %d)", bytes_needed);
       
   994       return;
       
   995     }
       
   996 
       
   997     GST_DEBUG_OBJECT (mp3parse, "Reading Xing header");
       
   998     mp3parse->xing_flags = xing_flags;
       
   999     data = gst_adapter_peek (mp3parse->adapter, bytes_needed);
       
  1000     data += offset + 8;
       
  1001 
       
  1002     if (xing_flags & XING_FRAMES_FLAG) {
       
  1003       mp3parse->xing_frames = GST_READ_UINT32_BE (data);
       
  1004       if (mp3parse->xing_frames == 0) {
       
  1005         GST_WARNING_OBJECT (mp3parse,
       
  1006             "Invalid number of frames in Xing header");
       
  1007         mp3parse->xing_flags &= ~XING_FRAMES_FLAG;
       
  1008       } else {
       
  1009         mp3parse->xing_total_time = gst_util_uint64_scale (GST_SECOND,
       
  1010             (guint64) (mp3parse->xing_frames) * (mp3parse->spf),
       
  1011             mp3parse->rate);
       
  1012       }
       
  1013 
       
  1014       data += 4;
       
  1015     } else {
       
  1016       mp3parse->xing_frames = 0;
       
  1017       mp3parse->xing_total_time = 0;
       
  1018     }
       
  1019 
       
  1020     if (xing_flags & XING_BYTES_FLAG) {
       
  1021       mp3parse->xing_bytes = GST_READ_UINT32_BE (data);
       
  1022       if (mp3parse->xing_bytes == 0) {
       
  1023         GST_WARNING_OBJECT (mp3parse, "Invalid number of bytes in Xing header");
       
  1024         mp3parse->xing_flags &= ~XING_BYTES_FLAG;
       
  1025       }
       
  1026 
       
  1027       data += 4;
       
  1028     } else {
       
  1029       mp3parse->xing_bytes = 0;
       
  1030     }
       
  1031 
       
  1032     /* If we know the upstream size and duration, compute the
       
  1033      * total bitrate, rounded up to the nearest kbit/sec */
       
  1034     if ((total_time = mp3parse->xing_total_time) &&
       
  1035         (total_bytes = mp3parse->xing_bytes)) {
       
  1036       mp3parse->xing_bitrate = gst_util_uint64_scale (total_bytes,
       
  1037           8 * GST_SECOND, total_time);
       
  1038       mp3parse->xing_bitrate += 500;
       
  1039       mp3parse->xing_bitrate -= mp3parse->xing_bitrate % 1000;
       
  1040     }
       
  1041 
       
  1042     if (xing_flags & XING_TOC_FLAG) {
       
  1043       int i, percent = 0;
       
  1044       guchar *table = mp3parse->xing_seek_table;
       
  1045       guchar old = 0, new;
       
  1046       guint first;
       
  1047 
       
  1048       first = data[0];
       
  1049       GST_DEBUG_OBJECT (mp3parse,
       
  1050           "Subtracting initial offset of %d bytes from Xing TOC", first);
       
  1051 
       
  1052       /* xing seek table: percent time -> 1/256 bytepos */
       
  1053       for (i = 0; i < 100; i++) {
       
  1054         new = data[i] - first;
       
  1055         if (old > new) {
       
  1056           GST_WARNING_OBJECT (mp3parse, "Skipping broken Xing TOC");
       
  1057           mp3parse->xing_flags &= ~XING_TOC_FLAG;
       
  1058           goto skip_toc;
       
  1059         }
       
  1060         mp3parse->xing_seek_table[i] = old = new;
       
  1061       }
       
  1062 
       
  1063       /* build inverse table: 1/256 bytepos -> 1/100 percent time */
       
  1064       for (i = 0; i < 256; i++) {
       
  1065         while (percent < 99 && table[percent + 1] <= i)
       
  1066           percent++;
       
  1067 
       
  1068         if (table[percent] == i) {
       
  1069           mp3parse->xing_seek_table_inverse[i] = percent * 100;
       
  1070         } else if (table[percent] < i && percent < 99) {
       
  1071           gdouble fa, fb, fx;
       
  1072           gint a = percent, b = percent + 1;
       
  1073 
       
  1074           fa = table[a];
       
  1075           fb = table[b];
       
  1076           fx = (b - a) / (fb - fa) * (i - fa) + a;
       
  1077           mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
       
  1078         } else if (percent == 99) {
       
  1079           gdouble fa, fb, fx;
       
  1080           gint a = percent, b = 100;
       
  1081 
       
  1082           fa = table[a];
       
  1083           fb = 256.0;
       
  1084           fx = (b - a) / (fb - fa) * (i - fa) + a;
       
  1085           mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
       
  1086         }
       
  1087       }
       
  1088     skip_toc:
       
  1089       data += 100;
       
  1090     } else {
       
  1091       memset (mp3parse->xing_seek_table, 0, 100);
       
  1092       memset (mp3parse->xing_seek_table_inverse, 0, 256);
       
  1093     }
       
  1094 
       
  1095     if (xing_flags & XING_VBR_SCALE_FLAG) {
       
  1096       mp3parse->xing_vbr_scale = GST_READ_UINT32_BE (data);
       
  1097     } else
       
  1098       mp3parse->xing_vbr_scale = 0;
       
  1099 
       
  1100     GST_DEBUG_OBJECT (mp3parse, "Xing header reported %u frames, time %"
       
  1101         GST_TIME_FORMAT ", %u bytes, vbr scale %u", mp3parse->xing_frames,
       
  1102         GST_TIME_ARGS (mp3parse->xing_total_time), mp3parse->xing_bytes,
       
  1103         mp3parse->xing_vbr_scale);
       
  1104 
       
  1105     /* check for truncated file */
       
  1106     if (upstream_total_bytes && mp3parse->xing_bytes &&
       
  1107         mp3parse->xing_bytes * 0.8 > upstream_total_bytes) {
       
  1108       GST_WARNING_OBJECT (mp3parse, "File appears to have been truncated; "
       
  1109           "invalidating Xing header duration and size");
       
  1110       mp3parse->xing_flags &= ~XING_BYTES_FLAG;
       
  1111       mp3parse->xing_flags &= ~XING_FRAMES_FLAG;
       
  1112     }
       
  1113   } else if (read_id == vbri_id) {
       
  1114     gint64 total_bytes, total_frames;
       
  1115     GstClockTime total_time;
       
  1116     guint16 nseek_points;
       
  1117 
       
  1118     GST_DEBUG_OBJECT (mp3parse, "Found VBRI header marker 0x%x", vbri_id);
       
  1119     if (avail < offset + 26) {
       
  1120       GST_DEBUG_OBJECT (mp3parse,
       
  1121           "Not enough data to read VBRI header (need %d)", offset + 26);
       
  1122       return;
       
  1123     }
       
  1124 
       
  1125     GST_DEBUG_OBJECT (mp3parse, "Reading VBRI header");
       
  1126     data = gst_adapter_peek (mp3parse->adapter, offset + 26);
       
  1127     data += offset + 4;
       
  1128 
       
  1129     if (GST_READ_UINT16_BE (data) != 0x0001) {
       
  1130       GST_WARNING_OBJECT (mp3parse,
       
  1131           "Unsupported VBRI version 0x%x", GST_READ_UINT16_BE (data));
       
  1132       return;
       
  1133     }
       
  1134     data += 2;
       
  1135 
       
  1136     /* Skip encoder delay */
       
  1137     data += 2;
       
  1138 
       
  1139     /* Skip quality */
       
  1140     data += 2;
       
  1141 
       
  1142     total_bytes = GST_READ_UINT32_BE (data);
       
  1143     if (total_bytes != 0)
       
  1144       mp3parse->vbri_bytes = total_bytes;
       
  1145     data += 4;
       
  1146 
       
  1147     total_frames = GST_READ_UINT32_BE (data);
       
  1148     if (total_frames != 0) {
       
  1149       mp3parse->vbri_frames = total_frames;
       
  1150       mp3parse->vbri_total_time = gst_util_uint64_scale (GST_SECOND,
       
  1151           (guint64) (mp3parse->vbri_frames) * (mp3parse->spf), mp3parse->rate);
       
  1152     }
       
  1153     data += 4;
       
  1154 
       
  1155     /* If we know the upstream size and duration, compute the 
       
  1156      * total bitrate, rounded up to the nearest kbit/sec */
       
  1157     if ((total_time = mp3parse->vbri_total_time) &&
       
  1158         (total_bytes = mp3parse->vbri_bytes)) {
       
  1159       mp3parse->vbri_bitrate = gst_util_uint64_scale (total_bytes,
       
  1160           8 * GST_SECOND, total_time);
       
  1161       mp3parse->vbri_bitrate += 500;
       
  1162       mp3parse->vbri_bitrate -= mp3parse->vbri_bitrate % 1000;
       
  1163     }
       
  1164 
       
  1165     nseek_points = GST_READ_UINT16_BE (data);
       
  1166     data += 2;
       
  1167 
       
  1168     if (nseek_points > 0) {
       
  1169       guint scale, seek_bytes, seek_frames;
       
  1170       gint i;
       
  1171 
       
  1172       mp3parse->vbri_seek_points = nseek_points;
       
  1173 
       
  1174       scale = GST_READ_UINT16_BE (data);
       
  1175       data += 2;
       
  1176 
       
  1177       seek_bytes = GST_READ_UINT16_BE (data);
       
  1178       data += 2;
       
  1179 
       
  1180       seek_frames = GST_READ_UINT16_BE (data);
       
  1181 
       
  1182       if (scale == 0 || seek_bytes == 0 || seek_bytes > 4 || seek_frames == 0) {
       
  1183         GST_WARNING_OBJECT (mp3parse, "Unsupported VBRI seek table");
       
  1184         goto out_vbri;
       
  1185       }
       
  1186 
       
  1187       if (avail < offset + 26 + nseek_points * seek_bytes) {
       
  1188         GST_WARNING_OBJECT (mp3parse,
       
  1189             "Not enough data to read VBRI seek table (need %d)",
       
  1190             offset + 26 + nseek_points * seek_bytes);
       
  1191         goto out_vbri;
       
  1192       }
       
  1193 
       
  1194       if (seek_frames * nseek_points < total_frames - seek_frames ||
       
  1195           seek_frames * nseek_points > total_frames + seek_frames) {
       
  1196         GST_WARNING_OBJECT (mp3parse,
       
  1197             "VBRI seek table doesn't cover the complete file");
       
  1198         goto out_vbri;
       
  1199       }
       
  1200 
       
  1201       data =
       
  1202           gst_adapter_peek (mp3parse->adapter,
       
  1203           offset + 26 + nseek_points * seek_bytes);
       
  1204       data += offset + 26;
       
  1205 
       
  1206 
       
  1207       /* VBRI seek table: frame/seek_frames -> byte */
       
  1208       mp3parse->vbri_seek_table = g_new (guint32, nseek_points);
       
  1209       if (seek_bytes == 4)
       
  1210         for (i = 0; i < nseek_points; i++) {
       
  1211           mp3parse->vbri_seek_table[i] = GST_READ_UINT32_BE (data) * scale;
       
  1212           data += 4;
       
  1213       } else if (seek_bytes == 3)
       
  1214         for (i = 0; i < nseek_points; i++) {
       
  1215           mp3parse->vbri_seek_table[i] = GST_READ_UINT24_BE (data) * scale;
       
  1216           data += 3;
       
  1217       } else if (seek_bytes == 2)
       
  1218         for (i = 0; i < nseek_points; i++) {
       
  1219           mp3parse->vbri_seek_table[i] = GST_READ_UINT16_BE (data) * scale;
       
  1220           data += 2;
       
  1221       } else                    /* seek_bytes == 1 */
       
  1222         for (i = 0; i < nseek_points; i++) {
       
  1223           mp3parse->vbri_seek_table[i] = GST_READ_UINT8 (data) * scale;
       
  1224           data += 1;
       
  1225         }
       
  1226     }
       
  1227   out_vbri:
       
  1228 
       
  1229     GST_DEBUG_OBJECT (mp3parse, "VBRI header reported %u frames, time %"
       
  1230         GST_TIME_FORMAT ", bytes %u", mp3parse->vbri_frames,
       
  1231         GST_TIME_ARGS (mp3parse->vbri_total_time), mp3parse->vbri_bytes);
       
  1232 
       
  1233     /* check for truncated file */
       
  1234     if (upstream_total_bytes && mp3parse->vbri_bytes &&
       
  1235         mp3parse->vbri_bytes * 0.8 > upstream_total_bytes) {
       
  1236       GST_WARNING_OBJECT (mp3parse, "File appears to have been truncated; "
       
  1237           "invalidating VBRI header duration and size");
       
  1238       mp3parse->vbri_valid = FALSE;
       
  1239     } else {
       
  1240       mp3parse->vbri_valid = TRUE;
       
  1241     }
       
  1242   } else {
       
  1243     GST_DEBUG_OBJECT (mp3parse,
       
  1244         "Xing, LAME or VBRI header not found in first frame");
       
  1245   }
       
  1246 }
       
  1247 
       
  1248 static void
       
  1249 gst_mp3parse_check_seekability (GstMPEGAudioParse * mp3parse)
       
  1250 {
       
  1251   GstQuery *query;
       
  1252   gboolean seekable = FALSE;
       
  1253   gint64 start = -1, stop = -1;
       
  1254   guint idx_interval = 0;
       
  1255 
       
  1256   query = gst_query_new_seeking (GST_FORMAT_BYTES);
       
  1257   if (!gst_pad_peer_query (mp3parse->sinkpad, query)) {
       
  1258     GST_DEBUG_OBJECT (mp3parse, "seeking query failed");
       
  1259     goto done;
       
  1260   }
       
  1261 
       
  1262   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
       
  1263 
       
  1264   /* try harder to query upstream size if we didn't get it the first time */
       
  1265   if (seekable && stop == -1) {
       
  1266     GstFormat fmt = GST_FORMAT_BYTES;
       
  1267 
       
  1268     GST_DEBUG_OBJECT (mp3parse, "doing duration query to fix up unset stop");
       
  1269     gst_pad_query_peer_duration (mp3parse->sinkpad, &fmt, &stop);
       
  1270   }
       
  1271 
       
  1272   /* if upstream doesn't know the size, it's likely that it's not seekable in
       
  1273    * practice even if it technically may be seekable */
       
  1274   if (seekable && (start != 0 || stop <= start)) {
       
  1275     GST_DEBUG_OBJECT (mp3parse, "seekable but unknown start/stop -> disable");
       
  1276     seekable = FALSE;
       
  1277   }
       
  1278 
       
  1279   /* let's not put every single frame into our index */
       
  1280   if (seekable) {
       
  1281     if (stop < 10 * 1024 * 1024)
       
  1282       idx_interval = 100;
       
  1283     else if (stop < 100 * 1024 * 1024)
       
  1284       idx_interval = 500;
       
  1285     else
       
  1286       idx_interval = 1000;
       
  1287   }
       
  1288 
       
  1289 done:
       
  1290 
       
  1291   GST_INFO_OBJECT (mp3parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
       
  1292       G_GUINT64_FORMAT ")", seekable, start, stop);
       
  1293   mp3parse->seekable = seekable;
       
  1294 
       
  1295   GST_INFO_OBJECT (mp3parse, "idx_interval: %ums", idx_interval);
       
  1296   mp3parse->idx_interval = idx_interval * GST_MSECOND;
       
  1297 
       
  1298   gst_query_unref (query);
       
  1299 }
       
  1300 
       
  1301 /* Flush some number of bytes and update tracked offsets */
       
  1302 static void
       
  1303 gst_mp3parse_flush_bytes (GstMPEGAudioParse * mp3parse, int bytes)
       
  1304 {
       
  1305   gst_adapter_flush (mp3parse->adapter, bytes);
       
  1306   if (mp3parse->cur_offset != -1)
       
  1307     mp3parse->cur_offset += bytes;
       
  1308   mp3parse->tracked_offset += bytes;
       
  1309 }
       
  1310 
       
  1311 /* Perform extended validation to check that subsequent headers match
       
  1312    the first header given here in important characteristics, to avoid
       
  1313    false sync. We look for a minimum of MIN_RESYNC_FRAMES consecutive
       
  1314    frames to match their major characteristics.
       
  1315 
       
  1316    If at_eos is set to TRUE, we just check that we don't find any invalid
       
  1317    frames in whatever data is available, rather than requiring a full
       
  1318    MIN_RESYNC_FRAMES of data.
       
  1319 
       
  1320    Returns TRUE if we've seen enough data to validate or reject the frame.
       
  1321    If TRUE is returned, then *valid contains TRUE if it validated, or false
       
  1322    if we decided it was false sync.
       
  1323  */
       
  1324 static gboolean
       
  1325 gst_mp3parse_validate_extended (GstMPEGAudioParse * mp3parse, guint32 header,
       
  1326     int bpf, gboolean at_eos, gboolean * valid)
       
  1327 {
       
  1328   guint32 next_header;
       
  1329   const guint8 *data;
       
  1330   guint available;
       
  1331   int frames_found = 1;
       
  1332   int offset = bpf;
       
  1333 
       
  1334   while (frames_found < MIN_RESYNC_FRAMES) {
       
  1335     /* Check if we have enough data for all these frames, plus the next
       
  1336        frame header. */
       
  1337     available = gst_adapter_available (mp3parse->adapter);
       
  1338     if (available < offset + 4) {
       
  1339       if (at_eos) {
       
  1340         /* Running out of data at EOS is fine; just accept it */
       
  1341         *valid = TRUE;
       
  1342         return TRUE;
       
  1343       } else {
       
  1344         return FALSE;
       
  1345       }
       
  1346     }
       
  1347 
       
  1348     data = gst_adapter_peek (mp3parse->adapter, offset + 4);
       
  1349     next_header = GST_READ_UINT32_BE (data + offset);
       
  1350     GST_DEBUG_OBJECT (mp3parse, "At %d: header=%08X, header2=%08X, bpf=%d",
       
  1351         offset, (unsigned int) header, (unsigned int) next_header, bpf);
       
  1352 
       
  1353 /* mask the bits which are allowed to differ between frames */
       
  1354 #define HDRMASK ~((0xF << 12)  /* bitrate */ | \
       
  1355                   (0x1 <<  9)  /* padding */ | \
       
  1356                   (0xf <<  4)  /* mode|mode extension */ | \
       
  1357                   (0xf))        /* copyright|emphasis */
       
  1358 
       
  1359     if ((next_header & HDRMASK) != (header & HDRMASK)) {
       
  1360       /* If any of the unmasked bits don't match, then it's not valid */
       
  1361       GST_DEBUG_OBJECT (mp3parse, "next header doesn't match "
       
  1362           "(header=%08X (%08X), header2=%08X (%08X), bpf=%d)",
       
  1363           (guint) header, (guint) header & HDRMASK, (guint) next_header,
       
  1364           (guint) next_header & HDRMASK, bpf);
       
  1365       *valid = FALSE;
       
  1366       return TRUE;
       
  1367     } else if ((((next_header >> 12) & 0xf) == 0) ||
       
  1368         (((next_header >> 12) & 0xf) == 0xf)) {
       
  1369       /* The essential parts were the same, but the bitrate held an
       
  1370          invalid value - also reject */
       
  1371       GST_DEBUG_OBJECT (mp3parse, "next header invalid (bitrate)");
       
  1372       *valid = FALSE;
       
  1373       return TRUE;
       
  1374     }
       
  1375 
       
  1376     bpf = mp3_type_frame_length_from_header (mp3parse, next_header,
       
  1377         NULL, NULL, NULL, NULL, NULL, NULL, NULL);
       
  1378 
       
  1379     offset += bpf;
       
  1380     frames_found++;
       
  1381   }
       
  1382 
       
  1383   *valid = TRUE;
       
  1384   return TRUE;
       
  1385 }
       
  1386 
       
  1387 static GstFlowReturn
       
  1388 gst_mp3parse_handle_data (GstMPEGAudioParse * mp3parse, gboolean at_eos)
       
  1389 {
       
  1390   GstFlowReturn flow = GST_FLOW_OK;
       
  1391   const guchar *data;
       
  1392   guint32 header;
       
  1393   int bpf;
       
  1394   guint available;
       
  1395   guint bitrate, layer, rate, channels, version, mode, crc;
       
  1396   gboolean caps_change;
       
  1397 
       
  1398   /* while we still have at least 4 bytes (for the header) available */
       
  1399   while (gst_adapter_available (mp3parse->adapter) >= 4) {
       
  1400     /* Get the header bytes, check if they're potentially valid */
       
  1401     data = gst_adapter_peek (mp3parse->adapter, 4);
       
  1402     header = GST_READ_UINT32_BE (data);
       
  1403 
       
  1404     if (!head_check (mp3parse, header)) {
       
  1405       /* Not a valid MP3 header; we start looking forward byte-by-byte trying to
       
  1406          find a place to resync */
       
  1407       if (!mp3parse->resyncing)
       
  1408         mp3parse->sync_offset = mp3parse->tracked_offset;
       
  1409       mp3parse->resyncing = TRUE;
       
  1410       gst_mp3parse_flush_bytes (mp3parse, 1);
       
  1411       GST_DEBUG_OBJECT (mp3parse, "wrong header, skipping byte");
       
  1412       continue;
       
  1413     }
       
  1414 
       
  1415     /* We have a potentially valid header.
       
  1416        If this is just a normal 'next frame', we go ahead and output it.
       
  1417 
       
  1418        However, sometimes, we do additional validation to ensure we haven't
       
  1419        got false sync (common with mp3 due to the short sync word).
       
  1420        The additional validation requires that we find several consecutive mp3
       
  1421        frames with the same major parameters, or reach EOS with a smaller
       
  1422        number of valid-looking frames.
       
  1423 
       
  1424        We do this if:
       
  1425        - This is the very first frame we've processed
       
  1426        - We're resyncing after a non-accurate seek, or after losing sync
       
  1427        due to invalid data.
       
  1428        - The format of the stream changes in a major way (number of channels,
       
  1429        sample rate, layer, or mpeg version).
       
  1430      */
       
  1431     available = gst_adapter_available (mp3parse->adapter);
       
  1432 
       
  1433     if (G_UNLIKELY (mp3parse->resyncing &&
       
  1434             mp3parse->tracked_offset - mp3parse->sync_offset > 2 * 1024 * 1024))
       
  1435       goto sync_failure;
       
  1436 
       
  1437     bpf = mp3_type_frame_length_from_header (mp3parse, header,
       
  1438         &version, &layer, &channels, &bitrate, &rate, &mode, &crc);
       
  1439     g_assert (bpf != 0);
       
  1440 
       
  1441     if (channels != mp3parse->channels ||
       
  1442         rate != mp3parse->rate || layer != mp3parse->layer ||
       
  1443         version != mp3parse->version)
       
  1444       caps_change = TRUE;
       
  1445     else
       
  1446       caps_change = FALSE;
       
  1447 
       
  1448     if (mp3parse->resyncing || caps_change) {
       
  1449       gboolean valid;
       
  1450       if (!gst_mp3parse_validate_extended (mp3parse, header, bpf, at_eos,
       
  1451               &valid)) {
       
  1452         /* Not enough data to validate; wait for more */
       
  1453         break;
       
  1454       }
       
  1455 
       
  1456       if (!valid) {
       
  1457         /* Extended validation failed; we probably got false sync.
       
  1458            Continue searching from the next byte in the stream */
       
  1459         if (!mp3parse->resyncing)
       
  1460           mp3parse->sync_offset = mp3parse->tracked_offset;
       
  1461         mp3parse->resyncing = TRUE;
       
  1462         gst_mp3parse_flush_bytes (mp3parse, 1);
       
  1463         continue;
       
  1464       }
       
  1465     }
       
  1466 
       
  1467     /* if we don't have the whole frame... */
       
  1468     if (available < bpf) {
       
  1469       GST_DEBUG_OBJECT (mp3parse, "insufficient data available, need "
       
  1470           "%d bytes, have %d", bpf, available);
       
  1471       break;
       
  1472     }
       
  1473 
       
  1474     if (caps_change) {
       
  1475       GstCaps *caps;
       
  1476 
       
  1477       caps = mp3_caps_create (version, layer, channels, rate);
       
  1478       gst_pad_set_caps (mp3parse->srcpad, caps);
       
  1479       gst_caps_unref (caps);
       
  1480 
       
  1481       mp3parse->channels = channels;
       
  1482       mp3parse->rate = rate;
       
  1483 
       
  1484       mp3parse->layer = layer;
       
  1485       mp3parse->version = version;
       
  1486 
       
  1487       /* see http://www.codeproject.com/audio/MPEGAudioInfo.asp */
       
  1488       if (mp3parse->layer == 1)
       
  1489         mp3parse->spf = 384;
       
  1490       else if (mp3parse->layer == 2)
       
  1491         mp3parse->spf = 1152;
       
  1492       else if (mp3parse->version == 1) {
       
  1493         mp3parse->spf = 1152;
       
  1494       } else {
       
  1495         /* MPEG-2 or "2.5" */
       
  1496         mp3parse->spf = 576;
       
  1497       }
       
  1498 
       
  1499       mp3parse->max_bitreservoir = gst_util_uint64_scale (GST_SECOND,
       
  1500           ((version == 1) ? 10 : 30) * mp3parse->spf, mp3parse->rate);
       
  1501     }
       
  1502 
       
  1503     mp3parse->bit_rate = bitrate;
       
  1504 
       
  1505     /* Check the first frame for a Xing header to get our total length */
       
  1506     if (mp3parse->frame_count == 0) {
       
  1507       /* For the first frame in the file, look for a Xing frame after 
       
  1508        * the header, and output a codec tag */
       
  1509       gst_mp3parse_handle_first_frame (mp3parse);
       
  1510 
       
  1511       /* Check if we're seekable */
       
  1512       gst_mp3parse_check_seekability (mp3parse);
       
  1513     }
       
  1514 
       
  1515     /* Update VBR stats */
       
  1516     mp3parse->bitrate_sum += mp3parse->bit_rate;
       
  1517     mp3parse->frame_count++;
       
  1518     /* Compute the average bitrate, rounded up to the nearest 1000 bits */
       
  1519     mp3parse->avg_bitrate =
       
  1520         (mp3parse->bitrate_sum / mp3parse->frame_count + 500);
       
  1521     mp3parse->avg_bitrate -= mp3parse->avg_bitrate % 1000;
       
  1522 
       
  1523     if (!mp3parse->skip) {
       
  1524       mp3parse->resyncing = FALSE;
       
  1525       flow = gst_mp3parse_emit_frame (mp3parse, bpf, mode, crc);
       
  1526       if (GST_FLOW_IS_FATAL (flow))
       
  1527         break;
       
  1528     } else {
       
  1529       GST_DEBUG_OBJECT (mp3parse, "skipping buffer of %d bytes", bpf);
       
  1530       gst_mp3parse_flush_bytes (mp3parse, bpf);
       
  1531       mp3parse->skip--;
       
  1532     }
       
  1533   }
       
  1534 
       
  1535   return flow;
       
  1536 
       
  1537   /* ERRORS */
       
  1538 sync_failure:
       
  1539   {
       
  1540     GST_ELEMENT_ERROR (mp3parse, STREAM, DECODE,
       
  1541         ("Failed to parse stream"), (NULL));
       
  1542     return GST_FLOW_ERROR;
       
  1543   }
       
  1544 }
       
  1545 
       
  1546 static GstFlowReturn
       
  1547 gst_mp3parse_chain (GstPad * pad, GstBuffer * buf)
       
  1548 {
       
  1549   GstMPEGAudioParse *mp3parse;
       
  1550   GstClockTime timestamp;
       
  1551 
       
  1552   mp3parse = GST_MP3PARSE (GST_PAD_PARENT (pad));
       
  1553 
       
  1554   GST_LOG_OBJECT (mp3parse, "buffer of %d bytes", GST_BUFFER_SIZE (buf));
       
  1555 
       
  1556   timestamp = GST_BUFFER_TIMESTAMP (buf);
       
  1557 
       
  1558   mp3parse->discont |= GST_BUFFER_IS_DISCONT (buf);
       
  1559 
       
  1560   /* If we don't yet have a next timestamp, save it and the incoming offset
       
  1561    * so we can apply it to the right outgoing buffer */
       
  1562   if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
       
  1563     gint64 avail = gst_adapter_available (mp3parse->adapter);
       
  1564 
       
  1565     mp3parse->pending_ts = timestamp;
       
  1566     mp3parse->pending_offset = mp3parse->tracked_offset + avail;
       
  1567 
       
  1568     /* If we have no data pending and the next timestamp is
       
  1569      * invalid we can use the upstream timestamp for the next frame.
       
  1570      *
       
  1571      * This will give us a timestamp if we're resyncing and upstream
       
  1572      * gave us -1 as offset. */
       
  1573     if (avail == 0 && !GST_CLOCK_TIME_IS_VALID (mp3parse->next_ts))
       
  1574       mp3parse->next_ts = timestamp;
       
  1575 
       
  1576     GST_LOG_OBJECT (mp3parse, "Have pending ts %" GST_TIME_FORMAT
       
  1577         " to apply in %" G_GINT64_FORMAT " bytes (@ off %" G_GINT64_FORMAT ")",
       
  1578         GST_TIME_ARGS (mp3parse->pending_ts), avail, mp3parse->pending_offset);
       
  1579   }
       
  1580 
       
  1581   /* Update the cur_offset we'll apply to outgoing buffers */
       
  1582   if (mp3parse->cur_offset == -1 && GST_BUFFER_OFFSET (buf) != -1)
       
  1583     mp3parse->cur_offset = GST_BUFFER_OFFSET (buf);
       
  1584 
       
  1585   /* And add the data to the pool */
       
  1586   gst_adapter_push (mp3parse->adapter, buf);
       
  1587 
       
  1588   return gst_mp3parse_handle_data (mp3parse, FALSE);
       
  1589 }
       
  1590 
       
  1591 static gboolean
       
  1592 head_check (GstMPEGAudioParse * mp3parse, unsigned long head)
       
  1593 {
       
  1594   GST_DEBUG_OBJECT (mp3parse, "checking mp3 header 0x%08lx", head);
       
  1595   /* if it's not a valid sync */
       
  1596   if ((head & 0xffe00000) != 0xffe00000) {
       
  1597     GST_WARNING_OBJECT (mp3parse, "invalid sync");
       
  1598     return FALSE;
       
  1599   }
       
  1600   /* if it's an invalid MPEG version */
       
  1601   if (((head >> 19) & 3) == 0x1) {
       
  1602     GST_WARNING_OBJECT (mp3parse, "invalid MPEG version: 0x%lx",
       
  1603         (head >> 19) & 3);
       
  1604     return FALSE;
       
  1605   }
       
  1606   /* if it's an invalid layer */
       
  1607   if (!((head >> 17) & 3)) {
       
  1608     GST_WARNING_OBJECT (mp3parse, "invalid layer: 0x%lx", (head >> 17) & 3);
       
  1609     return FALSE;
       
  1610   }
       
  1611   /* if it's an invalid bitrate */
       
  1612   if (((head >> 12) & 0xf) == 0x0) {
       
  1613     GST_WARNING_OBJECT (mp3parse, "invalid bitrate: 0x%lx."
       
  1614         "Free format files are not supported yet", (head >> 12) & 0xf);
       
  1615     return FALSE;
       
  1616   }
       
  1617   if (((head >> 12) & 0xf) == 0xf) {
       
  1618     GST_WARNING_OBJECT (mp3parse, "invalid bitrate: 0x%lx", (head >> 12) & 0xf);
       
  1619     return FALSE;
       
  1620   }
       
  1621   /* if it's an invalid samplerate */
       
  1622   if (((head >> 10) & 0x3) == 0x3) {
       
  1623     GST_WARNING_OBJECT (mp3parse, "invalid samplerate: 0x%lx",
       
  1624         (head >> 10) & 0x3);
       
  1625     return FALSE;
       
  1626   }
       
  1627 
       
  1628   if ((head & 0x3) == 0x2) {
       
  1629     /* Ignore this as there are some files with emphasis 0x2 that can
       
  1630      * be played fine. See BGO #537235 */
       
  1631     GST_WARNING_OBJECT (mp3parse, "invalid emphasis: 0x%lx", head & 0x3);
       
  1632   }
       
  1633 
       
  1634   return TRUE;
       
  1635 }
       
  1636 
       
  1637 static void
       
  1638 gst_mp3parse_set_property (GObject * object, guint prop_id,
       
  1639     const GValue * value, GParamSpec * pspec)
       
  1640 {
       
  1641   GstMPEGAudioParse *src;
       
  1642 
       
  1643   src = GST_MP3PARSE (object);
       
  1644 
       
  1645   switch (prop_id) {
       
  1646     case ARG_SKIP:
       
  1647       src->skip = g_value_get_int (value);
       
  1648       break;
       
  1649     default:
       
  1650       break;
       
  1651   }
       
  1652 }
       
  1653 
       
  1654 static void
       
  1655 gst_mp3parse_get_property (GObject * object, guint prop_id, GValue * value,
       
  1656     GParamSpec * pspec)
       
  1657 {
       
  1658   GstMPEGAudioParse *src;
       
  1659 
       
  1660   src = GST_MP3PARSE (object);
       
  1661 
       
  1662   switch (prop_id) {
       
  1663     case ARG_SKIP:
       
  1664       g_value_set_int (value, src->skip);
       
  1665       break;
       
  1666     case ARG_BIT_RATE:
       
  1667       g_value_set_int (value, src->bit_rate * 1000);
       
  1668       break;
       
  1669     default:
       
  1670       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
  1671       break;
       
  1672   }
       
  1673 }
       
  1674 
       
  1675 static GstStateChangeReturn
       
  1676 gst_mp3parse_change_state (GstElement * element, GstStateChange transition)
       
  1677 {
       
  1678   GstMPEGAudioParse *mp3parse;
       
  1679   GstStateChangeReturn result;
       
  1680 
       
  1681   mp3parse = GST_MP3PARSE (element);
       
  1682 
       
  1683   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
  1684 
       
  1685   switch (transition) {
       
  1686     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
  1687       gst_mp3parse_reset (mp3parse);
       
  1688       break;
       
  1689     default:
       
  1690       break;
       
  1691   }
       
  1692 
       
  1693   return result;
       
  1694 }
       
  1695 
       
  1696 static gboolean
       
  1697 mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total)
       
  1698 {
       
  1699   GstFormat fmt = GST_FORMAT_BYTES;
       
  1700 
       
  1701   if (gst_pad_query_peer_duration (mp3parse->sinkpad, &fmt, total))
       
  1702     return TRUE;
       
  1703 
       
  1704   if (mp3parse->xing_flags & XING_BYTES_FLAG) {
       
  1705     *total = mp3parse->xing_bytes;
       
  1706     return TRUE;
       
  1707   }
       
  1708 
       
  1709   if (mp3parse->vbri_bytes != 0 && mp3parse->vbri_valid) {
       
  1710     *total = mp3parse->vbri_bytes;
       
  1711     return TRUE;
       
  1712   }
       
  1713 
       
  1714   return FALSE;
       
  1715 }
       
  1716 
       
  1717 static gboolean
       
  1718 mp3parse_total_time (GstMPEGAudioParse * mp3parse, GstClockTime * total)
       
  1719 {
       
  1720   gint64 total_bytes;
       
  1721 
       
  1722   *total = GST_CLOCK_TIME_NONE;
       
  1723 
       
  1724   if (mp3parse->xing_flags & XING_FRAMES_FLAG) {
       
  1725     *total = mp3parse->xing_total_time;
       
  1726     return TRUE;
       
  1727   }
       
  1728 
       
  1729   if (mp3parse->vbri_total_time != 0 && mp3parse->vbri_valid) {
       
  1730     *total = mp3parse->vbri_total_time;
       
  1731     return TRUE;
       
  1732   }
       
  1733 
       
  1734   /* Calculate time from the measured bitrate */
       
  1735   if (!mp3parse_total_bytes (mp3parse, &total_bytes))
       
  1736     return FALSE;
       
  1737 
       
  1738   if (total_bytes != -1
       
  1739       && !mp3parse_bytepos_to_time (mp3parse, total_bytes, total, TRUE))
       
  1740     return FALSE;
       
  1741 
       
  1742   return TRUE;
       
  1743 }
       
  1744 
       
  1745 /* Convert a timestamp to the file position required to start decoding that
       
  1746  * timestamp. For now, this just uses the avg bitrate. Later, use an 
       
  1747  * incrementally accumulated seek table */
       
  1748 static gboolean
       
  1749 mp3parse_time_to_bytepos (GstMPEGAudioParse * mp3parse, GstClockTime ts,
       
  1750     gint64 * bytepos)
       
  1751 {
       
  1752   gint64 total_bytes;
       
  1753   GstClockTime total_time;
       
  1754 
       
  1755   /* -1 always maps to -1 */
       
  1756   if (ts == -1) {
       
  1757     *bytepos = -1;
       
  1758     return TRUE;
       
  1759   }
       
  1760 
       
  1761   /* If XING seek table exists use this for time->byte conversion */
       
  1762   if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
       
  1763       (total_bytes = mp3parse->xing_bytes) &&
       
  1764       (total_time = mp3parse->xing_total_time)) {
       
  1765     gdouble fa, fb, fx;
       
  1766     gdouble percent =
       
  1767         CLAMP ((100.0 * gst_util_guint64_to_gdouble (ts)) /
       
  1768         gst_util_guint64_to_gdouble (total_time), 0.0, 100.0);
       
  1769     gint index = CLAMP (percent, 0, 99);
       
  1770 
       
  1771     fa = mp3parse->xing_seek_table[index];
       
  1772     if (index < 99)
       
  1773       fb = mp3parse->xing_seek_table[index + 1];
       
  1774     else
       
  1775       fb = 256.0;
       
  1776 
       
  1777     fx = fa + (fb - fa) * (percent - index);
       
  1778 
       
  1779     *bytepos = (1.0 / 256.0) * fx * total_bytes;
       
  1780 
       
  1781     return TRUE;
       
  1782   }
       
  1783 
       
  1784   if (mp3parse->vbri_seek_table && (total_bytes = mp3parse->vbri_bytes) &&
       
  1785       (total_time = mp3parse->vbri_total_time)) {
       
  1786     gint i, j;
       
  1787     gdouble a, b, fa, fb;
       
  1788 
       
  1789     i = gst_util_uint64_scale (ts, mp3parse->vbri_seek_points - 1, total_time);
       
  1790     i = CLAMP (i, 0, mp3parse->vbri_seek_points - 1);
       
  1791 
       
  1792     a = gst_guint64_to_gdouble (gst_util_uint64_scale (i, total_time,
       
  1793             mp3parse->vbri_seek_points));
       
  1794     fa = 0.0;
       
  1795     for (j = i; j >= 0; j--)
       
  1796       fa += mp3parse->vbri_seek_table[j];
       
  1797 
       
  1798     if (i + 1 < mp3parse->vbri_seek_points) {
       
  1799       b = gst_guint64_to_gdouble (gst_util_uint64_scale (i + 1, total_time,
       
  1800               mp3parse->vbri_seek_points));
       
  1801       fb = fa + mp3parse->vbri_seek_table[i + 1];
       
  1802     } else {
       
  1803       b = gst_guint64_to_gdouble (total_time);
       
  1804       fb = total_bytes;
       
  1805     }
       
  1806 
       
  1807     *bytepos = fa + ((fb - fa) / (b - a)) * (gst_guint64_to_gdouble (ts) - a);
       
  1808 
       
  1809     return TRUE;
       
  1810   }
       
  1811 
       
  1812   if (mp3parse->avg_bitrate == 0)
       
  1813     goto no_bitrate;
       
  1814 
       
  1815   *bytepos =
       
  1816       gst_util_uint64_scale (ts, mp3parse->avg_bitrate, (8 * GST_SECOND));
       
  1817   return TRUE;
       
  1818 no_bitrate:
       
  1819   GST_DEBUG_OBJECT (mp3parse, "Cannot seek yet - no average bitrate");
       
  1820   return FALSE;
       
  1821 }
       
  1822 
       
  1823 static gboolean
       
  1824 mp3parse_bytepos_to_time (GstMPEGAudioParse * mp3parse,
       
  1825     gint64 bytepos, GstClockTime * ts, gboolean from_total_time)
       
  1826 {
       
  1827   gint64 total_bytes;
       
  1828   GstClockTime total_time;
       
  1829 
       
  1830   if (bytepos == -1) {
       
  1831     *ts = GST_CLOCK_TIME_NONE;
       
  1832     return TRUE;
       
  1833   }
       
  1834 
       
  1835   if (bytepos == 0) {
       
  1836     *ts = 0;
       
  1837     return TRUE;
       
  1838   }
       
  1839 
       
  1840   /* If XING seek table exists use this for byte->time conversion */
       
  1841   if (!from_total_time && (mp3parse->xing_flags & XING_TOC_FLAG) &&
       
  1842       (total_bytes = mp3parse->xing_bytes) &&
       
  1843       (total_time = mp3parse->xing_total_time)) {
       
  1844     gdouble fa, fb, fx;
       
  1845     gdouble pos;
       
  1846     gint index;
       
  1847 
       
  1848     pos = CLAMP ((bytepos * 256.0) / total_bytes, 0.0, 256.0);
       
  1849     index = CLAMP (pos, 0, 255);
       
  1850     fa = mp3parse->xing_seek_table_inverse[index];
       
  1851     if (index < 255)
       
  1852       fb = mp3parse->xing_seek_table_inverse[index + 1];
       
  1853     else
       
  1854       fb = 10000.0;
       
  1855 
       
  1856     fx = fa + (fb - fa) * (pos - index);
       
  1857 
       
  1858     *ts = (1.0 / 10000.0) * fx * gst_util_guint64_to_gdouble (total_time);
       
  1859 
       
  1860     return TRUE;
       
  1861   }
       
  1862 
       
  1863   if (!from_total_time && mp3parse->vbri_seek_table &&
       
  1864       (total_bytes = mp3parse->vbri_bytes) &&
       
  1865       (total_time = mp3parse->vbri_total_time)) {
       
  1866     gint i = 0;
       
  1867     guint64 sum = 0;
       
  1868     gdouble a, b, fa, fb;
       
  1869 
       
  1870     do {
       
  1871       sum += mp3parse->vbri_seek_table[i];
       
  1872       i++;
       
  1873     } while (i + 1 < mp3parse->vbri_seek_points
       
  1874         && sum + mp3parse->vbri_seek_table[i] < bytepos);
       
  1875     i--;
       
  1876 
       
  1877     a = gst_guint64_to_gdouble (sum);
       
  1878     fa = gst_guint64_to_gdouble (gst_util_uint64_scale (i, total_time,
       
  1879             mp3parse->vbri_seek_points));
       
  1880 
       
  1881     if (i + 1 < mp3parse->vbri_seek_points) {
       
  1882       b = a + mp3parse->vbri_seek_table[i + 1];
       
  1883       fb = gst_guint64_to_gdouble (gst_util_uint64_scale (i + 1, total_time,
       
  1884               mp3parse->vbri_seek_points));
       
  1885     } else {
       
  1886       b = total_bytes;
       
  1887       fb = gst_guint64_to_gdouble (total_time);
       
  1888     }
       
  1889 
       
  1890     *ts = gst_gdouble_to_guint64 (fa + ((fb - fa) / (b - a)) * (bytepos - a));
       
  1891 
       
  1892     return TRUE;
       
  1893   }
       
  1894 
       
  1895   /* Cannot convert anything except 0 if we don't have a bitrate yet */
       
  1896   if (mp3parse->avg_bitrate == 0)
       
  1897     return FALSE;
       
  1898 
       
  1899   *ts = (GstClockTime) gst_util_uint64_scale (GST_SECOND, bytepos * 8,
       
  1900       mp3parse->avg_bitrate);
       
  1901   return TRUE;
       
  1902 }
       
  1903 
       
  1904 static gboolean
       
  1905 mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event)
       
  1906 {
       
  1907   GstFormat format;
       
  1908   gdouble rate;
       
  1909   GstSeekFlags flags;
       
  1910   GstSeekType cur_type, stop_type;
       
  1911   gint64 cur, stop;
       
  1912   gint64 byte_cur, byte_stop;
       
  1913   MPEGAudioPendingAccurateSeek *seek;
       
  1914   GstClockTime start;
       
  1915 
       
  1916   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
       
  1917       &stop_type, &stop);
       
  1918 
       
  1919   GST_DEBUG_OBJECT (mp3parse, "Performing seek to %" GST_TIME_FORMAT,
       
  1920       GST_TIME_ARGS (cur));
       
  1921 
       
  1922   /* For any format other than TIME, see if upstream handles
       
  1923    * it directly or fail. For TIME, try upstream, but do it ourselves if
       
  1924    * it fails upstream */
       
  1925   if (format != GST_FORMAT_TIME) {
       
  1926     gst_event_ref (event);
       
  1927     return gst_pad_push_event (mp3parse->sinkpad, event);
       
  1928   } else {
       
  1929     gst_event_ref (event);
       
  1930     if (gst_pad_push_event (mp3parse->sinkpad, event))
       
  1931       return TRUE;
       
  1932   }
       
  1933 
       
  1934   seek = g_new0 (MPEGAudioPendingAccurateSeek, 1);
       
  1935 
       
  1936   seek->segment = mp3parse->segment;
       
  1937 
       
  1938   gst_segment_set_seek (&seek->segment, rate, GST_FORMAT_TIME,
       
  1939       flags, cur_type, cur, stop_type, stop, NULL);
       
  1940 
       
  1941   /* Handle TIME based seeks by converting to a BYTE position */
       
  1942 
       
  1943   /* For accurate seeking get the frame 9 (MPEG1) or 29 (MPEG2) frames
       
  1944    * before the one we want to seek to and push them all to the decoder.
       
  1945    *
       
  1946    * This is necessary because of the bit reservoir. See
       
  1947    * http://www.mars.org/mailman/public/mad-dev/2002-May/000634.html
       
  1948    *
       
  1949    */
       
  1950 
       
  1951   if (flags & GST_SEEK_FLAG_ACCURATE) {
       
  1952     if (!mp3parse->seek_table) {
       
  1953       byte_cur = 0;
       
  1954       byte_stop = -1;
       
  1955       start = 0;
       
  1956     } else {
       
  1957       MPEGAudioSeekEntry *entry = NULL, *start_entry = NULL, *stop_entry = NULL;
       
  1958       GList *start_node, *stop_node;
       
  1959       gint64 seek_ts = (cur > mp3parse->max_bitreservoir) ?
       
  1960           (cur - mp3parse->max_bitreservoir) : 0;
       
  1961 
       
  1962       for (start_node = mp3parse->seek_table; start_node;
       
  1963           start_node = start_node->next) {
       
  1964         entry = start_node->data;
       
  1965 
       
  1966         if (seek_ts >= entry->timestamp) {
       
  1967           start_entry = entry;
       
  1968           break;
       
  1969         }
       
  1970       }
       
  1971 
       
  1972       if (!start_entry) {
       
  1973         start_entry = mp3parse->seek_table->data;
       
  1974         start = start_entry->timestamp;
       
  1975         byte_cur = start_entry->byte;
       
  1976       } else {
       
  1977         start = start_entry->timestamp;
       
  1978         byte_cur = start_entry->byte;
       
  1979       }
       
  1980 
       
  1981       for (stop_node = mp3parse->seek_table; stop_node;
       
  1982           stop_node = stop_node->next) {
       
  1983         entry = stop_node->data;
       
  1984 
       
  1985         if (stop >= entry->timestamp) {
       
  1986           stop_node = stop_node->prev;
       
  1987           stop_entry = (stop_node) ? stop_node->data : NULL;
       
  1988           break;
       
  1989         }
       
  1990       }
       
  1991 
       
  1992       if (!stop_entry) {
       
  1993         byte_stop = -1;
       
  1994       } else {
       
  1995         byte_stop = stop_entry->byte;
       
  1996       }
       
  1997 
       
  1998     }
       
  1999     event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
       
  2000         byte_cur, stop_type, byte_stop);
       
  2001     g_mutex_lock (mp3parse->pending_seeks_lock);
       
  2002     seek->upstream_start = byte_cur;
       
  2003     seek->timestamp_start = start;
       
  2004     mp3parse->pending_accurate_seeks =
       
  2005         g_slist_prepend (mp3parse->pending_accurate_seeks, seek);
       
  2006     g_mutex_unlock (mp3parse->pending_seeks_lock);
       
  2007     if (gst_pad_push_event (mp3parse->sinkpad, event)) {
       
  2008       mp3parse->exact_position = TRUE;
       
  2009       return TRUE;
       
  2010     } else {
       
  2011       mp3parse->exact_position = TRUE;
       
  2012       g_mutex_lock (mp3parse->pending_seeks_lock);
       
  2013       mp3parse->pending_accurate_seeks =
       
  2014           g_slist_remove (mp3parse->pending_accurate_seeks, seek);
       
  2015       g_mutex_unlock (mp3parse->pending_seeks_lock);
       
  2016       g_free (seek);
       
  2017       return FALSE;
       
  2018     }
       
  2019   }
       
  2020 
       
  2021   mp3parse->exact_position = FALSE;
       
  2022 
       
  2023   /* Convert the TIME to the appropriate BYTE position at which to resume
       
  2024    * decoding. */
       
  2025   if (!mp3parse_time_to_bytepos (mp3parse, (GstClockTime) cur, &byte_cur))
       
  2026     goto no_pos;
       
  2027   if (!mp3parse_time_to_bytepos (mp3parse, (GstClockTime) stop, &byte_stop))
       
  2028     goto no_pos;
       
  2029 
       
  2030   GST_DEBUG_OBJECT (mp3parse, "Seeking to byte range %" G_GINT64_FORMAT
       
  2031       " to %" G_GINT64_FORMAT, byte_cur, byte_stop);
       
  2032 
       
  2033   /* Send BYTE based seek upstream */
       
  2034   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
       
  2035       byte_cur, stop_type, byte_stop);
       
  2036 
       
  2037   GST_LOG_OBJECT (mp3parse, "Storing pending seek");
       
  2038   g_mutex_lock (mp3parse->pending_seeks_lock);
       
  2039   seek->upstream_start = byte_cur;
       
  2040   seek->timestamp_start = cur;
       
  2041   mp3parse->pending_nonaccurate_seeks =
       
  2042       g_slist_prepend (mp3parse->pending_nonaccurate_seeks, seek);
       
  2043   g_mutex_unlock (mp3parse->pending_seeks_lock);
       
  2044   if (gst_pad_push_event (mp3parse->sinkpad, event)) {
       
  2045     return TRUE;
       
  2046   } else {
       
  2047     g_mutex_lock (mp3parse->pending_seeks_lock);
       
  2048     mp3parse->pending_nonaccurate_seeks =
       
  2049         g_slist_remove (mp3parse->pending_nonaccurate_seeks, seek);
       
  2050     g_mutex_unlock (mp3parse->pending_seeks_lock);
       
  2051     g_free (seek);
       
  2052     return FALSE;
       
  2053   }
       
  2054 
       
  2055 no_pos:
       
  2056   GST_DEBUG_OBJECT (mp3parse,
       
  2057       "Could not determine byte position for desired time");
       
  2058   return FALSE;
       
  2059 }
       
  2060 
       
  2061 static gboolean
       
  2062 mp3parse_src_event (GstPad * pad, GstEvent * event)
       
  2063 {
       
  2064   GstMPEGAudioParse *mp3parse;
       
  2065   gboolean res = FALSE;
       
  2066 
       
  2067   mp3parse = GST_MP3PARSE (gst_pad_get_parent (pad));
       
  2068 
       
  2069   switch (GST_EVENT_TYPE (event)) {
       
  2070     case GST_EVENT_SEEK:
       
  2071       res = mp3parse_handle_seek (mp3parse, event);
       
  2072       gst_event_unref (event);
       
  2073       break;
       
  2074     default:
       
  2075       res = gst_pad_event_default (pad, event);
       
  2076       break;
       
  2077   }
       
  2078 
       
  2079   gst_object_unref (mp3parse);
       
  2080   return res;
       
  2081 }
       
  2082 
       
  2083 static gboolean
       
  2084 mp3parse_src_query (GstPad * pad, GstQuery * query)
       
  2085 {
       
  2086   GstFormat format;
       
  2087   GstClockTime total;
       
  2088   GstMPEGAudioParse *mp3parse;
       
  2089   gboolean res = FALSE;
       
  2090   GstPad *peer;
       
  2091 
       
  2092   mp3parse = GST_MP3PARSE (gst_pad_get_parent (pad));
       
  2093 
       
  2094   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
       
  2095 
       
  2096   switch (GST_QUERY_TYPE (query)) {
       
  2097     case GST_QUERY_POSITION:
       
  2098       gst_query_parse_position (query, &format, NULL);
       
  2099 
       
  2100       if (format == GST_FORMAT_BYTES || format == GST_FORMAT_DEFAULT) {
       
  2101         if (mp3parse->cur_offset != -1) {
       
  2102           gst_query_set_position (query, GST_FORMAT_BYTES,
       
  2103               mp3parse->cur_offset);
       
  2104           res = TRUE;
       
  2105         }
       
  2106       } else if (format == GST_FORMAT_TIME) {
       
  2107         if (mp3parse->next_ts == GST_CLOCK_TIME_NONE)
       
  2108           goto out;
       
  2109         gst_query_set_position (query, GST_FORMAT_TIME, mp3parse->next_ts);
       
  2110         res = TRUE;
       
  2111       }
       
  2112 
       
  2113       /* If no answer above, see if upstream knows */
       
  2114       if (!res) {
       
  2115         if ((peer = gst_pad_get_peer (mp3parse->sinkpad)) != NULL) {
       
  2116           res = gst_pad_query (peer, query);
       
  2117           gst_object_unref (peer);
       
  2118           if (res)
       
  2119             goto out;
       
  2120         }
       
  2121       }
       
  2122       break;
       
  2123     case GST_QUERY_DURATION:
       
  2124       gst_query_parse_duration (query, &format, NULL);
       
  2125 
       
  2126       /* First, see if upstream knows */
       
  2127       if ((peer = gst_pad_get_peer (mp3parse->sinkpad)) != NULL) {
       
  2128         res = gst_pad_query (peer, query);
       
  2129         gst_object_unref (peer);
       
  2130         if (res)
       
  2131           goto out;
       
  2132       }
       
  2133 
       
  2134       if (format == GST_FORMAT_TIME) {
       
  2135         if (!mp3parse_total_time (mp3parse, &total) || total == -1)
       
  2136           goto out;
       
  2137         gst_query_set_duration (query, format, total);
       
  2138         res = TRUE;
       
  2139       }
       
  2140       break;
       
  2141     case GST_QUERY_SEEKING:
       
  2142       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
       
  2143 
       
  2144       /* does upstream handle ? */
       
  2145       if ((peer = gst_pad_get_peer (mp3parse->sinkpad)) != NULL) {
       
  2146         res = gst_pad_query (peer, query);
       
  2147         gst_object_unref (peer);
       
  2148       }
       
  2149       /* we may be able to help if in TIME */
       
  2150       if (format == GST_FORMAT_TIME) {
       
  2151         gboolean seekable;
       
  2152 
       
  2153         gst_query_parse_seeking (query, &format, &seekable, NULL, NULL);
       
  2154         /* already OK if upstream takes care */
       
  2155         if (!(res && seekable)) {
       
  2156           gint64 pos;
       
  2157 
       
  2158           seekable = TRUE;
       
  2159           if (!mp3parse_total_time (mp3parse, &total) || total == -1) {
       
  2160             seekable = FALSE;
       
  2161           } else if (!mp3parse_time_to_bytepos (mp3parse, 0, &pos)) {
       
  2162             seekable = FALSE;
       
  2163           } else {
       
  2164             GstQuery *q;
       
  2165 
       
  2166             q = gst_query_new_seeking (GST_FORMAT_BYTES);
       
  2167             if (!gst_pad_peer_query (mp3parse->sinkpad, q)) {
       
  2168               seekable = FALSE;
       
  2169             } else {
       
  2170               gst_query_parse_seeking (q, &format, &seekable, NULL, NULL);
       
  2171             }
       
  2172             gst_query_unref (q);
       
  2173           }
       
  2174           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, total);
       
  2175           res = TRUE;
       
  2176         }
       
  2177       }
       
  2178       break;
       
  2179     default:
       
  2180       res = gst_pad_query_default (pad, query);
       
  2181       break;
       
  2182   }
       
  2183 
       
  2184 out:
       
  2185   gst_object_unref (mp3parse);
       
  2186   return res;
       
  2187 }
       
  2188 
       
  2189 static const GstQueryType *
       
  2190 mp3parse_get_query_types (GstPad * pad G_GNUC_UNUSED)
       
  2191 {
       
  2192   static const GstQueryType query_types[] = {
       
  2193     GST_QUERY_POSITION,
       
  2194     GST_QUERY_DURATION,
       
  2195     0
       
  2196   };
       
  2197 
       
  2198   return query_types;
       
  2199 }