int is_cbr;
} MP3DecContext;
+enum CheckRet {
+ CHECK_WRONG_HEADER = -1,
+ CHECK_SEEK_FAILED = -2,
+};
+
static int check(AVIOContext *pb, int64_t pos, uint32_t *header);
/* mp3 read */
st->duration = av_rescale_q(mp3->frames, (AVRational){spf, c.sample_rate},
st->time_base);
if (mp3->header_filesize && mp3->frames && !mp3->is_cbr)
- st->codec->bit_rate = av_rescale(mp3->header_filesize, 8 * c.sample_rate, mp3->frames * (int64_t)spf);
+ st->codecpar->bit_rate = av_rescale(mp3->header_filesize, 8 * c.sample_rate, mp3->frames * (int64_t)spf);
return 0;
}
if (!st)
return AVERROR(ENOMEM);
- st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
- st->codec->codec_id = AV_CODEC_ID_MP3;
+ st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+ st->codecpar->codec_id = AV_CODEC_ID_MP3;
st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
st->start_time = 0;
ffio_ensure_seekback(s->pb, i + 1024 + 4);
frame_size = check(s->pb, off + i, &header);
if (frame_size > 0) {
- avio_seek(s->pb, off, SEEK_SET);
+ ret = avio_seek(s->pb, off, SEEK_SET);
+ if (ret < 0)
+ return ret;
ffio_ensure_seekback(s->pb, i + 1024 + frame_size + 4);
- if (check(s->pb, off + i + frame_size, &header2) >= 0 &&
+ ret = check(s->pb, off + i + frame_size, &header2);
+ if (ret >= 0 &&
(header & SAME_HEADER_MASK) == (header2 & SAME_HEADER_MASK))
{
- av_log(s, AV_LOG_INFO, "Skipping %d bytes of junk at %"PRId64".\n", i, off);
- avio_seek(s->pb, off + i, SEEK_SET);
+ av_log(s, i > 0 ? AV_LOG_INFO : AV_LOG_VERBOSE, "Skipping %d bytes of junk at %"PRId64".\n", i, off);
+ ret = avio_seek(s->pb, off + i, SEEK_SET);
+ if (ret < 0)
+ return ret;
break;
+ } else if (ret == CHECK_SEEK_FAILED) {
+ av_log(s, AV_LOG_ERROR, "Invalid frame size (%d): Could not seek to %"PRId64".\n", frame_size, off + i + frame_size);
+ return AVERROR(EINVAL);
}
+ } else if (frame_size == CHECK_SEEK_FAILED) {
+ av_log(s, AV_LOG_ERROR, "Failed to read frame size: Could not seek to %"PRId64".\n", (int64_t) (i + 1024 + frame_size + 4));
+ return AVERROR(EINVAL);
}
- avio_seek(s->pb, off, SEEK_SET);
+ ret = avio_seek(s->pb, off, SEEK_SET);
+ if (ret < 0)
+ return ret;
}
// the seek index is relative to the end of the xing vbr headers
static int check(AVIOContext *pb, int64_t pos, uint32_t *ret_header)
{
int64_t ret = avio_seek(pb, pos, SEEK_SET);
+ uint8_t header_buf[4];
unsigned header;
MPADecodeHeader sd;
if (ret < 0)
- return ret;
+ return CHECK_SEEK_FAILED;
- header = avio_rb32(pb);
+ ret = avio_read(pb, &header_buf[0], 4);
+ if (ret < 0)
+ return CHECK_SEEK_FAILED;
+
+ header = AV_RB32(&header_buf[0]);
if (ff_mpa_check_header(header) < 0)
- return -1;
+ return CHECK_WRONG_HEADER;
if (avpriv_mpegaudio_decode_header(&sd, header) == 1)
- return -1;
+ return CHECK_WRONG_HEADER;
if (ret_header)
*ret_header = header;
for(j=0; j<MIN_VALID; j++) {
ret = check(s->pb, pos, NULL);
- if(ret < 0)
- break;
+ if(ret < 0) {
+ if (ret == CHECK_WRONG_HEADER) {
+ break;
+ } else if (ret == CHECK_SEEK_FAILED) {
+ av_log(s, AV_LOG_ERROR, "Could not seek to %"PRId64".\n", pos);
+ return AVERROR(EINVAL);
+ }
+ }
if ((target_pos - pos)*dir <= 0 && abs(MIN_VALID/2-j) < score) {
candidate = pos;
score = abs(MIN_VALID/2-j);