Index: libmpcodecs/ad_mp3lib.c =================================================================== --- libmpcodecs/ad_mp3lib.c (Revision 22838) +++ libmpcodecs/ad_mp3lib.c (Arbeitskopie) @@ -47,10 +47,18 @@ 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 + if (sh->wf) + { + sh->channels=sh->wf->nChannels; + sh->i_bps=sh->wf->nAvgBytesPerSec; + } + else + { + sh->channels=2; + sh->i_bps=MP3_bitrate*(1000/8); + } sh->samplesize=2; sh->samplerate=MP3_samplerate; - sh->i_bps=MP3_bitrate*(1000/8); MP3_PrintHeader(); return 1; } Index: libmpdemux/mp3_hdr.c =================================================================== --- libmpdemux/mp3_hdr.c (Revision 22838) +++ libmpdemux/mp3_hdr.c (Arbeitskopie) @@ -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 (Revision 22838) +++ libmpdemux/mp3_hdr.h (Arbeitskopie) @@ -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 (Revision 22838) +++ libmpdemux/demux_audio.c (Arbeitskopie) @@ -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,16 +296,15 @@ 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; if( hdr[0] == 'R' && hdr[1] == 'I' && hdr[2] == 'F' && hdr[3] == 'F' ) { stream_skip(s,4); - if(s->eof) - break; stream_read(s,hdr,4); if(s->eof) break; @@ -316,16 +318,19 @@ int len; stream_skip(s,2); stream_read(s,hdr,4); + if(s->eof) + break; 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,39 @@ 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 framesnb_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(!s->eof) + 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,framesnb_hdr,4); + if(s->eof) + break; + frames_nb = (framesnb_hdr[0]<<24) | (framesnb_hdr[1]<<16) | (framesnb_hdr[2]<<8) | (framesnb_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,framesnb_hdr,4); + if(s->eof) + break; + frames_nb = (framesnb_hdr[0]<<24) | (framesnb_hdr[1]<<16) | (framesnb_hdr[2]<<8) | (framesnb_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 +397,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 +442,7 @@ demux_info_add(demuxer,"Genre",genres[g]); } } - break; + } break; case WAV: { unsigned int chunk_type; unsigned int chunk_size; @@ -709,13 +749,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: Index: libmpdemux/muxer_mpeg.c =================================================================== --- libmpdemux/muxer_mpeg.c (Revision 22838) +++ libmpdemux/muxer_mpeg.c (Arbeitskopie) @@ -2004,7 +2004,7 @@ { if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xE0) == 0xE0)) { - len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL); + len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL, NULL); if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len)) { score[layer]++; @@ -2057,7 +2057,7 @@ if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xE0) == 0xE0)) { - len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL); + len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL, NULL); if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len) && layer == spriv->mpa_layer) { Index: libmpcodecs/ad_hwmpa.c =================================================================== --- libmpcodecs/ad_hwmpa.c (Revision 22838) +++ libmpcodecs/ad_hwmpa.c (Arbeitskopie) @@ -35,7 +35,7 @@ { while(cnt + 4 < sh->a_in_buffer_len) { - x = mp_get_mp3_header(&(sh->a_in_buffer[cnt]), chans, srate, spf, mpa_layer, br); + x = mp_get_mp3_header(&(sh->a_in_buffer[cnt]), chans, srate, spf, mpa_layer, br, NULL); if(x > 0) { frames_count++;