int64_t audio_strm_offset;
int entry;
int ents_allocated;
+ int master_odml_riff_id_base;
AVIIentry** cluster;
} AVIIndex;
return 0;
}
+static void write_odml_master(AVFormatContext *s, int stream_index)
+{
+ AVIOContext *pb = s->pb;
+ AVStream *st = s->streams[stream_index];
+ AVCodecContext *enc = st->codec;
+ AVIStream *avist = st->priv_data;
+ unsigned char tag[5];
+ int j;
+
+ /* Starting to lay out AVI OpenDML master index.
+ * We want to make it JUNK entry for now, since we'd
+ * like to get away without making AVI an OpenDML one
+ * for compatibility reasons. */
+ avist->indexes.indx_start = ff_start_tag(pb, "JUNK");
+ avio_wl16(pb, 4); /* wLongsPerEntry */
+ avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */
+ avio_w8(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
+ avio_wl32(pb, 0); /* nEntriesInUse (will fill out later on) */
+ ffio_wfourcc(pb, avi_stream2fourcc(tag, stream_index, enc->codec_type));
+ /* dwChunkId */
+ avio_wl64(pb, 0); /* dwReserved[3] */
+ avio_wl32(pb, 0); /* Must be 0. */
+ for (j = 0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
+ avio_wl64(pb, 0);
+ ff_end_tag(pb, avist->indexes.indx_start);
+}
+
static int avi_write_header(AVFormatContext *s)
{
AVIContext *avi = s->priv_data;
}
if (pb->seekable) {
- unsigned char tag[5];
- int j;
-
- /* Starting to lay out AVI OpenDML master index.
- * We want to make it JUNK entry for now, since we'd
- * like to get away without making AVI an OpenDML one
- * for compatibility reasons. */
- avist->indexes.entry = avist->indexes.ents_allocated = 0;
- avist->indexes.indx_start = ff_start_tag(pb, "JUNK");
- avio_wl16(pb, 4); /* wLongsPerEntry */
- avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */
- avio_w8(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
- avio_wl32(pb, 0); /* nEntriesInUse (will fill out later on) */
- ffio_wfourcc(pb, avi_stream2fourcc(tag, i, enc->codec_type));
- /* dwChunkId */
- avio_wl64(pb, 0); /* dwReserved[3] */
- // avio_wl32(pb, 0); /* Must be 0. */
- for (j = 0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
- avio_wl64(pb, 0);
- ff_end_tag(pb, avist->indexes.indx_start);
+ write_odml_master(s, i);
}
if (enc->codec_type == AVMEDIA_TYPE_VIDEO &&
return 0;
}
+static void update_odml_entry(AVFormatContext *s, int stream_index, int64_t ix, int size)
+{
+ AVIOContext *pb = s->pb;
+ AVIContext *avi = s->priv_data;
+ AVIStream *avist = s->streams[stream_index]->priv_data;
+ int64_t pos;
+ int au_byterate, au_ssize, au_scale;
+
+ avio_flush(pb);
+ pos = avio_tell(pb);
+
+ /* Updating one entry in the AVI OpenDML master index */
+ avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET);
+ ffio_wfourcc(pb, "indx"); /* enabling this entry */
+ avio_skip(pb, 8);
+ avio_wl32(pb, avi->riff_id - avist->indexes.master_odml_riff_id_base); /* nEntriesInUse */
+ avio_skip(pb, 16 * (avi->riff_id - avist->indexes.master_odml_riff_id_base));
+ 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]->codec->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");
+ avist->sample_requested = 1;
+ }
+ avio_wl32(pb, audio_segm_size / au_ssize); /* dwDuration (sample count) */
+ } else
+ avio_wl32(pb, avist->indexes.entry); /* dwDuration (packet count) */
+
+ avio_seek(pb, pos, SEEK_SET);
+}
+
static int avi_write_ix(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
av_assert0(pb->seekable);
- if (avi->riff_id > AVI_MASTER_INDEX_SIZE) {
- 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) {
+ int64_t pos;
+ 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);
+ write_odml_master(s, i);
+ av_assert1(avio_tell(pb) - pos == size);
+ avist->indexes.master_odml_riff_id_base = avi->riff_id - 1;
+ }
+ av_assert0(avi->riff_id - avist->indexes.master_odml_riff_id_base < AVI_MASTER_INDEX_SIZE);
}
for (i = 0; i < s->nb_streams; i++) {
AVIStream *avist = s->streams[i]->priv_data;
- int64_t ix, pos;
- int au_byterate, au_ssize, au_scale;
+ int64_t ix;
avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type);
ix_tag[3] = '0' + i;
avio_wl32(pb, ((uint32_t) ie->len & ~0x80000000) |
(ie->flags & 0x10 ? 0 : 0x80000000));
}
- avio_flush(pb);
- pos = avio_tell(pb);
-
- /* Updating one entry in the AVI OpenDML master index */
- avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET);
- ffio_wfourcc(pb, "indx"); /* enabling this entry */
- avio_skip(pb, 8);
- avio_wl32(pb, avi->riff_id); /* nEntriesInUse */
- avio_skip(pb, 16 * avi->riff_id);
- avio_wl64(pb, ix); /* qwOffset */
- avio_wl32(pb, pos - ix); /* dwSize */
- ff_parse_specific_params(s->streams[i], &au_byterate, &au_ssize, &au_scale);
- if (s->streams[i]->codec->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");
- avist->sample_requested = 1;
- }
- avio_wl32(pb, audio_segm_size / au_ssize); /* dwDuration (sample count) */
- } else
- avio_wl32(pb, avist->indexes.entry); /* dwDuration (packet count) */
- avio_seek(pb, pos, SEEK_SET);
+ update_odml_entry(s, i, ix, avio_tell(pb) - ix);
}
return 0;
}