diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2010-06-16 20:32:37 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2010-06-16 20:32:37 +0200 |
commit | 3a53e93153ef7cdf3054bdabdbba5b2aee6d9cdd (patch) | |
tree | d1bc223a7e83ca80177e8880ba50d290ac8b1e60 /plugins/aac | |
parent | 5fd10493923e9d3d3028b522736816aa95eca788 (diff) |
raw aac seeking
Diffstat (limited to 'plugins/aac')
-rw-r--r-- | plugins/aac/aac.c | 139 | ||||
-rw-r--r-- | plugins/aac/aac_parser.c | 4 | ||||
-rw-r--r-- | plugins/aac/aac_parser.h | 2 |
3 files changed, 111 insertions, 34 deletions
diff --git a/plugins/aac/aac.c b/plugins/aac/aac.c index 8a8f0895..ab3e30ce 100644 --- a/plugins/aac/aac.c +++ b/plugins/aac/aac.c @@ -83,47 +83,54 @@ aac_fs_seek (void *user_data, uint64_t position) { static int parse_aac_stream(DB_FILE *fp, int *samplerate, int *channels, float *duration, int *totalsamples) { + int offs = deadbeef->ftell (fp); int fsize = deadbeef->fgetlength (fp); - uint8_t buf[8192]; + uint8_t buf[ADTS_HEADER_SIZE*8]; - int nframesfound = 0; int nsamples = 0; int stream_sr = 0; int stream_ch = 0; int eof = 0; int bufsize = 0; + int remaining = 0; + + int frame = 0; + do { + int size = sizeof (buf) - bufsize; + if (deadbeef->fread (buf + bufsize, 1, size, fp) != size) { + trace ("parse_aac_stream: eof\n"); + break; + } bufsize = sizeof (buf); - int bytesread = deadbeef->fread (buf, 1, bufsize, fp); - if (bytesread != bufsize) { - eof = 1; + + int channels, samplerate, bitrate, samples; + size = aac_sync (buf, &channels, &samplerate, &bitrate, &samples); + if (size == 0) { + memmove (buf, buf+1, sizeof (buf)-1); + bufsize--; + continue; } - bufsize = bytesread; - - uint8_t *ptr = buf; - while (ptr < buf + bufsize - ADTS_HEADER_SIZE*8) { - int channels, samplerate, bitrate, samples; - int size = aac_sync (ptr, &channels, &samplerate, &bitrate, &samples); - if (size == 0) { - ptr++; + else { + //trace ("aac: frame #%d sync: %d %d %d %d %d\n", frame, channels, samplerate, bitrate, samples, size); + frame++; + nsamples += samples; + if (!stream_sr) { + stream_sr = samplerate; } - else { - //trace ("aac: sync: %d %d %d %d %d\n", channels, samplerate, bitrate, samples, size); - nframesfound++; - nsamples += samples; - if (!stream_sr) { - stream_sr = samplerate; - } - if (!stream_ch) { - stream_ch = channels; - } - ptr += size; + if (!stream_ch) { + stream_ch = channels; } + if (deadbeef->fseek (fp, size-sizeof(buf), SEEK_CUR) == -1) { + trace ("parse_aac_stream: invalid seek %d\n", size-sizeof(buf)); + break; + } + bufsize = 0; } - } while (totalsamples && !eof); + } while (totalsamples || frame < 100); - if (!nframesfound || !stream_sr || !nsamples || !bufsize) { + if (!frame || !stream_sr || !nsamples) { return -1; } @@ -133,11 +140,13 @@ parse_aac_stream(DB_FILE *fp, int *samplerate, int *channels, float *duration, i if (totalsamples) { *totalsamples = nsamples; *duration = nsamples / (float)stream_sr; + trace ("aac: duration=%f (%d samples @ %d Hz), fsize=%d\n", *duration, *totalsamples, stream_sr, fsize); } else { - int totalsamples = fsize / bufsize * nsamples; + int pos = deadbeef->ftell (fp); + int totalsamples = fsize / (pos-offs) * nsamples; *duration = totalsamples / (float)stream_sr; - trace ("aac: duration=%f (%d samples @ %d Hz), fsize=%d, bufsize=%d\n", *duration, totalsamples, stream_sr, fsize, bufsize); + trace ("aac: duration=%f (%d samples @ %d Hz), fsize=%d\n", *duration, totalsamples, stream_sr, fsize); } return 0; @@ -456,10 +465,13 @@ aac_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) { if (res == 0) { eof = 1; } + info->remaining += res; } + //trace ("NeAACDecDecode %d bytes %d offs\n", info->remaining, deadbeef->ftell (info->file)); samples = NeAACDecDecode (info->dec, &frame_info, info->buffer, info->remaining); if (!samples) { + trace ("NeAACDecDecode failed\n"); break; } int consumed = frame_info.bytesconsumed; @@ -483,9 +495,68 @@ aac_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) { } info->currentsample += (initsize-size) / sample_size; + if (size != 0) { + trace ("aac_read_int16 eof\n"); + } return initsize-size; } +// returns -1 on error, 0 on success +int +seek_raw_aac (aac_info_t *info, int sample) { + deadbeef->rewind (info->file); + + int offs = deadbeef->ftell (info->file); + int fsize = deadbeef->fgetlength (info->file); + uint8_t buf[ADTS_HEADER_SIZE*8]; + + int nsamples = 0; + int stream_sr = 0; + int stream_ch = 0; + + int eof = 0; + int bufsize = 0; + int remaining = 0; + + int frame = 0; + + int frame_samples = 0; + int curr_sample = 0; + + do { + curr_sample += frame_samples; + int size = sizeof (buf) - bufsize; + if (deadbeef->fread (buf + bufsize, 1, size, info->file) != size) { + trace ("seek_raw_aac: eof\n"); + break; + } + bufsize = sizeof (buf); + + int channels, samplerate, bitrate; + size = aac_sync (buf, &channels, &samplerate, &bitrate, &frame_samples); + if (size == 0) { + memmove (buf, buf+1, sizeof (buf)-1); + bufsize--; + continue; + } + else { + //trace ("aac: frame #%d sync: %d %d %d %d %d\n", frame, channels, samplerate, bitrate, samples, size); + frame++; + if (deadbeef->fseek (info->file, size-sizeof(buf), SEEK_CUR) == -1) { + trace ("seek_raw_aac: invalid seek %d\n", size-sizeof(buf)); + break; + } + bufsize = 0; + } + } while (curr_sample + frame_samples < sample); + + if (curr_sample + frame_samples < sample) { + return -1; + } + + return sample - curr_sample; +} + static int aac_seek_sample (DB_fileinfo_t *_info, int sample) { aac_info_t *info = (aac_info_t *)_info; @@ -494,10 +565,16 @@ aac_seek_sample (DB_fileinfo_t *_info, int sample) { if (info->mp4file) { info->mp4sample = sample / (info->mp4framesize-1); info->skipsamples = sample - info->mp4sample * (info->mp4framesize-1); - info->remaining = 0; - info->out_remaining = 0; } - + else { + int res = seek_raw_aac (info, sample); + if (res < 0) { + return -1; + } + info->skipsamples = res; + } + info->remaining = 0; + info->out_remaining = 0; info->currentsample = sample - info->startsample; _info->readpos = (float)info->currentsample / _info->samplerate; return 0; diff --git a/plugins/aac/aac_parser.c b/plugins/aac/aac_parser.c index eea957df..32571aff 100644 --- a/plugins/aac/aac_parser.c +++ b/plugins/aac/aac_parser.c @@ -34,8 +34,6 @@ static const int aac_channels[8] = { 0, 1, 2, 3, 4, 5, 6, 8 }; -// buf size must be at least ADTS_HEADER_SIZE*8 -// returns frame size int aac_sync(const uint8_t *buf, int *channels, int *sample_rate, int *bit_rate, int *samples) { @@ -43,7 +41,7 @@ aac_sync(const uint8_t *buf, int *channels, int *sample_rate, int *bit_rate, int // 12 sync bits if (buf[0] != 0xff || (buf[1]&0xf0) != 0xf0) { - trace ("unsync\n"); + //trace ("unsync\n"); return 0; } diff --git a/plugins/aac/aac_parser.h b/plugins/aac/aac_parser.h index 4f872d4b..53e7916d 100644 --- a/plugins/aac/aac_parser.h +++ b/plugins/aac/aac_parser.h @@ -24,6 +24,8 @@ #define ADTS_HEADER_SIZE 7 +// buf size must be at least ADTS_HEADER_SIZE*8 +// returns frame size int aac_sync(const uint8_t *buf, int *channels, int *sample_rate, int *bit_rate, int *samples); |