blob: e8c0c7159e3373dbe51bcc0334687ad8743fadfe
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 <math.h> |
25 | |
26 | #include "avformat.h" |
27 | #include "internal.h" |
28 | #include "avi.h" |
29 | #include "avio_internal.h" |
30 | #include "riff.h" |
31 | #include "mpegts.h" |
32 | #include "libavformat/avlanguage.h" |
33 | #include "libavutil/avstring.h" |
34 | #include "libavutil/avutil.h" |
35 | #include "libavutil/internal.h" |
36 | #include "libavutil/intreadwrite.h" |
37 | #include "libavutil/dict.h" |
38 | #include "libavutil/avassert.h" |
39 | #include "libavutil/timestamp.h" |
40 | #include "libavutil/opt.h" |
41 | #include "libavutil/pixdesc.h" |
42 | #include "libavcodec/raw.h" |
43 | |
44 | /* |
45 | * TODO: |
46 | * - fill all fields if non streamed (nb_frames for example) |
47 | */ |
48 | |
49 | typedef struct AVIIentry { |
50 | char tag[4]; |
51 | unsigned int flags; |
52 | unsigned int pos; |
53 | unsigned int len; |
54 | } AVIIentry; |
55 | |
56 | #define AVI_INDEX_CLUSTER_SIZE 16384 |
57 | #define AVI_MASTER_INDEX_PREFIX_SIZE (8+2+1+1+4+8+4+4) |
58 | #define AVI_MASTER_INDEX_ENTRY_SIZE 16 /* bytes per entry */ |
59 | #define AVI_MASTER_INDEX_SIZE_DEFAULT 256 /* number of entries */ |
60 | |
61 | typedef struct AVIIndex { |
62 | int64_t indx_start; |
63 | int64_t audio_strm_offset; |
64 | int entry; |
65 | int ents_allocated; |
66 | int master_odml_riff_id_base; |
67 | AVIIentry** cluster; |
68 | } AVIIndex; |
69 | |
70 | typedef struct AVIContext { |
71 | const AVClass *class; |
72 | int64_t riff_start, movi_list, odml_list; |
73 | int64_t frames_hdr_all; |
74 | int riff_id; |
75 | int reserve_index_space; |
76 | int master_index_max_size; |
77 | int write_channel_mask; |
78 | } AVIContext; |
79 | |
80 | typedef struct AVIStream { |
81 | int64_t frames_hdr_strm; |
82 | int64_t audio_strm_length; |
83 | int packet_count; |
84 | int entry; |
85 | int max_size; |
86 | int sample_requested; |
87 | |
88 | int64_t last_dts; |
89 | |
90 | AVIIndex indexes; |
91 | |
92 | int64_t strh_flags_offset; |
93 | |
94 | uint32_t palette[AVPALETTE_COUNT]; |
95 | uint32_t old_palette[AVPALETTE_COUNT]; |
96 | int64_t pal_offset; |
97 | } AVIStream; |
98 | |
99 | static int avi_write_packet_internal(AVFormatContext *s, AVPacket *pkt); |
100 | |
101 | static inline AVIIentry *avi_get_ientry(const AVIIndex *idx, int ent_id) |
102 | { |
103 | int cl = ent_id / AVI_INDEX_CLUSTER_SIZE; |
104 | int id = ent_id % AVI_INDEX_CLUSTER_SIZE; |
105 | return &idx->cluster[cl][id]; |
106 | } |
107 | |
108 | static int avi_add_ientry(AVFormatContext *s, int stream_index, char *tag, |
109 | unsigned int flags, unsigned int size) |
110 | { |
111 | AVIContext *avi = s->priv_data; |
112 | AVIOContext *pb = s->pb; |
113 | AVIStream *avist = s->streams[stream_index]->priv_data; |
114 | AVIIndex *idx = &avist->indexes; |
115 | int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE; |
116 | int id = idx->entry % AVI_INDEX_CLUSTER_SIZE; |
117 | |
118 | if (idx->ents_allocated <= idx->entry) { |
119 | idx->cluster = av_realloc_f(idx->cluster, sizeof(void*), cl+1); |
120 | if (!idx->cluster) { |
121 | idx->ents_allocated = 0; |
122 | idx->entry = 0; |
123 | return AVERROR(ENOMEM); |
124 | } |
125 | idx->cluster[cl] = |
126 | av_malloc(AVI_INDEX_CLUSTER_SIZE * sizeof(AVIIentry)); |
127 | if (!idx->cluster[cl]) |
128 | return AVERROR(ENOMEM); |
129 | idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE; |
130 | } |
131 | |
132 | if (tag) |
133 | memcpy(idx->cluster[cl][id].tag, tag, 4); |
134 | else |
135 | memset(idx->cluster[cl][id].tag, 0, 4); |
136 | idx->cluster[cl][id].flags = flags; |
137 | idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list; |
138 | idx->cluster[cl][id].len = size; |
139 | avist->max_size = FFMAX(avist->max_size, size); |
140 | idx->entry++; |
141 | |
142 | return 0; |
143 | } |
144 | |
145 | static av_cold int avi_init(struct AVFormatContext *s) |
146 | { |
147 | AVIContext *avi = s->priv_data; |
148 | |
149 | if (avi->reserve_index_space > 0) { |
150 | avi->master_index_max_size = (avi->reserve_index_space - AVI_MASTER_INDEX_PREFIX_SIZE) / AVI_MASTER_INDEX_ENTRY_SIZE; |
151 | avi->master_index_max_size = FFMAX(avi->master_index_max_size, 16); |
152 | } else |
153 | avi->master_index_max_size = AVI_MASTER_INDEX_SIZE_DEFAULT; |
154 | av_log(s, AV_LOG_DEBUG, "reserve_index_space:%d master_index_max_size:%d\n", |
155 | avi->reserve_index_space, avi->master_index_max_size); |
156 | |
157 | return 1; /* stream initialization continues in avi_write_header */ |
158 | } |
159 | |
160 | static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb, |
161 | const char *riff_tag, const char *list_tag) |
162 | { |
163 | AVIContext *avi = s->priv_data; |
164 | int64_t loff; |
165 | int i; |
166 | |
167 | avi->riff_id++; |
168 | for (i = 0; i < s->nb_streams; i++) { |
169 | AVIStream *avist = s->streams[i]->priv_data; |
170 | avist->indexes.audio_strm_offset = avist->audio_strm_length; |
171 | avist->indexes.entry = 0; |
172 | } |
173 | |
174 | avi->riff_start = ff_start_tag(pb, "RIFF"); |
175 | ffio_wfourcc(pb, riff_tag); |
176 | loff = ff_start_tag(pb, "LIST"); |
177 | ffio_wfourcc(pb, list_tag); |
178 | return loff; |
179 | } |
180 | |
181 | static char *avi_stream2fourcc(char *tag, int index, enum AVMediaType type) |
182 | { |
183 | tag[0] = '0' + index / 10; |
184 | tag[1] = '0' + index % 10; |
185 | if (type == AVMEDIA_TYPE_VIDEO) { |
186 | tag[2] = 'd'; |
187 | tag[3] = 'c'; |
188 | } else if (type == AVMEDIA_TYPE_SUBTITLE) { |
189 | // note: this is not an official code |
190 | tag[2] = 's'; |
191 | tag[3] = 'b'; |
192 | } else { |
193 | tag[2] = 'w'; |
194 | tag[3] = 'b'; |
195 | } |
196 | tag[4] = '\0'; |
197 | return tag; |
198 | } |
199 | |
200 | static int avi_write_counters(AVFormatContext *s, int riff_id) |
201 | { |
202 | AVIOContext *pb = s->pb; |
203 | AVIContext *avi = s->priv_data; |
204 | int n, au_byterate, au_ssize, au_scale, nb_frames = 0; |
205 | int64_t file_size; |
206 | AVCodecParameters *par; |
207 | |
208 | file_size = avio_tell(pb); |
209 | for (n = 0; n < s->nb_streams; n++) { |
210 | AVIStream *avist = s->streams[n]->priv_data; |
211 | |
212 | av_assert0(avist->frames_hdr_strm); |
213 | par = s->streams[n]->codecpar; |
214 | avio_seek(pb, avist->frames_hdr_strm, SEEK_SET); |
215 | ff_parse_specific_params(s->streams[n], &au_byterate, &au_ssize, &au_scale); |
216 | if (au_ssize == 0) |
217 | avio_wl32(pb, avist->packet_count); |
218 | else |
219 | avio_wl32(pb, avist->audio_strm_length / au_ssize); |
220 | if (par->codec_type == AVMEDIA_TYPE_VIDEO) |
221 | nb_frames = FFMAX(nb_frames, avist->packet_count); |
222 | } |
223 | if (riff_id == 1) { |
224 | av_assert0(avi->frames_hdr_all); |
225 | avio_seek(pb, avi->frames_hdr_all, SEEK_SET); |
226 | avio_wl32(pb, nb_frames); |
227 | } |
228 | avio_seek(pb, file_size, SEEK_SET); |
229 | |
230 | return 0; |
231 | } |
232 | |
233 | static void write_odml_master(AVFormatContext *s, int stream_index) |
234 | { |
235 | AVIOContext *pb = s->pb; |
236 | AVIContext *avi = s->priv_data; |
237 | AVStream *st = s->streams[stream_index]; |
238 | AVCodecParameters *par = st->codecpar; |
239 | AVIStream *avist = st->priv_data; |
240 | unsigned char tag[5]; |
241 | int j; |
242 | |
243 | /* Starting to lay out AVI OpenDML master index. |
244 | * We want to make it JUNK entry for now, since we'd |
245 | * like to get away without making AVI an OpenDML one |
246 | * for compatibility reasons. */ |
247 | avist->indexes.indx_start = ff_start_tag(pb, "JUNK"); |
248 | avio_wl16(pb, 4); /* wLongsPerEntry */ |
249 | avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */ |
250 | avio_w8(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */ |
251 | avio_wl32(pb, 0); /* nEntriesInUse (will fill out later on) */ |
252 | ffio_wfourcc(pb, avi_stream2fourcc(tag, stream_index, par->codec_type)); |
253 | /* dwChunkId */ |
254 | avio_wl64(pb, 0); /* dwReserved[3] */ |
255 | avio_wl32(pb, 0); /* Must be 0. */ |
256 | for (j = 0; j < avi->master_index_max_size * 2; j++) |
257 | avio_wl64(pb, 0); |
258 | ff_end_tag(pb, avist->indexes.indx_start); |
259 | } |
260 | |
261 | static int avi_write_header(AVFormatContext *s) |
262 | { |
263 | AVIContext *avi = s->priv_data; |
264 | AVIOContext *pb = s->pb; |
265 | int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; |
266 | int64_t max_stream_duration = 0; |
267 | AVCodecParameters *video_par; |
268 | AVStream *video_st = NULL; |
269 | int64_t list1, list2, strh, strf; |
270 | AVDictionaryEntry *t = NULL; |
271 | int padding; |
272 | |
273 | if (s->nb_streams > AVI_MAX_STREAM_COUNT) { |
274 | av_log(s, AV_LOG_ERROR, "AVI does not support >%d streams\n", |
275 | AVI_MAX_STREAM_COUNT); |
276 | return AVERROR(EINVAL); |
277 | } |
278 | |
279 | for (n = 0; n < s->nb_streams; n++) { |
280 | s->streams[n]->priv_data = av_mallocz(sizeof(AVIStream)); |
281 | if (!s->streams[n]->priv_data) |
282 | return AVERROR(ENOMEM); |
283 | } |
284 | |
285 | /* header list */ |
286 | avi->riff_id = 0; |
287 | list1 = avi_start_new_riff(s, pb, "AVI ", "hdrl"); |
288 | |
289 | /* avi header */ |
290 | ffio_wfourcc(pb, "avih"); |
291 | avio_wl32(pb, 14 * 4); |
292 | bitrate = 0; |
293 | |
294 | video_par = NULL; |
295 | for (n = 0; n < s->nb_streams; n++) { |
296 | AVCodecParameters *par = s->streams[n]->codecpar; |
297 | AVStream *st = s->streams[n]; |
298 | bitrate = FFMIN(bitrate + par->bit_rate, INT32_MAX); |
299 | if (st->duration > 0) { |
300 | int64_t stream_duration = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q); |
301 | max_stream_duration = FFMAX(stream_duration, max_stream_duration); |
302 | } |
303 | if (par->codec_type == AVMEDIA_TYPE_VIDEO) { |
304 | video_par = par; |
305 | video_st = st; |
306 | } |
307 | } |
308 | |
309 | /* guess master index size based on bitrate and duration */ |
310 | if (!avi->reserve_index_space) { |
311 | double duration_est, filesize_est; |
312 | if (s->duration > 0) |
313 | duration_est = (double)s->duration / AV_TIME_BASE; |
314 | else if (max_stream_duration > 0) |
315 | duration_est = (double)max_stream_duration / AV_TIME_BASE; |
316 | else |
317 | duration_est = 10 * 60 * 60; /* default to 10 hours */ |
318 | filesize_est = duration_est * (bitrate / 8) * 1.10; /* add 10% safety margin for muxer+bitrate */ |
319 | avi->master_index_max_size = FFMAX((int)ceil(filesize_est / AVI_MAX_RIFF_SIZE) + 1, |
320 | avi->master_index_max_size); |
321 | av_log(s, AV_LOG_DEBUG, "duration_est:%0.3f, filesize_est:%0.1fGiB, master_index_max_size:%d\n", |
322 | duration_est, filesize_est / (1024*1024*1024), avi->master_index_max_size); |
323 | } |
324 | |
325 | nb_frames = 0; |
326 | |
327 | // TODO: should be avg_frame_rate |
328 | if (video_st) |
329 | avio_wl32(pb, (uint32_t) (INT64_C(1000000) * video_st->time_base.num / |
330 | video_st->time_base.den)); |
331 | else |
332 | avio_wl32(pb, 0); |
333 | avio_wl32(pb, bitrate / 8); /* XXX: not quite exact */ |
334 | avio_wl32(pb, 0); /* padding */ |
335 | if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) |
336 | avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */ |
337 | else |
338 | avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ |
339 | avi->frames_hdr_all = avio_tell(pb); /* remember this offset to fill later */ |
340 | avio_wl32(pb, nb_frames); /* nb frames, filled later */ |
341 | avio_wl32(pb, 0); /* initial frame */ |
342 | avio_wl32(pb, s->nb_streams); /* nb streams */ |
343 | avio_wl32(pb, 1024 * 1024); /* suggested buffer size */ |
344 | if (video_par) { |
345 | avio_wl32(pb, video_par->width); |
346 | avio_wl32(pb, video_par->height); |
347 | } else { |
348 | avio_wl32(pb, 0); |
349 | avio_wl32(pb, 0); |
350 | } |
351 | avio_wl32(pb, 0); /* reserved */ |
352 | avio_wl32(pb, 0); /* reserved */ |
353 | avio_wl32(pb, 0); /* reserved */ |
354 | avio_wl32(pb, 0); /* reserved */ |
355 | |
356 | /* stream list */ |
357 | for (i = 0; i < n; i++) { |
358 | AVStream *st = s->streams[i]; |
359 | AVCodecParameters *par = st->codecpar; |
360 | AVIStream *avist = st->priv_data; |
361 | list2 = ff_start_tag(pb, "LIST"); |
362 | ffio_wfourcc(pb, "strl"); |
363 | |
364 | /* stream generic header */ |
365 | strh = ff_start_tag(pb, "strh"); |
366 | switch (par->codec_type) { |
367 | case AVMEDIA_TYPE_SUBTITLE: |
368 | // XSUB subtitles behave like video tracks, other subtitles |
369 | // are not (yet) supported. |
370 | if (par->codec_id != AV_CODEC_ID_XSUB) { |
371 | avpriv_report_missing_feature(s, "Subtitle streams other than DivX XSUB"); |
372 | return AVERROR_PATCHWELCOME; |
373 | } |
374 | case AVMEDIA_TYPE_VIDEO: |
375 | ffio_wfourcc(pb, "vids"); |
376 | break; |
377 | case AVMEDIA_TYPE_AUDIO: |
378 | ffio_wfourcc(pb, "auds"); |
379 | break; |
380 | // case AVMEDIA_TYPE_TEXT: |
381 | // ffio_wfourcc(pb, "txts"); |
382 | // break; |
383 | case AVMEDIA_TYPE_DATA: |
384 | ffio_wfourcc(pb, "dats"); |
385 | break; |
386 | } |
387 | if (par->codec_type == AVMEDIA_TYPE_VIDEO || |
388 | par->codec_id == AV_CODEC_ID_XSUB) |
389 | avio_wl32(pb, par->codec_tag); |
390 | else |
391 | avio_wl32(pb, 1); |
392 | avist->strh_flags_offset = avio_tell(pb); |
393 | avio_wl32(pb, 0); /* flags */ |
394 | avio_wl16(pb, 0); /* priority */ |
395 | avio_wl16(pb, 0); /* language */ |
396 | avio_wl32(pb, 0); /* initial frame */ |
397 | |
398 | ff_parse_specific_params(st, &au_byterate, &au_ssize, &au_scale); |
399 | |
400 | if ( par->codec_type == AVMEDIA_TYPE_VIDEO |
401 | && par->codec_id != AV_CODEC_ID_XSUB |
402 | && au_byterate > 1000LL*au_scale) { |
403 | au_byterate = 600; |
404 | au_scale = 1; |
405 | } |
406 | avpriv_set_pts_info(st, 64, au_scale, au_byterate); |
407 | if (par->codec_id == AV_CODEC_ID_XSUB) |
408 | au_scale = au_byterate = 0; |
409 | |
410 | avio_wl32(pb, au_scale); /* scale */ |
411 | avio_wl32(pb, au_byterate); /* rate */ |
412 | |
413 | avio_wl32(pb, 0); /* start */ |
414 | /* remember this offset to fill later */ |
415 | avist->frames_hdr_strm = avio_tell(pb); |
416 | if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) |
417 | /* FIXME: this may be broken, but who cares */ |
418 | avio_wl32(pb, AVI_MAX_RIFF_SIZE); |
419 | else |
420 | avio_wl32(pb, 0); /* length, XXX: filled later */ |
421 | |
422 | /* suggested buffer size, is set to largest chunk size in avi_write_trailer */ |
423 | if (par->codec_type == AVMEDIA_TYPE_VIDEO) |
424 | avio_wl32(pb, 1024 * 1024); |
425 | else if (par->codec_type == AVMEDIA_TYPE_AUDIO) |
426 | avio_wl32(pb, 12 * 1024); |
427 | else |
428 | avio_wl32(pb, 0); |
429 | avio_wl32(pb, -1); /* quality */ |
430 | avio_wl32(pb, au_ssize); /* sample size */ |
431 | avio_wl32(pb, 0); |
432 | avio_wl16(pb, par->width); |
433 | avio_wl16(pb, par->height); |
434 | ff_end_tag(pb, strh); |
435 | |
436 | if (par->codec_type != AVMEDIA_TYPE_DATA) { |
437 | int ret, flags; |
438 | enum AVPixelFormat pix_fmt; |
439 | |
440 | strf = ff_start_tag(pb, "strf"); |
441 | switch (par->codec_type) { |
442 | case AVMEDIA_TYPE_SUBTITLE: |
443 | /* XSUB subtitles behave like video tracks, other subtitles |
444 | * are not (yet) supported. */ |
445 | if (par->codec_id != AV_CODEC_ID_XSUB) |
446 | break; |
447 | case AVMEDIA_TYPE_VIDEO: |
448 | /* WMP expects RGB 5:5:5 rawvideo in avi to have bpp set to 16. */ |
449 | if ( !par->codec_tag |
450 | && par->codec_id == AV_CODEC_ID_RAWVIDEO |
451 | && par->format == AV_PIX_FMT_RGB555LE |
452 | && par->bits_per_coded_sample == 15) |
453 | par->bits_per_coded_sample = 16; |
454 | avist->pal_offset = avio_tell(pb) + 40; |
455 | ff_put_bmp_header(pb, par, ff_codec_bmp_tags, 0, 0); |
456 | pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, |
457 | par->bits_per_coded_sample); |
458 | if ( !par->codec_tag |
459 | && par->codec_id == AV_CODEC_ID_RAWVIDEO |
460 | && par->format != pix_fmt |
461 | && par->format != AV_PIX_FMT_NONE) |
462 | av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to avi, output file will be unreadable\n", |
463 | av_get_pix_fmt_name(par->format)); |
464 | break; |
465 | case AVMEDIA_TYPE_AUDIO: |
466 | flags = (avi->write_channel_mask == 0) ? FF_PUT_WAV_HEADER_SKIP_CHANNELMASK : 0; |
467 | if ((ret = ff_put_wav_header(s, pb, par, flags)) < 0) |
468 | return ret; |
469 | break; |
470 | default: |
471 | av_log(s, AV_LOG_ERROR, |
472 | "Invalid or not supported codec type '%s' found in the input\n", |
473 | (char *)av_x_if_null(av_get_media_type_string(par->codec_type), "?")); |
474 | return AVERROR(EINVAL); |
475 | } |
476 | ff_end_tag(pb, strf); |
477 | if ((t = av_dict_get(st->metadata, "title", NULL, 0))) { |
478 | ff_riff_write_info_tag(s->pb, "strn", t->value); |
479 | t = NULL; |
480 | } |
481 | if (par->codec_id == AV_CODEC_ID_XSUB |
482 | && (t = av_dict_get(s->streams[i]->metadata, "language", NULL, 0))) { |
483 | const char* langstr = ff_convert_lang_to(t->value, AV_LANG_ISO639_1); |
484 | t = NULL; |
485 | if (langstr) { |
486 | char* str = av_asprintf("Subtitle - %s-xx;02", langstr); |
487 | if (!str) |
488 | return AVERROR(ENOMEM); |
489 | ff_riff_write_info_tag(s->pb, "strn", str); |
490 | av_free(str); |
491 | } |
492 | } |
493 | } |
494 | |
495 | if (pb->seekable & AVIO_SEEKABLE_NORMAL) { |
496 | write_odml_master(s, i); |
497 | } |
498 | |
499 | if (par->codec_type == AVMEDIA_TYPE_VIDEO && |
500 | st->sample_aspect_ratio.num > 0 && |
501 | st->sample_aspect_ratio.den > 0) { |
502 | int vprp = ff_start_tag(pb, "vprp"); |
503 | AVRational dar = av_mul_q(st->sample_aspect_ratio, |
504 | (AVRational) { par->width, |
505 | par->height }); |
506 | int num, den; |
507 | av_reduce(&num, &den, dar.num, dar.den, 0xFFFF); |
508 | |
509 | avio_wl32(pb, 0); // video format = unknown |
510 | avio_wl32(pb, 0); // video standard = unknown |
511 | // TODO: should be avg_frame_rate |
512 | avio_wl32(pb, (2LL*st->time_base.den + st->time_base.num - 1) / (2LL * st->time_base.num)); |
513 | avio_wl32(pb, par->width); |
514 | avio_wl32(pb, par->height); |
515 | avio_wl16(pb, den); |
516 | avio_wl16(pb, num); |
517 | avio_wl32(pb, par->width); |
518 | avio_wl32(pb, par->height); |
519 | avio_wl32(pb, 1); // progressive FIXME |
520 | |
521 | avio_wl32(pb, par->height); |
522 | avio_wl32(pb, par->width); |
523 | avio_wl32(pb, par->height); |
524 | avio_wl32(pb, par->width); |
525 | avio_wl32(pb, 0); |
526 | avio_wl32(pb, 0); |
527 | |
528 | avio_wl32(pb, 0); |
529 | avio_wl32(pb, 0); |
530 | ff_end_tag(pb, vprp); |
531 | } |
532 | |
533 | ff_end_tag(pb, list2); |
534 | } |
535 | |
536 | if (pb->seekable & AVIO_SEEKABLE_NORMAL) { |
537 | /* AVI could become an OpenDML one, if it grows beyond 2Gb range */ |
538 | avi->odml_list = ff_start_tag(pb, "JUNK"); |
539 | ffio_wfourcc(pb, "odml"); |
540 | ffio_wfourcc(pb, "dmlh"); |
541 | avio_wl32(pb, 248); |
542 | for (i = 0; i < 248; i += 4) |
543 | avio_wl32(pb, 0); |
544 | ff_end_tag(pb, avi->odml_list); |
545 | } |
546 | |
547 | ff_end_tag(pb, list1); |
548 | |
549 | ff_riff_write_info(s); |
550 | |
551 | |
552 | padding = s->metadata_header_padding; |
553 | if (padding < 0) |
554 | padding = 1016; |
555 | |
556 | /* some padding for easier tag editing */ |
557 | if (padding) { |
558 | list2 = ff_start_tag(pb, "JUNK"); |
559 | for (i = padding; i > 0; i -= 4) |
560 | avio_wl32(pb, 0); |
561 | ff_end_tag(pb, list2); |
562 | } |
563 | |
564 | avi->movi_list = ff_start_tag(pb, "LIST"); |
565 | ffio_wfourcc(pb, "movi"); |
566 | |
567 | avio_flush(pb); |
568 | |
569 | return 0; |
570 | } |
571 | |
572 | static void update_odml_entry(AVFormatContext *s, int stream_index, int64_t ix, int size) |
573 | { |
574 | AVIOContext *pb = s->pb; |
575 | AVIContext *avi = s->priv_data; |
576 | AVIStream *avist = s->streams[stream_index]->priv_data; |
577 | int64_t pos; |
578 | int au_byterate, au_ssize, au_scale; |
579 | |
580 | avio_flush(pb); |
581 | pos = avio_tell(pb); |
582 | |
583 | /* Updating one entry in the AVI OpenDML master index */ |
584 | avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET); |
585 | ffio_wfourcc(pb, "indx"); /* enabling this entry */ |
586 | avio_skip(pb, 8); |
587 | avio_wl32(pb, avi->riff_id - avist->indexes.master_odml_riff_id_base); /* nEntriesInUse */ |
588 | avio_skip(pb, 16 * (avi->riff_id - avist->indexes.master_odml_riff_id_base)); |
589 | avio_wl64(pb, ix); /* qwOffset */ |
590 | avio_wl32(pb, size); /* dwSize */ |
591 | ff_parse_specific_params(s->streams[stream_index], &au_byterate, &au_ssize, &au_scale); |
592 | if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && au_ssize > 0) { |
593 | uint32_t audio_segm_size = (avist->audio_strm_length - avist->indexes.audio_strm_offset); |
594 | if ((audio_segm_size % au_ssize > 0) && !avist->sample_requested) { |
595 | avpriv_request_sample(s, "OpenDML index duration for audio packets with partial frames"); |
596 | avist->sample_requested = 1; |
597 | } |
598 | avio_wl32(pb, audio_segm_size / au_ssize); /* dwDuration (sample count) */ |
599 | } else |
600 | avio_wl32(pb, avist->indexes.entry); /* dwDuration (packet count) */ |
601 | |
602 | avio_seek(pb, pos, SEEK_SET); |
603 | } |
604 | |
605 | static int avi_write_ix(AVFormatContext *s) |
606 | { |
607 | AVIOContext *pb = s->pb; |
608 | AVIContext *avi = s->priv_data; |
609 | char tag[5]; |
610 | char ix_tag[] = "ix00"; |
611 | int i, j; |
612 | |
613 | av_assert0(pb->seekable & AVIO_SEEKABLE_NORMAL); |
614 | |
615 | for (i = 0; i < s->nb_streams; i++) { |
616 | AVIStream *avist = s->streams[i]->priv_data; |
617 | if (avi->riff_id - avist->indexes.master_odml_riff_id_base == avi->master_index_max_size) { |
618 | int64_t pos; |
619 | int size = AVI_MASTER_INDEX_PREFIX_SIZE + AVI_MASTER_INDEX_ENTRY_SIZE * avi->master_index_max_size; |
620 | |
621 | pos = avio_tell(pb); |
622 | update_odml_entry(s, i, pos, size); |
623 | write_odml_master(s, i); |
624 | av_assert1(avio_tell(pb) - pos == size); |
625 | avist->indexes.master_odml_riff_id_base = avi->riff_id - 1; |
626 | } |
627 | av_assert0(avi->riff_id - avist->indexes.master_odml_riff_id_base < avi->master_index_max_size); |
628 | } |
629 | |
630 | for (i = 0; i < s->nb_streams; i++) { |
631 | AVIStream *avist = s->streams[i]->priv_data; |
632 | int64_t ix; |
633 | |
634 | avi_stream2fourcc(tag, i, s->streams[i]->codecpar->codec_type); |
635 | ix_tag[3] = '0' + i; |
636 | |
637 | /* Writing AVI OpenDML leaf index chunk */ |
638 | ix = avio_tell(pb); |
639 | ffio_wfourcc(pb, ix_tag); /* ix?? */ |
640 | avio_wl32(pb, avist->indexes.entry * 8 + 24); |
641 | /* chunk size */ |
642 | avio_wl16(pb, 2); /* wLongsPerEntry */ |
643 | avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */ |
644 | avio_w8(pb, 1); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */ |
645 | avio_wl32(pb, avist->indexes.entry); |
646 | /* nEntriesInUse */ |
647 | ffio_wfourcc(pb, tag); /* dwChunkId */ |
648 | avio_wl64(pb, avi->movi_list); /* qwBaseOffset */ |
649 | avio_wl32(pb, 0); /* dwReserved_3 (must be 0) */ |
650 | |
651 | for (j = 0; j < avist->indexes.entry; j++) { |
652 | AVIIentry *ie = avi_get_ientry(&avist->indexes, j); |
653 | avio_wl32(pb, ie->pos + 8); |
654 | avio_wl32(pb, ((uint32_t) ie->len & ~0x80000000) | |
655 | (ie->flags & 0x10 ? 0 : 0x80000000)); |
656 | } |
657 | |
658 | update_odml_entry(s, i, ix, avio_tell(pb) - ix); |
659 | } |
660 | return 0; |
661 | } |
662 | |
663 | static int avi_write_idx1(AVFormatContext *s) |
664 | { |
665 | AVIOContext *pb = s->pb; |
666 | AVIContext *avi = s->priv_data; |
667 | int64_t idx_chunk; |
668 | int i; |
669 | char tag[5]; |
670 | |
671 | if (pb->seekable & AVIO_SEEKABLE_NORMAL) { |
672 | AVIStream *avist; |
673 | AVIIentry *ie = 0, *tie; |
674 | int empty, stream_id = -1; |
675 | |
676 | idx_chunk = ff_start_tag(pb, "idx1"); |
677 | for (i = 0; i < s->nb_streams; i++) { |
678 | avist = s->streams[i]->priv_data; |
679 | avist->entry = 0; |
680 | } |
681 | |
682 | do { |
683 | empty = 1; |
684 | for (i = 0; i < s->nb_streams; i++) { |
685 | avist = s->streams[i]->priv_data; |
686 | if (avist->indexes.entry <= avist->entry) |
687 | continue; |
688 | |
689 | tie = avi_get_ientry(&avist->indexes, avist->entry); |
690 | if (empty || tie->pos < ie->pos) { |
691 | ie = tie; |
692 | stream_id = i; |
693 | } |
694 | empty = 0; |
695 | } |
696 | if (!empty) { |
697 | avist = s->streams[stream_id]->priv_data; |
698 | if (*ie->tag) |
699 | ffio_wfourcc(pb, ie->tag); |
700 | else { |
701 | avi_stream2fourcc(tag, stream_id, |
702 | s->streams[stream_id]->codecpar->codec_type); |
703 | ffio_wfourcc(pb, tag); |
704 | } |
705 | avio_wl32(pb, ie->flags); |
706 | avio_wl32(pb, ie->pos); |
707 | avio_wl32(pb, ie->len); |
708 | avist->entry++; |
709 | } |
710 | } while (!empty); |
711 | ff_end_tag(pb, idx_chunk); |
712 | |
713 | avi_write_counters(s, avi->riff_id); |
714 | } |
715 | return 0; |
716 | } |
717 | |
718 | static int write_skip_frames(AVFormatContext *s, int stream_index, int64_t dts) |
719 | { |
720 | AVIStream *avist = s->streams[stream_index]->priv_data; |
721 | AVCodecParameters *par = s->streams[stream_index]->codecpar; |
722 | |
723 | ff_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(dts), avist->packet_count, stream_index); |
724 | while (par->block_align == 0 && dts != AV_NOPTS_VALUE && |
725 | dts > avist->packet_count && par->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) { |
726 | AVPacket empty_packet; |
727 | |
728 | if (dts - avist->packet_count > 60000) { |
729 | av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", dts - avist->packet_count); |
730 | return AVERROR(EINVAL); |
731 | } |
732 | |
733 | av_init_packet(&empty_packet); |
734 | empty_packet.size = 0; |
735 | empty_packet.data = NULL; |
736 | empty_packet.stream_index = stream_index; |
737 | avi_write_packet_internal(s, &empty_packet); |
738 | ff_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(dts), avist->packet_count); |
739 | } |
740 | |
741 | return 0; |
742 | } |
743 | |
744 | static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) |
745 | { |
746 | const int stream_index = pkt->stream_index; |
747 | AVCodecParameters *par = s->streams[stream_index]->codecpar; |
748 | int ret; |
749 | |
750 | if (par->codec_id == AV_CODEC_ID_H264 && par->codec_tag == MKTAG('H','2','6','4') && pkt->size) { |
751 | ret = ff_check_h264_startcode(s, s->streams[stream_index], pkt); |
752 | if (ret < 0) |
753 | return ret; |
754 | } |
755 | |
756 | if ((ret = write_skip_frames(s, stream_index, pkt->dts)) < 0) |
757 | return ret; |
758 | |
759 | if (!pkt->size) |
760 | return avi_write_packet_internal(s, pkt); /* Passthrough */ |
761 | |
762 | if (par->codec_type == AVMEDIA_TYPE_VIDEO) { |
763 | AVIStream *avist = s->streams[stream_index]->priv_data; |
764 | AVIOContext *pb = s->pb; |
765 | AVPacket *opkt = pkt; |
766 | int reshuffle_ret; |
767 | if (par->codec_id == AV_CODEC_ID_RAWVIDEO && par->codec_tag == 0) { |
768 | int64_t bpc = par->bits_per_coded_sample != 15 ? par->bits_per_coded_sample : 16; |
769 | int expected_stride = ((par->width * bpc + 31) >> 5)*4; |
770 | reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, par, expected_stride); |
771 | if (reshuffle_ret < 0) |
772 | return reshuffle_ret; |
773 | } else |
774 | reshuffle_ret = 0; |
775 | if (par->format == AV_PIX_FMT_PAL8) { |
776 | ret = ff_get_packet_palette(s, opkt, reshuffle_ret, avist->palette); |
777 | if (ret < 0) |
778 | goto fail; |
779 | if (ret) { |
780 | int pal_size = 1 << par->bits_per_coded_sample; |
781 | int pc_tag, i; |
782 | |
783 | av_assert0(par->bits_per_coded_sample >= 0 && par->bits_per_coded_sample <= 8); |
784 | |
785 | if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && avist->pal_offset) { |
786 | int64_t cur_offset = avio_tell(pb); |
787 | avio_seek(pb, avist->pal_offset, SEEK_SET); |
788 | for (i = 0; i < pal_size; i++) { |
789 | uint32_t v = avist->palette[i]; |
790 | avio_wl32(pb, v & 0xffffff); |
791 | } |
792 | avio_seek(pb, cur_offset, SEEK_SET); |
793 | memcpy(avist->old_palette, avist->palette, pal_size * 4); |
794 | avist->pal_offset = 0; |
795 | } |
796 | if (memcmp(avist->palette, avist->old_palette, pal_size * 4)) { |
797 | unsigned char tag[5]; |
798 | avi_stream2fourcc(tag, stream_index, par->codec_type); |
799 | tag[2] = 'p'; tag[3] = 'c'; |
800 | if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { |
801 | if (avist->strh_flags_offset) { |
802 | int64_t cur_offset = avio_tell(pb); |
803 | avio_seek(pb, avist->strh_flags_offset, SEEK_SET); |
804 | avio_wl32(pb, AVISF_VIDEO_PALCHANGES); |
805 | avio_seek(pb, cur_offset, SEEK_SET); |
806 | avist->strh_flags_offset = 0; |
807 | } |
808 | ret = avi_add_ientry(s, stream_index, tag, AVIIF_NO_TIME, |
809 | pal_size * 4 + 4); |
810 | if (ret < 0) |
811 | goto fail; |
812 | } |
813 | pc_tag = ff_start_tag(pb, tag); |
814 | avio_w8(pb, 0); |
815 | avio_w8(pb, pal_size & 0xFF); |
816 | avio_wl16(pb, 0); // reserved |
817 | for (i = 0; i < pal_size; i++) { |
818 | uint32_t v = avist->palette[i]; |
819 | avio_wb32(pb, v<<8); |
820 | } |
821 | ff_end_tag(pb, pc_tag); |
822 | memcpy(avist->old_palette, avist->palette, pal_size * 4); |
823 | } |
824 | } |
825 | } |
826 | if (reshuffle_ret) { |
827 | ret = avi_write_packet_internal(s, pkt); |
828 | |
829 | fail: |
830 | if (reshuffle_ret) |
831 | av_packet_free(&pkt); |
832 | return ret; |
833 | } |
834 | } |
835 | |
836 | return avi_write_packet_internal(s, pkt); |
837 | } |
838 | |
839 | static int avi_write_packet_internal(AVFormatContext *s, AVPacket *pkt) |
840 | { |
841 | unsigned char tag[5]; |
842 | unsigned int flags = 0; |
843 | const int stream_index = pkt->stream_index; |
844 | int size = pkt->size; |
845 | AVIContext *avi = s->priv_data; |
846 | AVIOContext *pb = s->pb; |
847 | AVIStream *avist = s->streams[stream_index]->priv_data; |
848 | AVCodecParameters *par = s->streams[stream_index]->codecpar; |
849 | |
850 | if (pkt->dts != AV_NOPTS_VALUE) |
851 | avist->last_dts = pkt->dts + pkt->duration; |
852 | |
853 | avist->packet_count++; |
854 | |
855 | // Make sure to put an OpenDML chunk when the file size exceeds the limits |
856 | if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && |
857 | (avio_tell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) { |
858 | avi_write_ix(s); |
859 | ff_end_tag(pb, avi->movi_list); |
860 | |
861 | if (avi->riff_id == 1) |
862 | avi_write_idx1(s); |
863 | |
864 | ff_end_tag(pb, avi->riff_start); |
865 | avi->movi_list = avi_start_new_riff(s, pb, "AVIX", "movi"); |
866 | } |
867 | |
868 | avi_stream2fourcc(tag, stream_index, par->codec_type); |
869 | if (pkt->flags & AV_PKT_FLAG_KEY) |
870 | flags = 0x10; |
871 | if (par->codec_type == AVMEDIA_TYPE_AUDIO) |
872 | avist->audio_strm_length += size; |
873 | |
874 | if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { |
875 | int ret; |
876 | ret = avi_add_ientry(s, stream_index, NULL, flags, size); |
877 | if (ret < 0) |
878 | return ret; |
879 | } |
880 | |
881 | avio_write(pb, tag, 4); |
882 | avio_wl32(pb, size); |
883 | avio_write(pb, pkt->data, size); |
884 | if (size & 1) |
885 | avio_w8(pb, 0); |
886 | |
887 | return 0; |
888 | } |
889 | |
890 | static int avi_write_trailer(AVFormatContext *s) |
891 | { |
892 | AVIContext *avi = s->priv_data; |
893 | AVIOContext *pb = s->pb; |
894 | int res = 0; |
895 | int i, j, n, nb_frames; |
896 | int64_t file_size; |
897 | |
898 | for (i = 0; i < s->nb_streams; i++) { |
899 | AVIStream *avist = s->streams[i]->priv_data; |
900 | write_skip_frames(s, i, avist->last_dts); |
901 | } |
902 | |
903 | if (pb->seekable & AVIO_SEEKABLE_NORMAL) { |
904 | if (avi->riff_id == 1) { |
905 | ff_end_tag(pb, avi->movi_list); |
906 | res = avi_write_idx1(s); |
907 | ff_end_tag(pb, avi->riff_start); |
908 | } else { |
909 | avi_write_ix(s); |
910 | ff_end_tag(pb, avi->movi_list); |
911 | ff_end_tag(pb, avi->riff_start); |
912 | |
913 | file_size = avio_tell(pb); |
914 | avio_seek(pb, avi->odml_list - 8, SEEK_SET); |
915 | ffio_wfourcc(pb, "LIST"); /* Making this AVI OpenDML one */ |
916 | avio_skip(pb, 16); |
917 | |
918 | for (n = nb_frames = 0; n < s->nb_streams; n++) { |
919 | AVCodecParameters *par = s->streams[n]->codecpar; |
920 | AVIStream *avist = s->streams[n]->priv_data; |
921 | |
922 | if (par->codec_type == AVMEDIA_TYPE_VIDEO) { |
923 | if (nb_frames < avist->packet_count) |
924 | nb_frames = avist->packet_count; |
925 | } else { |
926 | if (par->codec_id == AV_CODEC_ID_MP2 || |
927 | par->codec_id == AV_CODEC_ID_MP3) |
928 | nb_frames += avist->packet_count; |
929 | } |
930 | } |
931 | avio_wl32(pb, nb_frames); |
932 | avio_seek(pb, file_size, SEEK_SET); |
933 | |
934 | avi_write_counters(s, avi->riff_id); |
935 | } |
936 | } |
937 | |
938 | if (avi->riff_id >= avi->master_index_max_size) { |
939 | int index_space = AVI_MASTER_INDEX_PREFIX_SIZE + |
940 | AVI_MASTER_INDEX_ENTRY_SIZE * avi->riff_id; |
941 | av_log(s, AV_LOG_WARNING, "Output file not strictly OpenDML compliant, " |
942 | "consider re-muxing with 'reserve_index_space' option value >= %d\n", |
943 | index_space); |
944 | } |
945 | |
946 | for (i = 0; i < s->nb_streams; i++) { |
947 | AVIStream *avist = s->streams[i]->priv_data; |
948 | for (j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++) |
949 | av_freep(&avist->indexes.cluster[j]); |
950 | av_freep(&avist->indexes.cluster); |
951 | avist->indexes.ents_allocated = avist->indexes.entry = 0; |
952 | if (pb->seekable & AVIO_SEEKABLE_NORMAL) { |
953 | avio_seek(pb, avist->frames_hdr_strm + 4, SEEK_SET); |
954 | avio_wl32(pb, avist->max_size); |
955 | } |
956 | } |
957 | |
958 | return res; |
959 | } |
960 | |
961 | #define OFFSET(x) offsetof(AVIContext, x) |
962 | #define ENC AV_OPT_FLAG_ENCODING_PARAM |
963 | static const AVOption options[] = { |
964 | { "reserve_index_space", "reserve space (in bytes) at the beginning of the file for each stream index", OFFSET(reserve_index_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, ENC }, |
965 | { "write_channel_mask", "write channel mask into wave format header", OFFSET(write_channel_mask), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC }, |
966 | { NULL }, |
967 | }; |
968 | |
969 | static const AVClass avi_muxer_class = { |
970 | .class_name = "AVI muxer", |
971 | .item_name = av_default_item_name, |
972 | .option = options, |
973 | .version = LIBAVUTIL_VERSION_INT, |
974 | }; |
975 | |
976 | AVOutputFormat ff_avi_muxer = { |
977 | .name = "avi", |
978 | .long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"), |
979 | .mime_type = "video/x-msvideo", |
980 | .extensions = "avi", |
981 | .priv_data_size = sizeof(AVIContext), |
982 | .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3, |
983 | .video_codec = AV_CODEC_ID_MPEG4, |
984 | .init = avi_init, |
985 | .write_header = avi_write_header, |
986 | .write_packet = avi_write_packet, |
987 | .write_trailer = avi_write_trailer, |
988 | .codec_tag = (const AVCodecTag * const []) { |
989 | ff_codec_bmp_tags, ff_codec_wav_tags, 0 |
990 | }, |
991 | .priv_class = &avi_muxer_class, |
992 | }; |
993 |