diff options
author | waker <wakeroid@gmail.com> | 2013-06-05 21:29:57 +0200 |
---|---|---|
committer | waker <wakeroid@gmail.com> | 2013-06-05 21:29:57 +0200 |
commit | c921f15c196680ea568fc427781027f4eed31779 (patch) | |
tree | 34fdb45d7ff60cc05f865af6ae91e783a1b7ce75 /plugins | |
parent | cb0bfa2b92fd467be34aeea991b2c5f32dc413ec (diff) |
mp3 parser: fix seeking to end of frame; new corrupted frame heuristic
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/mpgmad/mpgmad.c | 78 |
1 files changed, 37 insertions, 41 deletions
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c index 87761bb6..dab3fd87 100644 --- a/plugins/mpgmad/mpgmad.c +++ b/plugins/mpgmad/mpgmad.c @@ -190,6 +190,8 @@ static int cmp3_scan_stream (buffer_t *buffer, int sample) { trace ("cmp3_scan_stream %d (offs: %lld)\n", sample, deadbeef->ftell (buffer->file)); + int have_info = 0; + // {{{ prepare for scan - seek, reset averages, etc int initpos = deadbeef->ftell (buffer->file); trace ("initpos: %d\n", initpos); @@ -198,10 +200,8 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { int scansamples = 0; buffer->currentsample = 0; buffer->skipsamples = 0; -// int avg_bitrate = 0; int valid_frames = 0; int prev_bitrate = -1; - buffer->samplerate = 0; int64_t fsize = deadbeef->fgetlength (buffer->file); if (sample <= 0) { @@ -223,7 +223,6 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { buffer->startoffset = initpos; } - int had_invalid_frames = 0; int lastframe_valid = 0; int64_t offs = -1; // }}} @@ -241,12 +240,6 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { // {{{ parse frame header, sync stream // mp3 files often have some garbage in the beginning // try to skip it if this is the case - if (!lastframe_valid && valid_frames > 5) { - had_invalid_frames = 1; - } - if (!lastframe_valid && offs >= 0) { - deadbeef->fseek (buffer->file, offs+1, SEEK_SET); - } offs = deadbeef->ftell (buffer->file); //uint8_t fb[4+2+2]; // 4b frame header + 2b crc + 2b sideinfo main_data_begin uint8_t fb[4]; // just the header @@ -257,16 +250,16 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { uint32_t hdr; uint8_t sync = fb[0]; if (sync != 0xff) { -// trace ("[1]frame %d didn't seek to frame end\n", nframe); lastframe_valid = 0; +// trace ("[1]frame %d didn't seek to frame end\n", nframe); continue; // not an mpeg frame } else { // 2nd sync byte sync = fb[1]; if ((sync >> 5) != 7) { -// trace ("[2]frame %d didn't seek to frame end\n", nframe); lastframe_valid = 0; + // trace ("[2]frame %d didn't seek to frame end\n", nframe); continue; } } @@ -290,8 +283,8 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { int ver = (hdr & (3<<19)) >> 19; ver = vertbl[ver]; if (ver < 0) { - trace ("frame %d bad mpeg version %d\n", nframe, (hdr & (3<<19)) >> 19); lastframe_valid = 0; + trace ("frame %d bad mpeg version %d\n", nframe, (hdr & (3<<19)) >> 19); continue; // invalid frame } @@ -300,8 +293,8 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { int layer = (hdr & (3<<17)) >> 17; layer = ltbl[layer]; if (layer < 0) { - trace ("frame %d bad layer %d\n", nframe, (hdr & (3<<17)) >> 17); lastframe_valid = 0; + trace ("frame %d bad layer %d\n", nframe, (hdr & (3<<17)) >> 17); continue; // invalid frame } @@ -326,8 +319,8 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { } bitrate = brtable[idx][bitrate]; if (bitrate <= 0) { - trace ("frame %d bad bitrate %d\n", nframe, (hdr & (0x0f<<12)) >> 12); lastframe_valid = 0; + trace ("frame %d bad bitrate %d\n", nframe, (hdr & (0x0f<<12)) >> 12); continue; // invalid frame } @@ -340,8 +333,8 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { int samplerate = (hdr & (0x03<<10))>>10; samplerate = srtable[ver-1][samplerate]; if (samplerate < 0) { - trace ("frame %d bad samplerate %d\n", nframe, (hdr & (0x03<<10))>>10); lastframe_valid = 0; + trace ("frame %d bad samplerate %d\n", nframe, (hdr & (0x03<<10))>>10); continue; // invalid frame } @@ -355,13 +348,13 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { // check if channel/bitrate combination is valid for layer2 if (layer == 2) { if ((bitrate <= 56 || bitrate == 80) && nchannels != 1) { - trace ("mpgmad: bad frame %d: layer %d, channels %d, bitrate %d\n", nframe, layer, nchannels, bitrate); lastframe_valid = 0; + trace ("mpgmad: bad frame %d: layer %d, channels %d, bitrate %d\n", nframe, layer, nchannels, bitrate); continue; // bad frame } if (bitrate >= 224 && nchannels == 1) { - trace ("mpgmad: bad frame %d: layer %d, channels %d, bitrate %d\n", nframe, layer, nchannels, bitrate); lastframe_valid = 0; + trace ("mpgmad: bad frame %d: layer %d, channels %d, bitrate %d\n", nframe, layer, nchannels, bitrate); continue; // bad frame } } @@ -396,13 +389,13 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { } } packetlength = samples_per_frame / 8 * bitrate / samplerate + padding; -// if (sample > 0) { -// printf ("frame: %d, crc: %d, layer: %d, bitrate: %d, samplerate: %d, filepos: 0x%llX, dataoffs: 0x%X, size: 0x%X\n", nframe, prot, layer, bitrate, samplerate, deadbeef->ftell (buffer->file)-8, data_ptr, packetlength); -// } + if (sample > 0) { + trace ("frame: %d, layer: %d, bitrate: %d, samplerate: %d\n", nframe, layer, bitrate, samplerate); + } } else { - trace ("frame %d samplerate or bitrate is invalid\n", nframe); lastframe_valid = 0; + trace ("frame %d samplerate or bitrate is invalid\n", nframe); continue; } // }}} @@ -417,27 +410,25 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { valid_frames++; // {{{ update stream parameters, only when sample!=0 or 1st frame - if (sample != 0 || nframe == 0) +// trace ("have_info: %d, lastframe_valid=%d\n", have_info, lastframe_valid); + if (!have_info && lastframe_valid) { - if (sample == 0 && lastframe_valid) { - return 0; - } // don't get parameters from frames coming after any bad frame - if (!had_invalid_frames) { - buffer->version = ver; - buffer->layer = layer; - buffer->bitrate = bitrate; - buffer->samplerate = samplerate; - buffer->packetlength = packetlength; - if (nchannels > buffer->channels) { - buffer->channels = nchannels; - } - buffer->bitspersample = 16; -// trace ("frame %d mpeg v%d layer %d bitrate %d samplerate %d packetlength %d channels %d\n", nframe, ver, layer, bitrate, samplerate, packetlength, nchannels); + trace ("\033[0;31mgot info!\033[37;0m\n"); + have_info = 1; + buffer->version = ver; + buffer->layer = layer; + buffer->bitrate = bitrate; + buffer->samplerate = samplerate; + buffer->packetlength = packetlength; + if (nchannels > buffer->channels) { + buffer->channels = nchannels; } + buffer->bitspersample = 16; + trace ("frame %d mpeg v%d layer %d bitrate %d samplerate %d packetlength %d channels %d\n", nframe, ver, layer, bitrate, samplerate, packetlength, nchannels); } // }}} - + //trace ("lastframe_valid=1, valid_frames=%d, sample=%d, nframe=%d\n", valid_frames, sample, nframe); lastframe_valid = 1; int64_t framepos = deadbeef->ftell (buffer->file)-(int)sizeof(fb); @@ -612,6 +603,7 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { if (sample == 0) { deadbeef->fseek (buffer->file, framepos, SEEK_SET); + trace ("scan finished\n"); return 0; } } @@ -656,7 +648,7 @@ cmp3_scan_stream (buffer_t *buffer, int sample) { scansamples += samples_per_frame; nframe++; if (packetlength > 0) { - deadbeef->fseek (buffer->file, packetlength-(int)sizeof(fb), SEEK_CUR); + deadbeef->fseek (buffer->file, framepos+packetlength, SEEK_SET); } } end_scan: @@ -664,7 +656,7 @@ end_scan: trace ("cmp3_scan_stream: couldn't find mpeg frames in file\n"); return -1; } - if (sample == 0) { + if (sample == 0 && have_info) { // {{{ calculate final averages buffer->avg_packetlength /= (float)valid_frames; buffer->avg_samplerate /= valid_frames; @@ -679,14 +671,18 @@ end_scan: buffer->duration = (buffer->totalsamples - buffer->delay - buffer->padding) / buffer->avg_samplerate; } buffer->bitrate = (fsize-buffer->startoffset-buffer->endoffset) / buffer->duration * 8; - trace ("nframes: %d, fsize: %lld, spf: %d, smp: %d, totalsamples: %d\n", buffer->nframes, fsize, buffer->avg_samples_per_frame, buffer->avg_samplerate, buffer->totalsamples); + trace ("nframes: %d, fsize: %lld, spf: %d, smp: %d, totalsamples: %d, real_smp: %d\n", buffer->nframes, fsize, buffer->avg_samples_per_frame, buffer->avg_samplerate, buffer->totalsamples, buffer->samplerate); // }}} return 0; } + if (buffer->samplerate <= 0) { + trace ("invalid samplerate\n"); + return -1; + } buffer->totalsamples = scansamples; buffer->duration = (buffer->totalsamples - buffer->delay - buffer->padding) / buffer->samplerate; -// printf ("nframes=%d, totalsamples=%d, samplerate=%d, dur=%f\n", nframe, scansamples, buffer->samplerate, buffer->duration); +// trace ("nframes=%d, totalsamples=%d, samplerate=%d, dur=%f\n", nframe, scansamples, buffer->samplerate, buffer->duration); return 0; } |