|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 /* MPEG format parsing */ |
|
6 |
|
7 #include "mp3sniff.h" |
|
8 |
|
9 /* Maximum packet size is 320 kbits/s * 144 / 32 kHz + 1 padding byte */ |
|
10 #define MP3_MAX_SIZE 1441 |
|
11 |
|
12 typedef struct { |
|
13 int version; |
|
14 int layer; |
|
15 int errp; |
|
16 int bitrate; |
|
17 int freq; |
|
18 int pad; |
|
19 int priv; |
|
20 int mode; |
|
21 int modex; |
|
22 int copyright; |
|
23 int original; |
|
24 int emphasis; |
|
25 } mp3_header; |
|
26 |
|
27 /* Parse the 4-byte header in p and fill in the header struct. */ |
|
28 static void mp3_parse(const uint8_t *p, mp3_header *header) |
|
29 { |
|
30 const int bitrates[2][16] = { |
|
31 /* MPEG version 1 layer 3 bitrates. */ |
|
32 {0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, |
|
33 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0}, |
|
34 /* MPEG Version 2 and 2.5 layer 3 bitrates */ |
|
35 {0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, |
|
36 80000, 96000, 112000, 128000, 144000, 160000, 0} }; |
|
37 const int samplerates[4] = {44100, 48000, 32000, 0}; |
|
38 |
|
39 header->version = (p[1] & 0x18) >> 3; |
|
40 header->layer = 4 - ((p[1] & 0x06) >> 1); |
|
41 header->errp = (p[1] & 0x01); |
|
42 |
|
43 header->bitrate = bitrates[(header->version & 1) ? 0 : 1][(p[2] & 0xf0) >> 4]; |
|
44 header->freq = samplerates[(p[2] & 0x0c) >> 2]; |
|
45 if (header->version == 2) header->freq >>= 1; |
|
46 else if (header->version == 0) header->freq >>= 2; |
|
47 header->pad = (p[2] & 0x02) >> 1; |
|
48 header->priv = (p[2] & 0x01); |
|
49 |
|
50 header->mode = (p[3] & 0xc0) >> 6; |
|
51 header->modex = (p[3] & 0x30) >> 4; |
|
52 header->copyright = (p[3] & 0x08) >> 3; |
|
53 header->original = (p[3] & 0x04) >> 2; |
|
54 header->emphasis = (p[3] & 0x03); |
|
55 } |
|
56 |
|
57 /* calculate the size of an mp3 frame from its header */ |
|
58 static int mp3_framesize(mp3_header *header) |
|
59 { |
|
60 int size; |
|
61 int scale; |
|
62 |
|
63 if ((header->version & 1) == 0) scale = 72; |
|
64 else scale = 144; |
|
65 size = header->bitrate * scale / header->freq; |
|
66 if (header->pad) size += 1; |
|
67 |
|
68 return size; |
|
69 } |
|
70 |
|
71 static int is_mp3(const uint8_t *p, long length) { |
|
72 /* Do we have enough room to see a 4 byte header? */ |
|
73 if (length < 4) return 0; |
|
74 /* Do we have a sync pattern? */ |
|
75 if (p[0] == 0xff && (p[1] & 0xe0) == 0xe0) { |
|
76 /* Do we have any illegal field values? */ |
|
77 if (((p[1] & 0x06) >> 1) == 0) return 0; /* No layer 4 */ |
|
78 if (((p[2] & 0xf0) >> 4) == 15) return 0; /* Bitrate can't be 1111 */ |
|
79 if (((p[2] & 0x0c) >> 2) == 3) return 0; /* Samplerate can't be 11 */ |
|
80 /* Looks like a header. */ |
|
81 if ((4 - ((p[1] & 0x06) >> 1)) != 3) return 0; /* Only want level 3 */ |
|
82 return 1; |
|
83 } |
|
84 return 0; |
|
85 } |
|
86 |
|
87 /* Identify an ID3 tag based on its header. */ |
|
88 /* http://id3.org/id3v2.4.0-structure */ |
|
89 static int is_id3(const uint8_t *p, long length) { |
|
90 /* Do we have enough room to see the header? */ |
|
91 if (length < 10) return 0; |
|
92 /* Do we have a sync pattern? */ |
|
93 if (p[0] == 'I' && p[1] == 'D' && p[2] == '3') { |
|
94 if (p[3] == 0xff || p[4] == 0xff) return 0; /* Illegal version. */ |
|
95 if (p[6] & 0x80 || p[7] & 0x80 || |
|
96 p[8] & 0x80) return 0; /* Bad length encoding. */ |
|
97 /* Looks like an id3 header. */ |
|
98 return 1; |
|
99 } |
|
100 return 0; |
|
101 } |
|
102 |
|
103 /* Calculate the size of an id3 tag structure from its header. */ |
|
104 static int id3_framesize(const uint8_t *p, long length) |
|
105 { |
|
106 int size; |
|
107 |
|
108 /* Header is 10 bytes. */ |
|
109 if (length < 10) { |
|
110 return 0; |
|
111 } |
|
112 /* Frame is header plus declared size. */ |
|
113 size = 10 + (p[9] | (p[8] << 7) | (p[7] << 14) | (p[6] << 21)); |
|
114 |
|
115 return size; |
|
116 } |
|
117 |
|
118 int mp3_sniff(const uint8_t *buf, long length) |
|
119 { |
|
120 mp3_header header; |
|
121 const uint8_t *p, *q; |
|
122 long skip; |
|
123 long avail; |
|
124 |
|
125 p = buf; |
|
126 q = p; |
|
127 avail = length; |
|
128 while (avail >= 4) { |
|
129 if (is_id3(p, avail)) { |
|
130 /* Skip over any id3 tags */ |
|
131 skip = id3_framesize(p, avail); |
|
132 p += skip; |
|
133 avail -= skip; |
|
134 } else if (is_mp3(p, avail)) { |
|
135 mp3_parse(p, &header); |
|
136 skip = mp3_framesize(&header); |
|
137 if (skip < 4 || skip + 4 >= avail) { |
|
138 return 0; |
|
139 } |
|
140 p += skip; |
|
141 avail -= skip; |
|
142 /* Check for a second header at the expected offset. */ |
|
143 if (is_mp3(p, avail)) { |
|
144 /* Looks like mp3. */ |
|
145 return 1; |
|
146 } else { |
|
147 /* No second header. Not mp3. */ |
|
148 return 0; |
|
149 } |
|
150 } else { |
|
151 /* No id3 tag or mp3 header. Not mp3. */ |
|
152 return 0; |
|
153 } |
|
154 } |
|
155 |
|
156 return 0; |
|
157 } |