* the MS dshow demuxer */
AVFormatContext *sub_ctx;
- AVPacket sub_pkt;
+ AVPacket *sub_pkt;
AVBufferRef *sub_buffer;
int64_t seek_pos;
static const AVMetadataConv avi_metadata_conv[] = {
{ "strn", "title" },
+ { "isbj", "subject" },
+ { "inam", "title" },
+ { "iart", "artist" },
+ { "icop", "copyright" },
+ { "icmt", "comment" },
+ { "ignr", "genre" },
+ { "iprd", "product" },
+ { "isft", "software" },
+
{ 0 },
};
+static int avi_read_close(AVFormatContext *s);
static int avi_load_index(AVFormatContext *s);
static int guess_ni_flag(AVFormatContext *s);
if (ast->sample_size)
return len;
else if (ast->dshow_block_align)
- return (len + ast->dshow_block_align - 1) / ast->dshow_block_align;
+ return (len + (int64_t)ast->dshow_block_align - 1) / ast->dshow_block_align;
else
return 1;
}
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
AVIStream *ast = st->priv_data;
- int n = st->nb_index_entries;
+ int n = st->internal->nb_index_entries;
int max = ast->sample_size;
int64_t pos, size, ts;
while (max < 1024)
max += max;
- pos = st->index_entries[0].pos;
- size = st->index_entries[0].size;
- ts = st->index_entries[0].timestamp;
+ pos = st->internal->index_entries[0].pos;
+ size = st->internal->index_entries[0].size;
+ ts = st->internal->index_entries[0].timestamp;
for (j = 0; j < size; j += max)
av_add_index_entry(st, pos + j, ts + j, FFMIN(max, size - j), 0,
int64_t len = 0;
AVStream *st = s->streams[i];
- if (!st->nb_index_entries)
+ if (!st->internal->nb_index_entries)
continue;
- for (j = 0; j < st->nb_index_entries; j++)
- len += st->index_entries[j].size;
- maxpos = FFMAX(maxpos, st->index_entries[j-1].pos);
+ for (j = 0; j < st->internal->nb_index_entries; j++)
+ len += st->internal->index_entries[j].size;
+ maxpos = FFMAX(maxpos, st->internal->index_entries[j-1].pos);
lensum += len;
}
if (maxpos < av_rescale(avi->io_fsize, 9, 10)) // index does not cover the whole file
int64_t duration;
int64_t bitrate;
- for (j = 0; j < st->nb_index_entries; j++)
- len += st->index_entries[j].size;
+ for (j = 0; j < st->internal->nb_index_entries; j++)
+ len += st->internal->index_entries[j].size;
- if (st->nb_index_entries < 2 || st->codecpar->bit_rate > 0)
+ if (st->internal->nb_index_entries < 2 || st->codecpar->bit_rate > 0)
continue;
- duration = st->index_entries[j-1].timestamp - st->index_entries[0].timestamp;
+ duration = st->internal->index_entries[j-1].timestamp - st->internal->index_entries[0].timestamp;
bitrate = av_rescale(8*len, st->time_base.den, duration * st->time_base.num);
if (bitrate > 0) {
st->codecpar->bit_rate = bitrate;
return 1;
}
+#define RETURN_ERROR(code) do { ret = (code); goto fail; } while (0)
static int avi_read_header(AVFormatContext *s)
{
AVIContext *avi = s->priv_data;
frame_period = 0;
for (;;) {
if (avio_feof(pb))
- goto fail;
+ RETURN_ERROR(AVERROR_INVALIDDATA);
tag = avio_rl32(pb);
size = avio_rl32(pb);
stream_index++;
st = avformat_new_stream(s, NULL);
if (!st)
- goto fail;
+ RETURN_ERROR(AVERROR(ENOMEM));
st->id = stream_index;
ast = av_mallocz(sizeof(AVIStream));
if (!ast)
- goto fail;
+ RETURN_ERROR(AVERROR(ENOMEM));
st->priv_data = ast;
}
if (amv_file_format)
/* After some consideration -- I don't think we
* have to support anything but DV in type1 AVIs. */
if (s->nb_streams != 1)
- goto fail;
+ RETURN_ERROR(AVERROR_INVALIDDATA);
if (handler != MKTAG('d', 'v', 's', 'd') &&
handler != MKTAG('d', 'v', 'h', 'd') &&
handler != MKTAG('d', 'v', 's', 'l'))
- goto fail;
+ return AVERROR_INVALIDDATA;
if (!CONFIG_DV_DEMUXER)
return AVERROR_DEMUXER_NOT_FOUND;
"Invalid sample_size %d at stream %d\n",
ast->sample_size,
stream_index);
- goto fail;
+ RETURN_ERROR(AVERROR_INVALIDDATA);
}
av_log(s, AV_LOG_WARNING,
"Invalid sample_size %d at stream %d "
st->codecpar->codec_tag == MKTAG('H', '2', '6', '5'))
st->need_parsing = AVSTREAM_PARSE_FULL;
+ if (st->codecpar->codec_id == AV_CODEC_ID_AVRN &&
+ st->codecpar->codec_tag == MKTAG('A', 'V', 'R', 'n') &&
+ (st->codecpar->extradata_size < 31 ||
+ memcmp(&st->codecpar->extradata[28], "1:1", 3)))
+ st->codecpar->codec_id = AV_CODEC_ID_MJPEG;
+
if (st->codecpar->codec_tag == 0 && st->codecpar->height > 0 &&
st->codecpar->extradata_size < 1U << 30) {
st->codecpar->extradata_size += 9;
break;
case AVMEDIA_TYPE_SUBTITLE:
st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
- st->request_probe= 1;
+ st->internal->request_probe= 1;
avio_skip(pb, size);
break;
default:
av_log(s, AV_LOG_WARNING, "New extradata in strd chunk, freeing previous one.\n");
}
if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0)
- return ret;
+ goto fail;
}
if (st->codecpar->extradata_size & 1) //FIXME check if the encoder really did this correctly
avi->use_odml &&
read_odml_index(s, 0) < 0 &&
(s->error_recognition & AV_EF_EXPLODE))
- goto fail;
+ RETURN_ERROR(AVERROR_INVALIDDATA);
avio_seek(pb, pos + size, SEEK_SET);
break;
case MKTAG('v', 'p', 'r', 'p'):
avio_skip(pb, size);
break;
case MKTAG('s', 't', 'r', 'n'):
+ case MKTAG('i', 's', 'b', 'j'):
+ case MKTAG('i', 'n', 'a', 'm'):
+ case MKTAG('i', 'a', 'r', 't'):
+ case MKTAG('i', 'c', 'o', 'p'):
+ case MKTAG('i', 'c', 'm', 't'):
+ case MKTAG('i', 'g', 'n', 'r'):
+ case MKTAG('i', 'p', 'o', 'd'):
+ case MKTAG('i', 's', 'o', 'f'):
if (s->nb_streams) {
ret = avi_read_tag(s, s->streams[s->nb_streams - 1], tag, size);
if (ret < 0)
- return ret;
+ goto fail;
break;
}
default:
"I will ignore it and try to continue anyway.\n",
av_fourcc2str(tag), size);
if (s->error_recognition & AV_EF_EXPLODE)
- goto fail;
+ RETURN_ERROR(AVERROR_INVALIDDATA);
avi->movi_list = avio_tell(pb) - 4;
avi->movi_end = avi->fsize;
goto end_of_header;
end_of_header:
/* check stream number */
if (stream_index != s->nb_streams - 1) {
-
-fail:
- return AVERROR_INVALIDDATA;
+ RETURN_ERROR(AVERROR_INVALIDDATA);
}
if (!avi->index_loaded && (pb->seekable & AVIO_SEEKABLE_NORMAL))
avi->index_loaded |= 1;
if ((ret = guess_ni_flag(s)) < 0)
- return ret;
+ goto fail;
avi->non_interleaved |= ret | (s->flags & AVFMT_FLAG_SORT_DTS);
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
- if (st->nb_index_entries)
+ if (st->internal->nb_index_entries)
break;
}
// DV-in-AVI cannot be non-interleaved, if set this must be
ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);
return 0;
+fail:
+ avi_read_close(s);
+ return ret;
}
static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt)
uint8_t desc[256];
int score = AVPROBE_SCORE_EXTENSION, ret;
AVIStream *ast = st->priv_data;
- ff_const59 AVInputFormat *sub_demuxer;
+ const AVInputFormat *sub_demuxer;
AVRational time_base;
int size;
+ AVProbeData pd;
+ unsigned int desc_len;
AVIOContext *pb = avio_alloc_context(pkt->data + 7,
pkt->size - 7,
0, NULL, NULL, NULL, NULL);
- AVProbeData pd;
- unsigned int desc_len = avio_rl32(pb);
+ if (!pb)
+ goto error;
+
+ desc_len = avio_rl32(pb);
if (desc_len > pb->buf_end - pb->buf_ptr)
goto error;
if (strcmp(sub_demuxer->name, "srt") && strcmp(sub_demuxer->name, "ass"))
goto error;
+ if (!(ast->sub_pkt = av_packet_alloc()))
+ goto error;
+
if (!(ast->sub_ctx = avformat_alloc_context()))
goto error;
if (!avformat_open_input(&ast->sub_ctx, "", sub_demuxer, NULL)) {
if (ast->sub_ctx->nb_streams != 1)
goto error;
- ff_read_packet(ast->sub_ctx, &ast->sub_pkt);
+ ff_read_packet(ast->sub_ctx, ast->sub_pkt);
avcodec_parameters_copy(st->codecpar, ast->sub_ctx->streams[0]->codecpar);
time_base = ast->sub_ctx->streams[0]->time_base;
avpriv_set_pts_info(st, 64, time_base.num, time_base.den);
return 1;
error:
+ av_packet_free(&ast->sub_pkt);
av_freep(&ast->sub_ctx);
avio_context_free(&pb);
}
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
ast = st->priv_data;
- if (st->discard < AVDISCARD_ALL && ast && ast->sub_pkt.data) {
- ts = av_rescale_q(ast->sub_pkt.dts, st->time_base, AV_TIME_BASE_Q);
+ if (st->discard < AVDISCARD_ALL && ast && ast->sub_pkt && ast->sub_pkt->data) {
+ ts = av_rescale_q(ast->sub_pkt->dts, st->time_base, AV_TIME_BASE_Q);
if (ts <= next_ts && ts < ts_min) {
ts_min = ts;
sub_st = st;
if (sub_st) {
ast = sub_st->priv_data;
- *pkt = ast->sub_pkt;
+ av_packet_move_ref(pkt, ast->sub_pkt);
pkt->stream_index = sub_st->index;
- if (ff_read_packet(ast->sub_ctx, &ast->sub_pkt) < 0)
- ast->sub_pkt.data = NULL;
+ if (ff_read_packet(ast->sub_ctx, ast->sub_pkt) < 0)
+ ast->sub_pkt->data = NULL;
}
return sub_st;
}
AVStream *st1 = s->streams[1];
AVIStream *ast1 = st1->priv_data;
// workaround for broken small-file-bug402.avi
- if ( d[2] == 'w' && d[3] == 'b'
+ if (ast1 && d[2] == 'w' && d[3] == 'b'
&& n == 0
&& st ->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
&& st1->codecpar->codec_type == AVMEDIA_TYPE_AUDIO
if (size) {
uint64_t pos = avio_tell(pb) - 8;
- if (!st->index_entries || !st->nb_index_entries ||
- st->index_entries[st->nb_index_entries - 1].pos < pos) {
+ if (!st->internal->index_entries || !st->internal->nb_index_entries ||
+ st->internal->index_entries[st->internal->nb_index_entries - 1].pos < pos) {
av_add_index_entry(st, pos, ast->frame_offset, size,
0, AVINDEX_KEYFRAME);
}
int64_t ts = ast->frame_offset;
int64_t last_ts;
- if (!st->nb_index_entries)
+ if (!st->internal->nb_index_entries)
continue;
- last_ts = st->index_entries[st->nb_index_entries - 1].timestamp;
+ last_ts = st->internal->index_entries[st->internal->nb_index_entries - 1].timestamp;
if (!ast->remaining && ts > last_ts)
continue;
} else {
i = av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);
if (i >= 0)
- best_ast->frame_offset = best_st->index_entries[i].timestamp;
+ best_ast->frame_offset = best_st->internal->index_entries[i].timestamp;
}
if (i >= 0) {
- int64_t pos = best_st->index_entries[i].pos;
+ int64_t pos = best_st->internal->index_entries[i].pos;
pos += best_ast->packet_size - best_ast->remaining;
if (avio_seek(s->pb, pos + 8, SEEK_SET) < 0)
return AVERROR_EOF;
avi->stream_index = best_stream_index;
if (!best_ast->remaining)
best_ast->packet_size =
- best_ast->remaining = best_st->index_entries[i].size;
+ best_ast->remaining = best_st->internal->index_entries[i].size;
}
else
return AVERROR_EOF;
if (avi->stream_index >= 0) {
AVStream *st = s->streams[avi->stream_index];
AVIStream *ast = st->priv_data;
+ int dv_demux = CONFIG_DV_DEMUXER && avi->dv_demux;
int size, err;
if (get_subtitle_pkt(s, st, pkt))
return err;
size = err;
- if (ast->has_pal && pkt->size < (unsigned)INT_MAX / 2) {
+ if (ast->has_pal && pkt->size < (unsigned)INT_MAX / 2 && !dv_demux) {
uint8_t *pal;
pal = av_packet_new_side_data(pkt,
AV_PKT_DATA_PALETTE,
}
}
- if (CONFIG_DV_DEMUXER && avi->dv_demux) {
+ if (CONFIG_DV_DEMUXER && dv_demux) {
AVBufferRef *avbuf = pkt->buf;
size = avpriv_dv_produce_packet(avi->dv_demux, pkt,
pkt->data, pkt->size, pkt->pos);
pkt->dts /= ast->sample_size;
pkt->stream_index = avi->stream_index;
- if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->index_entries) {
+ if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->internal->index_entries) {
AVIndexEntry *e;
int index;
index = av_index_search_timestamp(st, ast->frame_offset, AVSEEK_FLAG_ANY);
- e = &st->index_entries[index];
+ e = &st->internal->index_entries[index];
if (index >= 0 && e->timestamp == ast->frame_offset) {
- if (index == st->nb_index_entries-1) {
+ if (index == st->internal->nb_index_entries-1) {
int key=1;
uint32_t state=-1;
if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
}
ast->seek_pos= 0;
- if (!avi->non_interleaved && st->nb_index_entries>1 && avi->index_loaded>1) {
+ if (!avi->non_interleaved && st->internal->nb_index_entries>1 && avi->index_loaded>1) {
int64_t dts= av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q);
if (avi->dts_max < dts) {
if (!anykey) {
for (index = 0; index < s->nb_streams; index++) {
st = s->streams[index];
- if (st->nb_index_entries)
- st->index_entries[0].flags |= AVINDEX_KEYFRAME;
+ if (st->internal->nb_index_entries)
+ st->internal->index_entries[0].flags |= AVINDEX_KEYFRAME;
}
}
return 0;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
AVIStream *ast = st->priv_data;
- int n = st->nb_index_entries;
- while (idx[i] < n && st->index_entries[idx[i]].pos < pos)
+ int n = st->internal->nb_index_entries;
+ while (idx[i] < n && st->internal->index_entries[idx[i]].pos < pos)
idx[i]++;
if (idx[i] < n) {
int64_t dts;
- dts = av_rescale_q(st->index_entries[idx[i]].timestamp /
+ dts = av_rescale_q(st->internal->index_entries[idx[i]].timestamp /
FFMAX(ast->sample_size, 1),
st->time_base, AV_TIME_BASE_Q);
min_dts = FFMIN(min_dts, dts);
- min_pos = FFMIN(min_pos, st->index_entries[idx[i]].pos);
+ min_pos = FFMIN(min_pos, st->internal->index_entries[idx[i]].pos);
}
}
for (i = 0; i < s->nb_streams; i++) {
AVIStream *ast = st->priv_data;
if (idx[i] && min_dts != INT64_MAX / 2) {
- int64_t dts;
- dts = av_rescale_q(st->index_entries[idx[i] - 1].timestamp /
+ int64_t dts, delta_dts;
+ dts = av_rescale_q(st->internal->index_entries[idx[i] - 1].timestamp /
FFMAX(ast->sample_size, 1),
st->time_base, AV_TIME_BASE_Q);
+ delta_dts = av_sat_sub64(dts, min_dts);
max_dts = FFMAX(max_dts, dts);
max_buffer = FFMAX(max_buffer,
- av_rescale(dts - min_dts,
+ av_rescale(delta_dts,
st->codecpar->bit_rate,
AV_TIME_BASE));
}
}
- if (max_dts - min_dts > 2 * AV_TIME_BASE ||
+ if (av_sat_sub64(max_dts, min_dts) > 2 * AV_TIME_BASE ||
max_buffer > 1024 * 1024 * 8 * 8) {
av_free(idx);
return 1;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
- int n = st->nb_index_entries;
+ int n = st->internal->nb_index_entries;
unsigned int size;
if (n <= 0)
continue;
if (n >= 2) {
- int64_t pos = st->index_entries[0].pos;
+ int64_t pos = st->internal->index_entries[0].pos;
unsigned tag[2];
avio_seek(s->pb, pos, SEEK_SET);
tag[0] = avio_r8(s->pb);
tag[1] = avio_r8(s->pb);
avio_rl16(s->pb);
size = avio_rl32(s->pb);
- if (get_stream_idx(tag) == i && pos + size > st->index_entries[1].pos)
+ if (get_stream_idx(tag) == i && pos + size > st->internal->index_entries[1].pos)
last_start = INT64_MAX;
- if (get_stream_idx(tag) == i && size == st->index_entries[0].size + 8)
+ if (get_stream_idx(tag) == i && size == st->internal->index_entries[0].size + 8)
last_start = INT64_MAX;
}
- if (st->index_entries[0].pos > last_start)
- last_start = st->index_entries[0].pos;
- if (st->index_entries[n - 1].pos < first_end)
- first_end = st->index_entries[n - 1].pos;
+ if (st->internal->index_entries[0].pos > last_start)
+ last_start = st->internal->index_entries[0].pos;
+ if (st->internal->index_entries[n - 1].pos < first_end)
+ first_end = st->internal->index_entries[n - 1].pos;
}
avio_seek(s->pb, oldpos, SEEK_SET);
{
AVIStream *ast2 = st2->priv_data;
int64_t ts2 = av_rescale_q(timestamp, st->time_base, st2->time_base);
- av_packet_unref(&ast2->sub_pkt);
+ av_packet_unref(ast2->sub_pkt);
if (avformat_seek_file(ast2->sub_ctx, 0, INT64_MIN, ts2, ts2, 0) >= 0 ||
avformat_seek_file(ast2->sub_ctx, 0, ts2, ts2, INT64_MAX, 0) >= 0)
- ff_read_packet(ast2->sub_ctx, &ast2->sub_pkt);
+ ff_read_packet(ast2->sub_ctx, ast2->sub_pkt);
}
static int avi_read_seek(AVFormatContext *s, int stream_index,
timestamp * FFMAX(ast->sample_size, 1),
flags);
if (index < 0) {
- if (st->nb_index_entries > 0)
+ if (st->internal->nb_index_entries > 0)
av_log(s, AV_LOG_DEBUG, "Failed to find timestamp %"PRId64 " in index %"PRId64 " .. %"PRId64 "\n",
timestamp * FFMAX(ast->sample_size, 1),
- st->index_entries[0].timestamp,
- st->index_entries[st->nb_index_entries - 1].timestamp);
+ st->internal->index_entries[0].timestamp,
+ st->internal->index_entries[st->internal->nb_index_entries - 1].timestamp);
return AVERROR_INVALIDDATA;
}
/* find the position */
- pos = st->index_entries[index].pos;
- timestamp = st->index_entries[index].timestamp / FFMAX(ast->sample_size, 1);
+ pos = st->internal->index_entries[index].pos;
+ timestamp = st->internal->index_entries[index].timestamp / FFMAX(ast->sample_size, 1);
av_log(s, AV_LOG_TRACE, "XX %"PRId64" %d %"PRId64"\n",
- timestamp, index, st->index_entries[index].timestamp);
+ timestamp, index, st->internal->index_entries[index].timestamp);
if (CONFIG_DV_DEMUXER && avi->dv_demux) {
/* One and only one real stream for DV in AVI, and it has video */
continue;
}
- if (st2->nb_index_entries <= 0)
+ if (st2->internal->nb_index_entries <= 0)
continue;
// av_assert1(st2->codecpar->block_align);
(st2->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
if (index < 0)
index = 0;
- ast2->seek_pos = st2->index_entries[index].pos;
+ ast2->seek_pos = st2->internal->index_entries[index].pos;
pos_min = FFMIN(pos_min,ast2->seek_pos);
}
for (i = 0; i < s->nb_streams; i++) {
AVStream *st2 = s->streams[i];
AVIStream *ast2 = st2->priv_data;
- if (ast2->sub_ctx || st2->nb_index_entries <= 0)
+ if (ast2->sub_ctx || st2->internal->nb_index_entries <= 0)
continue;
index = av_index_search_timestamp(
flags | AVSEEK_FLAG_BACKWARD | (st2->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
if (index < 0)
index = 0;
- while (!avi->non_interleaved && index>0 && st2->index_entries[index-1].pos >= pos_min)
+ while (!avi->non_interleaved && index>0 && st2->internal->index_entries[index-1].pos >= pos_min)
index--;
- ast2->frame_offset = st2->index_entries[index].timestamp;
+ ast2->frame_offset = st2->internal->index_entries[index].timestamp;
}
/* do the seek */
avformat_close_input(&ast->sub_ctx);
}
av_buffer_unref(&ast->sub_buffer);
- av_packet_unref(&ast->sub_pkt);
+ av_packet_free(&ast->sub_pkt);
}
}
return 0;
}
-AVInputFormat ff_avi_demuxer = {
+const AVInputFormat ff_avi_demuxer = {
.name = "avi",
.long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"),
.priv_data_size = sizeof(AVIContext),