1 /*
2 * This file is part of Checkmate, a program to check MP3 files for errors
3 *
4 * Copyright (C) 2006 Sjoerd Langkemper
5 *
6 * Checkmate is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 *****************************************************************************
21 *
22 * checkframe.c - checks an MP3 frame
23 *
24 */
25
26 #include "mpck.h"
27 #include "file.h"
28 #include "frame.h"
29 #include "print.h"
30 #include "metatag.h"
31 #include "crc.h"
32 #include "options.h"
33 #include "matrices.h"
34 #include "layer2.h"
35
36 #ifdef HAVE_ERRNO_H
37 #include <errno.h>
38 #endif
39
40 /* samplerate in Hz of frame fi with headervalue h */
41 #define samplerate(h, fi) samplerate_matrix[h][fi->version]
42
43 /* the duration of this frame in ms */
44 #define frametime(fi) (1000*fi->samples/fi->samplerate)
45
46 /* the number of samples in frame fi */
47 #define framesamples(fi) samples_matrix[fi->layer][fi->version]
48
49 /* the layer for headervalue h */
50 #define layer(h) (4-(h))
51
52 /* framelength(fi) calculates the length (in bytes) of a frame */
framelength(file,fi)53 static int framelength(file, fi)
54 const file_info * file;
55 const frame_info * fi;
56 {
57 /* if this is the last frame, it has a different length */
58 if ((file->lastframe_offset == fi->offset) && (file->lastframe_offset)) {
59 return file->lastframe_length;
60 }
61
62 /* else, just compute the frame length */
63 if (fi->layer == LAYER_1) {
64 return 4*fi->padding+4*((12*fi->bitrate)/fi->samplerate);
65 } else {
66 return fi->padding+fi->samples*fi->bitrate/(8*fi->samplerate);
67 }
68 }
69
70 static void
alienbytes(file,num)71 alienbytes(file, num)
72 file_info * file;
73 int num;
74 {
75 if (file->frames == 0)
76 file->alien_before += num;
77 else
78 file->alien_after += num;
79 }
80
81 /* checks for consistency */
82 static int
checkconsistency(file,frame)83 checkconsistency(file, frame)
84 const file_info * file;
85 const frame_info * frame;
86 {
87 int verbose = options_get_verbose();
88
89 if ((file->version == 0) && (file->layer == 0)) {
90 /* this is the first frame, nothing to check */
91 return TRUE;
92 }
93
94 if (file->version != frame->version) {
95 if (verbose) offseterror(file, "version differs from previous frame");
96 return FALSE;
97 }
98 if (file->layer != frame->layer) {
99 if (verbose) offseterror(file, "layer differs from previous frame");
100 return FALSE;
101 }
102 return TRUE;
103 }
104
105 /* sets consistency data to current frame */
106 static void
setconsistent(file,frame)107 setconsistent(file, frame)
108 file_info * file;
109 const frame_info * frame;
110 {
111 file->version = frame->version;
112 file->layer = frame->layer;
113 }
114
115 /* returns bitrate in bps */
bitrate(headervalue,fi)116 static int bitrate(headervalue, fi)
117 int headervalue; /* value of the bitrate as in the header */
118 frame_info * fi; /* this function uses version and layer */
119 {
120 return 1000*bitrate_matrix[3*fi->version+fi->layer-1][headervalue];
121 }
122
123 static int
mpegver(headervalue)124 mpegver(headervalue)
125 int headervalue;
126 {
127 if (headervalue == 3) return MPEG_VER_10;
128 if (headervalue == 2) return MPEG_VER_20;
129 if (headervalue == 0) return MPEG_VER_25;
130 return MPEG_VER_INVALID;
131 }
132
133 static void
parseframe(file,fr,buf)134 parseframe(file, fr, buf)
135 const file_info * file;
136 frame_info * fr;
137 char * buf;
138 {
139 int res;
140
141 fr->version =mpegver((buf[1]&24)>>3); /* bits 12,13 */
142 fr->layer =layer((buf[1]&6)>>1); /* bits 14,15 */
143 fr->crc16 =!(buf[1]&1); /* bit 16 */
144 fr->bitrate =bitrate((buf[2]&240)>>4, fr); /* bits 17-20 */
145 fr->samplerate =samplerate((buf[2]&12)>>2, fr);/* bits 21,22 */
146 fr->padding =(buf[2]&2) >>1; /* bit 23 */
147 fr->private =(buf[2]&1); /* bit 24 */
148 fr->stereo =(buf[3]&192)>>6; /* bits 25,26 */
149 fr->jointstereo =(buf[3]&48) >>4; /* bits 27,28 */
150 fr->copyright =(buf[3]&8) >>3; /* bit 29 */
151 fr->original =(buf[3]&4) >>2; /* bit 30 */
152 fr->emphasis =(buf[3]&3); /* bits 31,32 */
153
154 fr->offset =cftell(file->fp)-4;
155
156 if (fr->crc16) {
157 res=cfread(buf, 2, file->fp);
158 if (!res) offseterror(file, "CRC read error");
159 fr->crc16=(buf[0]&0xff)<<8;
160 fr->crc16 += (buf[1]&0xff);
161 }
162
163 if (fr->samplerate > 0) {
164 fr->samples =framesamples(fr);
165 fr->length =framelength(file, fr);
166 fr->time =frametime(fr);
167 }
168 }
169
170 /* checks the validity of struct frame_info fi */
171 int
checkvalidity(file,frame)172 checkvalidity(file, frame)
173 const file_info * file;
174 const frame_info * frame;
175 {
176 int verbose = options_get_verbose();
177
178 /* These values are not valid */
179 if (frame->version == MPEG_VER_INVALID) {
180 if (verbose) offseterror(file, "unknown version");
181 return FALSE;
182 }
183 if (frame->layer == 4) {
184 if (verbose) offseterror(file, "unknown layer (1-3 allowed)");
185 return FALSE;
186 }
187 if (frame->bitrate < 8000) {
188 // FIXME this ignores the freeform bitrate
189 if (verbose) offseterror(file, "unknown bitrate");
190 return FALSE;
191 }
192 if (frame->samplerate < 8000) {
193 if (verbose) offseterror(file, "unknown samplerate");
194 return FALSE;
195 }
196 return TRUE;
197 }
198
199 /*
200 * FIXME: return the number of bytes which could not be interpreted.
201 */
202 int
findframe(file,frame)203 findframe(file, frame)
204 file_info * file;
205 frame_info * frame;
206 {
207 int res;
208 char buf[8];
209 char * ptr;
210
211 do {
212 ptr = buf;
213 res = cfread(ptr, 1, file->fp);
214 if (res <= 0) {
215 if (cfeof(file->fp)) {
216 return FALSE;
217 } else {
218 offseterror(file, "read error");
219 }
220 continue;
221 }
222
223 if ((*ptr & 0xff) == 0xff) {
224 res = cfread(++ptr, 1, file->fp);
225 if (res < 1) continue;
226 if ((*ptr & 0xe0) == 0xe0) { /* possible MP3 frame header */
227 res = cfread(++ptr, 2, file->fp);
228 if (res < 2) continue;
229 parseframe(file, frame, buf);
230 return TRUE;
231 }
232 } else if (*ptr == 'T') { /* TAG -> ID3v1 tag */
233 res = cfread(++ptr, 2, file->fp);
234 if (res < 2) continue;
235 if (*ptr++ == 'A' && *ptr++ == 'G') {
236 skip_id3v1_tag(file);
237 } else {
238 alienbytes(file, 3);
239 }
240 } else if (*ptr == 'I') { /* ID3 -> ID3v2 tag */
241 res = cfread(++ptr, 2, file->fp);
242 if (res < 2) continue;
243 if (*ptr++ == 'D' && *ptr++ == '3') {
244 skip_id3v2_tag(file);
245 } else {
246 alienbytes(file, 3);
247 }
248 } else if (*ptr == 'A') { /* APETAGEX -> APE tag */
249 res = cfread(++ptr, 7, file->fp);
250 if (res < 7) continue;
251 if (*ptr++ == 'P' && *ptr++ == 'E' &&
252 *ptr++ == 'T' && *ptr++ == 'A' &&
253 *ptr++ == 'G' && *ptr++ == 'E' &&
254 *ptr++ == 'X') {
255 skip_ape_tag(file);
256 } else {
257 alienbytes(file, 8);
258 }
259 } else {
260 alienbytes(file, 1);
261 }
262 } while (!cfeof(file->fp));
263 return FALSE;
264 }
265
crcdatalength(file,frame)266 static int crcdatalength(file, frame)
267 const file_info * file;
268 frame_info * frame;
269 {
270 if (frame->layer == 2) {
271 return crcdatalength2(file, frame);
272 }
273 if (frame->version == MPEG_VER_10) {
274 if (frame->layer == 3) {
275 return (frame->stereo == MONO ? 17 * 8 : 32 * 8);
276 }
277 if (frame->layer == 1) {
278 return (frame->stereo == MONO ? 128 : 256);
279 }
280 } else {
281 return (frame->stereo == MONO ? 9 * 8 : 17 * 8);
282 }
283 return 0; // never reached, but supress warning
284 }
285
checkcrc16(file,frame)286 static int checkcrc16(file, frame)
287 const file_info * file;
288 frame_info * frame;
289 {
290 // This buffer needs to hold the header and all other CRC bytes.
291 // header is 2 bytes, crcdatalength2 returns max. 39 bytes.
292 char buf[41];
293 int res;
294 int nbits;
295 int nbytes;
296
297 nbits = crcdatalength(file, frame);
298 nbytes = nbits >> 3;
299 if (nbits & 7) nbytes += 1;
300
301 // read header
302 cfseek(file->fp, frame->offset+2, SEEK_SET);
303 res=cfread(buf, 2, file->fp);
304 if (!res) {
305 return FALSE;
306 }
307
308 // read data
309 cfseek(file->fp, frame->offset+6, SEEK_SET);
310 if (nbytes > frame->length - 6) {
311 nbytes = MAX(0, frame->length - 6);
312 nbits = nbytes * 8;
313 }
314 res = cfread(buf+2, nbytes, file->fp);
315 if (res<nbytes) {
316 return FALSE;
317 }
318
319 cfseek(file->fp, frame->offset + frame->length, SEEK_SET);
320
321 return frame->crc16 == crc16bits((unsigned char *)buf, nbits + 16);
322 }
323
324 int
checkframe(file,frame)325 checkframe(file, frame)
326 file_info * file;
327 frame_info * frame;
328 {
329 if (!checkvalidity(file, frame)) {
330 file->errors |= ERR_INVALID;
331 return FALSE;
332 }
333
334 if (frame->crc16) {
335 if (!checkcrc16(file, frame)) {
336 file->errors |= ERR_FRAMECRC;
337 return FALSE;
338 }
339 }
340
341 if (!checkconsistency(file, frame)) {
342 file->errors |= ERR_INCONSISTENT;
343 setconsistent(file, frame);
344 return FALSE;
345 }
346 return TRUE;
347 }
348