comparison src/madplug/plugin.c @ 2939:3877a02782bb

Adjust probing again.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 22 Sep 2008 06:39:32 +0300
parents f1b6f1b2cdb3
children 0910d4d2714d
comparison
equal deleted inserted replaced
2938:597857a52f7c 2939:3877a02782bb
265 } 265 }
266 266
267 return 0; 267 return 0;
268 } 268 }
269 269
270 static int 270 static guint32
271 mp3_head_convert(const guchar * hbuf) 271 mp3_head_convert(const guchar * hbuf)
272 { 272 {
273 return 273 return
274 ((guint32) hbuf[0] << 24) | 274 ((guint32) hbuf[0] << 24) |
275 ((guint32) hbuf[1] << 16) | 275 ((guint32) hbuf[1] << 16) |
276 ((guint32) hbuf[2] << 8) | 276 ((guint32) hbuf[2] << 8) |
277 ((guint32) hbuf[3]); 277 ((guint32) hbuf[3]);
278 } 278 }
279 279
280 #undef MADPROBE_DEBUG 280 #undef MADPROBE_DEBUG
281 //#define MADPROBE_DEBUG
281 282
282 #ifdef MADPROBE_DEBUG 283 #ifdef MADPROBE_DEBUG
283 static gchar *mp3_ver_table[4] = { "2.5", "INVALID", "2", "1" }; 284 static gchar *mp3_ver_table[4] = { "2.5", "INVALID", "2", "1" };
284 #define LULZ(...) do { fprintf(stderr, "madprobe: "); fprintf(stderr, __VA_ARGS__); } while (0) 285 #define LULZ(...) do { fprintf(stderr, "madprobe: "); fprintf(stderr, __VA_ARGS__); } while (0)
285 #define LOL(...) do { fprintf(stderr, __VA_ARGS__); } while (0) 286 #define LOL(...) do { fprintf(stderr, __VA_ARGS__); } while (0)
287 #define LULZ(...) do { } while(0) 288 #define LULZ(...) do { } while(0)
288 #define LOL(...) do { } while(0) 289 #define LOL(...) do { } while(0)
289 #endif 290 #endif
290 291
291 // audacious vfs fast version 292 // audacious vfs fast version
292 static int 293 static gint
293 audmad_is_our_fd(gchar *filename, VFSFile *fin) 294 audmad_is_our_fd(gchar *filename, VFSFile *fin)
294 { 295 {
295 gchar *ext = extname(filename); 296 gchar *ext = extname(filename);
297 const gint max_resync_bytes = 32, max_resync_tries = 8;
296 guint32 head = 0; 298 guint32 head = 0;
297 guchar chkbuf[2048]; 299 guchar chkbuf[1024];
298 gint state, 300 gint state,
299 next = -1, 301 next = -1,
300 tries = 0, 302 tries = 0,
301 chksize = 0, 303 chksize = 0,
302 chkpos = 0, 304 chkpos = 0,
333 return 0; 335 return 0;
334 } 336 }
335 337
336 state = STATE_REBUFFER; 338 state = STATE_REBUFFER;
337 next = STATE_HEADERS; 339 next = STATE_HEADERS;
338 340
339 /* Check stream data for frame header(s). We employ a simple 341 /* Check stream data for frame header(s). We employ a simple
340 * state-machine approach here to find number of sequential 342 * state-machine approach here to find number of sequential
341 * valid MPEG frame headers (with similar attributes). 343 * valid MPEG frame headers (with similar attributes).
342 */ 344 */
343 do { 345 do {
344 switch (state) { 346 switch (state) {
345 case STATE_HEADERS: 347 case STATE_HEADERS:
346 LULZ("check headers\n"); 348 LULZ("check headers (size=%d, pos=%d)\n", chksize, chkpos);
347 /* Check read size */ 349 /* Check read size */
348 if (chksize < 32) { 350 if (chksize - chkpos < 16) {
349 LULZ("headers check failed, not enough data!\n"); 351 LULZ("headers check failed, not enough data!\n");
350 state = STATE_FATAL; 352 state = STATE_FATAL;
351 } else { 353 } else {
352 state = STATE_GET_NEXT; 354 state = STATE_GET_NEXT;
353 355
356 guint tagsize = (chkbuf[chkpos+6] & 0x7f); tagsize <<= 7; 358 guint tagsize = (chkbuf[chkpos+6] & 0x7f); tagsize <<= 7;
357 tagsize |= (chkbuf[chkpos+7] & 0x7f); tagsize <<= 7; 359 tagsize |= (chkbuf[chkpos+7] & 0x7f); tagsize <<= 7;
358 tagsize |= (chkbuf[chkpos+8] & 0x7f); tagsize <<= 7; 360 tagsize |= (chkbuf[chkpos+8] & 0x7f); tagsize <<= 7;
359 tagsize |= (chkbuf[chkpos+9] & 0x7f); 361 tagsize |= (chkbuf[chkpos+9] & 0x7f);
360 362
361 LULZ("ID3 size = %08x\n", tagsize); 363 LULZ("ID3 size = %d\n", tagsize);
362 state = STATE_GOTO_NEXT; 364 state = STATE_GOTO_NEXT;
363 skip = tagsize + 10; 365 skip = tagsize + 10;
364 } else 366 } else
365 if (memcmp(&chkbuf[chkpos], "OggS", 4) == 0) 367 if (memcmp(&chkbuf[chkpos], "OggS", 4) == 0)
366 return 0; 368 return 0;
371 } 373 }
372 break; 374 break;
373 375
374 case STATE_REBUFFER: 376 case STATE_REBUFFER:
375 streampos = aud_vfs_ftell(fin); 377 streampos = aud_vfs_ftell(fin);
376 if ((chksize = aud_vfs_fread(chkbuf, 1, sizeof(chkbuf), fin)) == 0) 378 if ((chksize = aud_vfs_fread(chkbuf, 1, sizeof(chkbuf), fin)) == 0) {
377 state = STATE_FATAL; 379 state = STATE_FATAL;
378 else { 380 LULZ("fatal error rebuffering @ %08lx!\n", streampos);
381 } else {
379 chkpos = 0; 382 chkpos = 0;
380 state = next; 383 state = next;
384 LULZ("rebuffered = %d bytes @ %08lx\n", chksize, streampos);
381 } 385 }
382 LULZ("rebuffered = %d bytes\n", chksize);
383 break; 386 break;
384 387
385 case STATE_VALIDATE: 388 case STATE_VALIDATE:
386 LULZ("validate %08x .. ", head); 389 LULZ("validate %08x .. ", head);
387 /* Check for valid header */ 390 /* Check for valid header */
413 } else { 416 } else {
414 /* Nope, try (re)synchronizing */ 417 /* Nope, try (re)synchronizing */
415 if (chkcount > 1) { 418 if (chkcount > 1) {
416 LOL("no (%d), trying quick resync ..\n", res); 419 LOL("no (%d), trying quick resync ..\n", res);
417 state = STATE_RESYNC_DO; 420 state = STATE_RESYNC_DO;
418 resync_max = 32; 421 resync_max = max_resync_bytes;
419 } else { 422 } else {
420 LOL("no (%d)\n", res); 423 LOL("no (%d)\n", res);
421 state = STATE_RESYNC; 424 state = STATE_RESYNC;
422 } 425 }
423 } 426 }
424 break; 427 break;
425 428
426 case STATE_GOTO_NEXT: 429 case STATE_GOTO_NEXT:
427 LULZ("goto next (%x :: %x < %x) ? ", chkpos, skip, chksize); 430 LULZ("goto next (cpos=%x, csiz=%d :: skip=%d :: fpos=%lx) ? ", chkpos, chksize, skip, aud_vfs_ftell(fin));
428 /* Check if we have the next possible header in buffer? */ 431 /* Check if we have the next possible header in buffer? */
429 gint tmppos = chkpos + skip + sizeof(guint32); 432 gint tmppos = chkpos + skip + 16;
430 if (tmppos < chksize) { 433 if (tmppos < chksize) {
431 LOL("[in buffer]\n"); 434 LOL("[in buffer]\n");
432 chkpos += skip; 435 chkpos += skip;
433 state = STATE_GET_NEXT; 436 state = STATE_GET_NEXT;
434 } else { 437 } else {
435 /* No, re-fill buffer and try again .. */ 438 /* No, re-fill buffer and try again .. */
436 LOL("[rebuffering: %x, %x]\n", skip, chkpos + skip - chksize); 439 glong tmppos = skip - (chksize - chkpos);
437 aud_vfs_fseek(fin, chkpos + skip - chksize, SEEK_CUR); 440 gint tmpres = aud_vfs_fseek(fin, tmppos, SEEK_CUR);
441 LOL("[skipping: %ld -> %d]\n", tmppos, tmpres);
438 next = STATE_GET_NEXT; 442 next = STATE_GET_NEXT;
439 state = STATE_REBUFFER; 443 state = STATE_REBUFFER;
440 } 444 }
441 break; 445 break;
442 446
443 case STATE_GET_NEXT: 447 case STATE_GET_NEXT:
444 /* Get a header */ 448 /* Get a header */
445 LULZ("get next @ bufpos=%08x, streampos=%08lx, realpos=%08lx\n", chkpos, streampos, streampos+chkpos); 449 LULZ("get next @ chkpos=%08x, realpos=%08lx\n", chkpos, streampos+chkpos);
446 head = mp3_head_convert(&chkbuf[chkpos]); 450 head = mp3_head_convert(&chkbuf[chkpos]);
447 //chkpos += sizeof(guint32);
448 state = STATE_VALIDATE; 451 state = STATE_VALIDATE;
449 break; 452 break;
450 453
451 case STATE_RESYNC: 454 case STATE_RESYNC:
452 LULZ("resyncing try #%d ..\n", tries); 455 LULZ("resyncing try #%d ..\n", tries);
465 head |= chkbuf[chkpos]; 468 head |= chkbuf[chkpos];
466 469
467 if (mp3_head_validate(head, &frame) >= 0) { 470 if (mp3_head_validate(head, &frame) >= 0) {
468 /* Found, exit resync */ 471 /* Found, exit resync */
469 chkpos -= 3; 472 chkpos -= 3;
470 LULZ("resync found @ %x\n", chkpos); 473 LULZ("resync found @ %x (%lx)\n", chkpos, streampos + chkpos);
471 state = STATE_VALIDATE; 474 state = STATE_VALIDATE;
472 break; 475 break;
473 } 476 }
474 477
475 /* Check for maximum bytes to search */ 478 /* Check for maximum bytes to search */
486 next = state; 489 next = state;
487 state = STATE_REBUFFER; 490 state = STATE_REBUFFER;
488 } 491 }
489 break; 492 break;
490 } 493 }
491 } while (state != STATE_FATAL && tries < 16); 494 } while (state != STATE_FATAL && tries < max_resync_tries);
492 /* Give up after 16 failed resync attempts or fatal errors */ 495 /* Give up after given number of failed resync attempts or fatal error */
493 496
494 g_message("Rejecting %s (not an MP3 file?)", filename); 497 g_message("Rejecting %s (not an MP3 file?)", filename);
495 return 0; 498 return 0;
496 } 499 }
497 500