]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/avidec.c
avformat: Constify the API wrt AV(In|Out)putFormat
[ffmpeg] / libavformat / avidec.c
index bae9220a766313f1fa5f6d52ff02e18ff6973b36..ac020109c67511727924c97ae2e78f0c151c65c4 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
-#include "libavutil/bswap.h"
 #include "libavutil/opt.h"
 #include "libavutil/dict.h"
 #include "libavutil/internal.h"
@@ -60,8 +59,8 @@ typedef struct AVIStream {
                              * the MS dshow demuxer */
 
     AVFormatContext *sub_ctx;
-    AVPacket sub_pkt;
-    uint8_t *sub_buffer;
+    AVPacket *sub_pkt;
+    AVBufferRef *sub_buffer;
 
     int64_t seek_pos;
 } AVIStream;
@@ -111,14 +110,24 @@ static const char avi_headers[][8] = {
 
 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);
 
-#define print_tag(str, tag, size)                                      \
-    av_log(NULL, AV_LOG_TRACE, "pos:%"PRIX64" %s: tag=%s size=0x%x\n", \
+#define print_tag(s, str, tag, size)                                      \
+    av_log(s, AV_LOG_TRACE, "pos:%"PRIX64" %s: tag=%s size=0x%x\n", \
            avio_tell(pb), str, av_fourcc2str(tag), size)                  \
 
 static inline int get_duration(AVIStream *ast, int len)
@@ -126,7 +135,7 @@ static inline int get_duration(AVIStream *ast, int len)
     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;
 }
@@ -272,7 +281,7 @@ static void clean_index(AVFormatContext *s)
     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;
 
@@ -282,9 +291,9 @@ static void clean_index(AVFormatContext *s)
         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,
@@ -306,8 +315,10 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag,
     value = av_malloc(size + 1);
     if (!value)
         return AVERROR(ENOMEM);
-    if (avio_read(pb, value, size) != size)
+    if (avio_read(pb, value, size) != size) {
+        av_freep(&value);
         return AVERROR_INVALIDDATA;
+    }
     value[size] = 0;
 
     AV_WL32(key, tag);
@@ -430,15 +441,15 @@ static int calculate_bitrate(AVFormatContext *s)
         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 < avi->io_fsize*9/10) // index does not cover the whole file
+    if (maxpos < av_rescale(avi->io_fsize, 9, 10)) // index does not cover the whole file
         return 0;
     if (lensum*9/10 > maxpos || lensum < maxpos*9/10) // frame sum and filesize mismatch
         return 0;
