[FFmpeg-devel] [PATCH 1/3] avformat/avienc: write chained master index only if std_compliance is normal or below
Tobias Rapp
t.rapp at noa-archive.com
Mon Jan 9 10:56:50 EET 2017
OpenDML specification v1.02 states that entries of a master index chunk
shall point to standard or field index chunks.
Changed incorrect duration of last master index entry to -1 in case it
points to another master index.
Propagate error when index write fails.
Signed-off-by: Tobias Rapp <t.rapp at noa-archive.com>
---
libavformat/avienc.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index fd16fff..5d5c02a 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -524,7 +524,13 @@ static int avi_write_header(AVFormatContext *s)
return 0;
}
-static void update_odml_entry(AVFormatContext *s, int stream_index, int64_t ix, int size)
+/* Index entry points to standard index */
+#define AVI_UPDATE_ODML_ENTRY_DEFAULT 0x00000000
+
+/* Index entry points to another master index */
+#define AVI_UPDATE_ODML_ENTRY_MASTER 0x00000001
+
+static void update_odml_entry(AVFormatContext *s, int stream_index, int64_t ix, int size, int flags)
{
AVIOContext *pb = s->pb;
AVIContext *avi = s->priv_data;
@@ -544,7 +550,10 @@ static void update_odml_entry(AVFormatContext *s, int stream_index, int64_t ix,
avio_wl64(pb, ix); /* qwOffset */
avio_wl32(pb, size); /* dwSize */
ff_parse_specific_params(s->streams[stream_index], &au_byterate, &au_ssize, &au_scale);
- if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && au_ssize > 0) {
+ if (flags & AVI_UPDATE_ODML_ENTRY_MASTER) {
+ av_assert0(s->strict_std_compliance <= FF_COMPLIANCE_NORMAL);
+ avio_wl32(pb, -1); /* dwDuration (undefined) */
+ } else if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && au_ssize > 0) {
uint32_t audio_segm_size = (avist->audio_strm_length - avist->indexes.audio_strm_offset);
if ((audio_segm_size % au_ssize > 0) && !avist->sample_requested) {
avpriv_request_sample(s, "OpenDML index duration for audio packets with partial frames");
@@ -567,6 +576,12 @@ static int avi_write_ix(AVFormatContext *s)
av_assert0(pb->seekable);
+ if (avi->riff_id >= AVI_MASTER_INDEX_SIZE && s->strict_std_compliance > FF_COMPLIANCE_NORMAL) {
+ av_log(s, AV_LOG_ERROR, "Invalid riff index %d >= %d\n",
+ avi->riff_id, AVI_MASTER_INDEX_SIZE);
+ return AVERROR(EINVAL);
+ }
+
for (i = 0; i < s->nb_streams; i++) {
AVIStream *avist = s->streams[i]->priv_data;
if (avi->riff_id - avist->indexes.master_odml_riff_id_base == AVI_MASTER_INDEX_SIZE) {
@@ -574,7 +589,7 @@ static int avi_write_ix(AVFormatContext *s)
int size = 8+2+1+1+4+8+4+4+16*AVI_MASTER_INDEX_SIZE;
pos = avio_tell(pb);
- update_odml_entry(s, i, pos, size);
+ update_odml_entry(s, i, pos, size, AVI_UPDATE_ODML_ENTRY_MASTER);
write_odml_master(s, i);
av_assert1(avio_tell(pb) - pos == size);
avist->indexes.master_odml_riff_id_base = avi->riff_id - 1;
@@ -610,7 +625,7 @@ static int avi_write_ix(AVFormatContext *s)
(ie->flags & 0x10 ? 0 : 0x80000000));
}
- update_odml_entry(s, i, ix, avio_tell(pb) - ix);
+ update_odml_entry(s, i, ix, avio_tell(pb) - ix, AVI_UPDATE_ODML_ENTRY_DEFAULT);
}
return 0;
}
@@ -801,6 +816,7 @@ static int avi_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
AVIOContext *pb = s->pb;
AVIStream *avist = s->streams[stream_index]->priv_data;
AVCodecParameters *par = s->streams[stream_index]->codecpar;
+ int ret;
if (pkt->dts != AV_NOPTS_VALUE)
avist->last_dts = pkt->dts + pkt->duration;
@@ -810,7 +826,8 @@ static int avi_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
// Make sure to put an OpenDML chunk when the file size exceeds the limits
if (pb->seekable &&
(avio_tell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) {
- avi_write_ix(s);
+ if ((ret = avi_write_ix(s)) < 0)
+ return ret;
ff_end_tag(pb, avi->movi_list);
if (avi->riff_id == 1)
@@ -827,7 +844,6 @@ static int avi_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
avist->audio_strm_length += size;
if (s->pb->seekable) {
- int ret;
ret = avi_add_ientry(s, stream_index, NULL, flags, size);
if (ret < 0)
return ret;
@@ -861,7 +877,7 @@ static int avi_write_trailer(AVFormatContext *s)
res = avi_write_idx1(s);
ff_end_tag(pb, avi->riff_start);
} else {
- avi_write_ix(s);
+ res = avi_write_ix(s);
ff_end_tag(pb, avi->movi_list);
ff_end_tag(pb, avi->riff_start);
--
1.9.1
More information about the ffmpeg-devel
mailing list