comparison src/madplug/plugin.c @ 2688:17da667fb14d

A completely rewritten approach for probing MPEG Audio files, using a state-machine based validifier with semi-smart buffer management and re-synchronization.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 06 Jun 2008 13:40:13 +0300
parents 206f0322d221
children c56305e38520
comparison
equal deleted inserted replaced
2687:206f0322d221 2688:17da667fb14d
49 49
50 #ifndef NOGUI 50 #ifndef NOGUI
51 static GtkWidget *error_dialog = 0; 51 static GtkWidget *error_dialog = 0;
52 #endif 52 #endif
53 53
54 extern gboolean scan_file(struct mad_info_t *info, gboolean fast);
55
56 static gint mp3_bitrate_table[5][16] = { 54 static gint mp3_bitrate_table[5][16] = {
57 { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1 }, /* MPEG1 L1 */ 55 { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1 }, /* MPEG1 L1 */
58 { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1 }, /* MPEG1 L2 */ 56 { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1 }, /* MPEG1 L2 */
59 { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 }, /* MPEG1 L3 */ 57 { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 }, /* MPEG1 L3 */
60 { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, /* MPEG2(.5) L1 */ 58 { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, /* MPEG2(.5) L1 */
65 { 11025, 12000, 8000, -1 }, /* MPEG2.5 */ 63 { 11025, 12000, 8000, -1 }, /* MPEG2.5 */
66 { -1, -1, -1, -1 }, /* Reserved */ 64 { -1, -1, -1, -1 }, /* Reserved */
67 { 22050, 24000, 16000, -1 }, /* MPEG2 */ 65 { 22050, 24000, 16000, -1 }, /* MPEG2 */
68 { 44100, 48000, 32000, -1 } /* MPEG1 */ 66 { 44100, 48000, 32000, -1 } /* MPEG1 */
69 }; 67 };
68
69 typedef struct {
70 gint version,
71 layer,
72 bitRate,
73 sampleRate,
74 size,
75 lsf;
76 gboolean hasCRC;
77 } mp3_frame_t;
70 78
71 /* 79 /*
72 * Function extname (filename) 80 * Function extname (filename)
73 * 81 *
74 * Return pointer within filename to its extenstion, or NULL if 82 * Return pointer within filename to its extenstion, or NULL if
149 g_cond_free(mad_cond); 157 g_cond_free(mad_cond);
150 g_mutex_free(mad_mutex); 158 g_mutex_free(mad_mutex);
151 g_mutex_free(pb_mutex); 159 g_mutex_free(pb_mutex);
152 } 160 }
153 161
154 static gboolean 162 /* Validate a MPEG Audio header and extract some information from it.
155 mp3_head_check(guint32 head, gint *frameSize) 163 * References used:
156 { 164 * http://www.mp3-tech.org/programmer/frame_header.html
157 gint version, layer, bitIndex, bitRate, sampleIndex, sampleRate, padding; 165 * http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
158 166 */
159 /* http://www.mp3-tech.org/programmer/frame_header.html 167 static gint
160 * Bits 21-31 must be set (frame sync) 168 mp3_head_validate(guint32 head, mp3_frame_t *frame)
161 */ 169 {
170 gint bitIndex, sampleIndex, padding;
171
172 /* bits 21-31 must be set (frame sync) */
162 if ((head & 0xffe00000) != 0xffe00000) 173 if ((head & 0xffe00000) != 0xffe00000)
163 return FALSE; 174 return -1;
164 175
176 /* check for LSF */
177 if ((head >> 20) & 1)
178 frame->lsf = ((head >> 19) & 1) ? 0 : 1;
179 else
180 frame->lsf = 1;
181
165 /* check if layer bits (17-18) are good */ 182 /* check if layer bits (17-18) are good */
166 layer = (head >> 17) & 0x3; 183 frame->layer = (head >> 17) & 3;
167 if (!layer) 184 if (frame->layer == 0)
168 return FALSE; /* 00 = reserved */ 185 return -2; /* 00 = reserved */
169 layer = 4 - layer; 186 frame->layer = 4 - frame->layer;
170 187
188 /* check CRC bit. if set, a 16-bit CRC follows header (not counted in frameSize!) */
189 frame->hasCRC = (head >> 16) & 1;
190
171 /* check if bitrate index bits (12-15) are acceptable */ 191 /* check if bitrate index bits (12-15) are acceptable */
172 bitIndex = (head >> 12) & 0xf; 192 bitIndex = (head >> 12) & 0xf;
173 193
174 /* 1111 and 0000 are reserved values for all layers */ 194 /* 1111 and 0000 are reserved values for all layers */
175 if (bitIndex == 0xf || bitIndex == 0) 195 if (bitIndex == 0xf || bitIndex == 0)
176 return FALSE; 196 return -3;
177 197
178 /* check samplerate index bits (10-11) */ 198 /* check samplerate index bits (10-11) */
179 sampleIndex = (head >> 10) & 0x3; 199 sampleIndex = (head >> 10) & 3;
180 if (sampleIndex == 0x3) 200 if (sampleIndex == 3)
181 return FALSE; 201 return -4;
182 202
183 /* check version bits (19-20) and get bitRate */ 203 /* check version bits (19-20) and get bitRate */
184 version = (head >> 19) & 0x03; 204 frame->version = (head >> 19) & 0x03;
185 switch (version) { 205 switch (frame->version) {
186 case 0: /* 00 = MPEG Version 2.5 */ 206 case 0: /* 00 = MPEG Version 2.5 */
187 case 2: /* 10 = MPEG Version 2 */ 207 case 2: /* 10 = MPEG Version 2 */
188 if (layer == 1) 208 if (frame->layer == 1)
189 bitRate = mp3_bitrate_table[3][bitIndex]; 209 frame->bitRate = mp3_bitrate_table[3][bitIndex];
190 else 210 else
191 bitRate = mp3_bitrate_table[4][bitIndex]; 211 frame->bitRate = mp3_bitrate_table[4][bitIndex];
192 break; 212 break;
193 213
194 case 1: /* 01 = reserved */ 214 case 1: /* 01 = reserved */
195 return FALSE; 215 return -5;
196 216
197 case 3: /* 11 = MPEG Version 1 */ 217 case 3: /* 11 = MPEG Version 1 */
198 bitRate = mp3_bitrate_table[layer][bitIndex]; 218 frame->bitRate = mp3_bitrate_table[frame->layer - 1][bitIndex];
199 break; 219 break;
200 220
201 default: 221 default:
202 return FALSE; 222 return -6;
203 } 223 }
224
225 if (frame->bitRate < 0)
226 return -7;
204 227
205 /* check layer II restrictions vs. bitrate */ 228 /* check layer II restrictions vs. bitrate */
206 if (layer == 2) { 229 if (frame->layer == 2) {
207 gint chanMode = (head >> 6) & 0x3; 230 gint chanMode = (head >> 6) & 0x3;
208 231
209 if (chanMode == 0x3) { 232 if (chanMode == 0x3) {
210 /* single channel with bitrate > 192 */ 233 /* single channel with bitrate > 192 */
211 if (bitRate > 192) 234 if (frame->bitRate > 192)
212 return FALSE; 235 return -8;
213 } else { 236 } else {
214 /* any other mode with bitrates 32-56 and 80. 237 /* any other mode with bitrates 32-56 and 80.
215 * NOTICE! this check is not entirely correct, but I think 238 * NOTICE! this check is not entirely correct, but I think
216 * it is sufficient in most cases. 239 * it is sufficient in most cases.
217 */ 240 */
218 if (((bitRate >= 32 && bitRate <= 56) || bitRate == 80)) 241 if (((frame->bitRate >= 32 && frame->bitRate <= 56) || frame->bitRate == 80))
219 return FALSE; 242 return -9;
220 } 243 }
221 } 244 }
222 245
223 /* calculate approx. frame size */ 246 /* calculate approx. frame size */
224 padding = (head >> 9) & 1; 247 padding = (head >> 9) & 1;
225 sampleRate = mp3_samplerate_table[version][sampleIndex]; 248 frame->sampleRate = mp3_samplerate_table[frame->version][sampleIndex];
226 if (layer == 1) 249 if (frame->sampleRate < 0)
227 *frameSize = ((12 * bitRate * 1000 / sampleRate) + padding) * 4; 250 return -10;
228 else 251
229 *frameSize = (144 * bitRate * 1000) / (sampleRate + padding); 252 switch (frame->layer) {
230 253 case 1:
231 /* check if bits 16 - 19 are all set (MPEG 1 Layer I, not protected?) */ 254 frame->size = ((12 * 1000 * frame->bitRate) / frame->sampleRate + padding) * 4;
232 if (((head >> 19) & 1) == 1 && 255 break;
233 ((head >> 17) & 3) == 3 && ((head >> 16) & 1) == 1) 256
234 return FALSE; 257 case 2:
235 258 frame->size = (144 * 1000 * frame->bitRate) / frame->sampleRate + padding;
236 /* not sure why we check this, but ok! */ 259 break;
237 if ((head & 0xffff0000) == 0xfffe0000) 260
238 return FALSE; 261 case 3:
239 262 default:
240 return TRUE; 263 frame->size = (144 * 1000 * frame->bitRate) / (frame->sampleRate << frame->lsf) + padding;
264 break;
265 }
266
267 return 0;
241 } 268 }
242 269
243 static int 270 static int
244 mp3_head_convert(const guchar * hbuf) 271 mp3_head_convert(const guchar * hbuf)
245 { 272 {
246 return ((unsigned long) hbuf[0] << 24) | 273 return
247 ((unsigned long) hbuf[1] << 16) | 274 ((guint32) hbuf[0] << 24) |
248 ((unsigned long) hbuf[2] << 8) | (unsigned long) hbuf[3]; 275 ((guint32) hbuf[1] << 16) |
249 } 276 ((guint32) hbuf[2] << 8) |
277 ((guint32) hbuf[3]);
278 }
279
280 #if 0
281 static gchar *mp3_ver_table[4] = { "2.5", "INVALID", "2", "1" };
282 #define LULZ(...) do { fprintf(stderr, "madprobe: "); fprintf(stderr, __VA_ARGS__); } while (0)
283 #define LOL(...) do { fprintf(stderr, __VA_ARGS__); } while (0)
284 #else
285 #define LULZ(...) do { } while(0)
286 #define LOL(...) do { } while(0)
287 #endif
250 288
251 // audacious vfs fast version 289 // audacious vfs fast version
252 static int 290 static int
253 audmad_is_our_fd(char *filename, VFSFile *fin) 291 audmad_is_our_fd(gchar *filename, VFSFile *fin)
254 { 292 {
255 guint32 check;
256 gchar *ext = extname(filename); 293 gchar *ext = extname(filename);
257 guchar buf[16]; 294 guint32 head = 0;
295 guchar chkbuf[2048];
296 gint state,
297 next = -1,
298 tries = 0,
299 chksize = 0,
300 chkpos = 0,
301 chkcount = 0,
302 res, resync_max = -1,
303 skip = 0;
304 glong streampos = 0;
305 mp3_frame_t frame, prev;
306
307 enum {
308 STATE_HEADERS,
309 STATE_REBUFFER,
310 STATE_VALIDATE,
311 STATE_GOTO_NEXT,
312 STATE_GET_NEXT,
313 STATE_RESYNC,
314 STATE_RESYNC_DO,
315 STATE_FATAL
316 };
258 317
259 info.remote = aud_vfs_is_remote(filename); 318 info.remote = aud_vfs_is_remote(filename);
260 319
261 /* I've seen some flac files beginning with id3 frames.. 320 /* I've seen some flac files beginning with id3 frames..
262 so let's exclude known non-mp3 filename extensions */ 321 so let's exclude known non-mp3 filename extensions */
270 if (fin == NULL) { 329 if (fin == NULL) {
271 g_message("fin = NULL for %s", filename); 330 g_message("fin = NULL for %s", filename);
272 return 0; 331 return 0;
273 } 332 }
274 333
275 if (aud_vfs_fread(buf, 1, sizeof(buf), fin) == 0) { 334 state = STATE_REBUFFER;
276 g_message("aud_vfs_fread failed @1 %s", filename); 335 next = STATE_HEADERS;
277 return 0; 336
278 } 337 /* Check stream data for frame header(s). We employ a simple
279 338 * state-machine approach here to find number of sequential
280 check = mp3_head_convert(buf); 339 * valid MPEG frame headers (with similar attributes).
281 340 */
282 if (memcmp(buf, "ID3", 3) == 0) 341 do {
283 return 1; 342 switch (state) {
284 else if (memcmp(buf, "OggS", 4) == 0) 343 case STATE_HEADERS:
285 return 0; 344 LULZ("check headers\n");
286 else if (memcmp(buf, "RIFF", 4) == 0) 345 /* Check read size */
287 { 346 if (chksize < 32) {
288 aud_vfs_fseek(fin, 4, SEEK_CUR); 347 LULZ("headers check failed, not enough data!\n");
289 if(aud_vfs_fread(buf, 1, 4, fin) == 0) { 348 state = STATE_FATAL;
290 g_message("aud_vfs_fread failed @2 %s", filename); 349 } else {
291 return 0; 350 state = STATE_GET_NEXT;
351
352 if (memcmp(&chkbuf[chkpos], "ID3", 3) == 0) {
353 /* Skip ID3 header */
354 guint tagsize = (chkbuf[chkpos+6] & 0x7f); tagsize <<= 7;
355 tagsize |= (chkbuf[chkpos+7] & 0x7f); tagsize <<= 7;
356 tagsize |= (chkbuf[chkpos+8] & 0x7f); tagsize <<= 7;
357 tagsize |= (chkbuf[chkpos+9] & 0x7f);
358
359 LULZ("ID3 size = %08x\n", tagsize);
360 state = STATE_GOTO_NEXT;
361 skip = tagsize + 10;
362 } else
363 if (memcmp(&chkbuf[chkpos], "OggS", 4) == 0)
364 return 0;
365 else
366 if (memcmp(&chkbuf[chkpos], "RIFF", 4) == 0 &&
367 memcmp(&chkbuf[chkpos+8], "RMP3", 4) == 0)
368 return 1;
369 }
370 break;
371
372 case STATE_REBUFFER:
373 streampos = aud_vfs_ftell(fin);
374 if ((chksize = aud_vfs_fread(chkbuf, 1, sizeof(chkbuf), fin)) == 0)
375 state = STATE_FATAL;
376 else {
377 chkpos = 0;
378 state = next;
379 }
380 LULZ("rebuffered = %d bytes\n", chksize);
381 break;
382
383 case STATE_VALIDATE:
384 LULZ("validate %08x .. ", head);
385 /* Check for valid header */
386 if ((res = mp3_head_validate(head, &frame)) >= 0) {
387 LOL("[is MPEG%s/layer %d, %dHz, %dkbps]",
388 mp3_ver_table[frame.version], frame.layer, frame.sampleRate, frame.bitRate);
389 state = STATE_GOTO_NEXT;
390 skip = frame.size;
391 chkcount++;
392 if (chkcount > 1) {
393 if (frame.sampleRate != prev.sampleRate ||
394 frame.layer != prev.layer ||
395 frame.version != prev.version) {
396 /* Not similar frame... */
397 LOL(" .. but does not match (%d)!\n", chkcount);
398 state = STATE_RESYNC;
399 } else if (chkcount >= 5) {
400 /* Okay, accept this stream */
401 LOL(" .. accepted as mp3!!!\n");
402 return 1;
403 } else {
404 LOL(" .. match %d\n", chkcount);
405 }
406 } else {
407 /* First valid frame of sequence */
408 memcpy(&prev, &frame, sizeof(mp3_frame_t));
409 LOL(" .. first synced\n");
410 }
411 } else {
412 /* Nope, try (re)synchronizing */
413 if (chkcount > 1) {
414 LOL("no (%d), trying quick resync ..\n", res);
415 state = STATE_RESYNC_DO;
416 resync_max = 32;
417 } else {
418 LOL("no (%d)\n", res);
419 state = STATE_RESYNC;
420 }
421 }
422 break;
423
424 case STATE_GOTO_NEXT:
425 LULZ("goto next (%x :: %x < %x) ? ", chkpos, skip, chksize);
426 /* Check if we have the next possible header in buffer? */
427 gint tmppos = chkpos + skip + sizeof(guint32);
428 if (tmppos < chksize) {
429 LOL("[in buffer]\n");
430 chkpos += skip;
431 state = STATE_GET_NEXT;
432 } else {
433 /* No, re-fill buffer and try again .. */
434 LOL("[rebuffering: %x, %x]\n", skip, chkpos + skip - chksize);
435 aud_vfs_fseek(fin, chkpos + skip - chksize, SEEK_CUR);
436 next = STATE_GET_NEXT;
437 state = STATE_REBUFFER;
438 }
439 break;
440
441 case STATE_GET_NEXT:
442 /* Get a header */
443 LULZ("get next @ bufpos=%08x, streampos=%08lx, realpos=%08lx\n", chkpos, streampos, streampos+chkpos);
444 head = mp3_head_convert(&chkbuf[chkpos]);
445 //chkpos += sizeof(guint32);
446 state = STATE_VALIDATE;
447 break;
448
449 case STATE_RESYNC:
450 LULZ("resyncing try #%d ..\n", tries);
451 /* Re-synchronize aka try to find a valid header */
452 head = 0;
453 chkcount = 0;
454 resync_max = -1;
455 state = STATE_RESYNC_DO;
456 tries++;
457 break;
458
459 case STATE_RESYNC_DO:
460 /* Scan for valid frame header */
461 for (; chkpos < chksize; chkpos++) {
462 head <<= 8;
463 head |= chkbuf[chkpos];
464
465 if (mp3_head_validate(head, &frame) >= 0) {
466 /* Found, exit resync */
467 chkpos -= 3;
468 LULZ("resync found @ %x\n", chkpos);
469 state = STATE_VALIDATE;
470 break;
471 }
472
473 /* Check for maximum bytes to search */
474 if (resync_max > 0) {
475 resync_max--;
476 if (resync_max == 0) {
477 state = STATE_RESYNC;
478 break;
479 }
480 }
481 }
482 if (state == STATE_RESYNC_DO) {
483 /* Not found, refill buffer */
484 next = state;
485 state = STATE_REBUFFER;
486 }
487 break;
292 } 488 }
293 489 } while (state != STATE_FATAL && tries < 16);
294 if (memcmp(buf, "RMP3", 4) == 0) 490 /* Give up after 16 failed resync attempts or fatal errors */
295 return 1;
296 }
297
298 /* Check stream data for frame header(s)
299 */
300 guchar chkbuf[2048];
301 gint chkret, i, framesize, cyc, chkcount, chksize = sizeof(chkbuf);
302
303 for (cyc = chkcount = 0; cyc < 32; cyc++)
304 {
305 if ((chkret = aud_vfs_fread(chkbuf, 1, chksize, fin)) == 0)
306 break;
307
308 for (i = 0; i < chkret; i++)
309 {
310 check <<= 8;
311 check |= chkbuf[i];
312
313 if (mp3_head_check(check, &framesize)) {
314 /* when the first matching frame header is found, we check for
315 * another frame by seeking to the approximate start of the
316 * next header ... also reduce the check size.
317 */
318 if (++chkcount >= 4) return 1;
319 aud_vfs_fseek(fin, framesize-8, SEEK_CUR);
320 check = 0;
321 chksize = 16;
322 } else {
323 aud_vfs_fseek(fin, chksize, SEEK_CUR);
324 }
325 }
326 }
327 491
328 g_message("Rejecting %s (not an MP3 file?)", filename); 492 g_message("Rejecting %s (not an MP3 file?)", filename);
329 return 0; 493 return 0;
330 } 494 }
331 495