Line data Source code
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 0 : static void mp3_parse(const uint8_t *p, mp3_header *header)
29 : {
30 0 : 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 0 : const int samplerates[4] = {44100, 48000, 32000, 0};
38 :
39 0 : header->version = (p[1] & 0x18) >> 3;
40 0 : header->layer = 4 - ((p[1] & 0x06) >> 1);
41 0 : header->errp = (p[1] & 0x01);
42 :
43 0 : header->bitrate = bitrates[(header->version & 1) ? 0 : 1][(p[2] & 0xf0) >> 4];
44 0 : header->freq = samplerates[(p[2] & 0x0c) >> 2];
45 0 : if (header->version == 2) header->freq >>= 1;
46 0 : else if (header->version == 0) header->freq >>= 2;
47 0 : header->pad = (p[2] & 0x02) >> 1;
48 0 : header->priv = (p[2] & 0x01);
49 :
50 0 : header->mode = (p[3] & 0xc0) >> 6;
51 0 : header->modex = (p[3] & 0x30) >> 4;
52 0 : header->copyright = (p[3] & 0x08) >> 3;
53 0 : header->original = (p[3] & 0x04) >> 2;
54 0 : header->emphasis = (p[3] & 0x03);
55 0 : }
56 :
57 : /* calculate the size of an mp3 frame from its header */
58 0 : static int mp3_framesize(mp3_header *header)
59 : {
60 : int size;
61 : int scale;
62 :
63 0 : if ((header->version & 1) == 0) scale = 72;
64 0 : else scale = 144;
65 0 : size = header->bitrate * scale / header->freq;
66 0 : if (header->pad) size += 1;
67 :
68 0 : return size;
69 : }
70 :
71 0 : static int is_mp3(const uint8_t *p, long length) {
72 : /* Do we have enough room to see a 4 byte header? */
73 0 : if (length < 4) return 0;
74 : /* Do we have a sync pattern? */
75 0 : if (p[0] == 0xff && (p[1] & 0xe0) == 0xe0) {
76 : /* Do we have any illegal field values? */
77 0 : if (((p[1] & 0x06) >> 1) == 0) return 0; /* No layer 4 */
78 0 : if (((p[2] & 0xf0) >> 4) == 15) return 0; /* Bitrate can't be 1111 */
79 0 : if (((p[2] & 0x0c) >> 2) == 3) return 0; /* Samplerate can't be 11 */
80 : /* Looks like a header. */
81 0 : if ((4 - ((p[1] & 0x06) >> 1)) != 3) return 0; /* Only want level 3 */
82 0 : return 1;
83 : }
84 0 : return 0;
85 : }
86 :
87 : /* Identify an ID3 tag based on its header. */
88 : /* http://id3.org/id3v2.4.0-structure */
89 0 : static int is_id3(const uint8_t *p, long length) {
90 : /* Do we have enough room to see the header? */
91 0 : if (length < 10) return 0;
92 : /* Do we have a sync pattern? */
93 0 : if (p[0] == 'I' && p[1] == 'D' && p[2] == '3') {
94 0 : if (p[3] == 0xff || p[4] == 0xff) return 0; /* Illegal version. */
95 0 : if (p[6] & 0x80 || p[7] & 0x80 ||
96 0 : p[8] & 0x80) return 0; /* Bad length encoding. */
97 : /* Looks like an id3 header. */
98 0 : return 1;
99 : }
100 0 : return 0;
101 : }
102 :
103 : /* Calculate the size of an id3 tag structure from its header. */
104 0 : static int id3_framesize(const uint8_t *p, long length)
105 : {
106 : int size;
107 :
108 : /* Header is 10 bytes. */
109 0 : if (length < 10) {
110 0 : return 0;
111 : }
112 : /* Frame is header plus declared size. */
113 0 : size = 10 + (p[9] | (p[8] << 7) | (p[7] << 14) | (p[6] << 21));
114 :
115 0 : return size;
116 : }
117 :
118 0 : int mp3_sniff(const uint8_t *buf, long length)
119 : {
120 : mp3_header header;
121 : const uint8_t *p;
122 : long skip;
123 : long avail;
124 :
125 0 : p = buf;
126 0 : avail = length;
127 0 : while (avail >= 4) {
128 0 : if (is_id3(p, avail)) {
129 : /* Skip over any id3 tags */
130 0 : skip = id3_framesize(p, avail);
131 0 : p += skip;
132 0 : avail -= skip;
133 0 : } else if (is_mp3(p, avail)) {
134 0 : mp3_parse(p, &header);
135 0 : skip = mp3_framesize(&header);
136 0 : if (skip < 4 || skip + 4 >= avail) {
137 0 : return 0;
138 : }
139 0 : p += skip;
140 0 : avail -= skip;
141 : /* Check for a second header at the expected offset. */
142 0 : if (is_mp3(p, avail)) {
143 : /* Looks like mp3. */
144 0 : return 1;
145 : } else {
146 : /* No second header. Not mp3. */
147 0 : return 0;
148 : }
149 : } else {
150 : /* No id3 tag or mp3 header. Not mp3. */
151 0 : return 0;
152 : }
153 : }
154 :
155 0 : return 0;
156 : }
|