music_mad.c: Tag detection fixes, updates and cleanups:
authorOzkan Sezer
Sat, 07 Dec 2019 14:10:24 +0300
changeset 1058b799e2ec2b5d
parent 1056 4e97a14ce2bf
child 1060 c8f653ad25de
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.
src/codecs/music_mad.c
     1.1 --- a/src/codecs/music_mad.c	Thu Dec 05 01:56:50 2019 +0300
     1.2 +++ b/src/codecs/music_mad.c	Sat Dec 07 14:10:24 2019 +0300
     1.3 @@ -305,12 +305,14 @@
     1.4      }
     1.5      return SDL_TRUE;
     1.6  }
     1.7 -static SDL_INLINE long get_ape_len(const unsigned char *data, long datalen, Uint32 *version)
     1.8 +static SDL_INLINE long get_ape_len(const unsigned char *data)
     1.9  {
    1.10 +    Uint32 flags, version;
    1.11      long size = (long)((data[15]<<24) | (data[14]<<16) | (data[13]<<8) | data[12]);
    1.12 -    *version = (Uint32)((data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8]);
    1.13 -    (void)datalen;
    1.14 -    return size; /* caller will handle the additional v2 header length */
    1.15 +    version = (Uint32)((data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8]);
    1.16 +    flags = (Uint32)((data[23]<<24) | (data[22]<<16) | (data[21]<<8) | data[20]);
    1.17 +    if (version == 2000U && (flags & (1U<<31))) size += 32; /* header present. */
    1.18 +    return size;
    1.19  }
    1.20  
    1.21  static int skip_tags(MAD_Music *music)
    1.22 @@ -328,11 +330,10 @@
    1.23          music->length -= len;
    1.24          MAD_RWseek(music, 0, RW_SEEK_SET);
    1.25      }
    1.26 -    /* APE tag _might_ be at the start: read the header */
    1.27 +    /* APE tag _might_ be at the start (discouraged
    1.28 +     * but not forbidden, either.)  read the header. */
    1.29      else if (is_apetag(music->input_buffer, readsize)) {
    1.30 -        Uint32 v;
    1.31 -        len = get_ape_len(music->input_buffer, (long)readsize, &v);
    1.32 -        len += 32; /* we're at top: have a header. */
    1.33 +        len = get_ape_len(music->input_buffer);
    1.34          if (len >= music->length) return -1;
    1.35          music->start += len;
    1.36          music->length -= len;
    1.37 @@ -348,29 +349,10 @@
    1.38      if (is_id3v1(music->input_buffer, 128)) {
    1.39          music->length -= 128;
    1.40  
    1.41 -        /* APE tag may be before the ID3v1: read the footer */
    1.42 -        if (music->length < 32) goto end;
    1.43 -        MAD_RWseek(music, -32, RW_SEEK_END);
    1.44 -        readsize = MAD_RWread(music, music->input_buffer, 1, 32);
    1.45 -        MAD_RWseek(music, 0, RW_SEEK_SET);
    1.46 -        if (readsize != 32) return -1;
    1.47 -        if (is_apetag(music->input_buffer, 32)) {
    1.48 -            Uint32 v;
    1.49 -            len = get_ape_len(music->input_buffer, (long)readsize, &v);
    1.50 -            if (v == 2000U) len += 32; /* header */
    1.51 -            if (len >= music->length) return -1;
    1.52 -            if (v == 2000U) { /* verify header : */
    1.53 -                MAD_RWseek(music, -len, RW_SEEK_END);
    1.54 -                readsize = MAD_RWread(music, music->input_buffer, 1, 32);
    1.55 -                MAD_RWseek(music, 0, RW_SEEK_SET);
    1.56 -                if (readsize != 32) return -1;
    1.57 -                if (!is_apetag(music->input_buffer, 32)) return -1;
    1.58 -            }
    1.59 -            music->length -= len;
    1.60 -            goto end;
    1.61 -        }
    1.62 -        /* extended ID3v1 just before the ID3v1 tag? (unlikely)  */
    1.63 -        if (music->length < 227) goto end;
    1.64 +        /* extended ID3v1 just before the ID3v1 tag? (unlikely)
    1.65 +         * if found, assume no additional tags: this stupidity
    1.66 +         * is non-standard..  */
    1.67 +        if (music->length < 227) goto ape;
    1.68          MAD_RWseek(music, -227, RW_SEEK_END);
    1.69          readsize = MAD_RWread(music, music->input_buffer, 1, 227);
    1.70          MAD_RWseek(music, 0, RW_SEEK_SET);
    1.71 @@ -379,7 +361,10 @@
    1.72              music->length -= 227;
    1.73              goto end;
    1.74          }
    1.75 +
    1.76 +        /* FIXME: handle possible double-ID3v1 tags? */
    1.77      }
    1.78 +
    1.79      ape: /* APE tag may be at the end: read the footer */
    1.80      if (music->length >= 32) {
    1.81          MAD_RWseek(music, -32, RW_SEEK_END);
    1.82 @@ -387,17 +372,8 @@
    1.83          MAD_RWseek(music, 0, RW_SEEK_SET);
    1.84          if (readsize != 32) return -1;
    1.85          if (is_apetag(music->input_buffer, 32)) {
    1.86 -            Uint32 v;
    1.87 -            len = get_ape_len(music->input_buffer, (long)readsize, &v);
    1.88 -            if (v == 2000U) len += 32; /* header */
    1.89 +            len = get_ape_len(music->input_buffer);
    1.90              if (len >= music->length) return -1;
    1.91 -            if (v == 2000U) { /* verify header : */
    1.92 -                MAD_RWseek(music, -len, RW_SEEK_END);
    1.93 -                readsize = MAD_RWread(music, music->input_buffer, 1, 32);
    1.94 -                MAD_RWseek(music, 0, RW_SEEK_SET);
    1.95 -                if (readsize != 32) return -1;
    1.96 -                if (!is_apetag(music->input_buffer, 32)) return -1;
    1.97 -            }
    1.98              music->length -= len;
    1.99          }
   1.100      }