toolkit/components/mediasniffer/mp3sniff.c

branch
TOR_BUG_9701
changeset 14
925c144e1f1f
equal deleted inserted replaced
-1:000000000000 0:0446365604ee
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 }

mercurial