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