music_mad.c: Tag detection fixes, updates and cleanups: SDL-1.2
authorOzkan Sezer
Sat, 07 Dec 2019 14:10:02 +0300
branchSDL-1.2
changeset 10579448cf5038cd
parent 1037 477c0f3e5dc8
child 1059 ce75343f3b96
music_mad.c: Tag detection fixes, updates and cleanups:

- Fix APE header presence detection: APEv2 doesn't guarantee a header.
We rely on bit31 of the flags field of the header/footer, instead.
- Add a note that the 'Extended ID3v1' thingy is non-standard: we must
not assume any additional tags before it. (should we drop support??)
- The 'APE before ID3v1' is duplicated code (because we just return if
we detect a TAG+ thingy): removed it.
- Add a FIXME note about handling possible double-ID3v1 tags.
- possibly a few minor tidy-ups.
music_mad.c
     1.1 --- a/music_mad.c	Tue Nov 26 14:37:01 2019 +0300
     1.2 +++ b/music_mad.c	Sat Dec 07 14:10:02 2019 +0300
     1.3 @@ -170,7 +170,7 @@
     1.4      }
     1.5      return SDL_TRUE;
     1.6  }
     1.7 -static __inline__ int get_id3v2_len(const unsigned char *data, long length)
     1.8 +static __inline__ int get_id3v2_len(const unsigned char *data, int length)
     1.9  {
    1.10      /* size is a 'synchsafe' integer (see above) */
    1.11      int size = (int)((data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9]);
    1.12 @@ -207,11 +207,14 @@
    1.13      }
    1.14      return SDL_TRUE;
    1.15  }
    1.16 -static __inline__ int get_ape_len(const unsigned char *data, int datalen, Uint32 *version)
    1.17 +static __inline__ int get_ape_len(const unsigned char *data)
    1.18  {
    1.19 +    Uint32 flags, version;
    1.20      int size = (int)((data[15]<<24) | (data[14]<<16) | (data[13]<<8) | data[12]);
    1.21 -    *version = (data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8];
    1.22 -    return size; /* caller will handle the additional v2 header length */
    1.23 +    version = (data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8];
    1.24 +    flags = (data[23]<<24) | (data[22]<<16) | (data[21]<<8) | data[20];
    1.25 +    if (version == 2000U && (flags & (1U<<31))) size += 32; /* header present. */
    1.26 +    return size;
    1.27  }
    1.28  
    1.29  static int skip_tags(mad_data *music)
    1.30 @@ -229,11 +232,10 @@
    1.31          music->length -= len;
    1.32          MAD_RWseek(music, 0, RW_SEEK_SET);
    1.33      }
    1.34 -    /* APE tag _might_ be at the start: read the header */
    1.35 +    /* APE tag _might_ be at the start (discouraged
    1.36 +     * but not forbidden, either.)  read the header. */
    1.37      else if (is_apetag(music->input_buffer, readsize)) {
    1.38 -        Uint32 v;
    1.39 -        len = get_ape_len(music->input_buffer, readsize, &v);
    1.40 -        len += 32; /* we're at top: have a header. */
    1.41 +        len = get_ape_len(music->input_buffer);
    1.42          if (len >= music->length) return -1;
    1.43          music->start += len;
    1.44          music->length -= len;
    1.45 @@ -249,29 +251,10 @@
    1.46      if (is_id3v1(music->input_buffer, 128)) {
    1.47          music->length -= 128;
    1.48  
    1.49 -        /* APE tag may be before the ID3v1: read the footer */
    1.50 -        if (music->length < 32) goto end;
    1.51 -        MAD_RWseek(music, -32, RW_SEEK_END);
    1.52 -        readsize = MAD_RWread(music, music->input_buffer, 1, 32);
    1.53 -        MAD_RWseek(music, 0, RW_SEEK_SET);
    1.54 -        if (readsize != 32) return -1;
    1.55 -        if (is_apetag(music->input_buffer, 32)) {
    1.56 -            Uint32 v;
    1.57 -            len = get_ape_len(music->input_buffer, readsize, &v);
    1.58 -            if (v == 2000U) len += 32; /* header */
    1.59 -            if (len >= music->length) return -1;
    1.60 -            if (v == 2000U) { /* verify header : */
    1.61 -                MAD_RWseek(music, -len, RW_SEEK_END);
    1.62 -                readsize = MAD_RWread(music, music->input_buffer, 1, 32);
    1.63 -                MAD_RWseek(music, 0, RW_SEEK_SET);
    1.64 -                if (readsize != 32) return -1;
    1.65 -                if (!is_apetag(music->input_buffer, 32)) return -1;
    1.66 -            }
    1.67 -            music->length -= len;
    1.68 -            goto end;
    1.69 -        }
    1.70 -        /* extended ID3v1 just before the ID3v1 tag? (unlikely)  */
    1.71 -        if (music->length < 227) goto end;
    1.72 +        /* extended ID3v1 just before the ID3v1 tag? (unlikely)
    1.73 +         * if found, assume no additional tags: this stupidity
    1.74 +         * is non-standard..  */
    1.75 +        if (music->length < 227) goto ape;
    1.76          MAD_RWseek(music, -227, RW_SEEK_END);
    1.77          readsize = MAD_RWread(music, music->input_buffer, 1, 227);
    1.78          MAD_RWseek(music, 0, RW_SEEK_SET);
    1.79 @@ -280,7 +263,10 @@
    1.80              music->length -= 227;
    1.81              goto end;
    1.82          }
    1.83 +
    1.84 +        /* FIXME: handle possible double-ID3v1 tags? */
    1.85      }
    1.86 +
    1.87      ape: /* APE tag may be at the end: read the footer */
    1.88      if (music->length >= 32) {
    1.89          MAD_RWseek(music, -32, RW_SEEK_END);
    1.90 @@ -288,17 +274,8 @@
    1.91          MAD_RWseek(music, 0, RW_SEEK_SET);
    1.92          if (readsize != 32) return -1;
    1.93          if (is_apetag(music->input_buffer, 32)) {
    1.94 -            Uint32 v;
    1.95 -            len = get_ape_len(music->input_buffer, readsize, &v);
    1.96 -            if (v == 2000U) len += 32; /* header */
    1.97 +            len = get_ape_len(music->input_buffer);
    1.98              if (len >= music->length) return -1;
    1.99 -            if (v == 2000U) { /* verify header : */
   1.100 -                MAD_RWseek(music, -len, RW_SEEK_END);
   1.101 -                readsize = MAD_RWread(music, music->input_buffer, 1, 32);
   1.102 -                MAD_RWseek(music, 0, RW_SEEK_SET);
   1.103 -                if (readsize != 32) return -1;
   1.104 -                if (!is_apetag(music->input_buffer, 32)) return -1;
   1.105 -            }
   1.106              music->length -= len;
   1.107          }
   1.108      }
   1.109 @@ -325,7 +302,7 @@
   1.110  	  memmove(mp3_mad->input_buffer, mp3_mad->stream.next_frame, remaining);
   1.111  	  read_start = mp3_mad->input_buffer + remaining;
   1.112  	  read_size = MAD_INPUT_BUFFER_SIZE - remaining;
   1.113 -	  
   1.114 +
   1.115  	} else {
   1.116  	  read_size = MAD_INPUT_BUFFER_SIZE;
   1.117  	  read_start = mp3_mad->input_buffer;
   1.118 @@ -334,7 +311,7 @@
   1.119  
   1.120  	/* Now read additional bytes from the input file. */
   1.121  	read_size = MAD_RWread(mp3_mad, read_start, 1, read_size);
   1.122 -	
   1.123 +
   1.124  	if (read_size <= 0) {
   1.125  	  if ((mp3_mad->status & (MS_input_eof | MS_input_error)) == 0) {
   1.126  		if (read_size == 0) {
   1.127 @@ -342,14 +319,14 @@
   1.128  		} else {
   1.129  		  mp3_mad->status |= MS_input_error;
   1.130  		}
   1.131 -		
   1.132 +
   1.133  		/* At the end of the file, we must stuff MAD_BUFFER_GUARD
   1.134  		   number of 0 bytes. */
   1.135  		memset(read_start + read_size, 0, MAD_BUFFER_GUARD);
   1.136  		read_size += MAD_BUFFER_GUARD;
   1.137  	  }
   1.138  	}
   1.139 -	
   1.140 +
   1.141  	/* Now feed those bytes into the libmad stream. */
   1.142  	mad_stream_buffer(&mp3_mad->stream, mp3_mad->input_buffer,
   1.143  					  read_size + remaining);
   1.144 @@ -362,10 +339,10 @@
   1.145  	if (MAD_RECOVERABLE(mp3_mad->stream.error)) {
   1.146  	  mad_stream_sync(&mp3_mad->stream); /* to frame seek mode */
   1.147  	  return 0;
   1.148 -	  
   1.149 +
   1.150  	} else if (mp3_mad->stream.error == MAD_ERROR_BUFLEN) {
   1.151  	  return 0;
   1.152 -	  
   1.153 +
   1.154  	} else {
   1.155  	  mp3_mad->status |= MS_decode_error;
   1.156  	  return 0;
   1.157 @@ -402,7 +379,6 @@
   1.158    unsigned int nchannels, nsamples;
   1.159    mad_fixed_t const *left_ch, *right_ch;
   1.160    unsigned char *out;
   1.161 -  int ret;
   1.162  
   1.163    mad_synth_frame(&mp3_mad->synth, &mp3_mad->frame);
   1.164    pcm = &mp3_mad->synth.pcm;