avformat/avienc: factor frame skip code out
[ffmpeg.git] / libavformat / avienc.c
1 /*
2  * AVI muxer
3  * Copyright (c) 2000 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 //#define DEBUG
23
24 #include "avformat.h"
25 #include "internal.h"
26 #include "avi.h"
27 #include "avio_internal.h"
28 #include "riff.h"
29 #include "mpegts.h"
30 #include "libavformat/avlanguage.h"
31 #include "libavutil/avstring.h"
32 #include "libavutil/intreadwrite.h"
33 #include "libavutil/dict.h"
34 #include "libavutil/avassert.h"
35 #include "libavutil/timestamp.h"
36 #include "libavutil/pixdesc.h"
37 #include "libavcodec/raw.h"
38
39 /*
40  * TODO:
41  *  - fill all fields if non streamed (nb_frames for example)
42  */
43
44 typedef struct AVIIentry {
45     unsigned int flags, pos, len;
46 } AVIIentry;
47
48 #define AVI_INDEX_CLUSTER_SIZE 16384
49
50 typedef struct AVIIndex {
51     int64_t     indx_start;
52     int         entry;
53     int         ents_allocated;
54     AVIIentry** cluster;
55 } AVIIndex;
56
57 typedef struct {
58     int64_t riff_start, movi_list, odml_list;
59     int64_t frames_hdr_all;
60     int riff_id;
61 } AVIContext;
62
63 typedef struct  {
64     int64_t frames_hdr_strm;
65     int64_t audio_strm_length;
66     int packet_count;
67     int entry;
68     int max_size;
69
70     AVIIndex indexes;
71 } AVIStream;
72
73 static int avi_write_packet(AVFormatContext *s, AVPacket *pkt);
74
75 static inline AVIIentry *avi_get_ientry(const AVIIndex *idx, int ent_id)
76 {
77     int cl = ent_id / AVI_INDEX_CLUSTER_SIZE;
78     int id = ent_id % AVI_INDEX_CLUSTER_SIZE;
79     return &idx->cluster[cl][id];
80 }
81
82 static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb,
83                                   const char *riff_tag, const char *list_tag)
84 {
85     AVIContext *avi = s->priv_data;
86     int64_t loff;
87     int i;
88
89     avi->riff_id++;
90     for (i = 0; i < s->nb_streams; i++) {
91         AVIStream *avist = s->streams[i]->priv_data;
92         avist->indexes.entry = 0;
93     }
94
95     avi->riff_start = ff_start_tag(pb, "RIFF");
96     ffio_wfourcc(pb, riff_tag);
97     loff = ff_start_tag(pb, "LIST");
98     ffio_wfourcc(pb, list_tag);
99     return loff;
100 }
101
102 static char *avi_stream2fourcc(char *tag, int index, enum AVMediaType type)
103 {
104     tag[0] = '0' + index / 10;
105     tag[1] = '0' + index % 10;
106     if (type == AVMEDIA_TYPE_VIDEO) {
107         tag[2] = 'd';
108         tag[3] = 'c';
109     } else if (type == AVMEDIA_TYPE_SUBTITLE) {
110         // note: this is not an official code
111         tag[2] = 's';
112         tag[3] = 'b';
113     } else {
114         tag[2] = 'w';
115         tag[3] = 'b';
116     }
117     tag[4] = '\0';
118     return tag;
119 }
120
121 static int avi_write_counters(AVFormatContext *s, int riff_id)
122 {
123     AVIOContext *pb = s->pb;
124     AVIContext *avi = s->priv_data;
125     int n, au_byterate, au_ssize, au_scale, nb_frames = 0;
126     int64_t file_size;
127     AVCodecContext *stream;
128
129     file_size = avio_tell(pb);
130     for (n = 0; n < s->nb_streams; n++) {
131         AVIStream *avist = s->streams[n]->priv_data;
132
133         av_assert0(avist->frames_hdr_strm);
134         stream = s->streams[n]->codec;
135         avio_seek(pb, avist->frames_hdr_strm, SEEK_SET);
136         ff_parse_specific_params(s->streams[n], &au_byterate, &au_ssize, &au_scale);
137         if (au_ssize == 0)
138             avio_wl32(pb, avist->packet_count);
139         else
140             avio_wl32(pb, avist->audio_strm_length / au_ssize);
141         if (stream->codec_type == AVMEDIA_TYPE_VIDEO)
142             nb_frames = FFMAX(nb_frames, avist->packet_count);
143     }
144     if (riff_id == 1) {
145         av_assert0(avi->frames_hdr_all);
146         avio_seek(pb, avi->frames_hdr_all, SEEK_SET);
147         avio_wl32(pb, nb_frames);
148     }
149     avio_seek(pb, file_size, SEEK_SET);
150
151     return 0;
152 }
153
154 static int avi_write_header(AVFormatContext *s)
155 {
156     AVIContext *avi = s->priv_data;
157     AVIOContext *pb = s->pb;
158     int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale;
159     AVCodecContext *video_enc;
160     AVStream *video_st = NULL;
161     int64_t list1, list2, strh, strf;
162     AVDictionaryEntry *t = NULL;
163     int padding;
164
165     if (s->nb_streams > AVI_MAX_STREAM_COUNT) {
166         av_log(s, AV_LOG_ERROR, "AVI does not support >%d streams\n",
167                AVI_MAX_STREAM_COUNT);
168         return AVERROR(EINVAL);
169     }
170
171     for (n = 0; n < s->nb_streams; n++) {
172         s->streams[n]->priv_data = av_mallocz(sizeof(AVIStream));
173         if (!s->streams[n]->priv_data)
174             return AVERROR(ENOMEM);
175     }
176
177     /* header list */
178     avi->riff_id = 0;
179     list1 = avi_start_new_riff(s, pb, "AVI ", "hdrl");
180
181     /* avi header */
182     ffio_wfourcc(pb, "avih");
183     avio_wl32(pb, 14 * 4);
184     bitrate = 0;
185
186     video_enc = NULL;
187     for (n = 0; n < s->nb_streams; n++) {
188         AVCodecContext *codec = s->streams[n]->codec;
189         bitrate += codec->bit_rate;
190         if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
191             video_enc = codec;
192             video_st = s->streams[n];
193         }
194     }
195
196     nb_frames = 0;
197
198     // TODO: should be avg_frame_rate
199     if (video_st)
200         avio_wl32(pb, (uint32_t) (INT64_C(1000000) * video_st->time_base.num /
201                                   video_st->time_base.den));
202     else
203         avio_wl32(pb, 0);
204     avio_wl32(pb, bitrate / 8); /* XXX: not quite exact */
205     avio_wl32(pb, 0); /* padding */
206     if (!pb->seekable)
207         avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED);  /* flags */
208     else
209         avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED);  /* flags */
210     avi->frames_hdr_all = avio_tell(pb); /* remember this offset to fill later */
211     avio_wl32(pb, nb_frames); /* nb frames, filled later */
212     avio_wl32(pb, 0); /* initial frame */
213     avio_wl32(pb, s->nb_streams); /* nb streams */
214     avio_wl32(pb, 1024 * 1024); /* suggested buffer size */
215     if (video_enc) {
216         avio_wl32(pb, video_enc->width);
217         avio_wl32(pb, video_enc->height);
218     } else {
219         avio_wl32(pb, 0);
220         avio_wl32(pb, 0);
221     }
222     avio_wl32(pb, 0); /* reserved */
223     avio_wl32(pb, 0); /* reserved */
224     avio_wl32(pb, 0); /* reserved */
225     avio_wl32(pb, 0); /* reserved */
226
227     /* stream list */
228     for (i = 0; i < n; i++) {
229         AVStream *st = s->streams[i];
230         AVCodecContext *enc = st->codec;
231         AVIStream *avist = st->priv_data;
232         list2 = ff_start_tag(pb, "LIST");
233         ffio_wfourcc(pb, "strl");
234
235         /* stream generic header */
236         strh = ff_start_tag(pb, "strh");
237         switch (enc->codec_type) {
238         case AVMEDIA_TYPE_SUBTITLE:
239             // XSUB subtitles behave like video tracks, other subtitles
240             // are not (yet) supported.
241             if (enc->codec_id != AV_CODEC_ID_XSUB) {
242                 av_log(s, AV_LOG_ERROR,
243                        "Subtitle streams other than DivX XSUB are not supported by the AVI muxer.\n");
244                 return AVERROR_PATCHWELCOME;
245             }
246         case AVMEDIA_TYPE_VIDEO:
247             ffio_wfourcc(pb, "vids");
248             break;
249         case AVMEDIA_TYPE_AUDIO:
250             ffio_wfourcc(pb, "auds");
251             break;
252 //      case AVMEDIA_TYPE_TEXT:
253 //          ffio_wfourcc(pb, "txts");
254 //          break;
255         case AVMEDIA_TYPE_DATA:
256             ffio_wfourcc(pb, "dats");
257             break;
258         }
259         if (enc->codec_type == AVMEDIA_TYPE_VIDEO ||
260             enc->codec_id == AV_CODEC_ID_XSUB)
261             avio_wl32(pb, enc->codec_tag);
262         else
263             avio_wl32(pb, 1);
264         avio_wl32(pb, 0); /* flags */
265         avio_wl16(pb, 0); /* priority */
266         avio_wl16(pb, 0); /* language */
267         avio_wl32(pb, 0); /* initial frame */
268
269         ff_parse_specific_params(st, &au_byterate, &au_ssize, &au_scale);
270
271         if (   enc->codec_type == AVMEDIA_TYPE_VIDEO
272             && enc->codec_id != AV_CODEC_ID_XSUB
273             && au_byterate > 1000LL*au_scale) {
274             au_byterate = 600;
275             au_scale    = 1;
276         }
277         avpriv_set_pts_info(st, 64, au_scale, au_byterate);
278         if (enc->codec_id == AV_CODEC_ID_XSUB)
279             au_scale = au_byterate = 0;
280
281         avio_wl32(pb, au_scale); /* scale */
282         avio_wl32(pb, au_byterate); /* rate */
283
284         avio_wl32(pb, 0); /* start */
285         /* remember this offset to fill later */
286         avist->frames_hdr_strm = avio_tell(pb);
287         if (!pb->seekable)
288             /* FIXME: this may be broken, but who cares */
289             avio_wl32(pb, AVI_MAX_RIFF_SIZE);
290         else
291             avio_wl32(pb, 0);  /* length, XXX: filled later */
292
293         /* suggested buffer size, is set to largest chunk size in avi_write_trailer */
294         if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
295             avio_wl32(pb, 1024 * 1024);
296         else if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
297             avio_wl32(pb, 12 * 1024);
298         else
299             avio_wl32(pb, 0);
300         avio_wl32(pb, -1); /* quality */
301         avio_wl32(pb, au_ssize); /* sample size */
302         avio_wl32(pb, 0);
303         avio_wl16(pb, enc->width);
304         avio_wl16(pb, enc->height);
305         ff_end_tag(pb, strh);
306
307         if (enc->codec_type != AVMEDIA_TYPE_DATA) {
308             int ret;
309             enum AVPixelFormat pix_fmt;
310
311             strf = ff_start_tag(pb, "strf");
312             switch (enc->codec_type) {
313             case AVMEDIA_TYPE_SUBTITLE:
314                 /* XSUB subtitles behave like video tracks, other subtitles
315                  * are not (yet) supported. */
316                 if (enc->codec_id != AV_CODEC_ID_XSUB)
317                     break;
318             case AVMEDIA_TYPE_VIDEO:
319                 /* WMP expects RGB 5:5:5 rawvideo in avi to have bpp set to 16. */
320                 if (  !enc->codec_tag
321                     && enc->codec_id == AV_CODEC_ID_RAWVIDEO
322                     && enc->pix_fmt == AV_PIX_FMT_RGB555LE
323                     && enc->bits_per_coded_sample == 15)
324                     enc->bits_per_coded_sample = 16;
325                 ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 0, 0);
326                 pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi,
327                                               enc->bits_per_coded_sample);
328                 if (   !enc->codec_tag
329                     && enc->codec_id == AV_CODEC_ID_RAWVIDEO
330                     && enc->pix_fmt != pix_fmt
331                     && enc->pix_fmt != AV_PIX_FMT_NONE)
332                     av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to avi, output file will be unreadable\n",
333                           av_get_pix_fmt_name(enc->pix_fmt));
334                 break;
335             case AVMEDIA_TYPE_AUDIO:
336                 if ((ret = ff_put_wav_header(pb, enc, 0)) < 0)
337                     return ret;
338                 break;
339             default:
340                 av_log(s, AV_LOG_ERROR,
341                     "Invalid or not supported codec type '%s' found in the input\n",
342                     (char *)av_x_if_null(av_get_media_type_string(enc->codec_type), "?"));
343                 return AVERROR(EINVAL);
344             }
345             ff_end_tag(pb, strf);
346             if ((t = av_dict_get(st->metadata, "title", NULL, 0))) {
347                 ff_riff_write_info_tag(s->pb, "strn", t->value);
348                 t = NULL;
349             }
350             if (enc->codec_id == AV_CODEC_ID_XSUB
351             && (t = av_dict_get(s->streams[i]->metadata, "language", NULL, 0))) {
352                 const char* langstr = av_convert_lang_to(t->value, AV_LANG_ISO639_1);
353                 t = NULL;
354                 if (langstr) {
355                     char* str = av_asprintf("Subtitle - %s-xx;02", langstr);
356                     ff_riff_write_info_tag(s->pb, "strn", str);
357                     av_free(str);
358                 }
359             }
360         }
361
362         if (pb->seekable) {
363             unsigned char tag[5];
364             int j;
365
366             /* Starting to lay out AVI OpenDML master index.
367              * We want to make it JUNK entry for now, since we'd
368              * like to get away without making AVI an OpenDML one
369              * for compatibility reasons. */
370             avist->indexes.entry      = avist->indexes.ents_allocated = 0;
371             avist->indexes.indx_start = ff_start_tag(pb, "JUNK");
372             avio_wl16(pb, 4);   /* wLongsPerEntry */
373             avio_w8(pb, 0);     /* bIndexSubType (0 == frame index) */
374             avio_w8(pb, 0);     /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
375             avio_wl32(pb, 0);   /* nEntriesInUse (will fill out later on) */
376             ffio_wfourcc(pb, avi_stream2fourcc(tag, i, enc->codec_type));
377                                 /* dwChunkId */
378             avio_wl64(pb, 0);   /* dwReserved[3] */
379             // avio_wl32(pb, 0);   /* Must be 0.    */
380             for (j = 0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
381                 avio_wl64(pb, 0);
382             ff_end_tag(pb, avist->indexes.indx_start);
383         }
384
385         if (enc->codec_type == AVMEDIA_TYPE_VIDEO   &&
386             st->sample_aspect_ratio.num > 0 &&
387             st->sample_aspect_ratio.den > 0) {
388             int vprp       = ff_start_tag(pb, "vprp");
389             AVRational dar = av_mul_q(st->sample_aspect_ratio,
390                                       (AVRational) { enc->width,
391                                                      enc->height });
392             int num, den;
393             av_reduce(&num, &den, dar.num, dar.den, 0xFFFF);
394
395             avio_wl32(pb, 0); // video format   = unknown
396             avio_wl32(pb, 0); // video standard = unknown
397             // TODO: should be avg_frame_rate
398             avio_wl32(pb, lrintf(1.0 / av_q2d(st->time_base)));
399             avio_wl32(pb, enc->width);
400             avio_wl32(pb, enc->height);
401             avio_wl16(pb, den);
402             avio_wl16(pb, num);
403             avio_wl32(pb, enc->width);
404             avio_wl32(pb, enc->height);
405             avio_wl32(pb, 1); // progressive FIXME
406
407             avio_wl32(pb, enc->height);
408             avio_wl32(pb, enc->width);
409             avio_wl32(pb, enc->height);
410             avio_wl32(pb, enc->width);
411             avio_wl32(pb, 0);
412             avio_wl32(pb, 0);
413
414             avio_wl32(pb, 0);
415             avio_wl32(pb, 0);
416             ff_end_tag(pb, vprp);
417         }
418
419         ff_end_tag(pb, list2);
420     }
421
422     if (pb->seekable) {
423         /* AVI could become an OpenDML one, if it grows beyond 2Gb range */
424         avi->odml_list = ff_start_tag(pb, "JUNK");
425         ffio_wfourcc(pb, "odml");
426         ffio_wfourcc(pb, "dmlh");
427         avio_wl32(pb, 248);
428         for (i = 0; i < 248; i += 4)
429             avio_wl32(pb, 0);
430         ff_end_tag(pb, avi->odml_list);
431     }
432
433     ff_end_tag(pb, list1);
434
435     ff_riff_write_info(s);
436
437
438     padding = s->metadata_header_padding;
439     if (padding < 0)
440         padding = 1016;
441
442     /* some padding for easier tag editing */
443     if (padding) {
444         list2 = ff_start_tag(pb, "JUNK");
445         for (i = padding; i > 0; i -= 4)
446             avio_wl32(pb, 0);
447         ff_end_tag(pb, list2);
448     }
449
450     avi->movi_list = ff_start_tag(pb, "LIST");
451     ffio_wfourcc(pb, "movi");
452
453     avio_flush(pb);
454
455     return 0;
456 }
457
458 static int avi_write_ix(AVFormatContext *s)
459 {
460     AVIOContext *pb = s->pb;
461     AVIContext *avi = s->priv_data;
462     char tag[5];
463     char ix_tag[] = "ix00";
464     int i, j;
465
466     av_assert0(pb->seekable);
467
468     if (avi->riff_id > AVI_MASTER_INDEX_SIZE) {
469         av_log(s, AV_LOG_ERROR, "Invalid riff index %d > %d\n",
470                avi->riff_id, AVI_MASTER_INDEX_SIZE);
471         return AVERROR(EINVAL);
472     }
473
474     for (i = 0; i < s->nb_streams; i++) {
475         AVIStream *avist = s->streams[i]->priv_data;
476         int64_t ix, pos;
477
478         avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type);
479         ix_tag[3] = '0' + i;
480
481         /* Writing AVI OpenDML leaf index chunk */
482         ix = avio_tell(pb);
483         ffio_wfourcc(pb, ix_tag);      /* ix?? */
484         avio_wl32(pb, avist->indexes.entry * 8 + 24);
485         /* chunk size */
486         avio_wl16(pb, 2);           /* wLongsPerEntry */
487         avio_w8(pb, 0);             /* bIndexSubType (0 == frame index) */
488         avio_w8(pb, 1);             /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */
489         avio_wl32(pb, avist->indexes.entry);
490         /* nEntriesInUse */
491         ffio_wfourcc(pb, tag);         /* dwChunkId */
492         avio_wl64(pb, avi->movi_list); /* qwBaseOffset */
493         avio_wl32(pb, 0);              /* dwReserved_3 (must be 0) */
494
495         for (j = 0; j < avist->indexes.entry; j++) {
496             AVIIentry *ie = avi_get_ientry(&avist->indexes, j);
497             avio_wl32(pb, ie->pos + 8);
498             avio_wl32(pb, ((uint32_t) ie->len & ~0x80000000) |
499                           (ie->flags & 0x10 ? 0 : 0x80000000));
500         }
501         avio_flush(pb);
502         pos = avio_tell(pb);
503
504         /* Updating one entry in the AVI OpenDML master index */
505         avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET);
506         ffio_wfourcc(pb, "indx");             /* enabling this entry */
507         avio_skip(pb, 8);
508         avio_wl32(pb, avi->riff_id);          /* nEntriesInUse */
509         avio_skip(pb, 16 * avi->riff_id);
510         avio_wl64(pb, ix);                    /* qwOffset */
511         avio_wl32(pb, pos - ix);              /* dwSize */
512         avio_wl32(pb, avist->indexes.entry);  /* dwDuration */
513
514         avio_seek(pb, pos, SEEK_SET);
515     }
516     return 0;
517 }
518
519 static int avi_write_idx1(AVFormatContext *s)
520 {
521     AVIOContext *pb = s->pb;
522     AVIContext *avi = s->priv_data;
523     int64_t idx_chunk;
524     int i;
525     char tag[5];
526
527     if (pb->seekable) {
528         AVIStream *avist;
529         AVIIentry *ie = 0, *tie;
530         int empty, stream_id = -1;
531
532         idx_chunk = ff_start_tag(pb, "idx1");
533         for (i = 0; i < s->nb_streams; i++) {
534             avist        = s->streams[i]->priv_data;
535             avist->entry = 0;
536         }
537
538         do {
539             empty = 1;
540             for (i = 0; i < s->nb_streams; i++) {
541                 avist = s->streams[i]->priv_data;
542                 if (avist->indexes.entry <= avist->entry)
543                     continue;
544
545                 tie = avi_get_ientry(&avist->indexes, avist->entry);
546                 if (empty || tie->pos < ie->pos) {
547                     ie        = tie;
548                     stream_id = i;
549                 }
550                 empty = 0;
551             }
552             if (!empty) {
553                 avist = s->streams[stream_id]->priv_data;
554                 avi_stream2fourcc(tag, stream_id,
555                                   s->streams[stream_id]->codec->codec_type);
556                 ffio_wfourcc(pb, tag);
557                 avio_wl32(pb, ie->flags);
558                 avio_wl32(pb, ie->pos);
559                 avio_wl32(pb, ie->len);
560                 avist->entry++;
561             }
562         } while (!empty);
563         ff_end_tag(pb, idx_chunk);
564
565         avi_write_counters(s, avi->riff_id);
566     }
567     return 0;
568 }
569
570 static int write_skip_frames(AVFormatContext *s, int stream_index, int64_t dts)
571 {
572     AVIStream *avist    = s->streams[stream_index]->priv_data;
573     AVCodecContext *enc = s->streams[stream_index]->codec;
574
575     av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(dts), avist->packet_count, stream_index);
576     while (enc->block_align == 0 && dts != AV_NOPTS_VALUE &&
577            dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) {
578         AVPacket empty_packet;
579
580         if (dts - avist->packet_count > 60000) {
581             av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", dts - avist->packet_count);
582             return AVERROR(EINVAL);
583         }
584
585         av_init_packet(&empty_packet);
586         empty_packet.size         = 0;
587         empty_packet.data         = NULL;
588         empty_packet.stream_index = stream_index;
589         avi_write_packet(s, &empty_packet);
590         av_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(dts), avist->packet_count);
591     }
592
593     return 0;
594 }
595
596 static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
597 {
598     unsigned char tag[5];
599     unsigned int flags = 0;
600     const int stream_index = pkt->stream_index;
601     int size               = pkt->size;
602     AVIContext *avi     = s->priv_data;
603     AVIOContext *pb     = s->pb;
604     AVIStream *avist    = s->streams[stream_index]->priv_data;
605     AVCodecContext *enc = s->streams[stream_index]->codec;
606     int ret;
607
608     if (enc->codec_id == AV_CODEC_ID_H264 && enc->codec_tag == MKTAG('H','2','6','4') && pkt->size) {
609         ret = ff_check_h264_startcode(s, s->streams[stream_index], pkt);
610         if (ret < 0)
611             return ret;
612     }
613
614     if ((ret = write_skip_frames(s, stream_index, pkt->dts)) < 0)
615         return ret;
616
617     avist->packet_count++;
618
619     // Make sure to put an OpenDML chunk when the file size exceeds the limits
620     if (pb->seekable &&
621         (avio_tell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) {
622         avi_write_ix(s);
623         ff_end_tag(pb, avi->movi_list);
624
625         if (avi->riff_id == 1)
626             avi_write_idx1(s);
627
628         ff_end_tag(pb, avi->riff_start);
629         avi->movi_list = avi_start_new_riff(s, pb, "AVIX", "movi");
630     }
631
632     avi_stream2fourcc(tag, stream_index, enc->codec_type);
633     if (pkt->flags & AV_PKT_FLAG_KEY)
634         flags = 0x10;
635     if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
636         avist->audio_strm_length += size;
637
638     if (s->pb->seekable) {
639         AVIIndex *idx = &avist->indexes;
640         int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
641         int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
642         if (idx->ents_allocated <= idx->entry) {
643             idx->cluster = av_realloc_f(idx->cluster, sizeof(void*), cl+1);
644             if (!idx->cluster) {
645                 idx->ents_allocated = 0;
646                 idx->entry          = 0;
647                 return AVERROR(ENOMEM);
648             }
649             idx->cluster[cl] =
650                 av_malloc(AVI_INDEX_CLUSTER_SIZE * sizeof(AVIIentry));
651             if (!idx->cluster[cl])
652                 return AVERROR(ENOMEM);
653             idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
654         }
655
656         idx->cluster[cl][id].flags = flags;
657         idx->cluster[cl][id].pos   = avio_tell(pb) - avi->movi_list;
658         idx->cluster[cl][id].len   = size;
659         avist->max_size = FFMAX(avist->max_size, size);
660         idx->entry++;
661     }
662
663     avio_write(pb, tag, 4);
664     avio_wl32(pb, size);
665     avio_write(pb, pkt->data, size);
666     if (size & 1)
667         avio_w8(pb, 0);
668
669     return 0;
670 }
671
672 static int avi_write_trailer(AVFormatContext *s)
673 {
674     AVIContext *avi = s->priv_data;
675     AVIOContext *pb = s->pb;
676     int res = 0;
677     int i, j, n, nb_frames;
678     int64_t file_size;
679
680     if (pb->seekable) {
681         if (avi->riff_id == 1) {
682             ff_end_tag(pb, avi->movi_list);
683             res = avi_write_idx1(s);
684             ff_end_tag(pb, avi->riff_start);
685         } else {
686             avi_write_ix(s);
687             ff_end_tag(pb, avi->movi_list);
688             ff_end_tag(pb, avi->riff_start);
689
690             file_size = avio_tell(pb);
691             avio_seek(pb, avi->odml_list - 8, SEEK_SET);
692             ffio_wfourcc(pb, "LIST"); /* Making this AVI OpenDML one */
693             avio_skip(pb, 16);
694
695             for (n = nb_frames = 0; n < s->nb_streams; n++) {
696                 AVCodecContext *stream = s->streams[n]->codec;
697                 AVIStream *avist       = s->streams[n]->priv_data;
698
699                 if (stream->codec_type == AVMEDIA_TYPE_VIDEO) {
700                     if (nb_frames < avist->packet_count)
701                         nb_frames = avist->packet_count;
702                 } else {
703                     if (stream->codec_id == AV_CODEC_ID_MP2 ||
704                         stream->codec_id == AV_CODEC_ID_MP3)
705                         nb_frames += avist->packet_count;
706                 }
707             }
708             avio_wl32(pb, nb_frames);
709             avio_seek(pb, file_size, SEEK_SET);
710
711             avi_write_counters(s, avi->riff_id);
712         }
713     }
714
715     for (i = 0; i < s->nb_streams; i++) {
716         AVIStream *avist = s->streams[i]->priv_data;
717         for (j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++)
718             av_freep(&avist->indexes.cluster[j]);
719         av_freep(&avist->indexes.cluster);
720         avist->indexes.ents_allocated = avist->indexes.entry = 0;
721         if (pb->seekable) {
722             avio_seek(pb, avist->frames_hdr_strm + 4, SEEK_SET);
723             avio_wl32(pb, avist->max_size);
724         }
725     }
726
727     return res;
728 }
729
730 AVOutputFormat ff_avi_muxer = {
731     .name           = "avi",
732     .long_name      = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"),
733     .mime_type      = "video/x-msvideo",
734     .extensions     = "avi",
735     .priv_data_size = sizeof(AVIContext),
736     .audio_codec    = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3,
737     .video_codec    = AV_CODEC_ID_MPEG4,
738     .write_header   = avi_write_header,
739     .write_packet   = avi_write_packet,
740     .write_trailer  = avi_write_trailer,
741     .codec_tag      = (const AVCodecTag * const []) {
742         ff_codec_bmp_tags, ff_codec_wav_tags, 0
743     },
744 };