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