Browse code

mp3dec: detect CBR and use CBR axiom to seek

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

Michael Niedermayer authored on 2013/07/07 20:15:32
Showing 1 changed files
... ...
@@ -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;