Ok, the patch from 2003 about improving seeking still didn't make it
to CVS, so here is another try.
I made some benchmarking with the test_seeking utility from flac
sources to show how bad the current seeking is, especially without
seektable. Track used for the experiment had about 50 minutes.
In the following table is average number of seeks and number of
decoded frames required for one complete absolute seek. I tried
several files encoded with fixed/variable block size, seektable with
seekpoints every 10s, 100s and no seektable.
unpatched patched
block size seekdecoded decoded
points seeks frames seeks frames
fixed
10s 1.222.041.161.83
100s6.3712.26 2.223.21
- 16.80 341.61 3.845.23
variable
10s 1.182.931.422.57
100s8.8016.65 2.583.67
- 31.35 445.08 4.285.67
And another table shows the worst seek for the same files.
block size seekdecoded decoded
points seeks frames seeks frames
fixed
10s 49 49 3 6
100s55 55 5 8
- 1 10386 9
variable
10s 53 53 9 9
100s87 9 8 8
- 1 162010 13
Attached is the new patch.
--
Miroslav Lichvar
Index: stream_decoder.c
===
RCS file: /cvsroot/flac/flac/src/libFLAC/stream_decoder.c,v
retrieving revision 1.117
diff -u -r1.117 stream_decoder.c
--- stream_decoder.c16 Oct 2006 15:49:18 - 1.117
+++ stream_decoder.c28 Oct 2006 17:12:19 -
@@ -2923,18 +2923,18 @@
FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64
stream_length, FLAC__uint64 target_sample)
{
- FLAC__uint64 first_frame_offset =
decoder-private_-first_frame_offset, lower_bound, upper_bound;
+ FLAC__uint64 first_frame_offset =
decoder-private_-first_frame_offset, lower_bound, upper_bound,
lower_bound_sample, upper_bound_sample;
FLAC__int64 pos = -1, last_pos = -1;
- int i, lower_seek_point = -1, upper_seek_point = -1;
+ int i;
unsigned approx_bytes_per_frame;
- FLAC__uint64 last_frame_sample = FLAC__U64L(0x);
+ FLAC__uint64 last_frame_sample = FLAC__U64L(0x),
this_frame_sample;
FLAC__bool needs_seek;
const FLAC__uint64 total_samples =
FLAC__stream_decoder_get_total_samples(decoder);
const unsigned min_blocksize =
decoder-private_-stream_info.data.stream_info.min_blocksize;
const unsigned max_blocksize =
decoder-private_-stream_info.data.stream_info.max_blocksize;
const unsigned max_framesize =
decoder-private_-stream_info.data.stream_info.max_framesize;
- const unsigned channels = FLAC__stream_decoder_get_channels(decoder);
- const unsigned bps = FLAC__stream_decoder_get_bits_per_sample(decoder);
+ const unsigned channels =
decoder-private_-stream_info.data.stream_info.channels;
+ const unsigned bps =
decoder-private_-stream_info.data.stream_info.bits_per_sample;
const FLAC__StreamMetadata_SeekTable *seek_table =
decoder-private_-has_seek_table?
decoder-private_-seek_table.data.seek_table : 0;
/* we are just guessing here, but we want to guess high, not low */
@@ -2961,12 +2961,14 @@
* the first and last frames.
*/
lower_bound = first_frame_offset;
+ lower_bound_sample = 0;
/* calc the upper_bound, beyond which we never want to seek */
if(max_framesize 0)
upper_bound = stream_length - (max_framesize + 128 + 2); /* 128
for a possible ID3V1 tag, 2 for indexing differences */
else
upper_bound = stream_length - ((channels * bps *
FLAC__MAX_BLOCK_SIZE) / 8 + 128 + 2);
+ upper_bound_sample = total_samples 0 ? total_samples : target_sample;
/*
* Now we refine the bounds if we have a seektable with
@@ -2981,7 +2983,7 @@
}
if(i = 0) { /* i.e. we found a suitable seek point... */
lower_bound = first_frame_offset +
seek_table-points[i].stream_offset;
- lower_seek_point = i;
+ lower_bound_sample =
seek_table-points[i].sample_number;
}
/* find the closest seek point target_sample, if it exists */
@@ -2991,98 +2993,32 @@
}
if(i (int)seek_table-num_points) { /* i.e. we found a
suitable seek