Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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