[MPlayer-dev-eng] [PATCH] set i_bps in demux_audio, other fixes

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Fri Jul 29 14:18:50 CEST 2005


Hi,
the attached patch sets sh_audio->i_bps for MP3 and WAV files, avoiding
a division by zero (since the decoder can only set it _after_ the first
call to demux_audio_fill_buffer)
It also fixes that bug that the format field for MP3 is set according to
the last MPEG-Audio like header, instead of the one we decided is the
right one (mp3_found).
Please comment (and esp. test).

Greetings,
Reimar Döffinger
-------------- next part --------------
Index: libmpdemux/demux_audio.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demux_audio.c,v
retrieving revision 1.35
diff -u -r1.35 demux_audio.c
--- libmpdemux/demux_audio.c	18 Apr 2005 20:51:34 -0000	1.35
+++ libmpdemux/demux_audio.c	29 Jul 2005 12:11:07 -0000
@@ -36,6 +36,9 @@
   off_t next_frame_pos; // here we expect the next header with same parameters
   int mp3_chans;
   int mp3_freq;
+  int mpa_spf;
+  int mpa_layer;
+  int mpa_br;
   int cons_hdrs; // if this reaches MIN_MP3_HDRS we accept as MP3 file
   struct mp3_hdr *next;
 } mp3_hdr_t;
@@ -69,26 +72,35 @@
  * and when those are equal by frame_pos.
  * \param list pointer to the head-of-list pointer
  * \param st_pos stream position where the described header starts
- * \param mp3_chans number of channels as specified by the header
- * \param mp3_freq sampling frequency as specified by the header
+ * \param mp3_chans number of channels as specified by the header (*)
+ * \param mp3_freq sampling frequency as specified by the header (*)
+ * \param mpa_spf frame size as specified by the header
+ * \param mpa_layer layer type ("version") as specified by the header (*)
+ * \param mpa_br bitrate as specified by the header
  * \param mp3_flen length of the frame as specified by the header
  * \return If non-null the current file is accepted as MP3 and the
  * mp3_hdr struct describing the valid chain is returned. Must be
  * freed independent of the list.