@@ -449,20 +460,21 @@ static int calculate_bitrate(AVFormatContext *s)
         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 <= INT_MAX && bitrate > 0) {
+        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;
@@ -498,11 +510,11 @@ static int avi_read_header(AVFormatContext *s)
     frame_period = 0;
     for (;;) {
         if (avio_feof(pb))
-            goto fail;
+            RETURN_ERROR(AVERROR_INVALIDDATA);
         tag  = avio_rl32(pb);
         size = avio_rl32(pb);
 
-        print_tag("tag", tag, size);
+        print_tag(s, "tag", tag, size);
 
         switch (tag) {
         case MKTAG('L', 'I', 'S', 'T'):
@@ -510,7 +522,7 @@ static int avi_read_header(AVFormatContext *s)
             /* Ignored, except at start of video packets. */
             tag1 = avio_rl32(pb);
 
-            print_tag("list", tag1, 0);
+            print_tag(s, "list", tag1, 0);
 
             if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
                 avi->movi_list = avio_tell(pb) - 4;
@@ -518,7 +530,7 @@ static int avi_read_header(AVFormatContext *s)
                     avi->movi_end = avi->movi_list + size + (size & 1);
                 else
                     avi->movi_end = avi->fsize;
-                av_log(NULL, AV_LOG_TRACE, "movi end=%"PRIx64"\n", avi->movi_end);
+                av_log(s, AV_LOG_TRACE, "movi end=%"PRIx64"\n", avi->movi_end);
                 goto end_of_header;
             } else if (tag1 == MKTAG('I', 'N', 'F', 'O'))
                 ff_read_riff_info(s, size - 4);
@@ -570,19 +582,19 @@ static int avi_read_header(AVFormatContext *s)
                 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)
                 tag1 = stream_index ? MKTAG('a', 'u', 'd', 's')
                                     : MKTAG('v', 'i', 'd', 's');
 
-            print_tag("strh", tag1, -1);
+            print_tag(s, "strh", tag1, -1);
 
             if (tag1 == MKTAG('i', 'a', 'v', 's') ||
                 tag1 == MKTAG('i', 'v', 'a', 's')) {
@@ -591,35 +603,26 @@ static int avi_read_header(AVFormatContext *s)
                 /* 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;
 
                 ast = s->streams[0]->priv_data;
-                av_freep(&s->streams[0]->codecpar->extradata);
-                av_freep(&s->streams[0]->codecpar);
-#if FF_API_LAVF_AVCTX
-FF_DISABLE_DEPRECATION_WARNINGS
-                av_freep(&s->streams[0]->codec);
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
-                if (s->streams[0]->info)
-                    av_freep(&s->streams[0]->info->duration_error);
-                av_freep(&s->streams[0]->info);
-                if (s->streams[0]->internal)
-                    av_freep(&s->streams[0]->internal->avctx);
-                av_freep(&s->streams[0]->internal);
-                av_freep(&s->streams[0]);
-                s->nb_streams = 0;
-                if (CONFIG_DV_DEMUXER) {
-                    avi->dv_demux = avpriv_dv_init_demux(s);
-                    if (!avi->dv_demux)
-                        goto fail;
-                } else
-                    goto fail;
+                st->priv_data = NULL;
+                ff_free_stream(s, st);
+
+                avi->dv_demux = avpriv_dv_init_demux(s);
+                if (!avi->dv_demux) {
+                    av_free(ast);
+                    return AVERROR(ENOMEM);
+                }
+
                 s->streams[0]->priv_data = ast;
                 avio_skip(pb, 3 * 4);
                 ast->scale = avio_rl32(pb);
@@ -705,7 +708,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
                            "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 "
@@ -769,10 +772,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
                             st->codecpar->extradata_size =  size - 10 * 4;
                         if (st->codecpar->extradata) {
                             av_log(s, AV_LOG_WARNING, "New extradata in strf chunk, freeing previous one.\n");
-                            av_freep(&st->codecpar->extradata);
                         }
-                        if (ff_get_extradata(s, st->codecpar, pb, st->codecpar->extradata_size) < 0)
-                            return AVERROR(ENOMEM);
+                        ret = ff_get_extradata(s, st->codecpar, pb,
+                                               st->codecpar->extradata_size);
+                        if (ret < 0)
+                            return ret;
                     }
 
                     // FIXME: check if the encoder really did this correctly
@@ -800,7 +804,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
                         ast->has_pal = 1;
                     }
 
-                    print_tag("video", tag1, 0);
+                    print_tag(s, "video", tag1, 0);
 
                     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
                     st->codecpar->codec_tag  = tag1;
@@ -815,6 +819,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
                                   "mov tag found in avi (fourcc %s)\n",
                                   av_fourcc2str(tag1));
                     }
+                    if (!st->codecpar->codec_id)
+                        st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags_unofficial, tag1);
+
                     /* This is needed to get the pict type which is necessary
                      * for generating correct pts. */
                     st->need_parsing = AVSTREAM_PARSE_HEADERS;
@@ -827,6 +834,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
                         st->need_parsing = AVSTREAM_PARSE_FULL;
                     if (st->codecpar->codec_id == AV_CODEC_ID_RV40)
                         st->need_parsing = AVSTREAM_PARSE_NONE;
+                    if (st->codecpar->codec_id == AV_CODEC_ID_HEVC &&
+                        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) {
@@ -900,7 +916,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
                     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:
@@ -926,10 +942,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
                 if (size<(1<<30)) {
                     if (st->codecpar->extradata) {
                         av_log(s, AV_LOG_WARNING, "New extradata in strd chunk, freeing previous one.\n");
-                        av_freep(&st->codecpar->extradata);
                     }
-                    if (ff_get_extradata(s, st->codecpar, pb, size) < 0)
-                        return AVERROR(ENOMEM);
+                    if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0)
+                        goto fail;
                 }
 
                 if (st->codecpar->extradata_size & 1) //FIXME check if the encoder really did this correctly
@@ -947,7 +962,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
                 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'):
@@ -979,10 +994,18 @@ FF_ENABLE_DEPRECATION_WARNINGS
             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:
@@ -993,7 +1016,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
                        "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;
@@ -1010,9 +1033,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
 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))
