Index: libmpcodecs/ad_mp3lib.c
===================================================================
--- libmpcodecs/ad_mp3lib.c	(révision 22818)
+++ libmpcodecs/ad_mp3lib.c	(copie de travail)
@@ -47,10 +47,10 @@
   MP3_samplerate=MP3_channels=0;
   sh->a_buffer_len=MP3_DecodeFrame(sh->a_buffer,-1);
   if(!sh->a_buffer_len) return 0; // unsupported layer/format
-  sh->channels=2; // hack
+  sh->channels=sh->wf->nChannels;
   sh->samplesize=2;
   sh->samplerate=MP3_samplerate;
-  sh->i_bps=MP3_bitrate*(1000/8);
+  sh->i_bps=sh->wf->nAvgBytesPerSec;
   MP3_PrintHeader();
   return 1;
 }
Index: libmpdemux/mp3_hdr.c
===================================================================
--- libmpdemux/mp3_hdr.c	(révision 22818)
+++ libmpdemux/mp3_hdr.c	(copie de travail)
@@ -34,7 +34,7 @@
 /*
  * return frame size or -1 (bad frame)
  */
-int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* srate, int* spf, int* mpa_layer, int* br){
+int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* srate, int* spf, int* mpa_layer, int* br, int* side_info_size){
     int stereo,ssize,lsf,framesize,padding,bitrate_index,sampling_frequency, divisor;
     int bitrate;
     int layer, mult[3] = { 12000, 144000, 144000 };
@@ -99,6 +99,7 @@
     else
       ssize = (stereo == 1) ? 17 : 32;
     if(!((newhead>>16)&0x1)) ssize += 2; // CRC
+    if(side_info_size) *side_info_size = ssize;
 
     bitrate = tabsel_123[lsf][layer-1][bitrate_index];
     framesize = bitrate * mult[layer-1];
Index: libmpdemux/mp3_hdr.h
===================================================================
--- libmpdemux/mp3_hdr.h	(révision 22818)
+++ libmpdemux/mp3_hdr.h	(copie de travail)
@@ -1,7 +1,7 @@
 
-int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* freq, int* spf, int* mpa_layer, int* br);
+int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* freq, int* spf, int* mpa_layer, int* br, int* side_info_size);
 