+ *
+ * parameters marked by (*) must be the same for all headers in the same chain
  */
 static mp3_hdr_t *add_mp3_hdr(mp3_hdr_t **list, off_t st_pos,
-                               int mp3_chans, int mp3_freq, int mp3_flen) {
+                               int mp3_chans, int mp3_freq, int mpa_spf,
+                               int mpa_layer, int mpa_br, int mp3_flen) {
   mp3_hdr_t *tmp;
   int in_list = 0;
   while (*list && (*list)->next_frame_pos <= st_pos) {
     if (((*list)->next_frame_pos < st_pos) || ((*list)->mp3_chans != mp3_chans)
-         || ((*list)->mp3_freq != mp3_freq)) { // wasn't valid!
+         || ((*list)->mp3_freq != mp3_freq) || ((*list)->mpa_layer != mpa_layer) ) {
+      // wasn't valid!
       tmp = (*list)->next;
       free(*list);
       *list = tmp;
     } else {
       (*list)->cons_hdrs++;
       (*list)->next_frame_pos = st_pos + mp3_flen;
+      (*list)->mpa_spf = mpa_spf;
+      (*list)->mpa_br = mpa_br;
       if ((*list)->cons_hdrs >= MIN_MP3_HDRS) {
         // copy the valid entry, so that the list can be easily freed
         tmp = malloc(sizeof(mp3_hdr_t));
@@ -109,6 +121,9 @@
     tmp->next_frame_pos = st_pos + mp3_flen;
     tmp->mp3_chans = mp3_chans;
     tmp->mp3_freq = mp3_freq;
+    tmp->mpa_spf = mpa_spf;
+    tmp->mpa_layer = mpa_layer;
+    tmp->mpa_br = mpa_br;
     tmp->cons_hdrs = 1;
     tmp->next = *list;
     *list = tmp;
@@ -120,7 +135,7 @@
   stream_t *s;
   sh_audio_t* sh_audio;
   uint8_t hdr[HDR_SIZE];
-  int frmt = 0, n = 0, step, mp3_freq, mp3_chans, mp3_flen, mpa_layer = 3, mpa_spf = 1152;
+  int frmt = 0, n = 0, step;
   off_t st_pos = 0, next_frame_pos = 0;
   // mp3_hdrs list is sorted first by next_frame_pos and then by frame_pos
   mp3_hdr_t *mp3_hdrs = NULL, *mp3_found = NULL;
@@ -134,6 +149,7 @@
 
   stream_read(s, hdr, HDR_SIZE);
   while(n < 30000 && !s->eof) {
+    int mp3_freq, mp3_chans, mp3_flen, mpa_layer, mpa_spf, mpa_br;
     st_pos = stream_tell(s) - HDR_SIZE;
     step = 1;
 
@@ -160,8 +176,10 @@
     } 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)) > 0) {
-      mp3_found = add_mp3_hdr(&mp3_hdrs, st_pos, mp3_chans, mp3_freq, mp3_flen);
+    } else if((mp3_flen = mp_get_mp3_header(hdr, &mp3_chans, &mp3_freq,
+                                &mpa_spf, &mpa_layer, &mpa_br)) > 0) {
+      mp3_found = add_mp3_hdr(&mp3_hdrs, st_pos, mp3_chans, mp3_freq,
+                              mpa_spf, mpa_layer, mpa_br, mp3_flen);
       if (mp3_found) {
         frmt = MP3;
         break;
@@ -187,19 +205,21 @@
 
   switch(frmt) {
   case MP3:
-    sh_audio->format = (mpa_layer < 3 ? 0x50 : 0x55);
+    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;
     sh_audio->audio.dwSampleSize= 0;
-    sh_audio->audio.dwScale = mpa_spf;
+    sh_audio->audio.dwScale = mp3_found->mpa_spf;
     sh_audio->audio.dwRate = mp3_found->mp3_freq;
     sh_audio->wf = malloc(sizeof(WAVEFORMATEX));
     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->nBlockAlign = mpa_spf;
+    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;    
+    sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;
     free(mp3_found);
     mp3_found = NULL;
     if(s->end_pos) {
@@ -257,6 +277,7 @@
     w->nBlockAlign = stream_read_word_le(s);
     w->wBitsPerSample = sh_audio->samplesize = stream_read_word_le(s);
     w->cbSize = 0;
+    sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;
     l -= 16;
     if (l > 0) {
     w->cbSize = stream_read_word_le(s);
Index: libmpdemux/mp3_hdr.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/mp3_hdr.c,v
retrieving revision 1.11
diff -u -r1.11 mp3_hdr.c
--- libmpdemux/mp3_hdr.c	24 Apr 2005 08:41:45 -0000	1.11
+++ libmpdemux/mp3_hdr.c	29 Jul 2005 12:11:19 -0000
@@ -34,8 +34,9 @@
 /*
  * 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 mp_get_mp3_header(unsigned char* hbuf,int* chans, int* srate, int* spf, int* mpa_layer, int* br){
     int stereo,ssize,lsf,framesize,padding,bitrate_index,sampling_frequency, divisor;
+    int bitrate;
     int layer, mult[3] = { 12000, 144000, 144000 };
     unsigned long newhead = 
       hbuf[0] << 24 |
@@ -99,7 +100,8 @@
       ssize = (stereo == 1) ? 17 : 32;
     if(!((newhead>>16)&0x1)) ssize += 2; // CRC
 
-    framesize = tabsel_123[lsf][layer-1][bitrate_index] * mult[layer-1];
+    bitrate = tabsel_123[lsf][layer-1][bitrate_index];
+    framesize = bitrate * mult[layer-1];
 
     mp_msg(MSGT_DEMUXER,MSGL_DBG2,"FRAMESIZE: %d, layer: %d, bitrate: %d, mult: %d\n", 
     	framesize, layer, tabsel_123[lsf][layer-1][bitrate_index], mult[layer-1]);
@@ -131,6 +133,7 @@
     }
     if(mpa_layer) *mpa_layer = layer;
     if(chans) *chans = stereo;
+    if(br) *br = bitrate;
 
     return framesize;
 }
Index: libmpdemux/mp3_hdr.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/mp3_hdr.h,v
retrieving revision 1.3
diff -u -r1.3 mp3_hdr.h
--- libmpdemux/mp3_hdr.h	17 Apr 2005 09:42:51 -0000	1.3
+++ libmpdemux/mp3_hdr.h	29 Jul 2005 12:11:19 -0000
@@ -1,7 +1,7 @@
 
-int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* freq, int* spf, int* mpa_layer);
+int mp_get_mp3_header(unsigned char* hbuf,int* chans, int* freq, int* spf, int* mpa_layer, int* br);
 
-#define mp_decode_mp3_header(hbuf)  mp_get_mp3_header(hbuf,NULL,NULL,NULL,NULL)
+#define mp_decode_mp3_header(hbuf)  mp_get_mp3_header(hbuf,NULL,NULL,NULL,NULL,NULL)
 
 static inline int mp_check_mp3_header(unsigned int head){
     if( (head & 0x0000e0ff) != 0x0000e0ff ||  
Index: libmpdemux/muxer_mpeg.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/muxer_mpeg.c,v
retrieving revision 1.18
diff -u -r1.18 muxer_mpeg.c
--- libmpdemux/muxer_mpeg.c	10 Jul 2005 08:36:39 -0000	1.18
+++ libmpdemux/muxer_mpeg.c	29 Jul 2005 12:11:32 -0000
@@ -2312,7 +2312,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);
+					len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL);
 					if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))
 					{
 						frames++;


More information about the MPlayer-dev-eng mailing list