|
|
|
@@ -115,7 +115,8 @@ static void read_xing_toc(AVFormatContext *s, int64_t filesize, int64_t duration |
|
|
|
{ |
|
|
|
int i; |
|
|
|
MP3DecContext *mp3 = s->priv_data; |
|
|
|
int fill_index = mp3->usetoc == 1 && duration > 0; |
|
|
|
int fast_seek = s->flags & AVFMT_FLAG_FAST_SEEK; |
|
|
|
int fill_index = (mp3->usetoc || fast_seek) && duration > 0; |
|
|
|
|
|
|
|
if (!filesize && |
|
|
|
!(filesize = avio_size(s->pb))) { |
|
|
|
@@ -344,9 +345,6 @@ static int mp3_read_header(AVFormatContext *s) |
|
|
|
int ret; |
|
|
|
int i; |
|
|
|
|
|
|
|
if (mp3->usetoc < 0) |
|
|
|
mp3->usetoc = (s->flags & AVFMT_FLAG_FAST_SEEK) ? 1 : 2; |
|
|
|
|
|
|
|
st = avformat_new_stream(s, NULL); |
|
|
|
if (!st) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
@@ -501,35 +499,37 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, |
|
|
|
MP3DecContext *mp3 = s->priv_data; |
|
|
|
AVIndexEntry *ie, ie1; |
|
|
|
AVStream *st = s->streams[0]; |
|
|
|
int64_t ret = av_index_search_timestamp(st, timestamp, flags); |
|
|
|
int64_t best_pos; |
|
|
|
int fast_seek = (s->flags & AVFMT_FLAG_FAST_SEEK) ? 1 : 0; |
|
|
|
int fast_seek = s->flags & AVFMT_FLAG_FAST_SEEK; |
|
|
|
int64_t filesize = mp3->header_filesize; |
|
|
|
|
|
|
|
if (mp3->usetoc == 2) |
|
|
|
return -1; // generic index code |
|
|
|
|
|
|
|
if (filesize <= 0) { |
|
|
|
int64_t size = avio_size(s->pb); |
|
|
|
if (size > 0 && size > s->internal->data_offset) |
|
|
|
filesize = size - s->internal->data_offset; |
|
|
|
} |
|
|
|
|
|
|
|
if ( (mp3->is_cbr || fast_seek) |
|
|
|
&& (mp3->usetoc == 0 || !mp3->xing_toc) |
|
|
|
&& st->duration > 0 |
|
|
|
&& filesize > 0) { |
|
|
|
ie = &ie1; |
|
|
|
timestamp = av_clip64(timestamp, 0, st->duration); |
|
|
|
ie->timestamp = timestamp; |
|
|
|
ie->pos = av_rescale(timestamp, filesize, st->duration) + s->internal->data_offset; |
|
|
|
} else if (mp3->xing_toc) { |
|
|
|
if (mp3->xing_toc && (mp3->usetoc || (fast_seek && !mp3->is_cbr))) { |
|
|
|
int64_t ret = av_index_search_timestamp(st, timestamp, flags); |
|
|
|
|
|
|
|
// NOTE: The MP3 TOC is not a precise lookup table. Accuracy is worse |
|
|
|
// for bigger files. |
|
|
|
av_log(s, AV_LOG_WARNING, "Using MP3 TOC to seek; may be imprecise.\n"); |
|
|
|
|
|
|
|
if (ret < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
ie = &st->index_entries[ret]; |
|
|
|
} else if (fast_seek && st->duration > 0 && filesize > 0) { |
|
|
|
if (!mp3->is_cbr) |
|
|
|
av_log(s, AV_LOG_WARNING, "Using scaling to seek VBR MP3; may be imprecise.\n"); |
|
|
|
|
|
|
|
ie = &ie1; |
|
|
|
timestamp = av_clip64(timestamp, 0, st->duration); |
|
|
|
ie->timestamp = timestamp; |
|
|
|
ie->pos = av_rescale(timestamp, filesize, st->duration) + s->internal->data_offset; |
|
|
|
} else { |
|
|
|
return -1; |
|
|
|
return -1; // generic index code |
|
|
|
} |
|
|
|
|
|
|
|
best_pos = mp3_sync(s, ie->pos, flags); |
|
|
|
@@ -546,7 +546,7 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, |
|
|
|
} |
|
|
|
|
|
|
|
static const AVOption options[] = { |
|
|
|
{ "usetoc", "use table of contents", offsetof(MP3DecContext, usetoc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, AV_OPT_FLAG_DECODING_PARAM}, |
|
|
|
{ "usetoc", "use table of contents", offsetof(MP3DecContext, usetoc), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM}, |
|
|
|
{ NULL }, |
|
|
|
}; |
|
|
|
|
|
|
|
|