@@ -1021,7 +1042,7 @@ fail:
     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);
 
@@ -1036,7 +1057,7 @@ fail:
 
     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
@@ -1058,6 +1079,9 @@ fail:
     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)
@@ -1068,14 +1092,18 @@ 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;
@@ -1102,6 +1130,9 @@ static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt)
         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;
 
@@ -1113,16 +1144,18 @@ static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt)
         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);
         }
-        ast->sub_buffer = pkt->data;
-        memset(pkt, 0, sizeof(*pkt));
+        ast->sub_buffer = pkt->buf;
+        pkt->buf = NULL;
+        av_packet_unref(pkt);
         return 1;
 
 error:
+        av_packet_free(&ast->sub_pkt);
         av_freep(&ast->sub_ctx);
         avio_context_free(&pb);
     }
@@ -1143,8 +1176,8 @@ static AVStream *get_subtitle_pkt(AVFormatContext *s, AVStream *next_st,
     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;
@@ -1154,11 +1187,11 @@ static AVStream *get_subtitle_pkt(AVFormatContext *s, AVStream *next_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;
 }
@@ -1255,7 +1288,7 @@ start_sync:
                 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
@@ -1314,8 +1347,8 @@ start_sync:
 
                 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);
                     }
@@ -1345,10 +1378,10 @@ static int ni_prepare_read(AVFormatContext *s)
         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;
 
@@ -1377,11 +1410,11 @@ static int ni_prepare_read(AVFormatContext *s)
     } 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;
@@ -1391,7 +1424,7 @@ static int ni_prepare_read(AVFormatContext *s)
         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;
@@ -1423,6 +1456,7 @@ resync:
     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))
@@ -1445,7 +1479,7 @@ resync:
             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,
@@ -1459,7 +1493,7 @@ resync:
             }
         }
 
-        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);
@@ -1481,15 +1515,15 @@ resync:
                 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) {
@@ -1525,14 +1559,15 @@ resync:
         }
         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 > 2*AV_TIME_BASE) {
+            if (avi->dts_max < dts) {
+                avi->dts_max = dts;
+            } else if (avi->dts_max - (uint64_t)dts > 2*AV_TIME_BASE) {
                 avi->non_interleaved= 1;
                 av_log(s, AV_LOG_INFO, "Switching to NI mode, due to poor interleaving\n");
-            }else if (avi->dts_max < dts)
-                avi->dts_max = dts;
+            }
         }
 
         return 0;
@@ -1624,8 +1659,8 @@ static int avi_read_idx1(AVFormatContext *s, int size)
     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;
@@ -1650,16 +1685,16 @@ static int check_stream_max_drift(AVFormatContext *s)
         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++) {
@@ -1667,18 +1702,19 @@ static int check_stream_max_drift(AVFormatContext *s)
             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;
@@ -1697,30 +1733,30 @@ static int guess_ni_flag(AVFormatContext *s)
 
     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);
 
@@ -1774,10 +1810,10 @@ static void seek_subtitle(AVStream *st, AVStream *st2, int64_t timestamp)
 {
     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,
@@ -1808,20 +1844,20 @@ 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  */
@@ -1852,7 +1888,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
             continue;
         }
 
-        if (st2->nb_index_entries <= 0)
+        if (st2->internal->nb_index_entries <= 0)
             continue;
 
 //        av_assert1(st2->codecpar->block_align);
@@ -1866,14 +1902,14 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
                                           (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(
@@ -1882,9 +1918,9 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
                 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 */
@@ -1910,8 +1946,8 @@ static int avi_read_close(AVFormatContext *s)
                 av_freep(&ast->sub_ctx->pb);
                 avformat_close_input(&ast->sub_ctx);
             }
-            av_freep(&ast->sub_buffer);
-            av_packet_unref(&ast->sub_pkt);
+            av_buffer_unref(&ast->sub_buffer);
+            av_packet_free(&ast->sub_pkt);
         }
     }