- Cleanup
authorThibaut Mattern <tmattern@users.sourceforge.net>
Sat, 01 Oct 2005 08:03:36 +0000
changeset 76250f6618441605
parent 7624 3fb4319ce9ff
child 7626 ecd30a5c2314
- Cleanup
- Added vbri header support
- Fixed seeking problem with id3v2 tags
- Converted position to a time based position

CVS patchset: 7747
CVS date: 2005/10/01 08:03:36
src/demuxers/demux_mpgaudio.c
     1.1 --- a/src/demuxers/demux_mpgaudio.c	Tue Sep 27 02:05:31 2005 +0000
     1.2 +++ b/src/demuxers/demux_mpgaudio.c	Sat Oct 01 08:03:36 2005 +0000
     1.3 @@ -17,12 +17,12 @@
     1.4   * along with this program; if not, write to the Free Software
     1.5   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
     1.6   *
     1.7 - * $Id: demux_mpgaudio.c,v 1.141 2005/09/15 18:45:15 tmattern Exp $
     1.8 + * $Id: demux_mpgaudio.c,v 1.142 2005/10/01 08:03:36 tmattern Exp $
     1.9   *
    1.10   * demultiplexer for mpeg audio (i.e. mp3) streams
    1.11   *
    1.12   * mp3 file structure:
    1.13 - *   [id3v2] [Xing] Frame1 Frame2 Frame3... [id3v1]
    1.14 + *   [id3v2][Xing|Vbri] Frame1 Frame2 Frame3...FrameX [Lyrics][id3v2][id3v1]
    1.15   *
    1.16   */
    1.17  
    1.18 @@ -49,8 +49,11 @@
    1.19  #include "group_audio.h"
    1.20  #include "id3.h"
    1.21  
    1.22 -#define NUM_PREVIEW_BUFFERS  10
    1.23 -#define SNIFF_BUFFER_LENGTH  1024
    1.24 +/* 2 preview buffers are enough,
    1.25 + * the first mp3 frame is potentially a vbr header (xing, vbri)
    1.26 + * the second mp3 frame is sent to the decoder
    1.27 + */
    1.28 +#define NUM_PREVIEW_BUFFERS  2
    1.29  
    1.30  #define WRAP_THRESHOLD       120000
    1.31  
    1.32 @@ -70,6 +73,10 @@
    1.33  #define XING_VBR_SCALE_FLAG  0x0008
    1.34  #define XING_TOC_LENGTH      100
    1.35  
    1.36 +/* Xing header stuff */
    1.37 +#define VBRI_TAG FOURCC_TAG('V', 'B', 'R', 'I')
    1.38 +
    1.39 +/* mp3 frame struct */
    1.40  typedef struct {
    1.41    /* header */
    1.42    uint16_t  frame_sync;
    1.43 @@ -87,48 +94,65 @@
    1.44    uint8_t   original;
    1.45    uint8_t   emphasis;
    1.46  
    1.47 -  uint8_t   version_idx;
    1.48 -  int       bitrate;
    1.49 -  int       samplerate;
    1.50 -  int       length;               /* in bytes */
    1.51 -  double    duration;             /* in 1/90000 s */
    1.52 +  uint8_t   version_idx;          /* 0: mpeg1, 1: mpeg2, 2: mpeg2.5 */
    1.53 +  int       bitrate;              /* in bit per second */
    1.54 +  int       freq;                 /* in Hz */
    1.55 +  int       samples;              /* samples per frame */
    1.56 +  int       padding;              /* padding bytes (0, 1 or 4)*/
    1.57 +  int       size;                 /* in bytes */
    1.58 +  double    duration;             /* in xine pts */
    1.59  } mpg_audio_frame_t;
    1.60  
    1.61 +/* Xing Vbr Header struct */
    1.62 +typedef struct {
    1.63 +  uint32_t             flags;
    1.64 +  uint32_t             stream_frames;
    1.65 +  uint32_t             stream_size;
    1.66 +  uint8_t              toc[XING_TOC_LENGTH];
    1.67 +  uint32_t             vbr_scale;
    1.68 +} xing_header_t;
    1.69  
    1.70 +/* Vbri Vbr Header struct */
    1.71 +typedef struct {
    1.72 +  uint16_t             version;
    1.73 +  uint16_t             delai;
    1.74 +  uint16_t             quality;
    1.75 +  uint32_t             stream_size;
    1.76 +  uint32_t             stream_frames;
    1.77 +  uint16_t             toc_entries;
    1.78 +  uint16_t             toc_scale_factor;
    1.79 +  uint16_t             entry_size;
    1.80 +  uint16_t             entry_frames;
    1.81 +  int                 *toc;
    1.82 +} vbri_header_t;
    1.83 +
    1.84 +/* demuxer instance struct */
    1.85  typedef struct {
    1.86  
    1.87    demux_plugin_t       demux_plugin;
    1.88 -
    1.89    xine_stream_t       *stream;
    1.90 -
    1.91    fifo_buffer_t       *audio_fifo;
    1.92 -
    1.93    input_plugin_t      *input;
    1.94 -
    1.95    int                  status;
    1.96  
    1.97 -  int                  stream_length;
    1.98 -  int                  br;               /* bitrate */
    1.99 -  int                  abr;              /* average bitrate */
   1.100 -  int64_t              last_pts;
   1.101 -  int                  send_newpts;
   1.102 -  int                  buf_flag_seek;
   1.103 +  uint32_t             stream_length;    /* in seconds */
   1.104 +  int                  br;               /* bitrate in bits/second */
   1.105    uint32_t             blocksize;
   1.106  
   1.107    mpg_audio_frame_t    cur_frame;
   1.108 -  double               cur_fpts;
   1.109 -  int                  is_vbr;
   1.110 -  int                  meta_info_flag;
   1.111 +  double               cur_time;         /* in milliseconds */
   1.112  
   1.113 -  /* Xing header */
   1.114 -  int                  check_xing;
   1.115 -  uint32_t             xflags;
   1.116 -  uint32_t             xframes;
   1.117 -  uint32_t             xbytes;
   1.118 -  uint8_t              xtoc[100];
   1.119 -  uint32_t             xvbr_scale;
   1.120 +  off_t                mpg_frame_start;  /* offset */
   1.121 +  off_t                mpg_frame_end;    /* offset */
   1.122 +  off_t                mpg_size;         /* in bytes */
   1.123 +
   1.124 +  int                  check_vbr_header;
   1.125 +  xing_header_t       *xing_header;
   1.126 +  vbri_header_t       *vbri_header;
   1.127 +  
   1.128  } demux_mpgaudio_t ;
   1.129  
   1.130 +/* demuxer class struct */
   1.131  typedef struct {
   1.132  
   1.133    demux_class_t     demux_class;
   1.134 @@ -139,53 +163,47 @@
   1.135  
   1.136  } demux_mpgaudio_class_t;
   1.137  
   1.138 -/* bitrate table tabsel_123[mpeg version][layer][bitrate index]
   1.139 +/* bitrate table[mpeg version][layer][bitrate index]
   1.140   * values stored in kbps
   1.141   */
   1.142 -const int tabsel_123[2][3][16] = {
   1.143 -   { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,},
   1.144 -     {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,},
   1.145 -     {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} },
   1.146 -
   1.147 -   { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,},
   1.148 -     {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,},
   1.149 -     {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,} }
   1.150 +const int mp3_bitrates[3][3][16] = {
   1.151 +   { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
   1.152 +     {0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384,},
   1.153 +     {0, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320,} },
   1.154 +   { {0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256,},
   1.155 +     {0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160,},
   1.156 +     {0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160,} },
   1.157 +   { {0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256,},
   1.158 +     {0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160,},
   1.159 +     {0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160,} }
   1.160  };
   1.161  
   1.162 -static int frequencies[3][3] = {
   1.163 +/* frequency table[mpeg version][frequence index] (in KHz) */
   1.164 +static int mp3_freqs[3][3] = {
   1.165  	{ 44100, 48000, 32000 },
   1.166  	{ 22050, 24000, 16000 },
   1.167  	{ 11025, 12000,  8000 }
   1.168  };
   1.169  
   1.170 +/* samples per frame table[mpeg version][layer] */
   1.171 +static int mp3_samples[3][3] = {
   1.172 +	{ 384, 1152, 1152 },
   1.173 +	{ 384, 1152, 576 },
   1.174 +	{ 384, 1152, 576 }
   1.175 +};
   1.176  
   1.177 -static int mpg123_xhead_check(char *buf)
   1.178 -{
   1.179 -  return (BE_32(buf) == XING_TAG);
   1.180 -}
   1.181 +/* samples per frame table[layer][padding bit] */
   1.182 +static int mp3_paddings[3][2] = {
   1.183 +	{ 0, 4 },
   1.184 +	{ 0, 1 },
   1.185 +	{ 0, 1 }
   1.186 +};
   1.187  
   1.188 -static void check_newpts (demux_mpgaudio_t *this, int64_t pts) {
   1.189 -
   1.190 -  int64_t diff;
   1.191 -
   1.192 -  diff = pts - this->last_pts;
   1.193 -
   1.194 -  if( pts &&
   1.195 -      (this->send_newpts || (this->last_pts && abs(diff)>WRAP_THRESHOLD) ) ) {
   1.196 -    if (this->buf_flag_seek) {
   1.197 -      _x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK);
   1.198 -      this->buf_flag_seek = 0;
   1.199 -    } else {
   1.200 -      _x_demux_control_newpts(this->stream, pts, 0);
   1.201 -    }
   1.202 -    this->send_newpts = 0;
   1.203 -  }
   1.204 -
   1.205 -  if( pts )
   1.206 -    this->last_pts = pts;
   1.207 -}
   1.208 -
   1.209 -static int mpg123_parse_frame_header(mpg_audio_frame_t *frame, uint8_t *buf) {
   1.210 +/*
   1.211 + * Parse a mp3 frame
   1.212 + * return 1 on success
   1.213 + */
   1.214 +static int parse_frame_header(mpg_audio_frame_t *frame, uint8_t *buf) {
   1.215    uint32_t head;
   1.216  
   1.217    head = BE_32(buf);
   1.218 @@ -251,40 +269,47 @@
   1.219    }
   1.220  #endif
   1.221    
   1.222 -  frame->bitrate = tabsel_123[!frame->lsf_bit][frame->layer - 1][frame->bitrate_idx] * 1000;
   1.223 -  frame->samplerate = frequencies[frame->version_idx][frame->freq_idx];
   1.224 -  if (frame->layer == 1) {
   1.225 -    frame->length = (12 * frame->bitrate / frame->samplerate + frame->padding_bit) * 4;
   1.226 -    frame->duration = 90000.0 * 384.0 / (double)frame->samplerate;
   1.227 -  } else {
   1.228 -    int slots_per_frame;
   1.229 -    slots_per_frame = (frame->layer == 3 && !frame->lsf_bit) ? 72 : 144;
   1.230 +  frame->bitrate = mp3_bitrates[frame->version_idx][frame->layer - 1][frame->bitrate_idx] * 1000;
   1.231 +  frame->freq    = mp3_freqs[frame->version_idx][frame->freq_idx];
   1.232 +  frame->samples = mp3_samples[frame->version_idx][frame->layer - 1];
   1.233 +  frame->padding = mp3_paddings[frame->layer - 1][frame->padding_bit];
   1.234 +  
   1.235 +  frame->size  = frame->samples * (frame->bitrate / 8);
   1.236 +  frame->size /= frame->freq;
   1.237 +  frame->size += frame->padding;
   1.238  
   1.239 -    frame->length = slots_per_frame * frame->bitrate / frame->samplerate +
   1.240 -                    frame->padding_bit;
   1.241 -    frame->duration = 90000.0 * slots_per_frame * 8.0 / (double)frame->samplerate;
   1.242 -  }
   1.243 +  frame->duration  = 1000.0f * (double)frame->samples / (double)frame->freq;
   1.244  
   1.245    lprintf("mpeg %d, layer %d\n", frame->version_idx + 1, frame->layer);
   1.246 -  lprintf("bitrate: %d bps, samplerate: %d Hz\n", frame->bitrate, frame->samplerate);
   1.247 -  lprintf("length: %d bytes, %f pts\n", frame->length, frame->duration);
   1.248 +  lprintf("bitrate: %d bps, samplerate: %d Hz\n", frame->bitrate, frame->freq);
   1.249 +  lprintf("length: %d bytes, %f ms\n", frame->size, frame->duration);
   1.250 +  lprintf("padding: %d bytes\n", frame->padding);
   1.251    return 1;
   1.252  }
   1.253  
   1.254 -static int mpg123_parse_xing_header(demux_mpgaudio_t *this, uint8_t *buf, int bufsize) {
   1.255 +/*
   1.256 + * Parse a Xing header
   1.257 + * return the Xing header or NULL on error
   1.258 + */
   1.259 +static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame,
   1.260 +                                        uint8_t *buf, int bufsize) {
   1.261  
   1.262    int i;
   1.263    uint8_t *ptr = buf;
   1.264 -  double frame_duration;
   1.265 +  xing_header_t *xing;
   1.266 +
   1.267 +  xing = xine_xmalloc (sizeof (xing_header_t));
   1.268 +  if (!xing)
   1.269 +    return NULL;
   1.270  
   1.271    /* offset of the Xing header */
   1.272 -  if (this->cur_frame.lsf_bit) {
   1.273 -    if( this->cur_frame.channel_mode != 3 )
   1.274 +  if (frame->lsf_bit) {
   1.275 +    if (frame->channel_mode != 3)
   1.276        ptr += (32 + 4);
   1.277      else
   1.278        ptr += (17 + 4);
   1.279    } else {
   1.280 -    if( this->cur_frame.channel_mode != 3 )
   1.281 +    if (frame->channel_mode != 3)
   1.282        ptr += (17 + 4);
   1.283      else
   1.284        ptr += (9 + 4);
   1.285 @@ -292,75 +317,144 @@
   1.286    
   1.287    if (ptr >= (buf + bufsize - 4)) return 0;
   1.288    lprintf("checking %08X\n", *ptr);
   1.289 -  if (mpg123_xhead_check(ptr)) {
   1.290 +  if (BE_32(ptr) == XING_TAG) {
   1.291      lprintf("Xing header found\n");
   1.292      ptr += 4;
   1.293      
   1.294      if (ptr >= (buf + bufsize - 4)) return 0;
   1.295 -    this->xflags = BE_32(ptr); ptr += 4;
   1.296 +    xing->flags = BE_32(ptr); ptr += 4;
   1.297  
   1.298 -    if (this->xflags & XING_FRAMES_FLAG) {
   1.299 -	    if (ptr >= (buf + bufsize - 4)) return 0;
   1.300 -      this->xframes = BE_32(ptr); ptr += 4;
   1.301 -      lprintf("xframes: %d\n", this->xframes);
   1.302 +    if (xing->flags & XING_FRAMES_FLAG) {
   1.303 +      if (ptr >= (buf + bufsize - 4)) return 0;
   1.304 +      xing->stream_frames = BE_32(ptr); ptr += 4;
   1.305 +      lprintf("stream frames: %d\n", xing->stream_frames);
   1.306      }
   1.307 -    if (this->xflags & XING_BYTES_FLAG) {
   1.308 +    if (xing->flags & XING_BYTES_FLAG) {
   1.309        if (ptr >= (buf + bufsize - 4)) return 0;
   1.310 -      this->xbytes = BE_32(ptr); ptr += 4;
   1.311 -      lprintf("xbytes: %d\n", this->xbytes);
   1.312 +      xing->stream_size = BE_32(ptr); ptr += 4;
   1.313 +      lprintf("stream size: %d\n", xing->stream_size);
   1.314      }
   1.315 -    if (this->xflags & XING_TOC_FLAG) {
   1.316 +    if (xing->flags & XING_TOC_FLAG) {
   1.317        lprintf("toc found\n");
   1.318        if (ptr >= (buf + bufsize - XING_TOC_LENGTH)) return 0;
   1.319  
   1.320        for (i = 0; i < XING_TOC_LENGTH; i++) {
   1.321 -        this->xtoc[i] = *(ptr + i);
   1.322 +        xing->toc[i] = *(ptr + i);
   1.323  #ifdef LOG
   1.324 -        printf("%d ", this->xtoc[i]);
   1.325 +        printf("%d ", xing->toc[i]);
   1.326  #endif
   1.327        }
   1.328  #ifdef LOG
   1.329        printf("\n");
   1.330  #endif
   1.331 -	    ptr += XING_TOC_LENGTH;
   1.332 +      ptr += XING_TOC_LENGTH;
   1.333      }
   1.334 -    this->xvbr_scale = -1;
   1.335 -    if (this->xflags & XING_VBR_SCALE_FLAG) {
   1.336 +    xing->vbr_scale = -1;
   1.337 +    if (xing->flags & XING_VBR_SCALE_FLAG) {
   1.338        if (ptr >= (buf + bufsize - 4)) return 0;
   1.339 -      this->xvbr_scale = BE_32(ptr);
   1.340 -      lprintf("xvbr_scale: %d\n", this->xvbr_scale);
   1.341 +      xing->vbr_scale = BE_32(ptr);
   1.342 +      lprintf("vbr_scale: %d\n", xing->vbr_scale);
   1.343      }
   1.344  
   1.345 -    /* 1 kbit = 1000 bits ! (and not 1024 bits) */
   1.346 -    if (this->xflags & (XING_FRAMES_FLAG | XING_BYTES_FLAG)) {
   1.347 -      if (this->cur_frame.layer == 1) {
   1.348 -        frame_duration = 384.0 / (double)this->cur_frame.samplerate;
   1.349 -      } else {
   1.350 -        int slots_per_frame;
   1.351 -        slots_per_frame = (this->cur_frame.layer == 3 &&
   1.352 -                           !this->cur_frame.lsf_bit) ? 72 : 144;
   1.353 -        frame_duration = slots_per_frame * 8.0 / (double)this->cur_frame.samplerate;
   1.354 -      }
   1.355 -      this->abr = ((double)this->xbytes * 8.0) / ((double)this->xframes * frame_duration);
   1.356 -      this->stream_length = (double)this->xframes * frame_duration;
   1.357 -      this->is_vbr = 1;
   1.358 -      lprintf("abr: %d bps\n", this->abr);
   1.359 -      lprintf("stream_length: %d s, %d min %d s\n", this->stream_length,
   1.360 -              this->stream_length / 60, this->stream_length % 60);
   1.361 -    } else {
   1.362 -      /* it's a stupid Xing header */
   1.363 -      this->is_vbr = 0;
   1.364 -    }
   1.365 -    return 1;
   1.366 +    return xing;
   1.367    } else {
   1.368      lprintf("Xing header not found\n");
   1.369 -    return 0;
   1.370 +    free(xing);
   1.371 +    return NULL;
   1.372    }
   1.373  }
   1.374  
   1.375 -static int mpg123_parse_frame_payload(demux_mpgaudio_t *this,
   1.376 -                                      uint8_t *frame_header,
   1.377 -                                      int decoder_flags) {
   1.378 +/*
   1.379 + * Parse a Vbri header
   1.380 + * return the Vbri header or NULL on error
   1.381 + */
   1.382 +static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame,
   1.383 +                                        uint8_t *buf, int bufsize) {
   1.384 +
   1.385 +  int i;
   1.386 +  uint8_t *ptr = buf;
   1.387 +  vbri_header_t *vbri;
   1.388 +
   1.389 +  vbri = xine_xmalloc (sizeof (vbri_header_t));
   1.390 +  if (!vbri)
   1.391 +    return NULL;
   1.392 +
   1.393 +  ptr += (32 + 4);
   1.394 +  
   1.395 +  if ((ptr + 4) >= (buf + bufsize)) return 0;
   1.396 +  lprintf("Checking %08X\n", *ptr);
   1.397 +  if (BE_32(ptr) == VBRI_TAG) {
   1.398 +    lprintf("Vbri header found\n");
   1.399 +    ptr += 4;
   1.400 +    
   1.401 +    if ((ptr + 22) >= (buf + bufsize)) return 0;
   1.402 +    vbri->version           = BE_16(ptr); ptr += 2;
   1.403 +    vbri->delai             = BE_16(ptr); ptr += 2;
   1.404 +    vbri->quality           = BE_16(ptr); ptr += 2;
   1.405 +    vbri->stream_size       = BE_32(ptr); ptr += 4;
   1.406 +    vbri->stream_frames     = BE_32(ptr); ptr += 4;
   1.407 +    vbri->toc_entries       = BE_16(ptr); ptr += 2;
   1.408 +    vbri->toc_scale_factor  = BE_16(ptr); ptr += 2;
   1.409 +    vbri->entry_size        = BE_16(ptr); ptr += 2;
   1.410 +    vbri->entry_frames      = BE_16(ptr); ptr += 2;
   1.411 +    lprintf("version: %d\n", vbri->version);
   1.412 +    lprintf("delai: %d\n", vbri->delai);
   1.413 +    lprintf("quality: %d\n", vbri->quality);
   1.414 +    lprintf("stream_size: %d\n", vbri->stream_size);
   1.415 +    lprintf("stream_frames: %d\n", vbri->stream_frames);
   1.416 +    lprintf("toc_entries: %d\n", vbri->toc_entries);
   1.417 +    lprintf("toc_scale_factor: %d\n", vbri->toc_scale_factor);
   1.418 +    lprintf("entry_size: %d\n", vbri->entry_size);
   1.419 +    lprintf("entry_frames: %d\n", vbri->entry_frames);
   1.420 +
   1.421 +    if ((ptr + (vbri->toc_entries + 1) * vbri->entry_size) >= (buf + bufsize)) return 0;
   1.422 +    vbri->toc = xine_xmalloc (sizeof(int) * (vbri->toc_entries + 1));
   1.423 +    if (!vbri->toc) {
   1.424 +      free (vbri);
   1.425 +      return NULL;
   1.426 +    }
   1.427 +
   1.428 +    lprintf("toc entries: %d\n", vbri->toc_entries);
   1.429 +    for (i = 0; i <= vbri->toc_entries; i++) {
   1.430 +      int j;
   1.431 +      uint32_t value = 0;
   1.432 +
   1.433 +      for (j = 0; j < vbri->entry_size; j++) {
   1.434 +        value = (value << 8) | *(ptr + i * vbri->entry_size + j);
   1.435 +      }
   1.436 +      vbri->toc[i] = value;
   1.437 +#ifdef LOG
   1.438 +      printf("%d ", vbri->toc[i]);
   1.439 +#endif
   1.440 +    }
   1.441 +#ifdef LOG
   1.442 +    printf("\n");
   1.443 +#endif
   1.444 +    {
   1.445 +      int64_t toc_stream_size = 0;
   1.446 +
   1.447 +      /* Compute the stream size using the toc */
   1.448 +      for (i = 0; i <= vbri->toc_entries; i++) {
   1.449 +        toc_stream_size += vbri->toc[i];
   1.450 +      }
   1.451 +      lprintf("stream size from toc: %lld\n", toc_stream_size);
   1.452 +    }
   1.453 +
   1.454 +    return vbri;
   1.455 +  } else {
   1.456 +    lprintf("Vbri header not found\n");
   1.457 +    free (vbri);
   1.458 +    return NULL;
   1.459 +  }
   1.460 +}
   1.461 +
   1.462 +/*
   1.463 + * Parse a mp3 frame paylod
   1.464 + * return 1 on success, 0 on error
   1.465 + */
   1.466 +static int parse_frame_payload(demux_mpgaudio_t *this,
   1.467 +                               uint8_t *frame_header,
   1.468 +                               int decoder_flags) {
   1.469    buf_element_t *buf;
   1.470    off_t          frame_pos, len;
   1.471    uint64_t       pts = 0;
   1.472 @@ -370,7 +464,7 @@
   1.473  
   1.474    buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
   1.475  
   1.476 -  if (this->cur_frame.length > buf->max_size) {
   1.477 +  if (this->cur_frame.size > buf->max_size) {
   1.478      xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
   1.479              "demux_mpgaudio: frame size is greater than fifo buffer size\n");
   1.480      buf->free_buffer(buf);
   1.481 @@ -380,54 +474,34 @@
   1.482    /* the decoder needs the frame header */
   1.483    memcpy(buf->mem, frame_header, 4);
   1.484  
   1.485 -  len = this->input->read(this->input, buf->mem + 4, this->cur_frame.length - 4);
   1.486 -  if (len != (this->cur_frame.length - 4)) {
   1.487 +  len = this->input->read(this->input, buf->mem + 4, this->cur_frame.size - 4);
   1.488 +  if (len != (this->cur_frame.size - 4)) {
   1.489      buf->free_buffer(buf);
   1.490      return 0;
   1.491    }
   1.492  
   1.493 -  /*
   1.494 -   * compute stream length (in s)
   1.495 -   * use the Xing header if there is one (VBR) otherwise use CBR formula
   1.496 -   * set stream_info before sending any buffer to the decoder
   1.497 -   */
   1.498 -  if (this->check_xing) {
   1.499 -    mpg123_parse_xing_header(this, buf->mem, len + 4);
   1.500 -    if (!this->is_vbr) {
   1.501 -      this->stream_length = this->input->get_length(this->input) / (this->br / 8);
   1.502 -      _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->br);
   1.503 -      _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->br);
   1.504 -    } else {
   1.505 -      _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->abr);
   1.506 -      _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->abr);
   1.507 +  if (this->check_vbr_header) {
   1.508 +    this->check_vbr_header = 0;
   1.509 +    this->mpg_frame_start = frame_pos;
   1.510 +    this->xing_header = parse_xing_header(&this->cur_frame, buf->mem, this->cur_frame.size);
   1.511 +    if (this->xing_header) {
   1.512 +      buf->free_buffer(buf);
   1.513 +      return 1;
   1.514      }
   1.515 -    this->check_xing = 0;
   1.516 +    this->vbri_header = parse_vbri_header(&this->cur_frame, buf->mem, this->cur_frame.size);
   1.517 +    if (this->vbri_header) {
   1.518 +      buf->free_buffer(buf);
   1.519 +      return 1;
   1.520 +    }
   1.521    }
   1.522    
   1.523 -  /* set codec infos here
   1.524 -   * the decoder doesn't know if the stream is VBR
   1.525 -   */
   1.526 -  if (!this->meta_info_flag) {
   1.527 -    char scratch_buf[256];
   1.528 -    char *mpeg_ver[3] = {"1", "2", "2.5"};
   1.529 -    
   1.530 -    snprintf(scratch_buf, 256, "MPEG %s Layer %1d%s",
   1.531 -             mpeg_ver[this->cur_frame.version_idx], this->cur_frame.layer,
   1.532 -             (this->is_vbr)? " VBR" : " CBR" );
   1.533 -    _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, scratch_buf);
   1.534 -    
   1.535 -    this->meta_info_flag = 1;
   1.536 -  }
   1.537  
   1.538 -  this->cur_fpts += this->cur_frame.duration;
   1.539 +  pts = (int64_t)(this->cur_time * 90.0f);
   1.540  
   1.541 -  pts = (int64_t)this->cur_fpts;
   1.542 -  check_newpts(this, pts);
   1.543 +  if (this->stream_length)
   1.544 +    buf->extra_info->input_normpos = (this->cur_time * 65535.0f) / this->stream_length;
   1.545  
   1.546 -  if( this->input->get_length (this->input) )
   1.547 -    buf->extra_info->input_normpos = (int)( (double) frame_pos * 
   1.548 -                                     65535 / this->input->get_length (this->input) );
   1.549 -  buf->extra_info->input_time = pts / 90;
   1.550 +  buf->extra_info->input_time = this->cur_time;
   1.551    buf->pts                    = pts;
   1.552    buf->size                   = len + 4;
   1.553    buf->content                = buf->mem;
   1.554 @@ -436,81 +510,52 @@
   1.555    buf->decoder_flags          = decoder_flags;
   1.556  
   1.557    this->audio_fifo->put(this->audio_fifo, buf);
   1.558 +  lprintf("send buffer: pts=%lld\n", pts);  
   1.559 +  this->cur_time += this->cur_frame.duration;
   1.560    return 1;
   1.561  }
   1.562  
   1.563  
   1.564 -static unsigned char * demux_mpgaudio_read_buffer_header (input_plugin_t *input)
   1.565 -{
   1.566 -  int count;
   1.567 -  uint8_t buf[MAX_PREVIEW_SIZE];
   1.568 -  unsigned char *retval;
   1.569 -
   1.570 -  if(!input)
   1.571 -    return 0;
   1.572 -
   1.573 -  if((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) {
   1.574 -    input->seek(input, 0, SEEK_SET);
   1.575 -
   1.576 -    count = input->read(input, buf, SNIFF_BUFFER_LENGTH);
   1.577 -    if (count < SNIFF_BUFFER_LENGTH)
   1.578 -    {
   1.579 -      return NULL;
   1.580 -    }
   1.581 -  } else if ((input->get_capabilities(input) & INPUT_CAP_PREVIEW) != 0) {
   1.582 -    input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW);
   1.583 -  } else {
   1.584 -    return NULL;
   1.585 -  }
   1.586 -
   1.587 -  retval = xine_xmalloc (SNIFF_BUFFER_LENGTH);
   1.588 -  memcpy (retval, buf, SNIFF_BUFFER_LENGTH);
   1.589 -
   1.590 -  return retval;
   1.591 -}
   1.592 -
   1.593 -/* Scan through the first SNIFF_BUFFER_LENGTH bytes of the
   1.594 - * buffer to find a potential 32-bit MP3 frame header. */
   1.595 -static int sniff_buffer_looks_like_mp3 (input_plugin_t *input)
   1.596 +/* Scan through the preview buffer to find a potential
   1.597 + * 32-bit MP3 frame header.
   1.598 + * return 1 if found, 0 if not found
   1.599 + */
   1.600 +static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen)
   1.601  {
   1.602    int offset;
   1.603 -  unsigned char *buf;
   1.604    mpg_audio_frame_t frame;
   1.605  
   1.606 -  buf = demux_mpgaudio_read_buffer_header (input);
   1.607    if (buf == NULL)
   1.608      return 0;
   1.609  
   1.610 -  for (offset = 0; offset + 4 < SNIFF_BUFFER_LENGTH; offset++) {
   1.611 +  for (offset = 0; (offset + 4) < buflen; offset++) {
   1.612  
   1.613 -    if (mpg123_parse_frame_header(&frame, buf + offset)) {
   1.614 -      size_t length = frame.length;
   1.615 +    if (parse_frame_header(&frame, buf + offset)) {
   1.616 +      size_t size = frame.size;
   1.617  
   1.618        /* Since one frame is available, is there another frame
   1.619         * just to be sure this is more likely to be a real MP3
   1.620         * buffer? */
   1.621 -      offset += length;
   1.622 +      offset += size;
   1.623  
   1.624 -      if (offset + 4 > SNIFF_BUFFER_LENGTH)
   1.625 -      {
   1.626 -        free (buf);
   1.627 +      if (offset + 4 >= buflen) {
   1.628          return 0;
   1.629        }
   1.630  
   1.631 -      if (mpg123_parse_frame_header(&frame, buf + offset)) {
   1.632 -        free (buf);
   1.633 +      if (parse_frame_header(&frame, buf + offset)) {
   1.634          lprintf("mpeg audio frame detected\n");
   1.635          return 1;
   1.636        }
   1.637        break;
   1.638      }
   1.639    }
   1.640 -
   1.641 -  free (buf);
   1.642    return 0;
   1.643  }
   1.644  
   1.645 -static int mpg123_read_frame_header(demux_mpgaudio_t *this, uint8_t *header_buf, int bytes) {
   1.646 +/*
   1.647 + * Read a mp3 frame header (4 bytes)
   1.648 + */
   1.649 +static int read_frame_header(demux_mpgaudio_t *this, uint8_t *header_buf, int bytes) {
   1.650    off_t len;
   1.651    int i;
   1.652    
   1.653 @@ -525,22 +570,20 @@
   1.654    return 1;
   1.655  }
   1.656  
   1.657 +/*
   1.658 + * Parse next mp3 frame
   1.659 + */
   1.660  static int demux_mpgaudio_next (demux_mpgaudio_t *this, int decoder_flags) {
   1.661    uint8_t  header_buf[4];
   1.662    int      bytes = 4;
   1.663  
   1.664 -  if (!this->audio_fifo)
   1.665 -    return 0;
   1.666 -
   1.667    for (;;) {
   1.668  
   1.669 -    if (mpg123_read_frame_header(this, header_buf, bytes)) {
   1.670 +    if (read_frame_header(this, header_buf, bytes)) {
   1.671  
   1.672 -      if (mpg123_parse_frame_header(&this->cur_frame, header_buf)) {
   1.673 -        if (!this->br) {
   1.674 -          this->br = this->cur_frame.bitrate;
   1.675 -        }
   1.676 -        return mpg123_parse_frame_payload(this, header_buf, decoder_flags);
   1.677 +      if (parse_frame_header(&this->cur_frame, header_buf)) {
   1.678 +
   1.679 +        return parse_frame_payload(this, header_buf, decoder_flags);
   1.680          
   1.681        } else if ((BE_32(header_buf)) == ID3V22_TAG) {
   1.682          xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
   1.683 @@ -606,24 +649,11 @@
   1.684  static int demux_mpgaudio_read_head(input_plugin_t *input, uint8_t *buf) {
   1.685  
   1.686    int       bs = 0;
   1.687 -  int       i, optional;
   1.688  
   1.689 -  memset(buf, 0, 4);
   1.690 -
   1.691 -  if(!input)
   1.692 -    return 0;
   1.693 -
   1.694 -  if((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) {
   1.695 +  if (INPUT_IS_SEEKABLE(input)) {
   1.696      input->seek(input, 0, SEEK_SET);
   1.697  
   1.698 -    if (input->get_capabilities (input) & INPUT_CAP_BLOCK)
   1.699 -      bs = input->get_blocksize(input);
   1.700 -
   1.701 -    if(!bs)
   1.702 -      bs = MAX_PREVIEW_SIZE;
   1.703 -
   1.704 -    if (input->read(input, buf, bs) < 4)
   1.705 -      return 0;
   1.706 +    bs = input->read(input, buf, MAX_PREVIEW_SIZE);
   1.707  
   1.708      lprintf("stream is seekable\n");
   1.709  
   1.710 @@ -631,20 +661,67 @@
   1.711  
   1.712      lprintf("input plugin provides preview\n");
   1.713  
   1.714 -    optional = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW);
   1.715 -    optional = optional > 256 ? 256 : optional;
   1.716 +    bs = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW);
   1.717  
   1.718 -    lprintf("got preview %02x %02x %02x %02x\n",
   1.719 -	    buf[0], buf[1], buf[2], buf[3]);
   1.720 -    
   1.721 -    for(i = 0; i < (optional - 4); i++) {
   1.722 -      if (BE_32(buf + i) == RIFF_TAG)
   1.723 -        return 1;
   1.724 -    }
   1.725    } else {
   1.726      lprintf("not seekable, no preview\n");
   1.727      return 0;
   1.728    }
   1.729 +  return bs;
   1.730 +}
   1.731 +
   1.732 +/*
   1.733 + * mp3 stream detection
   1.734 + * return 1 if detected, 0 otherwise
   1.735 + */
   1.736 +static int detect_mpgaudio_file(input_plugin_t *input) {
   1.737 +  mpg_audio_frame_t frame;
   1.738 +  uint8_t buf[MAX_PREVIEW_SIZE];
   1.739 +  int preview_len;
   1.740 +  uint32_t head;
   1.741 +
   1.742 +  preview_len = demux_mpgaudio_read_head(input, buf);
   1.743 +  if (preview_len < 4)
   1.744 +    return 0;
   1.745 +
   1.746 +  lprintf("got preview %02x %02x %02x %02x\n",
   1.747 +    buf[0], buf[1], buf[2], buf[3]);
   1.748 +
   1.749 +  head = BE_32(buf);
   1.750 +
   1.751 +  if ((head == ID3V22_TAG) ||
   1.752 +      (head == ID3V23_TAG) ||
   1.753 +      (head == ID3V24_TAG)) {
   1.754 +    /* check if a mp3 frame follows the tag
   1.755 +     * id3v2 are not specific to mp3 files,
   1.756 +     * flac files can contain id3v2 tags
   1.757 +     */
   1.758 +    uint8_t *ptr = &buf[6];
   1.759 +    uint32_t tag_size = ((uint32_t)ptr[0] << 21) +
   1.760 +                        ((uint32_t)ptr[1] << 14) +
   1.761 +                        ((uint32_t)ptr[2] << 7) +
   1.762 +                         (uint32_t)ptr[3];
   1.763 +    lprintf("try to skip id3v2 tag (%d bytes)\n", tag_size);
   1.764 +    if ((10 + tag_size) >= preview_len) {
   1.765 +      lprintf("cannot skip id3v2 tag\n");
   1.766 +      return 0;
   1.767 +    }
   1.768 +    if ((10 + tag_size + 4) >= preview_len) {
   1.769 +      lprintf("cannot read mp3 frame header\n");
   1.770 +      return 0;
   1.771 +    }
   1.772 +    if (!parse_frame_header(&frame, &buf[10 + tag_size])) {
   1.773 +      lprintf ("invalid mp3 frame header\n");
   1.774 +      return 0;
   1.775 +    } else {
   1.776 +      lprintf ("a valid mp3 frame follows the id3v2 tag\n");
   1.777 +    }
   1.778 +  } else if (head == MPEG_MARKER) {
   1.779 +    return 0;
   1.780 +  } else if (!sniff_buffer_looks_like_mp3(buf, preview_len)) {
   1.781 +    lprintf ("sniff_buffer_looks_like_mp3 failed\n");
   1.782 +    return 0;
   1.783 +  }
   1.784    return 1;
   1.785  }
   1.786  
   1.787 @@ -654,15 +731,15 @@
   1.788    int i;
   1.789  
   1.790    this->stream_length = 0;
   1.791 -  this->last_pts      = 0;
   1.792    this->status        = DEMUX_OK;
   1.793 -  this->check_xing    = 1;
   1.794  
   1.795    _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0);
   1.796    _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
   1.797  
   1.798 +  _x_demux_control_start (this->stream);
   1.799 +
   1.800    /* read id3 info only from inputs with seeking and without "live" flag */
   1.801 -  if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) {
   1.802 +  if (INPUT_IS_SEEKABLE(this->input)) {
   1.803      off_t pos;
   1.804  
   1.805      /* check ID3 v1 at the end of the stream */
   1.806 @@ -671,141 +748,206 @@
   1.807        if (pos == this->input->seek (this->input, pos, SEEK_SET))
   1.808          id3v1_parse_tag (this->input, this->stream);
   1.809      }
   1.810 -  }
   1.811  
   1.812 -  /*
   1.813 -   * send preview buffers
   1.814 -   */
   1.815 -  _x_demux_control_start (this->stream);
   1.816 -
   1.817 -  if ((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0)
   1.818 +    /* seek back to the beginning */
   1.819      this->input->seek (this->input, 0, SEEK_SET);
   1.820  
   1.821 -  for (i = 0; i < NUM_PREVIEW_BUFFERS; i++) {
   1.822 -    if (!demux_mpgaudio_next (this, BUF_FLAG_PREVIEW)) {
   1.823 -      break;
   1.824 +    /*
   1.825 +     * send preview buffers
   1.826 +     */
   1.827 +    this->check_vbr_header = 1;
   1.828 +    for (i = 0; i < NUM_PREVIEW_BUFFERS; i++) {
   1.829 +      if (!demux_mpgaudio_next (this, BUF_FLAG_PREVIEW)) {
   1.830 +        break;
   1.831 +      }
   1.832 +    }
   1.833 +    
   1.834 +    if (this->xing_header) {
   1.835 +      xing_header_t *xing = this->xing_header;
   1.836 +
   1.837 +      this->mpg_size = xing->stream_size;
   1.838 +      this->mpg_frame_end = this->mpg_frame_start + this->mpg_size;
   1.839 +      this->stream_length = (double)xing->stream_frames * this->cur_frame.duration;
   1.840 +      /* compute abr */
   1.841 +      if (this->stream_length) {
   1.842 +        this->br = (xing->stream_size * 8 * 1000) / this->stream_length;
   1.843 +      }
   1.844 +      
   1.845 +    } else if (this->vbri_header) {
   1.846 +      vbri_header_t *vbri = this->vbri_header;
   1.847 +
   1.848 +      this->mpg_size = vbri->stream_size;
   1.849 +      this->mpg_frame_end = this->mpg_frame_start + this->mpg_size;
   1.850 +      this->stream_length = (double)vbri->stream_frames * this->cur_frame.duration;
   1.851 +      /* compute abr */
   1.852 +      if (this->stream_length) {
   1.853 +        this->br = (vbri->stream_size * 8 * 1000) / this->stream_length;
   1.854 +      }
   1.855 +    }
   1.856 + 
   1.857 +    /* Set to default if Vbr header is incomplete or not present */
   1.858 +    if (!this->br) {
   1.859 +      /* assume CBR */
   1.860 +      this->br = this->cur_frame.bitrate;
   1.861 +    }
   1.862 +    if (!this->mpg_frame_end) {
   1.863 +      this->mpg_frame_end = this->input->get_length(this->input);
   1.864 +    }
   1.865 +    if (!this->mpg_size) {
   1.866 +      this->mpg_size = this->mpg_frame_end - this->mpg_frame_start;
   1.867 +    }
   1.868 +    if (!this->stream_length && this->br) {
   1.869 +      this->stream_length = (this->mpg_size * 1000) / (this->br / 8);
   1.870 +    }
   1.871 +
   1.872 +    _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->br);
   1.873 +    _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->br);
   1.874 +    lprintf("frame_start: %lld, frame_end: %lld\n",
   1.875 +            this->mpg_frame_start, this->mpg_frame_end);
   1.876 +    lprintf("stream size: %lld, mp3 size: %lld\n",
   1.877 +            this->input->get_length(this->input),
   1.878 +            this->mpg_size);
   1.879 +    lprintf("stream_length: %lld min %lld s\n", 
   1.880 +            ((uint64_t)this->stream_length / 1000) / 60,
   1.881 +            ((uint64_t)this->stream_length / 1000) % 60);
   1.882 +
   1.883 +    /* set codec infos here
   1.884 +     * the decoder doesn't know if the stream is VBR
   1.885 +     */
   1.886 +    {
   1.887 +      char scratch_buf[256];
   1.888 +      char *mpeg_ver[3] = {"1", "2", "2.5"};
   1.889 +      
   1.890 +      snprintf(scratch_buf, 256, "MPEG %s Layer %1d%s",
   1.891 +               mpeg_ver[this->cur_frame.version_idx], this->cur_frame.layer,
   1.892 +               (this->xing_header)? " VBR" : " CBR" );
   1.893 +      _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, scratch_buf);
   1.894      }
   1.895    }
   1.896  
   1.897 -  if (this->cur_frame.samplerate) {
   1.898 -    if (this->cur_frame.layer == 1)
   1.899 -      _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION,
   1.900 -        384000 / this->cur_frame.samplerate);
   1.901 -    else
   1.902 -      _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION,
   1.903 -        1152000 / this->cur_frame.samplerate);
   1.904 -  }
   1.905 -  
   1.906    this->status = DEMUX_OK;
   1.907  }
   1.908  
   1.909 -/* interpolate in Xing TOC to get file seek point in bytes */
   1.910 -static off_t xing_get_seek_point(demux_mpgaudio_t *this, int time)
   1.911 +/*
   1.912 + * interpolate in Xing TOC to get file seek point in bytes
   1.913 + * return the stream offset of the seekpoint
   1.914 + */
   1.915 +static off_t xing_get_seek_point(xing_header_t *xing, int time, int stream_length)
   1.916  {
   1.917    off_t seekpoint;
   1.918    int a;
   1.919    float fa, fb, fx;
   1.920    float percent;
   1.921  
   1.922 -  percent = ((float)time / 10.0f)/ (float)this->stream_length;
   1.923 +  percent = ((float)time * 100.0f)/ (float)stream_length;
   1.924    if (percent < 0.0f)   percent = 0.0f;
   1.925    if (percent > 100.0f) percent = 100.0f;
   1.926  
   1.927    a = (int)percent;
   1.928    if (a > 99) a = 99;
   1.929 -  fa = this->xtoc[a];
   1.930 +  fa = xing->toc[a];
   1.931    if (a < 99) {
   1.932 -      fb = this->xtoc[a + 1];
   1.933 +      fb = xing->toc[a + 1];
   1.934    } else {
   1.935        fb = 256.0f;
   1.936    }
   1.937  
   1.938    fx = fa + (fb - fa) * (percent - a);
   1.939 -  seekpoint = (off_t)((1.0f / 256.0f) * fx * this->xbytes);
   1.940 +  seekpoint = (off_t)((1.0f / 256.0f) * fx * xing->stream_size);
   1.941  
   1.942    return seekpoint;
   1.943  }
   1.944  
   1.945 -/* interpolate in Xing TOC to get file seek point in ms */
   1.946 -static int xing_get_seek_time(demux_mpgaudio_t *this, off_t pos)
   1.947 +/*
   1.948 + * Interpolate in Vbri TOC to get file seek point in bytes
   1.949 + * return the stream offset of the seekpoint
   1.950 + */
   1.951 +static off_t vbri_get_seek_point(vbri_header_t *vbri, int time, int stream_length)
   1.952  {
   1.953 -  int seektime;
   1.954 -  int a, b;
   1.955 -  float fb, fx;
   1.956 -  float percent;
   1.957 +  double fa, fb, fx;
   1.958 +  double toc_entry;
   1.959 +  int i;
   1.960 +  int a;
   1.961  
   1.962 -  fx = 256.0f * (float)pos / (float)this->xbytes;
   1.963 -  if (fx < 0.0f)   fx = 0.0f;
   1.964 -  if (fx > 256.0f) fx = 256.0f;
   1.965 +  toc_entry = ((float)time * (float)(vbri->toc_entries + 1)) /
   1.966 +              (float)stream_length;
   1.967 +  lprintf("time: %d, stream length: %d, toc entry: %f\n",
   1.968 +          time, stream_length, toc_entry);
   1.969 +  if (toc_entry < 0.0f)
   1.970 +    toc_entry = 0.0f;
   1.971 +  if (toc_entry > (float)vbri->toc_entries)
   1.972 +    toc_entry = (float)vbri->toc_entries;
   1.973  
   1.974 -  for (b = 0; b < 100; b++) {
   1.975 -    fb = this->xtoc[b];
   1.976 -    if (fb > fx)
   1.977 -      break;
   1.978 +  a = (int)toc_entry;
   1.979 +  if (a > (vbri->toc_entries - 1))
   1.980 +    a = vbri->toc_entries - 1;
   1.981 +
   1.982 +  /* compute the stream offset of the toc entry */
   1.983 +  fa = 0.0f;
   1.984 +  for (i = 0; i < a; i++) {
   1.985 +    fa += (double)vbri->toc[i];
   1.986    }
   1.987 - 
   1.988 -  if (b > 0) {
   1.989 -    a = b - 1;
   1.990 -  } else {
   1.991 -    a = 0;
   1.992 -  }
   1.993 +  /* compute the stream offset of the next toc entry */
   1.994 +  fb = fa + (double)vbri->toc[a];
   1.995  
   1.996 -  percent = a + (fx - this->xtoc[a]);
   1.997 -  seektime = 10.0f * percent * this->stream_length;
   1.998 +  /* interpolate */
   1.999 +  fx = fa + (fb - fa) * (toc_entry - (double)a);
  1.1000  
  1.1001 -  return seektime;
  1.1002 +  return (off_t)fx;
  1.1003  }
  1.1004  
  1.1005 +/*
  1.1006 + * Seeking function
  1.1007 + * Try to use the Vbr header if present.
  1.1008 + * If no Vbr header is present then use a CBR formula
  1.1009 + *
  1.1010 + * Position seek is relative to the total time of the stream, the position
  1.1011 + * is converted to a time at the beginning of the function
  1.1012 + */
  1.1013  static int demux_mpgaudio_seek (demux_plugin_t *this_gen,
  1.1014                                  off_t start_pos, int start_time, int playing) {
  1.1015  
  1.1016    demux_mpgaudio_t *this = (demux_mpgaudio_t *) this_gen;
  1.1017 -  start_pos = (off_t) ( (double) start_pos / 65535 *
  1.1018 -              this->input->get_length (this->input) );
  1.1019 +  off_t seek_pos = this->mpg_frame_start;
  1.1020  
  1.1021    if ((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
  1.1022 -    if (!start_pos && start_time && this->stream_length > 0) {
  1.1023 -      if (this->is_vbr && (this->xflags & (XING_TOC_FLAG | XING_BYTES_FLAG))) {
  1.1024 -        /* vbr  */
  1.1025 -        start_pos = xing_get_seek_point(this, start_time);
  1.1026 -        lprintf("time seek: vbr: time=%d, pos=%lld\n", start_time, start_pos);
  1.1027 +    /* Convert position seek to time seek */
  1.1028 +    if (!start_time) {
  1.1029 +      start_time = (int)((double)start_pos * (double)this->stream_length / 65535.0f);
  1.1030 +      lprintf("position seek: start_pos=%lld => start_time=%d\n", start_pos, start_time);
  1.1031 +    }
  1.1032 +
  1.1033 +    if (start_time < 0)
  1.1034 +      start_time = 0;
  1.1035 +    if (start_time > this->stream_length)
  1.1036 +      start_time = this->stream_length;
  1.1037 +
  1.1038 +    if (this->stream_length > 0) {
  1.1039 +      if (this->xing_header &&
  1.1040 +          (this->xing_header->flags & (XING_TOC_FLAG | XING_BYTES_FLAG))) {
  1.1041 +        seek_pos += xing_get_seek_point(this->xing_header, start_time, this->stream_length);
  1.1042 +        lprintf("time seek: xing: time=%d, pos=%lld\n", start_time, seek_pos);
  1.1043 +      } else if (this->vbri_header) {
  1.1044 +        seek_pos += vbri_get_seek_point(this->vbri_header, start_time, this->stream_length);
  1.1045 +        lprintf("time seek: vbri: time=%d, pos=%lld\n", start_time, seek_pos);
  1.1046        } else {
  1.1047 -        /* cbr  */
  1.1048 -        off_t input_length = this->input->get_length(this->input);
  1.1049 -
  1.1050 -        if ((input_length > 0) && (this->stream_length > 0)) {
  1.1051 -          start_pos = start_time * input_length / (1000 * this->stream_length);
  1.1052 -          lprintf("time seek: cbr: time=%d, pos=%lld\n", start_time, start_pos);
  1.1053 -        }
  1.1054 -      }
  1.1055 -    } else {
  1.1056 -      if (this->is_vbr && (this->xflags & (XING_TOC_FLAG | XING_BYTES_FLAG))) {
  1.1057 -        /* vbr  */
  1.1058 -        start_time = xing_get_seek_time(this, start_pos);
  1.1059 -        lprintf("pos seek: vbr: time=%d, pos=%lld\n", start_time, start_pos);
  1.1060 -      } else {
  1.1061 -        /* cbr  */
  1.1062 -        off_t input_length = this->input->get_length(this->input);
  1.1063 -
  1.1064 -        if((input_length > 0) && (this->stream_length > 0)) {
  1.1065 -          start_time = (1000 * start_pos * this->stream_length) / input_length;
  1.1066 -          lprintf("pos seek: cbr\n");
  1.1067 -        }
  1.1068 +        /* cbr */
  1.1069 +        seek_pos += ((double)start_time / 1000.0) * ((double)this->br / 8.0);
  1.1070 +        lprintf("time seek: cbr: time=%d, pos=%lld\n", start_time, seek_pos);
  1.1071        }
  1.1072      }
  1.1073 -    this->cur_fpts = 90.0 * (double)start_time;
  1.1074 -    this->input->seek (this->input, start_pos, SEEK_SET);
  1.1075 +    /* assume seeking is always perfect... */
  1.1076 +    this->cur_time = start_time;
  1.1077 +    this->input->seek (this->input, seek_pos, SEEK_SET);
  1.1078 +    
  1.1079 +    if (playing) {
  1.1080 +      _x_demux_flush_engine(this->stream);
  1.1081 +    }
  1.1082 +    _x_demux_control_newpts(this->stream,
  1.1083 +                            (int64_t)(this->cur_time * 90.0f),
  1.1084 +                             (playing) ? BUF_FLAG_SEEK : 0);
  1.1085    }
  1.1086 -
  1.1087    this->status = DEMUX_OK;
  1.1088 -  this->send_newpts = 1;
  1.1089 -
  1.1090 -  if( !playing ) {
  1.1091 -    this->buf_flag_seek = 0;
  1.1092 -  } else {
  1.1093 -    this->buf_flag_seek = 1;
  1.1094 -    _x_demux_flush_engine(this->stream);
  1.1095 -  }
  1.1096  
  1.1097    return this->status;
  1.1098  }
  1.1099 @@ -819,7 +961,7 @@
  1.1100    demux_mpgaudio_t *this = (demux_mpgaudio_t *) this_gen;
  1.1101  
  1.1102    if (this->stream_length > 0) {
  1.1103 -    return this->stream_length * 1000;
  1.1104 +    return this->stream_length;
  1.1105    } else
  1.1106      return 0;
  1.1107  }
  1.1108 @@ -837,105 +979,14 @@
  1.1109                                      input_plugin_t *input) {
  1.1110  
  1.1111    demux_mpgaudio_t *this;
  1.1112 -  id3v2_header_t    tag_header;
  1.1113 -  mpg_audio_frame_t frame;
  1.1114 -  uint8_t           buf[MAX_PREVIEW_SIZE];
  1.1115 -  uint8_t          *riff_check;
  1.1116 -  int               i;
  1.1117 -  uint8_t          *ptr;
  1.1118  
  1.1119    lprintf("trying to open %s...\n", input->get_mrl(input));
  1.1120  
  1.1121    switch (stream->content_detection_method) {
  1.1122  
  1.1123    case METHOD_BY_CONTENT: {
  1.1124 -    uint32_t head;
  1.1125 -
  1.1126 -    if (!demux_mpgaudio_read_head(input, buf))
  1.1127 +    if (!detect_mpgaudio_file(input))
  1.1128        return NULL;
  1.1129 -
  1.1130 -    head = BE_32(buf);
  1.1131 -    lprintf("head is %8X\n", head);
  1.1132 -    
  1.1133 -    if (head == RIFF_TAG) {
  1.1134 -      int ok;
  1.1135 -
  1.1136 -      lprintf("found RIFF tag\n");
  1.1137 -      /* skip the length */
  1.1138 -      ptr = buf + 8;
  1.1139 -
  1.1140 -      riff_check = ptr; ptr += 4;
  1.1141 -      if ((buf + MAX_PREVIEW_SIZE) < ptr)
  1.1142 -        return NULL;
  1.1143 -
  1.1144 -      /* disqualify the file if it is, in fact, an AVI file or has a CDXA
  1.1145 -       * marker */
  1.1146 -      if ((BE_32(riff_check) == AVI_TAG) ||
  1.1147 -          (BE_32(riff_check) == CDXA_TAG)) {
  1.1148 -        lprintf("found AVI or CDXA tag\n");
  1.1149 -        return NULL;
  1.1150 -      }
  1.1151 -
  1.1152 -      /* skip 4 more bytes */
  1.1153 -      ptr += 4;
  1.1154 -
  1.1155 -      /* get the length of the next chunk */
  1.1156 -      riff_check = ptr; ptr += 4;
  1.1157 -      if ((buf + MAX_PREVIEW_SIZE) < ptr)
  1.1158 -        return NULL;
  1.1159 -      /* head gets to be a generic variable in this case */
  1.1160 -      head = LE_32(riff_check);
  1.1161 -      /* skip over the chunk and the 'data' tag and length */
  1.1162 -      ptr += 8;
  1.1163 -
  1.1164 -      /* load the next, I don't know...n bytes, and check for a valid
  1.1165 -       * MPEG audio header */
  1.1166 -      riff_check = ptr; ptr += RIFF_CHECK_BYTES;
  1.1167 -      if ((buf + MAX_PREVIEW_SIZE) < ptr)
  1.1168 -        return NULL;
  1.1169 -
  1.1170 -      ok = 0;
  1.1171 -      for (i = 0; i < RIFF_CHECK_BYTES - 4; i++) {
  1.1172 -        head = BE_32(riff_check + i);
  1.1173 -
  1.1174 -        lprintf("checking %08X\n", head);
  1.1175 -
  1.1176 -        if (sniff_buffer_looks_like_mp3(input))
  1.1177 -          ok = 1;
  1.1178 -      }
  1.1179 -      if (!ok)
  1.1180 -        return NULL;
  1.1181 -
  1.1182 -    } else if ((head == ID3V22_TAG) ||
  1.1183 -               (head == ID3V23_TAG) ||
  1.1184 -               (head == ID3V24_TAG)) {
  1.1185 -      /* check if a mp3 frame follows the tag
  1.1186 -       * id3v2 are not specific to mp3 files,
  1.1187 -       * flac files can contain id3v2 tags
  1.1188 -       */
  1.1189 -      ptr = buf + 4;
  1.1190 -      tag_header.size = (ptr[2] << 21) + (ptr[3] << 14) + (ptr[4] << 7) + ptr[5];
  1.1191 -      lprintf("id3v2.%d tag detected, size: %d\n", buf[3], tag_header.size);
  1.1192 -
  1.1193 -      ptr += tag_header.size + 6;
  1.1194 -      if ((ptr + 4) <= (buf + MAX_PREVIEW_SIZE)) {
  1.1195 -        if (!mpg123_parse_frame_header(&frame, ptr)) {
  1.1196 -          lprintf ("invalid mp3 frame header\n");
  1.1197 -          return NULL;
  1.1198 -        }
  1.1199 -        lprintf ("a valid mp3 frame follows the id3 tag\n");
  1.1200 -      } else {
  1.1201 -        lprintf ("the id3v2 tag is too long\n");
  1.1202 -        return NULL;
  1.1203 -      }
  1.1204 -
  1.1205 -    } else if (head == MPEG_MARKER) {
  1.1206 -      lprintf ("discard mpeg video\n");
  1.1207 -      return NULL;
  1.1208 -    } else if (!sniff_buffer_looks_like_mp3 (input)) {
  1.1209 -      lprintf ("sniff_buffer_looks_like_mp3 failed\n");
  1.1210 -      return NULL;
  1.1211 -    }
  1.1212    }
  1.1213    break;
  1.1214