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#include "avformat.h"
22#include "avi.h"
23#include "riff.h"
24
25/*
26 * TODO:
27 *  - fill all fields if non streamed (nb_frames for example)
28 */
29
30typedef struct AVIIentry {
31    unsigned int flags, pos, len;
32} AVIIentry;
33
34#define AVI_INDEX_CLUSTER_SIZE 16384
35
36typedef struct AVIIndex {
37    int64_t     indx_start;
38    int         entry;
39    int         ents_allocated;
40    AVIIentry** cluster;
41} AVIIndex;
42
43typedef struct {
44    int64_t riff_start, movi_list, odml_list;
45    int64_t frames_hdr_all, frames_hdr_strm[MAX_STREAMS];
46    int audio_strm_length[MAX_STREAMS];
47    int riff_id;
48    int packet_count[MAX_STREAMS];
49
50    AVIIndex indexes[MAX_STREAMS];
51} AVIContext;
52
53static inline AVIIentry* avi_get_ientry(AVIIndex* idx, int ent_id)
54{
55    int cl = ent_id / AVI_INDEX_CLUSTER_SIZE;
56    int id = ent_id % AVI_INDEX_CLUSTER_SIZE;
57    return &idx->cluster[cl][id];
58}
59
60static int64_t avi_start_new_riff(AVIContext *avi, ByteIOContext *pb,
61                                  const char* riff_tag, const char* list_tag)
62{
63    int64_t loff;
64    int i;
65
66    avi->riff_id++;
67    for (i=0; i<MAX_STREAMS; i++)
68         avi->indexes[i].entry = 0;
69
70    avi->riff_start = start_tag(pb, "RIFF");
71    put_tag(pb, riff_tag);
72    loff = start_tag(pb, "LIST");
73    put_tag(pb, list_tag);
74    return loff;
75}
76
77static char* avi_stream2fourcc(char* tag, int index, enum CodecType type)
78{
79    tag[0] = '0';
80    tag[1] = '0' + index;
81    if (type == CODEC_TYPE_VIDEO) {
82        tag[2] = 'd';
83        tag[3] = 'c';
84    } else {
85        tag[2] = 'w';
86        tag[3] = 'b';
87    }
88    tag[4] = '\0';
89    return tag;
90}
91
92static void avi_write_info_tag(ByteIOContext *pb, const char *tag, const char *str)
93{
94    int len = strlen(str);
95    if (len > 0) {
96        len++;
97        put_tag(pb, tag);
98        put_le32(pb, len);
99        put_strz(pb, str);
100        if (len & 1)
101            put_byte(pb, 0);
102    }
103}
104
105static void avi_write_info_tag2(AVFormatContext *s, const char *fourcc, const char *key1, const char *key2)
106{
107    AVMetadataTag *tag= av_metadata_get(s->metadata, key1, NULL, 0);
108    if(!tag && key2)
109        tag= av_metadata_get(s->metadata, key2, NULL, 0);
110    if(tag)
111        avi_write_info_tag(s->pb, fourcc, tag->value);
112}
113
114static int avi_write_counters(AVFormatContext* s, int riff_id)
115{
116    ByteIOContext *pb = s->pb;
117    AVIContext *avi = s->priv_data;
118    int n, au_byterate, au_ssize, au_scale, nb_frames = 0;
119    int64_t file_size;
120    AVCodecContext* stream;
121
122    file_size = url_ftell(pb);
123    for(n = 0; n < s->nb_streams; n++) {
124        assert(avi->frames_hdr_strm[n]);
125        stream = s->streams[n]->codec;
126        url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET);
127        ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
128        if(au_ssize == 0) {
129            put_le32(pb, avi->packet_count[n]);
130        } else {
131            put_le32(pb, avi->audio_strm_length[n] / au_ssize);
132        }
133        if(stream->codec_type == CODEC_TYPE_VIDEO)
134            nb_frames = FFMAX(nb_frames, avi->packet_count[n]);
135    }
136    if(riff_id == 1) {
137        assert(avi->frames_hdr_all);
138        url_fseek(pb, avi->frames_hdr_all, SEEK_SET);
139        put_le32(pb, nb_frames);
140    }
141    url_fseek(pb, file_size, SEEK_SET);
142
143    return 0;
144}
145
146static int avi_write_header(AVFormatContext *s)
147{
148    AVIContext *avi = s->priv_data;
149    ByteIOContext *pb = s->pb;
150    int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale;
151    AVCodecContext *stream, *video_enc;
152    int64_t list1, list2, strh, strf;
153
154    /* header list */
155    avi->riff_id = 0;
156    list1 = avi_start_new_riff(avi, pb, "AVI ", "hdrl");
157
158    /* avi header */
159    put_tag(pb, "avih");
160    put_le32(pb, 14 * 4);
161    bitrate = 0;
162
163    video_enc = NULL;
164    for(n=0;n<s->nb_streams;n++) {
165        stream = s->streams[n]->codec;
166        bitrate += stream->bit_rate;
167        if (stream->codec_type == CODEC_TYPE_VIDEO)
168            video_enc = stream;
169    }
170
171    nb_frames = 0;
172
173    if(video_enc){
174        put_le32(pb, (uint32_t)(INT64_C(1000000) * video_enc->time_base.num / video_enc->time_base.den));
175    } else {
176        put_le32(pb, 0);
177    }
178    put_le32(pb, bitrate / 8); /* XXX: not quite exact */
179    put_le32(pb, 0); /* padding */
180    if (url_is_streamed(pb))
181        put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */
182    else
183        put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
184    avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */
185    put_le32(pb, nb_frames); /* nb frames, filled later */
186    put_le32(pb, 0); /* initial frame */
187    put_le32(pb, s->nb_streams); /* nb streams */
188    put_le32(pb, 1024 * 1024); /* suggested buffer size */
189    if(video_enc){
190        put_le32(pb, video_enc->width);
191        put_le32(pb, video_enc->height);
192    } else {
193        put_le32(pb, 0);
194        put_le32(pb, 0);
195    }
196    put_le32(pb, 0); /* reserved */
197    put_le32(pb, 0); /* reserved */
198    put_le32(pb, 0); /* reserved */
199    put_le32(pb, 0); /* reserved */
200
201    /* stream list */
202    for(i=0;i<n;i++) {
203        list2 = start_tag(pb, "LIST");
204        put_tag(pb, "strl");
205
206        stream = s->streams[i]->codec;
207
208        /* stream generic header */
209        strh = start_tag(pb, "strh");
210        switch(stream->codec_type) {
211        case CODEC_TYPE_VIDEO: put_tag(pb, "vids"); break;
212        case CODEC_TYPE_AUDIO: put_tag(pb, "auds"); break;
213//        case CODEC_TYPE_TEXT : put_tag(pb, "txts"); break;
214        case CODEC_TYPE_DATA : put_tag(pb, "dats"); break;
215        }
216        if(stream->codec_type == CODEC_TYPE_VIDEO)
217            put_le32(pb, stream->codec_tag);
218        else
219            put_le32(pb, 1);
220        put_le32(pb, 0); /* flags */
221        put_le16(pb, 0); /* priority */
222        put_le16(pb, 0); /* language */
223        put_le32(pb, 0); /* initial frame */
224
225        ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
226
227        put_le32(pb, au_scale); /* scale */
228        put_le32(pb, au_byterate); /* rate */
229        av_set_pts_info(s->streams[i], 64, au_scale, au_byterate);
230
231        put_le32(pb, 0); /* start */
232        avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
233        if (url_is_streamed(pb))
234            put_le32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */
235        else
236            put_le32(pb, 0); /* length, XXX: filled later */
237
238        /* suggested buffer size */ //FIXME set at the end to largest chunk
239        if(stream->codec_type == CODEC_TYPE_VIDEO)
240            put_le32(pb, 1024 * 1024);
241        else if(stream->codec_type == CODEC_TYPE_AUDIO)
242            put_le32(pb, 12 * 1024);
243        else
244            put_le32(pb, 0);
245        put_le32(pb, -1); /* quality */
246        put_le32(pb, au_ssize); /* sample size */
247        put_le32(pb, 0);
248        put_le16(pb, stream->width);
249        put_le16(pb, stream->height);
250        end_tag(pb, strh);
251
252      if(stream->codec_type != CODEC_TYPE_DATA){
253        strf = start_tag(pb, "strf");
254        switch(stream->codec_type) {
255        case CODEC_TYPE_VIDEO:
256            put_bmp_header(pb, stream, codec_bmp_tags, 0);
257            break;
258        case CODEC_TYPE_AUDIO:
259            if (put_wav_header(pb, stream) < 0) {
260                return -1;
261            }
262            break;
263        default:
264            return -1;
265        }
266        end_tag(pb, strf);
267      }
268
269        if (!url_is_streamed(pb)) {
270            unsigned char tag[5];
271            int j;
272
273            /* Starting to lay out AVI OpenDML master index.
274             * We want to make it JUNK entry for now, since we'd
275             * like to get away without making AVI an OpenDML one
276             * for compatibility reasons.
277             */
278            avi->indexes[i].entry = avi->indexes[i].ents_allocated = 0;
279            avi->indexes[i].indx_start = start_tag(pb, "JUNK");
280            put_le16(pb, 4);        /* wLongsPerEntry */
281            put_byte(pb, 0);        /* bIndexSubType (0 == frame index) */
282            put_byte(pb, 0);        /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
283            put_le32(pb, 0);        /* nEntriesInUse (will fill out later on) */
284            put_tag(pb, avi_stream2fourcc(&tag[0], i, stream->codec_type));
285                                    /* dwChunkId */
286            put_le64(pb, 0);        /* dwReserved[3]
287            put_le32(pb, 0);           Must be 0.    */
288            for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++)
289                 put_le64(pb, 0);
290            end_tag(pb, avi->indexes[i].indx_start);
291        }
292
293        if(   stream->codec_type == CODEC_TYPE_VIDEO
294           && s->streams[i]->sample_aspect_ratio.num>0
295           && s->streams[i]->sample_aspect_ratio.den>0){
296            int vprp= start_tag(pb, "vprp");
297            AVRational dar = av_mul_q(s->streams[i]->sample_aspect_ratio,
298                                      (AVRational){stream->width, stream->height});
299            int num, den;
300            av_reduce(&num, &den, dar.num, dar.den, 0xFFFF);
301
302            put_le32(pb, 0); //video format  = unknown
303            put_le32(pb, 0); //video standard= unknown
304            put_le32(pb, lrintf(1.0/av_q2d(stream->time_base)));
305            put_le32(pb, stream->width );
306            put_le32(pb, stream->height);
307            put_le16(pb, den);
308            put_le16(pb, num);
309            put_le32(pb, stream->width );
310            put_le32(pb, stream->height);
311            put_le32(pb, 1); //progressive FIXME
312
313            put_le32(pb, stream->height);
314            put_le32(pb, stream->width );
315            put_le32(pb, stream->height);
316            put_le32(pb, stream->width );
317            put_le32(pb, 0);
318            put_le32(pb, 0);
319
320            put_le32(pb, 0);
321            put_le32(pb, 0);
322            end_tag(pb, vprp);
323        }
324
325        end_tag(pb, list2);
326    }
327
328    if (!url_is_streamed(pb)) {
329        /* AVI could become an OpenDML one, if it grows beyond 2Gb range */
330        avi->odml_list = start_tag(pb, "JUNK");
331        put_tag(pb, "odml");
332        put_tag(pb, "dmlh");
333        put_le32(pb, 248);
334        for (i = 0; i < 248; i+= 4)
335             put_le32(pb, 0);
336        end_tag(pb, avi->odml_list);
337    }
338
339    end_tag(pb, list1);
340
341    list2 = start_tag(pb, "LIST");
342    put_tag(pb, "INFO");
343    avi_write_info_tag2(s, "INAM", "Title", NULL);
344    avi_write_info_tag2(s, "IART", "Artist", "Author");
345    avi_write_info_tag2(s, "ICOP", "Copyright", NULL);
346    avi_write_info_tag2(s, "ICMT", "Comment", NULL);
347    avi_write_info_tag2(s, "IPRD", "Album", NULL);
348    avi_write_info_tag2(s, "IGNR", "Genre", NULL);
349    avi_write_info_tag2(s, "IPRT", "Track", NULL);
350    if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
351        avi_write_info_tag(pb, "ISFT", LIBAVFORMAT_IDENT);
352    end_tag(pb, list2);
353
354    /* some padding for easier tag editing */
355    list2 = start_tag(pb, "JUNK");
356    for (i = 0; i < 1016; i += 4)
357        put_le32(pb, 0);
358    end_tag(pb, list2);
359
360    avi->movi_list = start_tag(pb, "LIST");
361    put_tag(pb, "movi");
362
363    put_flush_packet(pb);
364
365    return 0;
366}
367
368static int avi_write_ix(AVFormatContext *s)
369{
370    ByteIOContext *pb = s->pb;
371    AVIContext *avi = s->priv_data;
372    char tag[5];
373    char ix_tag[] = "ix00";
374    int i, j;
375
376    assert(!url_is_streamed(pb));
377
378    if (avi->riff_id > AVI_MASTER_INDEX_SIZE)
379        return -1;
380
381    for (i=0;i<s->nb_streams;i++) {
382         int64_t ix, pos;
383
384         avi_stream2fourcc(&tag[0], i, s->streams[i]->codec->codec_type);
385         ix_tag[3] = '0' + i;
386
387         /* Writing AVI OpenDML leaf index chunk */
388         ix = url_ftell(pb);
389         put_tag(pb, &ix_tag[0]);     /* ix?? */
390         put_le32(pb, avi->indexes[i].entry * 8 + 24);
391                                      /* chunk size */
392         put_le16(pb, 2);             /* wLongsPerEntry */
393         put_byte(pb, 0);             /* bIndexSubType (0 == frame index) */
394         put_byte(pb, 1);             /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */
395         put_le32(pb, avi->indexes[i].entry);
396                                      /* nEntriesInUse */
397         put_tag(pb, &tag[0]);        /* dwChunkId */
398         put_le64(pb, avi->movi_list);/* qwBaseOffset */
399         put_le32(pb, 0);             /* dwReserved_3 (must be 0) */
400
401         for (j=0; j<avi->indexes[i].entry; j++) {
402             AVIIentry* ie = avi_get_ientry(&avi->indexes[i], j);
403             put_le32(pb, ie->pos + 8);
404             put_le32(pb, ((uint32_t)ie->len & ~0x80000000) |
405                          (ie->flags & 0x10 ? 0 : 0x80000000));
406         }
407         put_flush_packet(pb);
408         pos = url_ftell(pb);
409
410         /* Updating one entry in the AVI OpenDML master index */
411         url_fseek(pb, avi->indexes[i].indx_start - 8, SEEK_SET);
412         put_tag(pb, "indx");                 /* enabling this entry */
413         url_fskip(pb, 8);
414         put_le32(pb, avi->riff_id);          /* nEntriesInUse */
415         url_fskip(pb, 16*avi->riff_id);
416         put_le64(pb, ix);                    /* qwOffset */
417         put_le32(pb, pos - ix);              /* dwSize */
418         put_le32(pb, avi->indexes[i].entry); /* dwDuration */
419
420         url_fseek(pb, pos, SEEK_SET);
421    }
422    return 0;
423}
424
425static int avi_write_idx1(AVFormatContext *s)
426{
427    ByteIOContext *pb = s->pb;
428    AVIContext *avi = s->priv_data;
429    int64_t idx_chunk;
430    int i;
431    char tag[5];
432
433    if (!url_is_streamed(pb)) {
434        AVIIentry* ie = 0, *tie;
435        int entry[MAX_STREAMS];
436        int empty, stream_id = -1;
437
438        idx_chunk = start_tag(pb, "idx1");
439        memset(&entry[0], 0, sizeof(entry));
440        do {
441            empty = 1;
442            for (i=0; i<s->nb_streams; i++) {
443                 if (avi->indexes[i].entry <= entry[i])
444                     continue;
445
446                 tie = avi_get_ientry(&avi->indexes[i], entry[i]);
447                 if (empty || tie->pos < ie->pos) {
448                     ie = tie;
449                     stream_id = i;
450                 }
451                 empty = 0;
452            }
453            if (!empty) {
454                avi_stream2fourcc(&tag[0], stream_id,
455                                  s->streams[stream_id]->codec->codec_type);
456                put_tag(pb, &tag[0]);
457                put_le32(pb, ie->flags);
458                put_le32(pb, ie->pos);
459                put_le32(pb, ie->len);
460                entry[stream_id]++;
461            }
462        } while (!empty);
463        end_tag(pb, idx_chunk);
464
465        avi_write_counters(s, avi->riff_id);
466    }
467    return 0;
468}
469
470static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
471{
472    AVIContext *avi = s->priv_data;
473    ByteIOContext *pb = s->pb;
474    unsigned char tag[5];
475    unsigned int flags=0;
476    const int stream_index= pkt->stream_index;
477    AVCodecContext *enc= s->streams[stream_index]->codec;
478    int size= pkt->size;
479
480//    av_log(s, AV_LOG_DEBUG, "%"PRId64" %d %d\n", pkt->dts, avi->packet_count[stream_index], stream_index);
481    while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avi->packet_count[stream_index]){
482        AVPacket empty_packet;
483
484        av_init_packet(&empty_packet);
485        empty_packet.size= 0;
486        empty_packet.data= NULL;
487        empty_packet.stream_index= stream_index;
488        avi_write_packet(s, &empty_packet);
489//        av_log(s, AV_LOG_DEBUG, "dup %"PRId64" %d\n", pkt->dts, avi->packet_count[stream_index]);
490    }
491    avi->packet_count[stream_index]++;
492
493    // Make sure to put an OpenDML chunk when the file size exceeds the limits
494    if (!url_is_streamed(pb) &&
495        (url_ftell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) {
496
497        avi_write_ix(s);
498        end_tag(pb, avi->movi_list);
499
500        if (avi->riff_id == 1)
501            avi_write_idx1(s);
502
503        end_tag(pb, avi->riff_start);
504        avi->movi_list = avi_start_new_riff(avi, pb, "AVIX", "movi");
505    }
506
507    avi_stream2fourcc(&tag[0], stream_index, enc->codec_type);
508    if(pkt->flags&PKT_FLAG_KEY)
509        flags = 0x10;
510    if (enc->codec_type == CODEC_TYPE_AUDIO) {
511       avi->audio_strm_length[stream_index] += size;
512    }
513
514    if (!url_is_streamed(s->pb)) {
515        AVIIndex* idx = &avi->indexes[stream_index];
516        int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
517        int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
518        if (idx->ents_allocated <= idx->entry) {
519            idx->cluster = av_realloc(idx->cluster, (cl+1)*sizeof(void*));
520            if (!idx->cluster)
521                return -1;
522            idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry));
523            if (!idx->cluster[cl])
524                return -1;
525            idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
526        }
527
528        idx->cluster[cl][id].flags = flags;
529        idx->cluster[cl][id].pos = url_ftell(pb) - avi->movi_list;
530        idx->cluster[cl][id].len = size;
531        idx->entry++;
532    }
533
534    put_buffer(pb, tag, 4);
535    put_le32(pb, size);
536    put_buffer(pb, pkt->data, size);
537    if (size & 1)
538        put_byte(pb, 0);
539
540    put_flush_packet(pb);
541    return 0;
542}
543
544static int avi_write_trailer(AVFormatContext *s)
545{
546    AVIContext *avi = s->priv_data;
547    ByteIOContext *pb = s->pb;
548    int res = 0;
549    int i, j, n, nb_frames;
550    int64_t file_size;
551
552    if (!url_is_streamed(pb)){
553        if (avi->riff_id == 1) {
554            end_tag(pb, avi->movi_list);
555            res = avi_write_idx1(s);
556            end_tag(pb, avi->riff_start);
557        } else {
558            avi_write_ix(s);
559            end_tag(pb, avi->movi_list);
560            end_tag(pb, avi->riff_start);
561
562            file_size = url_ftell(pb);
563            url_fseek(pb, avi->odml_list - 8, SEEK_SET);
564            put_tag(pb, "LIST"); /* Making this AVI OpenDML one */
565            url_fskip(pb, 16);
566
567            for (n=nb_frames=0;n<s->nb_streams;n++) {
568                AVCodecContext *stream = s->streams[n]->codec;
569                if (stream->codec_type == CODEC_TYPE_VIDEO) {
570                    if (nb_frames < avi->packet_count[n])
571                        nb_frames = avi->packet_count[n];
572                } else {
573                    if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3) {
574                        nb_frames += avi->packet_count[n];
575                    }
576                }
577            }
578            put_le32(pb, nb_frames);
579            url_fseek(pb, file_size, SEEK_SET);
580
581            avi_write_counters(s, avi->riff_id);
582        }
583    }
584    put_flush_packet(pb);
585
586    for (i=0; i<MAX_STREAMS; i++) {
587         for (j=0; j<avi->indexes[i].ents_allocated/AVI_INDEX_CLUSTER_SIZE; j++)
588              av_free(avi->indexes[i].cluster[j]);
589         av_free(avi->indexes[i].cluster);
590         avi->indexes[i].cluster = NULL;
591         avi->indexes[i].ents_allocated = avi->indexes[i].entry = 0;
592    }
593
594    return res;
595}
596
597AVOutputFormat avi_muxer = {
598    "avi",
599    NULL_IF_CONFIG_SMALL("AVI format"),
600    "video/x-msvideo",
601    "avi",
602    sizeof(AVIContext),
603    CODEC_ID_MP2,
604    CODEC_ID_MPEG4,
605    avi_write_header,
606    avi_write_packet,
607    avi_write_trailer,
608    .codec_tag= (const AVCodecTag* const []){codec_bmp_tags, codec_wav_tags, 0},
609    .flags= AVFMT_VARIABLE_FPS,
610};
611