summaryrefslogtreecommitdiff
path: root/plugins/mpgmad/mpgmad.c
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2013-06-05 21:29:57 +0200
committerGravatar waker <wakeroid@gmail.com>2013-06-05 21:29:57 +0200
commitc921f15c196680ea568fc427781027f4eed31779 (patch)
tree34fdb45d7ff60cc05f865af6ae91e783a1b7ce75 /plugins/mpgmad/mpgmad.c
parentcb0bfa2b92fd467be34aeea991b2c5f32dc413ec (diff)
mp3 parser: fix seeking to end of frame; new corrupted frame heuristic
Diffstat (limited to 'plugins/mpgmad/mpgmad.c')
-rw-r--r--plugins/mpgmad/mpgmad.c78
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;
}