]> git.sesse.net Git - ffmpeg/blob - libavformat/avienc.c
f14b1cb274535364276ad39846008692c3720589
[ffmpeg] / libavformat / avienc.c
1 /*
2  * AVI encoder.
3  * Copyright (c) 2000 Fabrice Bellard.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 #include "avformat.h"
20 #include "avi.h"
21
22 /*
23  * TODO: 
24  *  - fill all fields if non streamed (nb_frames for example)
25  */
26
27 typedef struct AVIIndex {
28     unsigned char tag[4];
29     unsigned int flags, pos, len;
30     struct AVIIndex *next;
31 } AVIIndex;
32
33 typedef struct {
34     offset_t movi_list, frames_hdr_all, frames_hdr_strm[MAX_STREAMS];
35     int audio_strm_length[MAX_STREAMS];
36     AVIIndex *first, *last;
37 } AVIContext;
38
39 offset_t start_tag(ByteIOContext *pb, const char *tag)
40 {
41     put_tag(pb, tag);
42     put_le32(pb, 0);
43     return url_ftell(pb);
44 }
45
46 void end_tag(ByteIOContext *pb, offset_t start)
47 {
48     offset_t pos;
49
50     pos = url_ftell(pb);
51     url_fseek(pb, start - 4, SEEK_SET);
52     put_le32(pb, (UINT32)(pos - start));
53     url_fseek(pb, pos, SEEK_SET);
54 }
55
56 /* Note: when encoding, the first matching tag is used, so order is
57    important if multiple tags possible for a given codec. */
58 const CodecTag codec_bmp_tags[] = {
59     { CODEC_ID_H263, MKTAG('H', '2', '6', '3') },
60     { CODEC_ID_H263P, MKTAG('H', '2', '6', '3') },
61     { CODEC_ID_H263I, MKTAG('I', '2', '6', '3') }, /* intel h263 */
62     { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
63     { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X'), .invalid_asf = 1 },
64     { CODEC_ID_MPEG4, MKTAG('d', 'i', 'v', 'x'), .invalid_asf = 1 },
65     { CODEC_ID_MPEG4, MKTAG('D', 'X', '5', '0'), .invalid_asf = 1 },
66     { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D'), .invalid_asf = 1 },
67     { CODEC_ID_MPEG4, MKTAG('x', 'v', 'i', 'd'), .invalid_asf = 1 },
68     { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 's'), .invalid_asf = 1 },
69     { CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') },
70     { CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') },
71     { CODEC_ID_MPEG4, MKTAG('m', '4', 's', '2') },
72     { CODEC_ID_MPEG4, MKTAG(0x04, 0, 0, 0) }, /* some broken avi use this */
73     { CODEC_ID_MSMPEG4V3, MKTAG('D', 'I', 'V', '3'), .invalid_asf = 1 }, /* default signature when using MSMPEG4 */
74     { CODEC_ID_MSMPEG4V3, MKTAG('d', 'i', 'v', '3'), .invalid_asf = 1 },
75     { CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') }, 
76     { CODEC_ID_MSMPEG4V2, MKTAG('M', 'P', '4', '2') }, 
77     { CODEC_ID_MSMPEG4V1, MKTAG('M', 'P', 'G', '4') }, 
78     { CODEC_ID_WMV1, MKTAG('W', 'M', 'V', '1') }, 
79     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') }, 
80     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'd') }, 
81     { CODEC_ID_DVVIDEO, MKTAG('D', 'V', 'S', 'D') }, 
82     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') }, 
83     { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') }, 
84     { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') }, 
85     { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') }, 
86     { CODEC_ID_MJPEG, MKTAG('M', 'J', 'P', 'G') },
87     { 0, 0 },
88 };
89
90 unsigned int codec_get_tag(const CodecTag *tags, int id)
91 {
92     while (tags->id != 0) {
93         if (tags->id == id)
94             return tags->tag;
95         tags++;
96     }
97     return 0;
98 }
99
100 static unsigned int codec_get_asf_tag(const CodecTag *tags, int id)
101 {
102     while (tags->id != 0) {
103         if (!tags->invalid_asf && tags->id == id)
104             return tags->tag;
105         tags++;
106     }
107     return 0;
108 }
109
110 int codec_get_id(const CodecTag *tags, unsigned int tag)
111 {
112     while (tags->id != 0) {
113         if (tags->tag == tag)
114             return tags->id;
115         tags++;
116     }
117     return 0;
118 }
119
120 unsigned int codec_get_bmp_tag(int id)
121 {
122     return codec_get_tag(codec_bmp_tags, id);
123 }
124
125 /* BITMAPINFOHEADER header */
126 void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc, const CodecTag *tags, int for_asf)
127 {
128     put_le32(pb, 40); /* size */
129     put_le32(pb, enc->width);
130     put_le32(pb, enc->height);
131     put_le16(pb, 1); /* planes */
132     put_le16(pb, 24); /* depth */
133     /* compression type */
134     put_le32(pb, for_asf ? codec_get_asf_tag(tags, enc->codec_id) : codec_get_tag(tags, enc->codec_id));
135     put_le32(pb, enc->width * enc->height * 3);
136     put_le32(pb, 0);
137     put_le32(pb, 0);
138     put_le32(pb, 0);
139     put_le32(pb, 0);
140 }
141
142 static void parse_specific_params(AVCodecContext *stream, int *au_byterate, int *au_ssize, int *au_scale)
143 {
144     switch(stream->codec_id) {
145     case CODEC_ID_PCM_S16LE:
146        *au_scale = *au_ssize = 2*stream->channels;
147        *au_byterate = *au_ssize * stream->sample_rate;
148         break;
149     case CODEC_ID_PCM_U8:
150     case CODEC_ID_PCM_ALAW:
151     case CODEC_ID_PCM_MULAW:
152         *au_scale = *au_ssize = stream->channels;
153         *au_byterate = *au_ssize * stream->sample_rate;
154         break;
155     case CODEC_ID_MP2:
156         *au_ssize = 1;
157         *au_scale = 1;
158         *au_byterate = stream->bit_rate / 8;
159     case CODEC_ID_MP3LAME:
160         *au_ssize = 1;
161         *au_scale = 1;
162         *au_byterate = stream->bit_rate / 8;    
163     default:
164         *au_ssize = 1;
165         *au_scale = 1; 
166         *au_byterate = stream->bit_rate / 8;
167         break;
168     }
169 }
170
171 static int avi_write_header(AVFormatContext *s)
172 {
173     AVIContext *avi = s->priv_data;
174     ByteIOContext *pb = &s->pb;
175     int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale;
176     AVCodecContext *stream, *video_enc;
177     offset_t list1, list2, strh, strf;
178
179     put_tag(pb, "RIFF");
180     put_le32(pb, 0); /* file length */
181     put_tag(pb, "AVI ");
182
183     /* header list */
184     list1 = start_tag(pb, "LIST");
185     put_tag(pb, "hdrl");
186
187     /* avi header */
188     put_tag(pb, "avih");
189     put_le32(pb, 14 * 4);
190     bitrate = 0;
191
192     video_enc = NULL;
193     for(n=0;n<s->nb_streams;n++) {
194         stream = &s->streams[n]->codec;
195         bitrate += stream->bit_rate;
196         if (stream->codec_type == CODEC_TYPE_VIDEO)
197             video_enc = stream;
198     }
199     
200     if (!video_enc) {
201         av_free(avi);
202         return -1;
203     }
204     nb_frames = 0;
205
206     put_le32(pb, (UINT32)(INT64_C(1000000) * FRAME_RATE_BASE / video_enc->frame_rate));
207     put_le32(pb, bitrate / 8); /* XXX: not quite exact */
208     put_le32(pb, 0); /* padding */
209     put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
210     avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */
211     put_le32(pb, nb_frames); /* nb frames, filled later */
212     put_le32(pb, 0); /* initial frame */
213     put_le32(pb, s->nb_streams); /* nb streams */
214     put_le32(pb, 1024 * 1024); /* suggested buffer size */
215     put_le32(pb, video_enc->width);
216     put_le32(pb, video_enc->height);
217     put_le32(pb, 0); /* reserved */
218     put_le32(pb, 0); /* reserved */
219     put_le32(pb, 0); /* reserved */
220     put_le32(pb, 0); /* reserved */
221     
222     /* stream list */
223     for(i=0;i<n;i++) {
224         list2 = start_tag(pb, "LIST");
225         put_tag(pb, "strl");
226     
227         stream = &s->streams[i]->codec;
228
229         /* stream generic header */
230         strh = start_tag(pb, "strh");
231         switch(stream->codec_type) {
232         case CODEC_TYPE_VIDEO:
233             put_tag(pb, "vids");
234             put_le32(pb, codec_get_bmp_tag(stream->codec_id));
235             put_le32(pb, 0); /* flags */
236             put_le16(pb, 0); /* priority */
237             put_le16(pb, 0); /* language */
238             put_le32(pb, 0); /* initial frame */
239             put_le32(pb, 1000); /* scale */
240             put_le32(pb, (1000 * stream->frame_rate) / FRAME_RATE_BASE); /* rate */
241             put_le32(pb, 0); /* start */
242             avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
243             put_le32(pb, nb_frames); /* length, XXX: fill later */
244             put_le32(pb, 1024 * 1024); /* suggested buffer size */
245             put_le32(pb, -1); /* quality */
246             put_le32(pb, stream->width * stream->height * 3); /* sample size */
247             put_le16(pb, 0);
248             put_le16(pb, 0);
249             put_le16(pb, stream->width);
250             put_le16(pb, stream->height);
251             break;
252         case CODEC_TYPE_AUDIO:
253             put_tag(pb, "auds");
254             put_le32(pb, 1); /* tag */
255             put_le32(pb, 0); /* flags */
256             put_le16(pb, 0); /* priority */
257             put_le16(pb, 0); /* language */
258             put_le32(pb, 0); /* initial frame */
259             parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
260             put_le32(pb, au_scale); /* scale */
261             put_le32(pb, au_byterate); /* rate */
262             put_le32(pb, 0); /* start */
263             avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
264             put_le32(pb, 0); /* length, XXX: filled later */
265             put_le32(pb, 12 * 1024); /* suggested buffer size */
266             put_le32(pb, -1); /* quality */
267             put_le32(pb, au_ssize); /* sample size */
268             put_le32(pb, 0);
269             put_le32(pb, 0);
270             break;
271         default:
272             av_abort();
273         }
274         end_tag(pb, strh);
275
276         strf = start_tag(pb, "strf");
277         switch(stream->codec_type) {
278         case CODEC_TYPE_VIDEO:
279             put_bmp_header(pb, stream, codec_bmp_tags, 0);
280             break;
281         case CODEC_TYPE_AUDIO:
282             if (put_wav_header(pb, stream) < 0) {
283                 av_free(avi);
284                 return -1;
285             }
286             break;
287         default:
288             av_abort();
289         }
290         end_tag(pb, strf);
291         end_tag(pb, list2);
292     }
293
294     end_tag(pb, list1);
295     
296     avi->movi_list = start_tag(pb, "LIST");
297     avi->first = NULL;
298     avi->last = NULL;
299     put_tag(pb, "movi");
300
301     put_flush_packet(pb);
302
303     return 0;
304 }
305
306 static int avi_write_packet(AVFormatContext *s, int stream_index,
307                             UINT8 *buf, int size, int force_pts)
308 {
309     AVIContext *avi = s->priv_data;
310     ByteIOContext *pb = &s->pb;
311     AVIIndex *idx;
312     unsigned char tag[5];
313     unsigned int flags;
314     AVCodecContext *enc;
315     
316     enc = &s->streams[stream_index]->codec;
317
318     tag[0] = '0';
319     tag[1] = '0' + stream_index;
320     if (enc->codec_type == CODEC_TYPE_VIDEO) {
321         tag[2] = 'd';
322         tag[3] = 'c';
323         flags = enc->coded_frame->key_frame ? 0x10 : 0x00;
324     } else {
325         tag[2] = 'w';
326         tag[3] = 'b';
327         flags = 0x10;
328     }
329     if (enc->codec_type == CODEC_TYPE_AUDIO) 
330        avi->audio_strm_length[stream_index] += size;
331
332     if (!url_is_streamed(&s->pb)) {
333         idx = av_malloc(sizeof(AVIIndex));
334         memcpy(idx->tag, tag, 4);
335         idx->flags = flags;
336         idx->pos = url_ftell(pb) - avi->movi_list;
337         idx->len = size;
338         idx->next = NULL;
339         if (!avi->last)
340             avi->first = idx;
341         else
342             avi->last->next = idx;
343         avi->last = idx;
344     }
345     
346     put_buffer(pb, tag, 4);
347     put_le32(pb, size);
348     put_buffer(pb, buf, size);
349     if (size & 1)
350         put_byte(pb, 0);
351
352     put_flush_packet(pb);
353     return 0;
354 }
355
356 static int avi_write_trailer(AVFormatContext *s)
357 {
358     ByteIOContext *pb = &s->pb;
359     AVIContext *avi = s->priv_data;
360     offset_t file_size, idx_chunk;
361     int n, nb_frames, au_byterate, au_ssize, au_scale;
362     AVCodecContext *stream;
363     AVIIndex *idx;
364
365     if (!url_is_streamed(&s->pb)) {
366         end_tag(pb, avi->movi_list);
367
368         idx_chunk = start_tag(pb, "idx1");
369         idx = avi->first;
370         while (idx != NULL) {
371             put_buffer(pb, idx->tag, 4);
372             put_le32(pb, idx->flags);
373             put_le32(pb, idx->pos);
374             put_le32(pb, idx->len);
375             idx = idx->next;
376         }
377         end_tag(pb, idx_chunk);
378         
379         /* update file size */
380         file_size = url_ftell(pb);
381         url_fseek(pb, 4, SEEK_SET);
382         put_le32(pb, (UINT32)(file_size - 8));
383
384         /* Fill in frame/sample counters */
385         nb_frames = 0;
386         for(n=0;n<s->nb_streams;n++) {
387             if (avi->frames_hdr_strm[n] != 0) {
388                 stream = &s->streams[n]->codec;
389                 url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET);
390                 if (stream->codec_type == CODEC_TYPE_VIDEO) {
391                     put_le32(pb, stream->frame_number); 
392                     if (nb_frames < stream->frame_number)
393                         nb_frames = stream->frame_number;
394                 } else {
395                     if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3LAME) {
396                         put_le32(pb, stream->frame_number);
397                         nb_frames += stream->frame_number;
398                     } else {
399                         parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
400                         put_le32(pb, avi->audio_strm_length[n] / au_ssize);
401                     }
402                 }
403             }
404        }
405        if (avi->frames_hdr_all != 0) {
406            url_fseek(pb, avi->frames_hdr_all, SEEK_SET);
407            put_le32(pb, nb_frames); 
408        }
409         url_fseek(pb, file_size, SEEK_SET);
410     }
411     put_flush_packet(pb);
412     return 0;
413 }
414
415 static AVOutputFormat avi_oformat = {
416     "avi",
417     "avi format",
418     "video/x-msvideo",
419     "avi",
420     sizeof(AVIContext),
421     CODEC_ID_MP2,
422     CODEC_ID_MSMPEG4V3,
423     avi_write_header,
424     avi_write_packet,
425     avi_write_trailer,
426 };
427
428 int avienc_init(void)
429 {
430     av_register_output_format(&avi_oformat);
431     return 0;
432 }