-#define mp_decode_mp3_header(hbuf)  mp_get_mp3_header(hbuf,NULL,NULL,NULL,NULL,NULL)
+#define mp_decode_mp3_header(hbuf)  mp_get_mp3_header(hbuf,NULL,NULL,NULL,NULL,NULL,NULL)
 
 static inline int mp_check_mp3_header(unsigned int head){
     if( (head & 0x0000e0ff) != 0x0000e0ff ||  
Index: libmpdemux/demux_audio.c
===================================================================
--- libmpdemux/demux_audio.c	(révision 22818)
+++ libmpdemux/demux_audio.c	(copie de travail)
@@ -43,6 +43,7 @@
   int mpa_spf;
   int mpa_layer;
   int mpa_br;
+  int mpa_ssize;
   int cons_hdrs; // if this reaches MIN_MP3_HDRS we accept as MP3 file
   struct mp3_hdr *next;
 } mp3_hdr_t;
@@ -88,7 +89,7 @@
  */
 static mp3_hdr_t *add_mp3_hdr(mp3_hdr_t **list, off_t st_pos,
                                int mp3_chans, int mp3_freq, int mpa_spf,
-                               int mpa_layer, int mpa_br, int mp3_flen) {
+                               int mpa_layer, int mpa_br, int mp3_flen, int mpa_ssize) {
   mp3_hdr_t *tmp;
   int in_list = 0;
   while (*list && (*list)->next_frame_pos <= st_pos) {
@@ -125,6 +126,7 @@
     tmp->mp3_freq = mp3_freq;
     tmp->mpa_spf = mpa_spf;
     tmp->mpa_layer = mpa_layer;
+    tmp->mpa_ssize = mpa_ssize;
     tmp->mpa_br = mpa_br;
     tmp->cons_hdrs = 1;
     tmp->next = *list;
@@ -286,6 +288,7 @@
   // mp3_hdrs list is sorted first by next_frame_pos and then by frame_pos
   mp3_hdr_t *mp3_hdrs = NULL, *mp3_found = NULL;
   da_priv_t* priv;
+  off_t mpeghdr_pos;
 #ifdef MP_DEBUG
   assert(demuxer != NULL);
   assert(demuxer->stream != NULL);
@@ -293,9 +296,10 @@
   
   s = demuxer->stream;
 
+  mpeghdr_pos = stream_tell(s);
   stream_read(s, hdr, HDR_SIZE);
   while(n < 30000 && !s->eof) {
-    int mp3_freq, mp3_chans, mp3_flen, mpa_layer, mpa_spf, mpa_br;
+    int mp3_freq, mp3_chans, mp3_flen, mpa_layer, mpa_spf, mpa_br, mpa_ssize;
     st_pos = stream_tell(s) - HDR_SIZE;
     step = 1;
 
@@ -318,14 +322,15 @@
       stream_read(s,hdr,4);
       len = (hdr[0]<<21) | (hdr[1]<<14) | (hdr[2]<<7) | hdr[3];
       stream_skip(s,len);
+      mpeghdr_pos = stream_tell(s);
       step = 4;
     } else if( hdr[0] == 'f' && hdr[1] == 'm' && hdr[2] == 't' && hdr[3] == ' ' ) {
       frmt = WAV;
       break;      
     } else if((mp3_flen = mp_get_mp3_header(hdr, &mp3_chans, &mp3_freq,
-                                &mpa_spf, &mpa_layer, &mpa_br)) > 0) {
+                                &mpa_spf, &mpa_layer, &mpa_br, &mpa_ssize)) > 0) {
       mp3_found = add_mp3_hdr(&mp3_hdrs, st_pos, mp3_chans, mp3_freq,
-                              mpa_spf, mpa_layer, mpa_br, mp3_flen);
+                              mpa_spf, mpa_layer, mpa_br, mp3_flen, mpa_ssize);
       if (mp3_found) {
         frmt = MP3;
         break;
@@ -349,7 +354,34 @@
   sh_audio = new_sh_audio(demuxer,0);
 
   switch(frmt) {
-  case MP3:
+  case MP3: {
+    // Search for VBR header and compute correct bitrate if necessary
+    uint8_t vbrhdr[4];
+    uint8_t frames_in_hdr[4];
+    int frames_nb = -1;
+    uint8_t frames_field;
+    stream_seek(s,mpeghdr_pos+4+mp3_found->mpa_ssize);
+    stream_read(s,vbrhdr,4);
+    if( (vbrhdr[0] == 'X' && vbrhdr[1] == 'i' && vbrhdr[2] == 'n' && vbrhdr[3] == 'g')
+        || (vbrhdr[0] == 'I' && vbrhdr[1] == 'n' && vbrhdr[2] == 'f' && vbrhdr[3] == 'o') ) { // We found a XING header
+      stream_seek(s,mpeghdr_pos+11+mp3_found->mpa_ssize);
+      stream_read(s,&frames_field,1);
+      if( frames_field & 1 ) {
+	stream_seek(s,mpeghdr_pos+12+mp3_found->mpa_ssize); // We jump to Frames number
+	stream_read(s,frames_in_hdr,4);
+	frames_nb = (frames_in_hdr[0]<<24) | (frames_in_hdr[1]<<16) | (frames_in_hdr[2]<<8) | hdr[3];
+      }
+    }
+    else {
+      stream_seek(s,mpeghdr_pos+36);
+      stream_read(s,vbrhdr,4);
+      if( vbrhdr[0] == 'V' && vbrhdr[1] == 'B' && vbrhdr[2] == 'R' && vbrhdr[3] == 'I' ) { // We found a VBRI header
+	stream_seek(s,mpeghdr_pos+50); // We jump to Frames number
+	stream_read(s,frames_in_hdr,4);
+	frames_nb = (frames_in_hdr[0]<<24) | (frames_in_hdr[1]<<16) | (frames_in_hdr[2]<<8) | hdr[3];
+      }
+    }
+   
     sh_audio->format = (mp3_found->mpa_layer < 3 ? 0x50 : 0x55);
     demuxer->movi_start = mp3_found->frame_pos;
     next_frame_pos = mp3_found->next_frame_pos;
@@ -360,7 +392,10 @@
     sh_audio->wf->wFormatTag = sh_audio->format;
     sh_audio->wf->nChannels = mp3_found->mp3_chans;
     sh_audio->wf->nSamplesPerSec = mp3_found->mp3_freq;
-    sh_audio->wf->nAvgBytesPerSec = mp3_found->mpa_br * (1000 / 8);
+    if (frames_nb >= 0)
+      sh_audio->wf->nAvgBytesPerSec = ((demuxer->movi_end-demuxer->movi_start)*mp3_found->mp3_freq)/(frames_nb*mp3_found->mpa_spf);
+    else
+      sh_audio->wf->nAvgBytesPerSec = mp3_found->mpa_br * (1000 / 8);
     sh_audio->wf->nBlockAlign = mp3_found->mpa_spf;
     sh_audio->wf->wBitsPerSample = 16;
     sh_audio->wf->cbSize = 0;    
@@ -402,7 +437,7 @@
 	demux_info_add(demuxer,"Genre",genres[g]);
       }
     }
-    break;
+  } break;
   case WAV: {
     unsigned int chunk_type;
     unsigned int chunk_size;
@@ -709,13 +744,13 @@
 
 static int demux_audio_control(demuxer_t *demuxer,int cmd, void *arg){
     sh_audio_t *sh_audio=demuxer->audio->sh;
-    int audio_length = demuxer->movi_end / sh_audio->i_bps;
+    double audio_length = (double)(demuxer->movi_end-demuxer->movi_start) / (double)sh_audio->i_bps;
     da_priv_t* priv = demuxer->priv;
-	    
+
     switch(cmd) {
 	case DEMUXER_CTRL_GET_TIME_LENGTH:
 	    if (audio_length<=0) return DEMUXER_CTRL_DONTKNOW;
-	    *((double *)arg)=(double)audio_length;
+	    *((double *)arg)=audio_length;
 	    return DEMUXER_CTRL_GUESS;
 
 	case DEMUXER_CTRL_GET_PERCENT_POS:
