//mpegps_mp3_unrecognized_format.mpg has max_frames=3
}
-static void read_xing_toc(AVFormatContext *s, int64_t base, int64_t filesize, int64_t duration)
+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 && duration > 0;
+ int fill_index = mp3->usetoc == 1 && duration > 0;
if (!filesize &&
!(filesize = avio_size(s->pb))) {
uint8_t b = avio_r8(s->pb);
if (fill_index)
av_add_index_entry(s->streams[0],
- av_rescale(b, filesize, 256) + base,
+ av_rescale(b, filesize, 256),
av_rescale(i, duration, XING_TOC_COUNT),
0, 0, AVINDEX_KEYFRAME);
}
mp3->xing_toc = 1;
}
-static void mp3_parse_info_tag(AVFormatContext *s, AVStream *st, int64_t base,
+static void mp3_parse_info_tag(AVFormatContext *s, AVStream *st,
MPADecodeHeader *c, uint32_t spf)
{
#define LAST_BITS(k, n) ((k) & ((1 << (n)) - 1))
}
}
if (v & XING_FLAG_TOC)
- read_xing_toc(s, base, mp3->header_filesize, av_rescale_q(mp3->frames,
+ read_xing_toc(s, mp3->header_filesize, av_rescale_q(mp3->frames,
(AVRational){spf, c->sample_rate},
st->time_base));
/* VBR quality */
mp3->start_pad = v>>12;
mp3-> end_pad = v&4095;
- st->skip_samples = mp3->start_pad + 528 + 1;
+ st->start_skip_samples = mp3->start_pad + 528 + 1;
if (mp3->frames) {
st->first_discard_sample = -mp3->end_pad + 528 + 1 + mp3->frames * (int64_t)spf;
st->last_discard_sample = mp3->frames * (int64_t)spf;
}
if (!st->start_time)
- st->start_time = av_rescale_q(st->skip_samples,
+ st->start_time = av_rescale_q(st->start_skip_samples,
(AVRational){1, c->sample_rate},
st->time_base);
av_log(s, AV_LOG_DEBUG, "pad %d %d\n", mp3->start_pad, mp3-> end_pad);
mp3->frames = 0;
mp3->header_filesize = 0;
- mp3_parse_info_tag(s, st, base, &c, spf);
+ mp3_parse_info_tag(s, st, &c, spf);
mp3_parse_vbri_tag(s, st, base);
if (!mp3->frames && !mp3->header_filesize)
AVStream *st;
int64_t off;
int ret;
+ int i;
+
+ if (mp3->usetoc < 0)
+ mp3->usetoc = 2;
st = avformat_new_stream(s, NULL);
if (!st)
if (ret < 0)
return ret;
+ // the seek index is relative to the end of the xing vbr headers
+ for (i = 0; i < st->nb_index_entries; i++)
+ st->index_entries[i].pos += avio_tell(s->pb);
+
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
int64_t best_pos;
int best_score;
+ if (mp3->usetoc == 2)
+ return -1; // generic index code
+
if ( mp3->is_cbr
+ && (mp3->usetoc == 0 || !mp3->xing_toc)
&& st->duration > 0
&& mp3->header_filesize > s->internal->data_offset
&& mp3->frames) {
- int64_t filesize = avio_size(s->pb);
- int64_t duration;
- if (filesize <= s->internal->data_offset)
- filesize = mp3->header_filesize;
- filesize -= s->internal->data_offset;
- duration = av_rescale(st->duration, filesize, mp3->header_filesize - s->internal->data_offset);
ie = &ie1;
- timestamp = av_clip64(timestamp, 0, duration);
+ timestamp = av_clip64(timestamp, 0, st->duration);
ie->timestamp = timestamp;
- ie->pos = av_rescale(timestamp, filesize, duration) + s->internal->data_offset;
+ ie->pos = av_rescale(timestamp, mp3->header_filesize, st->duration) + s->internal->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;
-
return -1;
}
ret = avio_seek(s->pb, best_pos, SEEK_SET);
if (ret < 0)
return ret;
+
+ if (mp3->is_cbr && ie == &ie1) {
+ int frame_duration = av_rescale(st->duration, 1, mp3->frames);
+ ie1.timestamp = frame_duration * av_rescale(best_pos - s->internal->data_offset, mp3->frames, mp3->header_filesize);
+ }
+
ff_update_cur_dts(s, st, ie->timestamp);
- st->skip_samples = ie->timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0;
return 0;
}
static const AVOption options[] = {
- { "usetoc", "use table of contents", offsetof(MP3DecContext, usetoc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM},
+ { "usetoc", "use table of contents", offsetof(MP3DecContext, usetoc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, AV_OPT_FLAG_DECODING_PARAM},
{ NULL },
};