src/codecs/mp3utils.c
changeset 1111 e56a612a3daa
parent 1103 4e1c2282e6f1
child 1123 d40dacdd4ab1
equal deleted inserted replaced
1109:ee22b0e110b3 1111:e56a612a3daa
    38     return ret;
    38     return ret;
    39 }
    39 }
    40 
    40 
    41 Sint64 MP3_RWseek(struct mp3file_t *fil, Sint64 offset, int whence) {
    41 Sint64 MP3_RWseek(struct mp3file_t *fil, Sint64 offset, int whence) {
    42     Sint64 ret;
    42     Sint64 ret;
    43     switch (whence) { /* assumes a legal whence value */
    43     switch (whence) {
    44     case RW_SEEK_CUR:
    44     case RW_SEEK_CUR:
    45         offset += fil->pos;
    45         offset += fil->pos;
    46         break;
    46         break;
    47     case RW_SEEK_END:
    47     case RW_SEEK_END:
    48         offset = fil->length + offset;
    48         offset += fil->length;
    49         break;
    49         break;
    50     }
    50     }
    51     if (offset < 0) return -1;
    51     if (offset < 0) return -1;
    52     if (offset > fil->length)
    52     if (offset > fil->length)
    53         offset = fil->length;
    53         offset = fil->length;
    58 }
    58 }
    59 
    59 
    60 
    60 
    61 /*************************** TAG HANDLING: ******************************/
    61 /*************************** TAG HANDLING: ******************************/
    62 
    62 
    63 static SDL_INLINE SDL_bool is_id3v1(const unsigned char *data, size_t length)
    63 static SDL_INLINE SDL_bool is_id3v1(const unsigned char *data, long length) {
    64 {
       
    65     /* http://id3.org/ID3v1 :  3 bytes "TAG" identifier and 125 bytes tag data */
    64     /* http://id3.org/ID3v1 :  3 bytes "TAG" identifier and 125 bytes tag data */
    66     if (length < 3 || SDL_memcmp(data,"TAG",3) != 0) {
    65     if (length < 3 || SDL_memcmp(data,"TAG",3) != 0) {
    67         return SDL_FALSE;
    66         return SDL_FALSE;
    68     }
    67     }
    69     return SDL_TRUE;
    68     return SDL_TRUE;
    70 }
    69 }
    71 static SDL_bool is_id3v2(const unsigned char *data, size_t length)
    70 static SDL_bool is_id3v2(const unsigned char *data, size_t length) {
    72 {
       
    73     /* ID3v2 header is 10 bytes:  http://id3.org/id3v2.4.0-structure */
    71     /* ID3v2 header is 10 bytes:  http://id3.org/id3v2.4.0-structure */
    74     /* bytes 0-2: "ID3" identifier */
    72     /* bytes 0-2: "ID3" identifier */
    75     if (length < 10 || SDL_memcmp(data,"ID3",3) != 0) {
    73     if (length < 10 || SDL_memcmp(data,"ID3",3) != 0) {
    76         return SDL_FALSE;
    74         return SDL_FALSE;
    77     }
    75     }
    85     if (data[6] >= 0x80 || data[7] >= 0x80 || data[8] >= 0x80 || data[9] >= 0x80) {
    83     if (data[6] >= 0x80 || data[7] >= 0x80 || data[8] >= 0x80 || data[9] >= 0x80) {
    86         return SDL_FALSE;
    84         return SDL_FALSE;
    87     }
    85     }
    88     return SDL_TRUE;
    86     return SDL_TRUE;
    89 }
    87 }
    90 static long get_id3v2_len(const unsigned char *data, long length)
    88 static long get_id3v2_len(const unsigned char *data, long length) {
    91 {
       
    92     /* size is a 'synchsafe' integer (see above) */
    89     /* size is a 'synchsafe' integer (see above) */
    93     long size = (long)((data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9]);
    90     long size = (long)((data[6]<<21) + (data[7]<<14) + (data[8]<<7) + data[9]);
    94     size += 10; /* header size */
    91     size += 10; /* header size */
    95     /* ID3v2 header[5] is flags (bits 4-7 only, 0-3 are zero).
    92     /* ID3v2 header[5] is flags (bits 4-7 only, 0-3 are zero).
    96      * bit 4 set: footer is present (a copy of the header but
    93      * bit 4 set: footer is present (a copy of the header but
   102     while (size < length && data[size] == 0) {
    99     while (size < length && data[size] == 0) {
   103         ++size;
   100         ++size;
   104     }
   101     }
   105     return size;
   102     return size;
   106 }
   103 }
   107 static SDL_bool is_apetag(const unsigned char *data, size_t length)
   104 static SDL_bool is_apetag(const unsigned char *data, size_t length) {
   108 {
       
   109    /* http://wiki.hydrogenaud.io/index.php?title=APEv2_specification
   105    /* http://wiki.hydrogenaud.io/index.php?title=APEv2_specification
   110     * Header/footer is 32 bytes: bytes 0-7 ident, bytes 8-11 version,
   106     * Header/footer is 32 bytes: bytes 0-7 ident, bytes 8-11 version,
   111     * bytes 12-17 size. bytes 24-31 are reserved: must be all zeroes. */
   107     * bytes 12-17 size. bytes 24-31 are reserved: must be all zeroes. */
   112     Uint32 v;
   108     Uint32 v;
   113 
   109 
   122     if (SDL_memcmp(&data[24],&v,4) != 0 || SDL_memcmp(&data[28],&v,4) != 0) {
   118     if (SDL_memcmp(&data[24],&v,4) != 0 || SDL_memcmp(&data[28],&v,4) != 0) {
   123         return SDL_FALSE;
   119         return SDL_FALSE;
   124     }
   120     }
   125     return SDL_TRUE;
   121     return SDL_TRUE;
   126 }
   122 }
   127 static long get_ape_len(const unsigned char *data)
   123 static long get_ape_len(const unsigned char *data) {
   128 {
       
   129     Uint32 flags, version;
   124     Uint32 flags, version;
   130     long size = (long)((data[15]<<24) | (data[14]<<16) | (data[13]<<8) | data[12]);
   125     long size = (long)((data[15]<<24) | (data[14]<<16) | (data[13]<<8) | data[12]);
   131     version = (Uint32)((data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8]);
   126     version = (Uint32)((data[11]<<24) | (data[10]<<16) | (data[9]<<8) | data[8]);
   132     flags = (Uint32)((data[23]<<24) | (data[22]<<16) | (data[21]<<8) | data[20]);
   127     flags = (Uint32)((data[23]<<24) | (data[22]<<16) | (data[21]<<8) | data[20]);
   133     if (version == 2000U && (flags & (1U<<31))) size += 32; /* header present. */
   128     if (version == 2000U && (flags & (1U<<31))) size += 32; /* header present. */
   161     /* 6 bytes before the end marker is size in decimal format -
   156     /* 6 bytes before the end marker is size in decimal format -
   162      * does not include the 9 bytes end marker and size field. */
   157      * does not include the 9 bytes end marker and size field. */
   163     if (length != 6) return 0;
   158     if (length != 6) return 0;
   164     return SDL_strtol((const char *)data, NULL, 10) + 15;
   159     return SDL_strtol((const char *)data, NULL, 10) + 15;
   165 }
   160 }
   166 static SDL_bool verify_lyrics3v2(const unsigned char *data, long length) {
   161 static SDL_INLINE SDL_bool verify_lyrics3v2(const unsigned char *data, long length) {
   167     if (length < 11) return SDL_FALSE;
   162     if (length < 11) return SDL_FALSE;
   168     if (SDL_memcmp(data,"LYRICSBEGIN",11) == 0) return SDL_TRUE;
   163     if (SDL_memcmp(data,"LYRICSBEGIN",11) == 0) return SDL_TRUE;
   169     return SDL_FALSE;
   164     return SDL_FALSE;
   170 }
   165 }
   171 #define MMTAG_PARANOID
   166 #define MMTAG_PARANOID
   333         if (len == 2) {
   328         if (len == 2) {
   334             len = get_lyrics3v2_len(buf, 6);
   329             len = get_lyrics3v2_len(buf, 6);
   335             if (len >= fil->length) return -1;
   330             if (len >= fil->length) return -1;
   336             if (len < 15) return -1;
   331             if (len < 15) return -1;
   337             MP3_RWseek(fil, -len, RW_SEEK_END);
   332             MP3_RWseek(fil, -len, RW_SEEK_END);
   338             if (MP3_RWread(fil, buf, 1, 11)!= 11)
   333             if (MP3_RWread(fil, buf, 1, 11) != 11)
   339                 return -1;
   334                 return -1;
   340             if (!verify_lyrics3v2(buf, 11)) return -1;
   335             if (!verify_lyrics3v2(buf, 11)) return -1;
   341             fil->length -= len;
   336             fil->length -= len;
   342             return 1;
   337             return 1;
   343         }
   338         }
   359     int rc = -1;
   354     int rc = -1;
   360 
   355 
   361     /* MP3 standard has no metadata format, so everyone invented
   356     /* MP3 standard has no metadata format, so everyone invented
   362      * their own thing, even with extensions, until ID3v2 became
   357      * their own thing, even with extensions, until ID3v2 became
   363      * dominant: Hence the impossible mess here.
   358      * dominant: Hence the impossible mess here.
       
   359      *
       
   360      * Note: I don't yet care about freaky broken mp3 files with
       
   361      * double tags. -- O.S.
   364      */
   362      */
   365 
   363 
   366     readsize = MP3_RWread(fil, buf, 1, 128);
   364     readsize = MP3_RWread(fil, buf, 1, 128);
   367     if (!readsize) goto fail;
   365     if (!readsize) goto fail;
   368 
   366 
   420     rc = (fil->length > 0)? 0 : -1;
   418     rc = (fil->length > 0)? 0 : -1;
   421     fail:
   419     fail:
   422     MP3_RWseek(fil, 0, RW_SEEK_SET);
   420     MP3_RWseek(fil, 0, RW_SEEK_SET);
   423     return rc;
   421     return rc;
   424 }
   422 }
   425 #endif /* MUSIC_MP3_????? */
   423 #endif /* MUSIC_MP3_??? */
   426 
   424 
   427 /* vi: set ts=4 sw=4 expandtab: */
   425 /* vi: set ts=4 sw=4 expandtab: */