|
|
@@ -39,10 +39,12 @@ |
|
|
typedef struct { |
|
|
typedef struct { |
|
|
AVClass *class; |
|
|
AVClass *class; |
|
|
int64_t filesize; |
|
|
int64_t filesize; |
|
|
|
|
|
int64_t header_filesize; |
|
|
int xing_toc; |
|
|
int xing_toc; |
|
|
int start_pad; |
|
|
int start_pad; |
|
|
int end_pad; |
|
|
int end_pad; |
|
|
int usetoc; |
|
|
int usetoc; |
|
|
|
|
|
int is_cbr; |
|
|
} MP3DecContext; |
|
|
} MP3DecContext; |
|
|
|
|
|
|
|
|
/* mp3 read */ |
|
|
/* mp3 read */ |
|
|
@@ -190,6 +192,9 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) |
|
|
if (size && frames && !is_cbr) |
|
|
if (size && frames && !is_cbr) |
|
|
st->codec->bit_rate = av_rescale(size, 8 * c.sample_rate, frames * (int64_t)spf); |
|
|
st->codec->bit_rate = av_rescale(size, 8 * c.sample_rate, frames * (int64_t)spf); |
|
|
|
|
|
|
|
|
|
|
|
mp3->is_cbr = is_cbr; |
|
|
|
|
|
mp3->header_filesize = size; |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -279,21 +284,33 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, |
|
|
int flags) |
|
|
int flags) |
|
|
{ |
|
|
{ |
|
|
MP3DecContext *mp3 = s->priv_data; |
|
|
MP3DecContext *mp3 = s->priv_data; |
|
|
AVIndexEntry *ie; |
|
|
|
|
|
|
|
|
AVIndexEntry *ie, ie1; |
|
|
AVStream *st = s->streams[0]; |
|
|
AVStream *st = s->streams[0]; |
|
|
int64_t ret = av_index_search_timestamp(st, timestamp, flags); |
|
|
int64_t ret = av_index_search_timestamp(st, timestamp, flags); |
|
|
int i, j; |
|
|
int i, j; |
|
|
|
|
|
|
|
|
if (!mp3->xing_toc) { |
|
|
|
|
|
|
|
|
if (mp3->is_cbr && st->duration > 0 && mp3->header_filesize > s->data_offset) { |
|
|
|
|
|
int64_t filesize = avio_size(s->pb); |
|
|
|
|
|
int64_t duration; |
|
|
|
|
|
if (filesize <= s->data_offset) |
|
|
|
|
|
filesize = mp3->header_filesize; |
|
|
|
|
|
filesize -= s->data_offset; |
|
|
|
|
|
duration = av_rescale(st->duration, filesize, mp3->header_filesize - s->data_offset); |
|
|
|
|
|
ie = &ie1; |
|
|
|
|
|
timestamp = av_clip64(timestamp, 0, duration); |
|
|
|
|
|
ie->timestamp = timestamp; |
|
|
|
|
|
ie->pos = av_rescale(timestamp, filesize, duration) + s->data_offset; |
|
|
|
|
|
} else if (mp3->xing_toc) { |
|
|
|
|
|
if (ret < 0) |
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
|
|
ie = &st->index_entries[ret]; |
|
|
|
|
|
} else { |
|
|
st->skip_samples = timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0; |
|
|
st->skip_samples = timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0; |
|
|
|
|
|
|
|
|
return -1; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (ret < 0) |
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
|
|
ie = &st->index_entries[ret]; |
|
|
|
|
|
ret = avio_seek(s->pb, ie->pos, SEEK_SET); |
|
|
ret = avio_seek(s->pb, ie->pos, SEEK_SET); |
|
|
if (ret < 0) |
|
|
if (ret < 0) |
|
|
return ret; |
|
|
return ret; |
|
|
|