[FFmpeg-devel] [PATCH 2/3] avformat/avienc: add reserve_index_space option

Tobias Rapp t.rapp at noa-archive.com
Mon Jan 9 10:56:51 EET 2017


Allows the user to reserve space for the ODML master index. A sufficient
sized master index in the AVI header avoids storing follow-up master
indexes within the 'movi' data later.

Signed-off-by: Tobias Rapp <t.rapp at noa-archive.com>
---
 libavformat/avi.h     |  1 -
 libavformat/avienc.c  | 36 +++++++++++++++++++++++++++++-------
 libavformat/version.h |  2 +-
 3 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/libavformat/avi.h b/libavformat/avi.h
index af21f2c..b1711f0 100644
--- a/libavformat/avi.h
+++ b/libavformat/avi.h
@@ -29,7 +29,6 @@
 #define AVIF_COPYRIGHTED        0x00020000
 
 #define AVI_MAX_RIFF_SIZE       0x40000000LL
-#define AVI_MASTER_INDEX_SIZE   256
 #define AVI_MAX_STREAM_COUNT    100
 
 /* stream header flags */
diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index 5d5c02a..faa86e1 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -51,6 +51,9 @@ typedef struct AVIIentry {
 } AVIIentry;
 
 #define AVI_INDEX_CLUSTER_SIZE 16384
+#define AVI_MASTER_INDEX_PREFIX_SIZE    (8+2+1+1+4+8+4+4)
+#define AVI_MASTER_INDEX_ENTRY_SIZE     16
+#define AVI_MASTER_INDEX_CLUSTER_SIZE   (AVI_MASTER_INDEX_PREFIX_SIZE + 256 * AVI_MASTER_INDEX_ENTRY_SIZE)
 
 typedef struct AVIIndex {
     int64_t     indx_start;
@@ -66,6 +69,8 @@ typedef struct AVIContext {
     int64_t riff_start, movi_list, odml_list;
     int64_t frames_hdr_all;
     int riff_id;
+    int reserve_index_space;
+    int master_index_max_size;
     int write_channel_mask;
 } AVIContext;
 
@@ -134,6 +139,20 @@ static int avi_add_ientry(AVFormatContext *s, int stream_index, char *tag,
     return 0;
 }
 
+static av_cold int avi_init(struct AVFormatContext *s)
+{
+    AVIContext *avi = s->priv_data;
+    const int reserve_index_space = (avi->reserve_index_space > 0) ?
+        avi->reserve_index_space : AVI_MASTER_INDEX_CLUSTER_SIZE;
+
+    avi->master_index_max_size = (reserve_index_space - AVI_MASTER_INDEX_PREFIX_SIZE) / AVI_MASTER_INDEX_ENTRY_SIZE;
+    avi->master_index_max_size = FFMAX(avi->master_index_max_size, 16);
+    av_log(s, AV_LOG_DEBUG, "reserve_index_space:%d master_index_max_size:%d\n",
+           avi->reserve_index_space, avi->master_index_max_size);
+
+    return 0;
+}
+
 static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb,
                                   const char *riff_tag, const char *list_tag)
 {
@@ -210,6 +229,7 @@ static int avi_write_counters(AVFormatContext *s, int riff_id)
 static void write_odml_master(AVFormatContext *s, int stream_index)
 {
     AVIOContext *pb = s->pb;
+    AVIContext *avi = s->priv_data;
     AVStream *st = s->streams[stream_index];
     AVCodecParameters *par = st->codecpar;
     AVIStream *avist = st->priv_data;
@@ -229,7 +249,7 @@ static void write_odml_master(AVFormatContext *s, int stream_index)
                         /* dwChunkId */
     avio_wl64(pb, 0);   /* dwReserved[3] */
     avio_wl32(pb, 0);   /* Must be 0.    */
-    for (j = 0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
+    for (j = 0; j < avi->master_index_max_size * 2; j++)
         avio_wl64(pb, 0);
     ff_end_tag(pb, avist->indexes.indx_start);
 }
@@ -576,17 +596,17 @@ 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);
+    if (avi->riff_id >= avi->master_index_max_size && s->strict_std_compliance > FF_COMPLIANCE_NORMAL) {
+        av_log(s, AV_LOG_ERROR, "Invalid riff index %d >= %d, consider increasing the 'reserve_index_space' option value\n",
+               avi->riff_id, avi->master_index_max_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) {
+        if (avi->riff_id - avist->indexes.master_odml_riff_id_base == avi->master_index_max_size) {
             int64_t pos;
-            int size = 8+2+1+1+4+8+4+4+16*AVI_MASTER_INDEX_SIZE;
+            int size = AVI_MASTER_INDEX_PREFIX_SIZE + AVI_MASTER_INDEX_ENTRY_SIZE * avi->master_index_max_size;
 
             pos = avio_tell(pb);
             update_odml_entry(s, i, pos, size, AVI_UPDATE_ODML_ENTRY_MASTER);
@@ -594,7 +614,7 @@ static int avi_write_ix(AVFormatContext *s)
             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);
+        av_assert0(avi->riff_id - avist->indexes.master_odml_riff_id_base < avi->master_index_max_size);
     }
 
     for (i = 0; i < s->nb_streams; i++) {
@@ -924,6 +944,7 @@ static int avi_write_trailer(AVFormatContext *s)
 #define OFFSET(x) offsetof(AVIContext, x)
 #define ENC AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
+    { "reserve_index_space", "reserve space (in bytes) at the beginning of the file for each stream index", OFFSET(reserve_index_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, ENC },
     { "write_channel_mask", "write channel mask into wave format header", OFFSET(write_channel_mask), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC },
     { NULL },
 };
@@ -943,6 +964,7 @@ AVOutputFormat ff_avi_muxer = {
     .priv_data_size = sizeof(AVIContext),
     .audio_codec    = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3,
     .video_codec    = AV_CODEC_ID_MPEG4,
+    .init           = avi_init,
     .write_header   = avi_write_header,
     .write_packet   = avi_write_packet,
     .write_trailer  = avi_write_trailer,
diff --git a/libavformat/version.h b/libavformat/version.h
index 21cc8a9..70c8467 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -33,7 +33,7 @@
 // Also please add any ticket numbers that you believe might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  57
 #define LIBAVFORMAT_VERSION_MINOR  62
-#define LIBAVFORMAT_VERSION_MICRO 100
+#define LIBAVFORMAT_VERSION_MICRO 101
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \
-- 
1.9.1




More information about the ffmpeg-devel mailing list