This should also work reasonable with truncated and growing mp3s.
Fixes Ticket2590
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit e096283ea55bc36a637b47329e19ddb26fb1440b)
Conflicts:
libavformat/mp3dec.c
... | ... |
@@ -37,9 +37,11 @@ |
37 | 37 |
|
38 | 38 |
typedef struct { |
39 | 39 |
int64_t filesize; |
40 |
+ int64_t header_filesize; |
|
40 | 41 |
int xing_toc; |
41 | 42 |
int start_pad; |
42 | 43 |
int end_pad; |
44 |
+ int is_cbr; |
|
43 | 45 |
} MP3Context; |
44 | 46 |
|
45 | 47 |
/* mp3 read */ |
... | ... |
@@ -185,6 +187,9 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) |
185 | 185 |
if (size && frames && !is_cbr) |
186 | 186 |
st->codec->bit_rate = av_rescale(size, 8 * c.sample_rate, frames * (int64_t)spf); |
187 | 187 |
|
188 |
+ mp3->is_cbr = is_cbr; |
|
189 |
+ mp3->header_filesize = size; |
|
190 |
+ |
|
188 | 191 |
return 0; |
189 | 192 |
} |
190 | 193 |
|
... | ... |
@@ -274,21 +279,33 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, |
274 | 274 |
int flags) |
275 | 275 |
{ |
276 | 276 |
MP3Context *mp3 = s->priv_data; |
277 |
- AVIndexEntry *ie; |
|
277 |
+ AVIndexEntry *ie, ie1; |
|
278 | 278 |
AVStream *st = s->streams[0]; |
279 | 279 |
int64_t ret = av_index_search_timestamp(st, timestamp, flags); |
280 | 280 |
int i, j; |
281 | 281 |
|
282 |
- if (!mp3->xing_toc) { |
|
282 |
+ if (mp3->is_cbr && st->duration > 0 && mp3->header_filesize > s->data_offset) { |
|
283 |
+ int64_t filesize = avio_size(s->pb); |
|
284 |
+ int64_t duration; |
|
285 |
+ if (filesize <= s->data_offset) |
|
286 |
+ filesize = mp3->header_filesize; |
|
287 |
+ filesize -= s->data_offset; |
|
288 |
+ duration = av_rescale(st->duration, filesize, mp3->header_filesize - s->data_offset); |
|
289 |
+ ie = &ie1; |
|
290 |
+ timestamp = av_clip64(timestamp, 0, duration); |
|
291 |
+ ie->timestamp = timestamp; |
|
292 |
+ ie->pos = av_rescale(timestamp, filesize, duration) + s->data_offset; |
|
293 |
+ } else if (mp3->xing_toc) { |
|
294 |
+ if (ret < 0) |
|
295 |
+ return ret; |
|
296 |
+ |
|
297 |
+ ie = &st->index_entries[ret]; |
|
298 |
+ } else { |
|
283 | 299 |
st->skip_samples = timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0; |
284 | 300 |
|
285 | 301 |
return -1; |
286 | 302 |
} |
287 | 303 |
|
288 |
- if (ret < 0) |
|
289 |
- return ret; |
|
290 |
- |
|
291 |
- ie = &st->index_entries[ret]; |
|
292 | 304 |
ret = avio_seek(s->pb, ie->pos, SEEK_SET); |
293 | 305 |
if (ret < 0) |
294 | 306 |
return ret; |