3 * Copyright (c) 2003 Thomas Raivio
4 * Copyright (c) 2004 Gildas Bazin <gbazin at videolan dot org>
5 * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
7 * This file is part of Libav.
9 * Libav is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * Libav is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with Libav; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "avio_internal.h"
31 #include "libavcodec/get_bits.h"
32 #include "libavcodec/put_bits.h"
33 #include "libavcodec/vc1.h"
35 #include "libavutil/avstring.h"
36 #include "libavutil/intfloat.h"
37 #include "libavutil/mathematics.h"
38 #include "libavutil/opt.h"
39 #include "libavutil/dict.h"
46 static const AVOption options
[] = {
47 { "movflags", "MOV muxer flags", offsetof(MOVMuxContext
, flags
), AV_OPT_TYPE_FLAGS
, {.i64
= 0}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
48 { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_RTP_HINT
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
49 { "empty_moov", "Make the initial moov atom empty (not supported by QuickTime)", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_EMPTY_MOOV
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
50 { "frag_keyframe", "Fragment at video keyframes", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_FRAG_KEYFRAME
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
51 { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_SEPARATE_MOOF
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
52 { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_FRAG_CUSTOM
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
53 { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_ISML
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
54 { "faststart", "Run a second pass to put the index (moov atom) at the beginning of the file", 0, AV_OPT_TYPE_CONST
, {.i64
= FF_MOV_FLAG_FASTSTART
}, INT_MIN
, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
, "movflags" },
55 FF_RTP_FLAG_OPTS(MOVMuxContext
, rtp_flags
),
56 { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext
, iods_skip
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM
},
57 { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext
, iods_audio_profile
), AV_OPT_TYPE_INT
, {.i64
= -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM
},
58 { "iods_video_profile", "iods video profile atom.", offsetof(MOVMuxContext
, iods_video_profile
), AV_OPT_TYPE_INT
, {.i64
= -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM
},
59 { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext
, max_fragment_duration
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
60 { "min_frag_duration", "Minimum fragment duration", offsetof(MOVMuxContext
, min_fragment_duration
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
61 { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext
, max_fragment_size
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
62 { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext
, ism_lookahead
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, INT_MAX
, AV_OPT_FLAG_ENCODING_PARAM
},
66 #define MOV_CLASS(flavor)\
67 static const AVClass flavor ## _muxer_class = {\
68 .class_name = #flavor " muxer",\
69 .item_name = av_default_item_name,\
71 .version = LIBAVUTIL_VERSION_INT,\
74 //FIXME support 64 bit variant with wide placeholders
75 static int64_t update_size(AVIOContext
*pb
, int64_t pos
)
77 int64_t curpos
= avio_tell(pb
);
78 avio_seek(pb
, pos
, SEEK_SET
);
79 avio_wb32(pb
, curpos
- pos
); /* rewrite size */
80 avio_seek(pb
, curpos
, SEEK_SET
);
85 static int co64_required(const MOVTrack
*track
)
87 if (track
->entry
> 0 && track
->cluster
[track
->entry
- 1].pos
+ track
->data_offset
> UINT32_MAX
)
92 /* Chunk offset atom */
93 static int mov_write_stco_tag(AVIOContext
*pb
, MOVTrack
*track
)
96 int mode64
= co64_required(track
); // use 32 bit size variant if possible
97 int64_t pos
= avio_tell(pb
);
98 avio_wb32(pb
, 0); /* size */
100 ffio_wfourcc(pb
, "co64");
102 ffio_wfourcc(pb
, "stco");
103 avio_wb32(pb
, 0); /* version & flags */
104 avio_wb32(pb
, track
->entry
); /* entry count */
105 for (i
= 0; i
< track
->entry
; i
++) {
107 avio_wb64(pb
, track
->cluster
[i
].pos
+ track
->data_offset
);
109 avio_wb32(pb
, track
->cluster
[i
].pos
+ track
->data_offset
);
111 return update_size(pb
, pos
);
114 /* Sample size atom */
115 static int mov_write_stsz_tag(AVIOContext
*pb
, MOVTrack
*track
)
118 int i
, j
, entries
= 0, tst
= -1, oldtst
= -1;
120 int64_t pos
= avio_tell(pb
);
121 avio_wb32(pb
, 0); /* size */
122 ffio_wfourcc(pb
, "stsz");
123 avio_wb32(pb
, 0); /* version & flags */
125 for (i
= 0; i
< track
->entry
; i
++) {
126 tst
= track
->cluster
[i
].size
/ track
->cluster
[i
].entries
;
127 if (oldtst
!= -1 && tst
!= oldtst
)
130 entries
+= track
->cluster
[i
].entries
;
132 if (equalChunks
&& track
->entry
) {
133 int sSize
= track
->entry ? track
->cluster
[0].size
/ track
->cluster
[0].entries
: 0;
134 sSize
= FFMAX(1, sSize
); // adpcm mono case could make sSize == 0
135 avio_wb32(pb
, sSize
); // sample size
136 avio_wb32(pb
, entries
); // sample count
138 avio_wb32(pb
, 0); // sample size
139 avio_wb32(pb
, entries
); // sample count
140 for (i
= 0; i
< track
->entry
; i
++) {
141 for (j
= 0; j
< track
->cluster
[i
].entries
; j
++) {
142 avio_wb32(pb
, track
->cluster
[i
].size
/
143 track
->cluster
[i
].entries
);
147 return update_size(pb
, pos
);
150 /* Sample to chunk atom */
151 static int mov_write_stsc_tag(AVIOContext
*pb
, MOVTrack
*track
)
153 int index
= 0, oldval
= -1, i
;
154 int64_t entryPos
, curpos
;
156 int64_t pos
= avio_tell(pb
);
157 avio_wb32(pb
, 0); /* size */
158 ffio_wfourcc(pb
, "stsc");
159 avio_wb32(pb
, 0); // version & flags
160 entryPos
= avio_tell(pb
);
161 avio_wb32(pb
, track
->entry
); // entry count
162 for (i
= 0; i
< track
->entry
; i
++) {
163 if (oldval
!= track
->cluster
[i
].samples_in_chunk
) {
164 avio_wb32(pb
, i
+ 1); // first chunk
165 avio_wb32(pb
, track
->cluster
[i
].samples_in_chunk
); // samples per chunk
166 avio_wb32(pb
, 0x1); // sample description index
167 oldval
= track
->cluster
[i
].samples_in_chunk
;
171 curpos
= avio_tell(pb
);
172 avio_seek(pb
, entryPos
, SEEK_SET
);
173 avio_wb32(pb
, index
); // rewrite size
174 avio_seek(pb
, curpos
, SEEK_SET
);
176 return update_size(pb
, pos
);
179 /* Sync sample atom */
180 static int mov_write_stss_tag(AVIOContext
*pb
, MOVTrack
*track
, uint32_t flag
)
182 int64_t curpos
, entryPos
;
184 int64_t pos
= avio_tell(pb
);
185 avio_wb32(pb
, 0); // size
186 ffio_wfourcc(pb
, flag
== MOV_SYNC_SAMPLE ?
"stss" : "stps");
187 avio_wb32(pb
, 0); // version & flags
188 entryPos
= avio_tell(pb
);
189 avio_wb32(pb
, track
->entry
); // entry count
190 for (i
= 0; i
< track
->entry
; i
++) {
191 if (track
->cluster
[i
].flags
& flag
) {
192 avio_wb32(pb
, i
+ 1);
196 curpos
= avio_tell(pb
);
197 avio_seek(pb
, entryPos
, SEEK_SET
);
198 avio_wb32(pb
, index
); // rewrite size
199 avio_seek(pb
, curpos
, SEEK_SET
);
200 return update_size(pb
, pos
);
203 static int mov_write_amr_tag(AVIOContext
*pb
, MOVTrack
*track
)
205 avio_wb32(pb
, 0x11); /* size */
206 if (track
->mode
== MODE_MOV
) ffio_wfourcc(pb
, "samr");
207 else ffio_wfourcc(pb
, "damr");
208 ffio_wfourcc(pb
, "FFMP");
209 avio_w8(pb
, 0); /* decoder version */
211 avio_wb16(pb
, 0x81FF); /* Mode set (all modes for AMR_NB) */
212 avio_w8(pb
, 0x00); /* Mode change period (no restriction) */
213 avio_w8(pb
, 0x01); /* Frames per sample */
217 static int mov_write_ac3_tag(AVIOContext
*pb
, MOVTrack
*track
)
222 int fscod
, bsid
, bsmod
, acmod
, lfeon
, frmsizecod
;
224 if (track
->vos_len
< 7)
228 ffio_wfourcc(pb
, "dac3");
230 init_get_bits(&gbc
, track
->vos_data
+ 4, (track
->vos_len
- 4) * 8);
231 fscod
= get_bits(&gbc
, 2);
232 frmsizecod
= get_bits(&gbc
, 6);
233 bsid
= get_bits(&gbc
, 5);
234 bsmod
= get_bits(&gbc
, 3);
235 acmod
= get_bits(&gbc
, 3);
237 skip_bits(&gbc
, 2); // dsurmod
239 if ((acmod
& 1) && acmod
!= 1)
240 skip_bits(&gbc
, 2); // cmixlev
242 skip_bits(&gbc
, 2); // surmixlev
244 lfeon
= get_bits1(&gbc
);
246 init_put_bits(&pbc
, buf
, sizeof(buf
));
247 put_bits(&pbc
, 2, fscod
);
248 put_bits(&pbc
, 5, bsid
);
249 put_bits(&pbc
, 3, bsmod
);
250 put_bits(&pbc
, 3, acmod
);
251 put_bits(&pbc
, 1, lfeon
);
252 put_bits(&pbc
, 5, frmsizecod
>> 1); // bit_rate_code
253 put_bits(&pbc
, 5, 0); // reserved
255 flush_put_bits(&pbc
);
256 avio_write(pb
, buf
, sizeof(buf
));
262 * This function writes extradata "as is".
263 * Extradata must be formatted like a valid atom (with size and tag).
265 static int mov_write_extradata_tag(AVIOContext
*pb
, MOVTrack
*track
)
267 avio_write(pb
, track
->enc
->extradata
, track
->enc
->extradata_size
);
268 return track
->enc
->extradata_size
;
271 static void put_descr(AVIOContext
*pb
, int tag
, unsigned int size
)
276 avio_w8(pb
, (size
>> (7 * i
)) | 0x80);
277 avio_w8(pb
, size
& 0x7F);
280 static int mov_write_esds_tag(AVIOContext
*pb
, MOVTrack
*track
) // Basic
282 int64_t pos
= avio_tell(pb
);
283 int decoder_specific_info_len
= track
->vos_len ?
5 + track
->vos_len
: 0;
285 avio_wb32(pb
, 0); // size
286 ffio_wfourcc(pb
, "esds");
287 avio_wb32(pb
, 0); // Version
290 put_descr(pb
, 0x03, 3 + 5+13 + decoder_specific_info_len
+ 5+1);
291 avio_wb16(pb
, track
->track_id
);
292 avio_w8(pb
, 0x00); // flags (= no flags)
294 // DecoderConfig descriptor
295 put_descr(pb
, 0x04, 13 + decoder_specific_info_len
);
297 // Object type indication
298 if ((track
->enc
->codec_id
== AV_CODEC_ID_MP2
||
299 track
->enc
->codec_id
== AV_CODEC_ID_MP3
) &&
300 track
->enc
->sample_rate
> 24000)
301 avio_w8(pb
, 0x6B); // 11172-3
303 avio_w8(pb
, ff_codec_get_tag(ff_mp4_obj_type
, track
->enc
->codec_id
));
305 // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
306 // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
307 if (track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
)
308 avio_w8(pb
, 0x15); // flags (= Audiostream)
310 avio_w8(pb
, 0x11); // flags (= Visualstream)
312 avio_wb24(pb
, track
->enc
->rc_buffer_size
>> 3); // Buffersize DB
314 avio_wb32(pb
, FFMAX(track
->enc
->bit_rate
, track
->enc
->rc_max_rate
)); // maxbitrate (FIXME should be max rate in any 1 sec window)
315 if (track
->enc
->rc_max_rate
!= track
->enc
->rc_min_rate
||
316 track
->enc
->rc_min_rate
== 0)
317 avio_wb32(pb
, 0); // vbr
319 avio_wb32(pb
, track
->enc
->rc_max_rate
); // avg bitrate
321 if (track
->vos_len
) {
322 // DecoderSpecific info descriptor
323 put_descr(pb
, 0x05, track
->vos_len
);
324 avio_write(pb
, track
->vos_data
, track
->vos_len
);
328 put_descr(pb
, 0x06, 1);
330 return update_size(pb
, pos
);
333 static int mov_write_ms_tag(AVIOContext
*pb
, MOVTrack
*track
)
335 int64_t pos
= avio_tell(pb
);
337 avio_wl32(pb
, track
->tag
); // store it byteswapped
338 track
->enc
->codec_tag
= av_bswap16(track
->tag
>> 16);
339 ff_put_wav_header(pb
, track
->enc
);
340 return update_size(pb
, pos
);
343 static int mov_write_wfex_tag(AVIOContext
*pb
, MOVTrack
*track
)
345 int64_t pos
= avio_tell(pb
);
347 ffio_wfourcc(pb
, "wfex");
348 ff_put_wav_header(pb
, track
->enc
);
349 return update_size(pb
, pos
);
352 static int mov_write_chan_tag(AVIOContext
*pb
, MOVTrack
*track
)
354 uint32_t layout_tag
, bitmap
;
355 int64_t pos
= avio_tell(pb
);
357 layout_tag
= ff_mov_get_channel_layout_tag(track
->enc
->codec_id
,
358 track
->enc
->channel_layout
,
361 av_log(track
->enc
, AV_LOG_WARNING
, "not writing 'chan' tag due to "
362 "lack of channel information\n");
366 avio_wb32(pb
, 0); // Size
367 ffio_wfourcc(pb
, "chan"); // Type
368 avio_w8(pb
, 0); // Version
369 avio_wb24(pb
, 0); // Flags
370 avio_wb32(pb
, layout_tag
); // mChannelLayoutTag
371 avio_wb32(pb
, bitmap
); // mChannelBitmap
372 avio_wb32(pb
, 0); // mNumberChannelDescriptions
374 return update_size(pb
, pos
);
377 static int mov_write_wave_tag(AVIOContext
*pb
, MOVTrack
*track
)
379 int64_t pos
= avio_tell(pb
);
381 avio_wb32(pb
, 0); /* size */
382 ffio_wfourcc(pb
, "wave");
384 avio_wb32(pb
, 12); /* size */
385 ffio_wfourcc(pb
, "frma");
386 avio_wl32(pb
, track
->tag
);
388 if (track
->enc
->codec_id
== AV_CODEC_ID_AAC
) {
389 /* useless atom needed by mplayer, ipod, not needed by quicktime */
390 avio_wb32(pb
, 12); /* size */
391 ffio_wfourcc(pb
, "mp4a");
393 mov_write_esds_tag(pb
, track
);
394 } else if (track
->enc
->codec_id
== AV_CODEC_ID_AMR_NB
) {
395 mov_write_amr_tag(pb
, track
);
396 } else if (track
->enc
->codec_id
== AV_CODEC_ID_AC3
) {
397 mov_write_ac3_tag(pb
, track
);
398 } else if (track
->enc
->codec_id
== AV_CODEC_ID_ALAC
) {
399 mov_write_extradata_tag(pb
, track
);
400 } else if (track
->enc
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
401 track
->enc
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
) {
402 mov_write_ms_tag(pb
, track
);
405 avio_wb32(pb
, 8); /* size */
406 avio_wb32(pb
, 0); /* null tag */
408 return update_size(pb
, pos
);
411 static int mov_write_dvc1_structs(MOVTrack
*track
, uint8_t *buf
)
414 const uint8_t *start
, *next
, *end
= track
->vos_data
+ track
->vos_len
;
415 int unescaped_size
, seq_found
= 0;
416 int level
= 0, interlace
= 0;
417 int packet_seq
= track
->vc1_info
.packet_seq
;
418 int packet_entry
= track
->vc1_info
.packet_entry
;
419 int slices
= track
->vc1_info
.slices
;
422 if (track
->start_dts
== AV_NOPTS_VALUE
) {
423 /* No packets written yet, vc1_info isn't authoritative yet. */
424 /* Assume inline sequence and entry headers. This will be
425 * overwritten at the end if the file is seekable. */
426 packet_seq
= packet_entry
= 1;
429 unescaped
= av_mallocz(track
->vos_len
+ FF_INPUT_BUFFER_PADDING_SIZE
);
431 return AVERROR(ENOMEM
);
432 start
= find_next_marker(track
->vos_data
, end
);
433 for (next
= start
; next
< end
; start
= next
) {
436 next
= find_next_marker(start
+ 4, end
);
437 size
= next
- start
- 4;
440 unescaped_size
= vc1_unescape_buffer(start
+ 4, size
, unescaped
);
441 init_get_bits(&gb
, unescaped
, 8 * unescaped_size
);
442 if (AV_RB32(start
) == VC1_CODE_SEQHDR
) {
443 int profile
= get_bits(&gb
, 2);
444 if (profile
!= PROFILE_ADVANCED
) {
446 return AVERROR(ENOSYS
);
449 level
= get_bits(&gb
, 3);
450 /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag,
452 skip_bits_long(&gb
, 2 + 3 + 5 + 1 + 2*12);
453 skip_bits(&gb
, 1); /* broadcast */
454 interlace
= get_bits1(&gb
);
455 skip_bits(&gb
, 4); /* tfcntrflag, finterpflag, reserved, psf */
460 return AVERROR(ENOSYS
);
463 init_put_bits(&pbc
, buf
, 7);
464 /* VC1DecSpecStruc */
465 put_bits(&pbc
, 4, 12); /* profile - advanced */
466 put_bits(&pbc
, 3, level
);
467 put_bits(&pbc
, 1, 0); /* reserved */
468 /* VC1AdvDecSpecStruc */
469 put_bits(&pbc
, 3, level
);
470 put_bits(&pbc
, 1, 0); /* cbr */
471 put_bits(&pbc
, 6, 0); /* reserved */
472 put_bits(&pbc
, 1, !interlace
); /* no interlace */
473 put_bits(&pbc
, 1, !packet_seq
); /* no multiple seq */
474 put_bits(&pbc
, 1, !packet_entry
); /* no multiple entry */
475 put_bits(&pbc
, 1, !slices
); /* no slice code */
476 put_bits(&pbc
, 1, 0); /* no bframe */
477 put_bits(&pbc
, 1, 0); /* reserved */
478 put_bits32(&pbc
, track
->enc
->time_base
.den
); /* framerate */
479 flush_put_bits(&pbc
);
486 static int mov_write_dvc1_tag(AVIOContext
*pb
, MOVTrack
*track
)
488 uint8_t buf
[7] = { 0 };
491 if ((ret
= mov_write_dvc1_structs(track
, buf
)) < 0)
494 avio_wb32(pb
, track
->vos_len
+ 8 + sizeof(buf
));
495 ffio_wfourcc(pb
, "dvc1");
496 track
->vc1_info
.struct_offset
= avio_tell(pb
);
497 avio_write(pb
, buf
, sizeof(buf
));
498 avio_write(pb
, track
->vos_data
, track
->vos_len
);
503 static int mov_write_glbl_tag(AVIOContext
*pb
, MOVTrack
*track
)
505 avio_wb32(pb
, track
->vos_len
+ 8);
506 ffio_wfourcc(pb
, "glbl");
507 avio_write(pb
, track
->vos_data
, track
->vos_len
);
508 return 8 + track
->vos_len
;
512 * Compute flags for 'lpcm' tag.
513 * See CoreAudioTypes and AudioStreamBasicDescription at Apple.
515 static int mov_get_lpcm_flags(enum AVCodecID codec_id
)
518 case AV_CODEC_ID_PCM_F32BE
:
519 case AV_CODEC_ID_PCM_F64BE
:
521 case AV_CODEC_ID_PCM_F32LE
:
522 case AV_CODEC_ID_PCM_F64LE
:
524 case AV_CODEC_ID_PCM_U8
:
526 case AV_CODEC_ID_PCM_S16BE
:
527 case AV_CODEC_ID_PCM_S24BE
:
528 case AV_CODEC_ID_PCM_S32BE
:
530 case AV_CODEC_ID_PCM_S8
:
531 case AV_CODEC_ID_PCM_S16LE
:
532 case AV_CODEC_ID_PCM_S24LE
:
533 case AV_CODEC_ID_PCM_S32LE
:
540 static int get_cluster_duration(MOVTrack
*track
, int cluster_idx
)
544 if (cluster_idx
>= track
->entry
)
547 if (cluster_idx
+ 1 == track
->entry
)
548 next_dts
= track
->track_duration
+ track
->start_dts
;
550 next_dts
= track
->cluster
[cluster_idx
+ 1].dts
;
552 return next_dts
- track
->cluster
[cluster_idx
].dts
;
555 static int get_samples_per_packet(MOVTrack
*track
)
557 int i
, first_duration
;
559 /* use 1 for raw PCM */
560 if (!track
->audio_vbr
)
563 /* check to see if duration is constant for all clusters */
566 first_duration
= get_cluster_duration(track
, 0);
567 for (i
= 1; i
< track
->entry
; i
++) {
568 if (get_cluster_duration(track
, i
) != first_duration
)
571 return first_duration
;
574 static int mov_write_audio_tag(AVIOContext
*pb
, MOVTrack
*track
)
576 int64_t pos
= avio_tell(pb
);
578 uint32_t tag
= track
->tag
;
580 if (track
->mode
== MODE_MOV
) {
581 if (mov_get_lpcm_flags(track
->enc
->codec_id
))
582 tag
= AV_RL32("lpcm");
586 avio_wb32(pb
, 0); /* size */
587 avio_wl32(pb
, tag
); // store it byteswapped
588 avio_wb32(pb
, 0); /* Reserved */
589 avio_wb16(pb
, 0); /* Reserved */
590 avio_wb16(pb
, 1); /* Data-reference index, XXX == 1 */
592 /* SoundDescription */
593 avio_wb16(pb
, version
); /* Version */
594 avio_wb16(pb
, 0); /* Revision level */
595 avio_wb32(pb
, 0); /* Reserved */
600 avio_wb16(pb
, 0xfffe);
602 avio_wb32(pb
, 0x00010000);
604 avio_wb64(pb
, av_double2int(track
->enc
->sample_rate
));
605 avio_wb32(pb
, track
->enc
->channels
);
606 avio_wb32(pb
, 0x7F000000);
607 avio_wb32(pb
, av_get_bits_per_sample(track
->enc
->codec_id
));
608 avio_wb32(pb
, mov_get_lpcm_flags(track
->enc
->codec_id
));
609 avio_wb32(pb
, track
->sample_size
);
610 avio_wb32(pb
, get_samples_per_packet(track
));
612 /* reserved for mp4/3gp */
617 avio_wb16(pb
, 0); /* packet size (= 0) */
618 avio_wb16(pb
, track
->enc
->sample_rate
<= UINT16_MAX ?
619 track
->enc
->sample_rate
: 0);
620 avio_wb16(pb
, 0); /* Reserved */
623 if (track
->mode
== MODE_MOV
&&
624 (track
->enc
->codec_id
== AV_CODEC_ID_AAC
||
625 track
->enc
->codec_id
== AV_CODEC_ID_AC3
||
626 track
->enc
->codec_id
== AV_CODEC_ID_AMR_NB
||
627 track
->enc
->codec_id
== AV_CODEC_ID_ALAC
||
628 track
->enc
->codec_id
== AV_CODEC_ID_ADPCM_MS
||
629 track
->enc
->codec_id
== AV_CODEC_ID_ADPCM_IMA_WAV
))
630 mov_write_wave_tag(pb
, track
);
631 else if (track
->tag
== MKTAG('m','p','4','a'))
632 mov_write_esds_tag(pb
, track
);
633 else if (track
->enc
->codec_id
== AV_CODEC_ID_AMR_NB
)
634 mov_write_amr_tag(pb
, track
);
635 else if (track
->enc
->codec_id
== AV_CODEC_ID_AC3
)
636 mov_write_ac3_tag(pb
, track
);
637 else if (track
->enc
->codec_id
== AV_CODEC_ID_ALAC
)
638 mov_write_extradata_tag(pb
, track
);
639 else if (track
->enc
->codec_id
== AV_CODEC_ID_WMAPRO
)
640 mov_write_wfex_tag(pb
, track
);
641 else if (track
->vos_len
> 0)
642 mov_write_glbl_tag(pb
, track
);
644 if (track
->mode
== MODE_MOV
&& track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
)
645 mov_write_chan_tag(pb
, track
);
647 return update_size(pb
, pos
);
650 static int mov_write_d263_tag(AVIOContext
*pb
)
652 avio_wb32(pb
, 0xf); /* size */
653 ffio_wfourcc(pb
, "d263");
654 ffio_wfourcc(pb
, "FFMP");
655 avio_w8(pb
, 0); /* decoder version */
656 /* FIXME use AVCodecContext level/profile, when encoder will set values */
657 avio_w8(pb
, 0xa); /* level */
658 avio_w8(pb
, 0); /* profile */
662 /* TODO: No idea about these values */
663 static int mov_write_svq3_tag(AVIOContext
*pb
)
666 ffio_wfourcc(pb
, "SMI ");
667 ffio_wfourcc(pb
, "SEQH");
669 avio_wb32(pb
, 0xe2c0211d);
670 avio_wb32(pb
, 0xc0000000);
675 static int mov_write_avcc_tag(AVIOContext
*pb
, MOVTrack
*track
)
677 int64_t pos
= avio_tell(pb
);
680 ffio_wfourcc(pb
, "avcC");
681 ff_isom_write_avcc(pb
, track
->vos_data
, track
->vos_len
);
682 return update_size(pb
, pos
);
685 /* also used by all avid codecs (dv, imx, meridien) and their variants */
686 static int mov_write_avid_tag(AVIOContext
*pb
, MOVTrack
*track
)
689 avio_wb32(pb
, 24); /* size */
690 ffio_wfourcc(pb
, "ACLR");
691 ffio_wfourcc(pb
, "ACLR");
692 ffio_wfourcc(pb
, "0001");
693 avio_wb32(pb
, 2); /* yuv range: full 1 / normal 2 */
694 avio_wb32(pb
, 0); /* unknown */
696 avio_wb32(pb
, 24); /* size */
697 ffio_wfourcc(pb
, "APRG");
698 ffio_wfourcc(pb
, "APRG");
699 ffio_wfourcc(pb
, "0001");
700 avio_wb32(pb
, 1); /* unknown */
701 avio_wb32(pb
, 0); /* unknown */
703 avio_wb32(pb
, 120); /* size */
704 ffio_wfourcc(pb
, "ARES");
705 ffio_wfourcc(pb
, "ARES");
706 ffio_wfourcc(pb
, "0001");
707 avio_wb32(pb
, AV_RB32(track
->vos_data
+ 0x28)); /* dnxhd cid, some id ? */
708 avio_wb32(pb
, track
->enc
->width
);
709 /* values below are based on samples created with quicktime and avid codecs */
710 if (track
->vos_data
[5] & 2) { // interlaced
711 avio_wb32(pb
, track
->enc
->height
/ 2);
712 avio_wb32(pb
, 2); /* unknown */
713 avio_wb32(pb
, 0); /* unknown */
714 avio_wb32(pb
, 4); /* unknown */
716 avio_wb32(pb
, track
->enc
->height
);
717 avio_wb32(pb
, 1); /* unknown */
718 avio_wb32(pb
, 0); /* unknown */
719 if (track
->enc
->height
== 1080)
720 avio_wb32(pb
, 5); /* unknown */
722 avio_wb32(pb
, 6); /* unknown */
725 for (i
= 0; i
< 10; i
++)
728 /* extra padding for stsd needed */
733 static int mp4_get_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
735 int tag
= track
->enc
->codec_tag
;
737 if (!ff_codec_get_tag(ff_mp4_obj_type
, track
->enc
->codec_id
))
740 if (track
->enc
->codec_id
== AV_CODEC_ID_H264
) tag
= MKTAG('a','v','c','1');
741 else if (track
->enc
->codec_id
== AV_CODEC_ID_AC3
) tag
= MKTAG('a','c','-','3');
742 else if (track
->enc
->codec_id
== AV_CODEC_ID_DIRAC
) tag
= MKTAG('d','r','a','c');
743 else if (track
->enc
->codec_id
== AV_CODEC_ID_MOV_TEXT
) tag
= MKTAG('t','x','3','g');
744 else if (track
->enc
->codec_id
== AV_CODEC_ID_VC1
) tag
= MKTAG('v','c','-','1');
745 else if (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
) tag
= MKTAG('m','p','4','v');
746 else if (track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) tag
= MKTAG('m','p','4','a');
751 static const AVCodecTag codec_ipod_tags
[] = {
752 { AV_CODEC_ID_H264
, MKTAG('a','v','c','1') },
753 { AV_CODEC_ID_MPEG4
, MKTAG('m','p','4','v') },
754 { AV_CODEC_ID_AAC
, MKTAG('m','p','4','a') },
755 { AV_CODEC_ID_ALAC
, MKTAG('a','l','a','c') },
756 { AV_CODEC_ID_AC3
, MKTAG('a','c','-','3') },
757 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t','x','3','g') },
758 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t','e','x','t') },
759 { AV_CODEC_ID_NONE
, 0 },
762 static int ipod_get_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
764 int tag
= track
->enc
->codec_tag
;
766 // keep original tag for subs, ipod supports both formats
767 if (!(track
->enc
->codec_type
== AVMEDIA_TYPE_SUBTITLE
&&
768 (tag
== MKTAG('t', 'x', '3', 'g') ||
769 tag
== MKTAG('t', 'e', 'x', 't'))))
770 tag
= ff_codec_get_tag(codec_ipod_tags
, track
->enc
->codec_id
);
772 if (!av_match_ext(s
->filename
, "m4a") && !av_match_ext(s
->filename
, "m4v"))
773 av_log(s
, AV_LOG_WARNING
, "Warning, extension is not .m4a nor .m4v "
774 "Quicktime/Ipod might not play the file\n");
779 static int mov_get_dv_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
783 if (track
->enc
->width
== 720) /* SD */
784 if (track
->enc
->height
== 480) /* NTSC */
785 if (track
->enc
->pix_fmt
== AV_PIX_FMT_YUV422P
) tag
= MKTAG('d','v','5','n');
786 else tag
= MKTAG('d','v','c',' ');
787 else if (track
->enc
->pix_fmt
== AV_PIX_FMT_YUV422P
) tag
= MKTAG('d','v','5','p');
788 else if (track
->enc
->pix_fmt
== AV_PIX_FMT_YUV420P
) tag
= MKTAG('d','v','c','p');
789 else tag
= MKTAG('d','v','p','p');
790 else if (track
->enc
->height
== 720) /* HD 720 line */
791 if (track
->enc
->time_base
.den
== 50) tag
= MKTAG('d','v','h','q');
792 else tag
= MKTAG('d','v','h','p');
793 else if (track
->enc
->height
== 1080) /* HD 1080 line */
794 if (track
->enc
->time_base
.den
== 25) tag
= MKTAG('d','v','h','5');
795 else tag
= MKTAG('d','v','h','6');
797 av_log(s
, AV_LOG_ERROR
, "unsupported height for dv codec\n");
804 static const struct {
805 enum AVPixelFormat pix_fmt
;
808 } mov_pix_fmt_tags
[] = {
809 { AV_PIX_FMT_YUYV422
, MKTAG('y','u','v','s'), 0 },
810 { AV_PIX_FMT_UYVY422
, MKTAG('2','v','u','y'), 0 },
811 { AV_PIX_FMT_RGB555BE
,MKTAG('r','a','w',' '), 16 },
812 { AV_PIX_FMT_RGB555LE
,MKTAG('L','5','5','5'), 16 },
813 { AV_PIX_FMT_RGB565LE
,MKTAG('L','5','6','5'), 16 },
814 { AV_PIX_FMT_RGB565BE
,MKTAG('B','5','6','5'), 16 },
815 { AV_PIX_FMT_GRAY16BE
,MKTAG('b','1','6','g'), 16 },
816 { AV_PIX_FMT_RGB24
, MKTAG('r','a','w',' '), 24 },
817 { AV_PIX_FMT_BGR24
, MKTAG('2','4','B','G'), 24 },
818 { AV_PIX_FMT_ARGB
, MKTAG('r','a','w',' '), 32 },
819 { AV_PIX_FMT_BGRA
, MKTAG('B','G','R','A'), 32 },
820 { AV_PIX_FMT_RGBA
, MKTAG('R','G','B','A'), 32 },
821 { AV_PIX_FMT_ABGR
, MKTAG('A','B','G','R'), 32 },
822 { AV_PIX_FMT_RGB48BE
, MKTAG('b','4','8','r'), 48 },
825 static int mov_get_rawvideo_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
827 int tag
= track
->enc
->codec_tag
;
830 for (i
= 0; i
< FF_ARRAY_ELEMS(mov_pix_fmt_tags
); i
++) {
831 if (track
->enc
->pix_fmt
== mov_pix_fmt_tags
[i
].pix_fmt
) {
832 tag
= mov_pix_fmt_tags
[i
].tag
;
833 track
->enc
->bits_per_coded_sample
= mov_pix_fmt_tags
[i
].bps
;
841 static int mov_get_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
843 int tag
= track
->enc
->codec_tag
;
845 if (!tag
|| (track
->enc
->strict_std_compliance
>= FF_COMPLIANCE_NORMAL
&&
846 (track
->enc
->codec_id
== AV_CODEC_ID_DVVIDEO
||
847 track
->enc
->codec_id
== AV_CODEC_ID_RAWVIDEO
||
848 track
->enc
->codec_id
== AV_CODEC_ID_H263
||
849 av_get_bits_per_sample(track
->enc
->codec_id
)))) { // pcm audio
850 if (track
->enc
->codec_id
== AV_CODEC_ID_DVVIDEO
)
851 tag
= mov_get_dv_codec_tag(s
, track
);
852 else if (track
->enc
->codec_id
== AV_CODEC_ID_RAWVIDEO
)
853 tag
= mov_get_rawvideo_codec_tag(s
, track
);
854 else if (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
855 tag
= ff_codec_get_tag(ff_codec_movvideo_tags
, track
->enc
->codec_id
);
856 if (!tag
) { // if no mac fcc found, try with Microsoft tags
857 tag
= ff_codec_get_tag(ff_codec_bmp_tags
, track
->enc
->codec_id
);
859 av_log(s
, AV_LOG_WARNING
, "Using MS style video codec tag, "
860 "the file may be unplayable!\n");
862 } else if (track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
863 tag
= ff_codec_get_tag(ff_codec_movaudio_tags
, track
->enc
->codec_id
);
864 if (!tag
) { // if no mac fcc found, try with Microsoft tags
865 int ms_tag
= ff_codec_get_tag(ff_codec_wav_tags
, track
->enc
->codec_id
);
867 tag
= MKTAG('m', 's', ((ms_tag
>> 8) & 0xff), (ms_tag
& 0xff));
868 av_log(s
, AV_LOG_WARNING
, "Using MS style audio codec tag, "
869 "the file may be unplayable!\n");
872 } else if (track
->enc
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)
873 tag
= ff_codec_get_tag(ff_codec_movsubtitle_tags
, track
->enc
->codec_id
);
879 static const AVCodecTag codec_3gp_tags
[] = {
880 { AV_CODEC_ID_H263
, MKTAG('s','2','6','3') },
881 { AV_CODEC_ID_H264
, MKTAG('a','v','c','1') },
882 { AV_CODEC_ID_MPEG4
, MKTAG('m','p','4','v') },
883 { AV_CODEC_ID_AAC
, MKTAG('m','p','4','a') },
884 { AV_CODEC_ID_AMR_NB
, MKTAG('s','a','m','r') },
885 { AV_CODEC_ID_AMR_WB
, MKTAG('s','a','w','b') },
886 { AV_CODEC_ID_MOV_TEXT
, MKTAG('t','x','3','g') },
887 { AV_CODEC_ID_NONE
, 0 },
890 static int mov_find_codec_tag(AVFormatContext
*s
, MOVTrack
*track
)
894 if (track
->mode
== MODE_MP4
|| track
->mode
== MODE_PSP
)
895 tag
= mp4_get_codec_tag(s
, track
);
896 else if (track
->mode
== MODE_ISM
) {
897 tag
= mp4_get_codec_tag(s
, track
);
898 if (!tag
&& track
->enc
->codec_id
== AV_CODEC_ID_WMAPRO
)
899 tag
= MKTAG('w', 'm', 'a', ' ');
900 } else if (track
->mode
== MODE_IPOD
)
901 tag
= ipod_get_codec_tag(s
, track
);
902 else if (track
->mode
& MODE_3GP
)
903 tag
= ff_codec_get_tag(codec_3gp_tags
, track
->enc
->codec_id
);
905 tag
= mov_get_codec_tag(s
, track
);
911 * Needed to make file play in iPods running newest firmware
912 * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1
914 static int mov_write_uuid_tag_ipod(AVIOContext
*pb
)
917 ffio_wfourcc(pb
, "uuid");
918 avio_wb32(pb
, 0x6b6840f2);
919 avio_wb32(pb
, 0x5f244fc5);
920 avio_wb32(pb
, 0xba39a51b);
921 avio_wb32(pb
, 0xcf0323f3);
926 static const uint16_t fiel_data
[] = {
927 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
930 static int mov_write_fiel_tag(AVIOContext
*pb
, MOVTrack
*track
)
932 unsigned mov_field_order
= 0;
933 if (track
->enc
->field_order
< FF_ARRAY_ELEMS(fiel_data
))
934 mov_field_order
= fiel_data
[track
->enc
->field_order
];
938 ffio_wfourcc(pb
, "fiel");
939 avio_wb16(pb
, mov_field_order
);
943 static int mov_write_subtitle_tag(AVIOContext
*pb
, MOVTrack
*track
)
945 int64_t pos
= avio_tell(pb
);
946 avio_wb32(pb
, 0); /* size */
947 avio_wl32(pb
, track
->tag
); // store it byteswapped
948 avio_wb32(pb
, 0); /* Reserved */
949 avio_wb16(pb
, 0); /* Reserved */
950 avio_wb16(pb
, 1); /* Data-reference index */
952 if (track
->enc
->extradata_size
)
953 avio_write(pb
, track
->enc
->extradata
, track
->enc
->extradata_size
);
955 return update_size(pb
, pos
);
958 static int mov_write_pasp_tag(AVIOContext
*pb
, MOVTrack
*track
)
961 av_reduce(&sar
.num
, &sar
.den
, track
->enc
->sample_aspect_ratio
.num
,
962 track
->enc
->sample_aspect_ratio
.den
, INT_MAX
);
965 ffio_wfourcc(pb
, "pasp");
966 avio_wb32(pb
, sar
.num
);
967 avio_wb32(pb
, sar
.den
);
971 static int mov_write_video_tag(AVIOContext
*pb
, MOVTrack
*track
)
973 int64_t pos
= avio_tell(pb
);
974 char compressor_name
[32] = { 0 };
976 avio_wb32(pb
, 0); /* size */
977 avio_wl32(pb
, track
->tag
); // store it byteswapped
978 avio_wb32(pb
, 0); /* Reserved */
979 avio_wb16(pb
, 0); /* Reserved */
980 avio_wb16(pb
, 1); /* Data-reference index */
982 avio_wb16(pb
, 0); /* Codec stream version */
983 avio_wb16(pb
, 0); /* Codec stream revision (=0) */
984 if (track
->mode
== MODE_MOV
) {
985 ffio_wfourcc(pb
, "FFMP"); /* Vendor */
986 if (track
->enc
->codec_id
== AV_CODEC_ID_RAWVIDEO
) {
987 avio_wb32(pb
, 0); /* Temporal Quality */
988 avio_wb32(pb
, 0x400); /* Spatial Quality = lossless*/
990 avio_wb32(pb
, 0x200); /* Temporal Quality = normal */
991 avio_wb32(pb
, 0x200); /* Spatial Quality = normal */
994 avio_wb32(pb
, 0); /* Reserved */
995 avio_wb32(pb
, 0); /* Reserved */
996 avio_wb32(pb
, 0); /* Reserved */
998 avio_wb16(pb
, track
->enc
->width
); /* Video width */
999 avio_wb16(pb
, track
->height
); /* Video height */
1000 avio_wb32(pb
, 0x00480000); /* Horizontal resolution 72dpi */
1001 avio_wb32(pb
, 0x00480000); /* Vertical resolution 72dpi */
1002 avio_wb32(pb
, 0); /* Data size (= 0) */
1003 avio_wb16(pb
, 1); /* Frame count (= 1) */
1005 /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */
1006 if (track
->mode
== MODE_MOV
&& track
->enc
->codec
&& track
->enc
->codec
->name
)
1007 av_strlcpy(compressor_name
, track
->enc
->codec
->name
, 32);
1008 avio_w8(pb
, strlen(compressor_name
));
1009 avio_write(pb
, compressor_name
, 31);
1011 if (track
->mode
== MODE_MOV
&& track
->enc
->bits_per_coded_sample
)
1012 avio_wb16(pb
, track
->enc
->bits_per_coded_sample
);
1014 avio_wb16(pb
, 0x18); /* Reserved */
1015 avio_wb16(pb
, 0xffff); /* Reserved */
1016 if (track
->tag
== MKTAG('m','p','4','v'))
1017 mov_write_esds_tag(pb
, track
);
1018 else if (track
->enc
->codec_id
== AV_CODEC_ID_H263
)
1019 mov_write_d263_tag(pb
);
1020 else if (track
->enc
->codec_id
== AV_CODEC_ID_SVQ3
)
1021 mov_write_svq3_tag(pb
);
1022 else if (track
->enc
->codec_id
== AV_CODEC_ID_DNXHD
)
1023 mov_write_avid_tag(pb
, track
);
1024 else if (track
->enc
->codec_id
== AV_CODEC_ID_H264
) {
1025 mov_write_avcc_tag(pb
, track
);
1026 if (track
->mode
== MODE_IPOD
)
1027 mov_write_uuid_tag_ipod(pb
);
1028 } else if (track
->enc
->field_order
!= AV_FIELD_UNKNOWN
)
1029 mov_write_fiel_tag(pb
, track
);
1030 else if (track
->enc
->codec_id
== AV_CODEC_ID_VC1
&& track
->vos_len
> 0)
1031 mov_write_dvc1_tag(pb
, track
);
1032 else if (track
->vos_len
> 0)
1033 mov_write_glbl_tag(pb
, track
);
1035 if (track
->enc
->sample_aspect_ratio
.den
&& track
->enc
->sample_aspect_ratio
.num
&&
1036 track
->enc
->sample_aspect_ratio
.den
!= track
->enc
->sample_aspect_ratio
.num
) {
1037 mov_write_pasp_tag(pb
, track
);
1040 return update_size(pb
, pos
);
1043 static int mov_write_rtp_tag(AVIOContext
*pb
, MOVTrack
*track
)
1045 int64_t pos
= avio_tell(pb
);
1046 avio_wb32(pb
, 0); /* size */
1047 ffio_wfourcc(pb
, "rtp ");
1048 avio_wb32(pb
, 0); /* Reserved */
1049 avio_wb16(pb
, 0); /* Reserved */
1050 avio_wb16(pb
, 1); /* Data-reference index */
1052 avio_wb16(pb
, 1); /* Hint track version */
1053 avio_wb16(pb
, 1); /* Highest compatible version */
1054 avio_wb32(pb
, track
->max_packet_size
); /* Max packet size */
1056 avio_wb32(pb
, 12); /* size */
1057 ffio_wfourcc(pb
, "tims");
1058 avio_wb32(pb
, track
->timescale
);
1060 return update_size(pb
, pos
);
1063 static int mov_write_stsd_tag(AVIOContext
*pb
, MOVTrack
*track
)
1065 int64_t pos
= avio_tell(pb
);
1066 avio_wb32(pb
, 0); /* size */
1067 ffio_wfourcc(pb
, "stsd");
1068 avio_wb32(pb
, 0); /* version & flags */
1069 avio_wb32(pb
, 1); /* entry count */
1070 if (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
)
1071 mov_write_video_tag(pb
, track
);
1072 else if (track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
)
1073 mov_write_audio_tag(pb
, track
);
1074 else if (track
->enc
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)
1075 mov_write_subtitle_tag(pb
, track
);
1076 else if (track
->enc
->codec_tag
== MKTAG('r','t','p',' '))
1077 mov_write_rtp_tag(pb
, track
);
1078 return update_size(pb
, pos
);
1081 static int mov_write_ctts_tag(AVIOContext
*pb
, MOVTrack
*track
)
1083 MOVStts
*ctts_entries
;
1084 uint32_t entries
= 0;
1088 ctts_entries
= av_malloc((track
->entry
+ 1) * sizeof(*ctts_entries
)); /* worst case */
1089 ctts_entries
[0].count
= 1;
1090 ctts_entries
[0].duration
= track
->cluster
[0].cts
;
1091 for (i
= 1; i
< track
->entry
; i
++) {
1092 if (track
->cluster
[i
].cts
== ctts_entries
[entries
].duration
) {
1093 ctts_entries
[entries
].count
++; /* compress */
1096 ctts_entries
[entries
].duration
= track
->cluster
[i
].cts
;
1097 ctts_entries
[entries
].count
= 1;
1100 entries
++; /* last one */
1101 atom_size
= 16 + (entries
* 8);
1102 avio_wb32(pb
, atom_size
); /* size */
1103 ffio_wfourcc(pb
, "ctts");
1104 avio_wb32(pb
, 0); /* version & flags */
1105 avio_wb32(pb
, entries
); /* entry count */
1106 for (i
= 0; i
< entries
; i
++) {
1107 avio_wb32(pb
, ctts_entries
[i
].count
);
1108 avio_wb32(pb
, ctts_entries
[i
].duration
);
1110 av_free(ctts_entries
);
1114 /* Time to sample atom */
1115 static int mov_write_stts_tag(AVIOContext
*pb
, MOVTrack
*track
)
1117 MOVStts
*stts_entries
;
1118 uint32_t entries
= -1;
1122 if (track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
&& !track
->audio_vbr
) {
1123 stts_entries
= av_malloc(sizeof(*stts_entries
)); /* one entry */
1124 stts_entries
[0].count
= track
->sample_count
;
1125 stts_entries
[0].duration
= 1;
1128 stts_entries
= track
->entry ?
1129 av_malloc(track
->entry
* sizeof(*stts_entries
)) : /* worst case */
1131 for (i
= 0; i
< track
->entry
; i
++) {
1132 int duration
= get_cluster_duration(track
, i
);
1133 if (i
&& duration
== stts_entries
[entries
].duration
) {
1134 stts_entries
[entries
].count
++; /* compress */
1137 stts_entries
[entries
].duration
= duration
;
1138 stts_entries
[entries
].count
= 1;
1141 entries
++; /* last one */
1143 atom_size
= 16 + (entries
* 8);
1144 avio_wb32(pb
, atom_size
); /* size */
1145 ffio_wfourcc(pb
, "stts");
1146 avio_wb32(pb
, 0); /* version & flags */
1147 avio_wb32(pb
, entries
); /* entry count */
1148 for (i
= 0; i
< entries
; i
++) {
1149 avio_wb32(pb
, stts_entries
[i
].count
);
1150 avio_wb32(pb
, stts_entries
[i
].duration
);
1152 av_free(stts_entries
);
1156 static int mov_write_dref_tag(AVIOContext
*pb
)
1158 avio_wb32(pb
, 28); /* size */
1159 ffio_wfourcc(pb
, "dref");
1160 avio_wb32(pb
, 0); /* version & flags */
1161 avio_wb32(pb
, 1); /* entry count */
1163 avio_wb32(pb
, 0xc); /* size */
1164 ffio_wfourcc(pb
, "url ");
1165 avio_wb32(pb
, 1); /* version & flags */
1170 static int mov_write_stbl_tag(AVIOContext
*pb
, MOVTrack
*track
)
1172 int64_t pos
= avio_tell(pb
);
1173 avio_wb32(pb
, 0); /* size */
1174 ffio_wfourcc(pb
, "stbl");
1175 mov_write_stsd_tag(pb
, track
);
1176 mov_write_stts_tag(pb
, track
);
1177 if ((track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
||
1178 track
->enc
->codec_tag
== MKTAG('r','t','p',' ')) &&
1179 track
->has_keyframes
&& track
->has_keyframes
< track
->entry
)
1180 mov_write_stss_tag(pb
, track
, MOV_SYNC_SAMPLE
);
1181 if (track
->mode
== MODE_MOV
&& track
->flags
& MOV_TRACK_STPS
)
1182 mov_write_stss_tag(pb
, track
, MOV_PARTIAL_SYNC_SAMPLE
);
1183 if (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
&&
1184 track
->flags
& MOV_TRACK_CTTS
)
1185 mov_write_ctts_tag(pb
, track
);
1186 mov_write_stsc_tag(pb
, track
);
1187 mov_write_stsz_tag(pb
, track
);
1188 mov_write_stco_tag(pb
, track
);
1189 return update_size(pb
, pos
);
1192 static int mov_write_dinf_tag(AVIOContext
*pb
)
1194 int64_t pos
= avio_tell(pb
);
1195 avio_wb32(pb
, 0); /* size */
1196 ffio_wfourcc(pb
, "dinf");
1197 mov_write_dref_tag(pb
);
1198 return update_size(pb
, pos
);
1201 static int mov_write_nmhd_tag(AVIOContext
*pb
)
1204 ffio_wfourcc(pb
, "nmhd");
1209 static int mov_write_gmhd_tag(AVIOContext
*pb
)
1211 avio_wb32(pb
, 0x20); /* size */
1212 ffio_wfourcc(pb
, "gmhd");
1213 avio_wb32(pb
, 0x18); /* gmin size */
1214 ffio_wfourcc(pb
, "gmin");/* generic media info */
1215 avio_wb32(pb
, 0); /* version & flags */
1216 avio_wb16(pb
, 0x40); /* graphics mode = */
1217 avio_wb16(pb
, 0x8000); /* opColor (r?) */
1218 avio_wb16(pb
, 0x8000); /* opColor (g?) */
1219 avio_wb16(pb
, 0x8000); /* opColor (b?) */
1220 avio_wb16(pb
, 0); /* balance */
1221 avio_wb16(pb
, 0); /* reserved */
1225 static int mov_write_smhd_tag(AVIOContext
*pb
)
1227 avio_wb32(pb
, 16); /* size */
1228 ffio_wfourcc(pb
, "smhd");
1229 avio_wb32(pb
, 0); /* version & flags */
1230 avio_wb16(pb
, 0); /* reserved (balance, normally = 0) */
1231 avio_wb16(pb
, 0); /* reserved */
1235 static int mov_write_vmhd_tag(AVIOContext
*pb
)
1237 avio_wb32(pb
, 0x14); /* size (always 0x14) */
1238 ffio_wfourcc(pb
, "vmhd");
1239 avio_wb32(pb
, 0x01); /* version & flags */
1240 avio_wb64(pb
, 0); /* reserved (graphics mode = copy) */
1244 static int mov_write_hdlr_tag(AVIOContext
*pb
, MOVTrack
*track
)
1246 const char *hdlr
, *descr
= NULL
, *hdlr_type
= NULL
;
1247 int64_t pos
= avio_tell(pb
);
1251 descr
= "DataHandler";
1254 hdlr
= (track
->mode
== MODE_MOV
) ?
"mhlr" : "\0\0\0\0";
1255 if (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
1257 descr
= "VideoHandler";
1258 } else if (track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
1260 descr
= "SoundHandler";
1261 } else if (track
->enc
->codec_type
== AVMEDIA_TYPE_SUBTITLE
) {
1262 if (track
->tag
== MKTAG('t','x','3','g')) hdlr_type
= "sbtl";
1263 else hdlr_type
= "text";
1264 descr
= "SubtitleHandler";
1265 } else if (track
->enc
->codec_tag
== MKTAG('r','t','p',' ')) {
1267 descr
= "HintHandler";
1268 } else if (track
->enc
->codec_tag
== MKTAG('t','m','c','d')) {
1270 descr
= "TimeCodeHandler";
1273 av_get_codec_tag_string(tag_buf
, sizeof(tag_buf
),
1274 track
->enc
->codec_tag
);
1276 av_log(track
->enc
, AV_LOG_WARNING
,
1277 "Unknown hldr_type for %s / 0x%04X, writing dummy values\n",
1278 tag_buf
, track
->enc
->codec_tag
);
1282 avio_wb32(pb
, 0); /* size */
1283 ffio_wfourcc(pb
, "hdlr");
1284 avio_wb32(pb
, 0); /* Version & flags */
1285 avio_write(pb
, hdlr
, 4); /* handler */
1286 ffio_wfourcc(pb
, hdlr_type
); /* handler type */
1287 avio_wb32(pb
, 0); /* reserved */
1288 avio_wb32(pb
, 0); /* reserved */
1289 avio_wb32(pb
, 0); /* reserved */
1290 if (!track
|| track
->mode
== MODE_MOV
)
1291 avio_w8(pb
, strlen(descr
)); /* pascal string */
1292 avio_write(pb
, descr
, strlen(descr
)); /* handler description */
1293 if (track
&& track
->mode
!= MODE_MOV
)
1294 avio_w8(pb
, 0); /* c string */
1295 return update_size(pb
, pos
);
1298 static int mov_write_hmhd_tag(AVIOContext
*pb
)
1300 /* This atom must be present, but leaving the values at zero
1301 * seems harmless. */
1302 avio_wb32(pb
, 28); /* size */
1303 ffio_wfourcc(pb
, "hmhd");
1304 avio_wb32(pb
, 0); /* version, flags */
1305 avio_wb16(pb
, 0); /* maxPDUsize */
1306 avio_wb16(pb
, 0); /* avgPDUsize */
1307 avio_wb32(pb
, 0); /* maxbitrate */
1308 avio_wb32(pb
, 0); /* avgbitrate */
1309 avio_wb32(pb
, 0); /* reserved */
1313 static int mov_write_minf_tag(AVIOContext
*pb
, MOVTrack
*track
)
1315 int64_t pos
= avio_tell(pb
);
1316 avio_wb32(pb
, 0); /* size */
1317 ffio_wfourcc(pb
, "minf");
1318 if (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
)
1319 mov_write_vmhd_tag(pb
);
1320 else if (track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
)
1321 mov_write_smhd_tag(pb
);
1322 else if (track
->enc
->codec_type
== AVMEDIA_TYPE_SUBTITLE
) {
1323 if (track
->tag
== MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb
);
1324 else mov_write_nmhd_tag(pb
);
1325 } else if (track
->tag
== MKTAG('r','t','p',' ')) {
1326 mov_write_hmhd_tag(pb
);
1328 if (track
->mode
== MODE_MOV
) /* FIXME: Why do it for MODE_MOV only ? */
1329 mov_write_hdlr_tag(pb
, NULL
);
1330 mov_write_dinf_tag(pb
);
1331 mov_write_stbl_tag(pb
, track
);
1332 return update_size(pb
, pos
);
1335 static int mov_write_mdhd_tag(AVIOContext
*pb
, MOVTrack
*track
)
1337 int version
= track
->track_duration
< INT32_MAX ?
0 : 1;
1339 if (track
->mode
== MODE_ISM
)
1342 (version
== 1) ?
avio_wb32(pb
, 44) : avio_wb32(pb
, 32); /* size */
1343 ffio_wfourcc(pb
, "mdhd");
1344 avio_w8(pb
, version
);
1345 avio_wb24(pb
, 0); /* flags */
1347 avio_wb64(pb
, track
->time
);
1348 avio_wb64(pb
, track
->time
);
1350 avio_wb32(pb
, track
->time
); /* creation time */
1351 avio_wb32(pb
, track
->time
); /* modification time */
1353 avio_wb32(pb
, track
->timescale
); /* time scale (sample rate for audio) */
1355 (version
== 1) ?
avio_wb64(pb
, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb
, 0xffffffff);
1357 (version
== 1) ?
avio_wb64(pb
, track
->track_duration
) : avio_wb32(pb
, track
->track_duration
); /* duration */
1358 avio_wb16(pb
, track
->language
); /* language */
1359 avio_wb16(pb
, 0); /* reserved (quality) */
1361 if (version
!= 0 && track
->mode
== MODE_MOV
) {
1362 av_log(NULL
, AV_LOG_ERROR
,
1363 "FATAL error, file duration too long for timebase, this file will not be\n"
1364 "playable with quicktime. Choose a different timebase or a different\n"
1365 "container format\n");
1371 static int mov_write_mdia_tag(AVIOContext
*pb
, MOVTrack
*track
)
1373 int64_t pos
= avio_tell(pb
);
1374 avio_wb32(pb
, 0); /* size */
1375 ffio_wfourcc(pb
, "mdia");
1376 mov_write_mdhd_tag(pb
, track
);
1377 mov_write_hdlr_tag(pb
, track
);
1378 mov_write_minf_tag(pb
, track
);
1379 return update_size(pb
, pos
);
1382 static int mov_write_tkhd_tag(AVIOContext
*pb
, MOVTrack
*track
, AVStream
*st
)
1384 int64_t duration
= av_rescale_rnd(track
->track_duration
, MOV_TIMESCALE
,
1385 track
->timescale
, AV_ROUND_UP
);
1386 int version
= duration
< INT32_MAX ?
0 : 1;
1388 if (track
->mode
== MODE_ISM
)
1391 (version
== 1) ?
avio_wb32(pb
, 104) : avio_wb32(pb
, 92); /* size */
1392 ffio_wfourcc(pb
, "tkhd");
1393 avio_w8(pb
, version
);
1394 avio_wb24(pb
, (track
->flags
& MOV_TRACK_ENABLED
) ?
1395 MOV_TKHD_FLAG_ENABLED
| MOV_TKHD_FLAG_IN_MOVIE
:
1396 MOV_TKHD_FLAG_IN_MOVIE
);
1398 avio_wb64(pb
, track
->time
);
1399 avio_wb64(pb
, track
->time
);
1401 avio_wb32(pb
, track
->time
); /* creation time */
1402 avio_wb32(pb
, track
->time
); /* modification time */
1404 avio_wb32(pb
, track
->track_id
); /* track-id */
1405 avio_wb32(pb
, 0); /* reserved */
1407 (version
== 1) ?
avio_wb64(pb
, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb
, 0xffffffff);
1409 (version
== 1) ?
avio_wb64(pb
, duration
) : avio_wb32(pb
, duration
);
1411 avio_wb32(pb
, 0); /* reserved */
1412 avio_wb32(pb
, 0); /* reserved */
1413 avio_wb16(pb
, 0); /* layer */
1414 avio_wb16(pb
, st ? st
->codec
->codec_type
: 0); /* alternate group) */
1415 /* Volume, only for audio */
1416 if (track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
)
1417 avio_wb16(pb
, 0x0100);
1420 avio_wb16(pb
, 0); /* reserved */
1422 /* Matrix structure */
1423 avio_wb32(pb
, 0x00010000); /* reserved */
1424 avio_wb32(pb
, 0x0); /* reserved */
1425 avio_wb32(pb
, 0x0); /* reserved */
1426 avio_wb32(pb
, 0x0); /* reserved */
1427 avio_wb32(pb
, 0x00010000); /* reserved */
1428 avio_wb32(pb
, 0x0); /* reserved */
1429 avio_wb32(pb
, 0x0); /* reserved */
1430 avio_wb32(pb
, 0x0); /* reserved */
1431 avio_wb32(pb
, 0x40000000); /* reserved */
1433 /* Track width and height, for visual only */
1434 if (st
&& (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
||
1435 track
->enc
->codec_type
== AVMEDIA_TYPE_SUBTITLE
)) {
1436 if (track
->mode
== MODE_MOV
) {
1437 avio_wb32(pb
, track
->enc
->width
<< 16);
1438 avio_wb32(pb
, track
->height
<< 16);
1440 double sample_aspect_ratio
= av_q2d(st
->sample_aspect_ratio
);
1441 if (!sample_aspect_ratio
|| track
->height
!= track
->enc
->height
)
1442 sample_aspect_ratio
= 1;
1443 avio_wb32(pb
, sample_aspect_ratio
* track
->enc
->width
* 0x10000);
1444 avio_wb32(pb
, track
->height
* 0x10000);
1453 static int mov_write_tapt_tag(AVIOContext
*pb
, MOVTrack
*track
)
1455 int32_t width
= av_rescale(track
->enc
->sample_aspect_ratio
.num
, track
->enc
->width
,
1456 track
->enc
->sample_aspect_ratio
.den
);
1458 int64_t pos
= avio_tell(pb
);
1460 avio_wb32(pb
, 0); /* size */
1461 ffio_wfourcc(pb
, "tapt");
1464 ffio_wfourcc(pb
, "clef");
1466 avio_wb32(pb
, width
<< 16);
1467 avio_wb32(pb
, track
->enc
->height
<< 16);
1470 ffio_wfourcc(pb
, "enof");
1472 avio_wb32(pb
, track
->enc
->width
<< 16);
1473 avio_wb32(pb
, track
->enc
->height
<< 16);
1475 return update_size(pb
, pos
);
1478 // This box seems important for the psp playback ... without it the movie seems to hang
1479 static int mov_write_edts_tag(AVIOContext
*pb
, MOVTrack
*track
)
1481 int64_t duration
= av_rescale_rnd(track
->track_duration
, MOV_TIMESCALE
,
1482 track
->timescale
, AV_ROUND_UP
);
1483 int version
= duration
< INT32_MAX ?
0 : 1;
1484 int entry_size
, entry_count
, size
;
1485 int64_t delay
, start_ct
= track
->cluster
[0].cts
;
1486 delay
= av_rescale_rnd(track
->cluster
[0].dts
+ start_ct
, MOV_TIMESCALE
,
1487 track
->timescale
, AV_ROUND_DOWN
);
1488 version
|= delay
< INT32_MAX ?
0 : 1;
1490 entry_size
= (version
== 1) ?
20 : 12;
1491 entry_count
= 1 + (delay
> 0);
1492 size
= 24 + entry_count
* entry_size
;
1494 /* write the atom data */
1495 avio_wb32(pb
, size
);
1496 ffio_wfourcc(pb
, "edts");
1497 avio_wb32(pb
, size
- 8);
1498 ffio_wfourcc(pb
, "elst");
1499 avio_w8(pb
, version
);
1500 avio_wb24(pb
, 0); /* flags */
1502 avio_wb32(pb
, entry_count
);
1503 if (delay
> 0) { /* add an empty edit to delay presentation */
1505 avio_wb64(pb
, delay
);
1508 avio_wb32(pb
, delay
);
1511 avio_wb32(pb
, 0x00010000);
1516 avio_wb64(pb
, duration
);
1517 avio_wb64(pb
, start_ct
);
1519 avio_wb32(pb
, duration
);
1520 avio_wb32(pb
, start_ct
);
1522 avio_wb32(pb
, 0x00010000);
1526 static int mov_write_tref_tag(AVIOContext
*pb
, MOVTrack
*track
)
1528 avio_wb32(pb
, 20); // size
1529 ffio_wfourcc(pb
, "tref");
1530 avio_wb32(pb
, 12); // size (subatom)
1531 avio_wl32(pb
, track
->tref_tag
);
1532 avio_wb32(pb
, track
->tref_id
);
1536 // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
1537 static int mov_write_uuid_tag_psp(AVIOContext
*pb
, MOVTrack
*mov
)
1539 avio_wb32(pb
, 0x34); /* size ... reports as 28 in mp4box! */
1540 ffio_wfourcc(pb
, "uuid");
1541 ffio_wfourcc(pb
, "USMT");
1542 avio_wb32(pb
, 0x21d24fce);
1543 avio_wb32(pb
, 0xbb88695c);
1544 avio_wb32(pb
, 0xfac9c740);
1545 avio_wb32(pb
, 0x1c); // another size here!
1546 ffio_wfourcc(pb
, "MTDT");
1547 avio_wb32(pb
, 0x00010012);
1548 avio_wb32(pb
, 0x0a);
1549 avio_wb32(pb
, 0x55c40000);
1555 static int mov_write_udta_sdp(AVIOContext
*pb
, MOVTrack
*track
)
1557 AVFormatContext
*ctx
= track
->rtp_ctx
;
1558 char buf
[1000] = "";
1561 ff_sdp_write_media(buf
, sizeof(buf
), ctx
->streams
[0], track
->src_track
,
1562 NULL
, NULL
, 0, 0, ctx
);
1563 av_strlcatf(buf
, sizeof(buf
), "a=control:streamid=%d\r\n", track
->track_id
);
1566 avio_wb32(pb
, len
+ 24);
1567 ffio_wfourcc(pb
, "udta");
1568 avio_wb32(pb
, len
+ 16);
1569 ffio_wfourcc(pb
, "hnti");
1570 avio_wb32(pb
, len
+ 8);
1571 ffio_wfourcc(pb
, "sdp ");
1572 avio_write(pb
, buf
, len
);
1576 static int mov_write_trak_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
1577 MOVTrack
*track
, AVStream
*st
)
1579 int64_t pos
= avio_tell(pb
);
1580 avio_wb32(pb
, 0); /* size */
1581 ffio_wfourcc(pb
, "trak");
1582 mov_write_tkhd_tag(pb
, track
, st
);
1583 if (track
->mode
== MODE_PSP
|| track
->flags
& MOV_TRACK_CTTS
||
1584 (track
->entry
&& track
->cluster
[0].dts
)) {
1585 if (!(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
1586 mov_write_edts_tag(pb
, track
); // PSP Movies require edts box
1588 if (track
->tref_tag
)
1589 mov_write_tref_tag(pb
, track
);
1590 mov_write_mdia_tag(pb
, track
);
1591 if (track
->mode
== MODE_PSP
)
1592 mov_write_uuid_tag_psp(pb
, track
); // PSP Movies require this uuid box
1593 if (track
->tag
== MKTAG('r','t','p',' '))
1594 mov_write_udta_sdp(pb
, track
);
1595 if (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
&& track
->mode
== MODE_MOV
) {
1596 double sample_aspect_ratio
= av_q2d(st
->sample_aspect_ratio
);
1597 if (0.0 != sample_aspect_ratio
&& 1.0 != sample_aspect_ratio
)
1598 mov_write_tapt_tag(pb
, track
);
1600 return update_size(pb
, pos
);
1603 static int mov_write_iods_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
1605 int i
, has_audio
= 0, has_video
= 0;
1606 int64_t pos
= avio_tell(pb
);
1607 int audio_profile
= mov
->iods_audio_profile
;
1608 int video_profile
= mov
->iods_video_profile
;
1609 for (i
= 0; i
< mov
->nb_streams
; i
++) {
1610 if (mov
->tracks
[i
].entry
> 0) {
1611 has_audio
|= mov
->tracks
[i
].enc
->codec_type
== AVMEDIA_TYPE_AUDIO
;
1612 has_video
|= mov
->tracks
[i
].enc
->codec_type
== AVMEDIA_TYPE_VIDEO
;
1615 if (audio_profile
< 0)
1616 audio_profile
= 0xFF - has_audio
;
1617 if (video_profile
< 0)
1618 video_profile
= 0xFF - has_video
;
1619 avio_wb32(pb
, 0x0); /* size */
1620 ffio_wfourcc(pb
, "iods");
1621 avio_wb32(pb
, 0); /* version & flags */
1622 put_descr(pb
, 0x10, 7);
1623 avio_wb16(pb
, 0x004f);
1626 avio_w8(pb
, audio_profile
);
1627 avio_w8(pb
, video_profile
);
1629 return update_size(pb
, pos
);
1632 static int mov_write_trex_tag(AVIOContext
*pb
, MOVTrack
*track
)
1634 avio_wb32(pb
, 0x20); /* size */
1635 ffio_wfourcc(pb
, "trex");
1636 avio_wb32(pb
, 0); /* version & flags */
1637 avio_wb32(pb
, track
->track_id
); /* track ID */
1638 avio_wb32(pb
, 1); /* default sample description index */
1639 avio_wb32(pb
, 0); /* default sample duration */
1640 avio_wb32(pb
, 0); /* default sample size */
1641 avio_wb32(pb
, 0); /* default sample flags */
1645 static int mov_write_mvex_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
1647 int64_t pos
= avio_tell(pb
);
1649 avio_wb32(pb
, 0x0); /* size */
1650 ffio_wfourcc(pb
, "mvex");
1651 for (i
= 0; i
< mov
->nb_streams
; i
++)
1652 mov_write_trex_tag(pb
, &mov
->tracks
[i
]);
1653 return update_size(pb
, pos
);
1656 static int mov_write_mvhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
1658 int max_track_id
= 1, i
;
1659 int64_t max_track_len_temp
, max_track_len
= 0;
1662 for (i
= 0; i
< mov
->nb_streams
; i
++) {
1663 if (mov
->tracks
[i
].entry
> 0 && mov
->tracks
[i
].timescale
) {
1664 max_track_len_temp
= av_rescale_rnd(mov
->tracks
[i
].track_duration
,
1666 mov
->tracks
[i
].timescale
,
1668 if (max_track_len
< max_track_len_temp
)
1669 max_track_len
= max_track_len_temp
;
1670 if (max_track_id
< mov
->tracks
[i
].track_id
)
1671 max_track_id
= mov
->tracks
[i
].track_id
;
1675 version
= max_track_len
< UINT32_MAX ?
0 : 1;
1676 (version
== 1) ?
avio_wb32(pb
, 120) : avio_wb32(pb
, 108); /* size */
1677 ffio_wfourcc(pb
, "mvhd");
1678 avio_w8(pb
, version
);
1679 avio_wb24(pb
, 0); /* flags */
1681 avio_wb64(pb
, mov
->time
);
1682 avio_wb64(pb
, mov
->time
);
1684 avio_wb32(pb
, mov
->time
); /* creation time */
1685 avio_wb32(pb
, mov
->time
); /* modification time */
1687 avio_wb32(pb
, MOV_TIMESCALE
);
1688 (version
== 1) ?
avio_wb64(pb
, max_track_len
) : avio_wb32(pb
, max_track_len
); /* duration of longest track */
1690 avio_wb32(pb
, 0x00010000); /* reserved (preferred rate) 1.0 = normal */
1691 avio_wb16(pb
, 0x0100); /* reserved (preferred volume) 1.0 = normal */
1692 avio_wb16(pb
, 0); /* reserved */
1693 avio_wb32(pb
, 0); /* reserved */
1694 avio_wb32(pb
, 0); /* reserved */
1696 /* Matrix structure */
1697 avio_wb32(pb
, 0x00010000); /* reserved */
1698 avio_wb32(pb
, 0x0); /* reserved */
1699 avio_wb32(pb
, 0x0); /* reserved */
1700 avio_wb32(pb
, 0x0); /* reserved */
1701 avio_wb32(pb
, 0x00010000); /* reserved */
1702 avio_wb32(pb
, 0x0); /* reserved */
1703 avio_wb32(pb
, 0x0); /* reserved */
1704 avio_wb32(pb
, 0x0); /* reserved */
1705 avio_wb32(pb
, 0x40000000); /* reserved */
1707 avio_wb32(pb
, 0); /* reserved (preview time) */
1708 avio_wb32(pb
, 0); /* reserved (preview duration) */
1709 avio_wb32(pb
, 0); /* reserved (poster time) */
1710 avio_wb32(pb
, 0); /* reserved (selection time) */
1711 avio_wb32(pb
, 0); /* reserved (selection duration) */
1712 avio_wb32(pb
, 0); /* reserved (current time) */
1713 avio_wb32(pb
, max_track_id
+ 1); /* Next track id */
1717 static int mov_write_itunes_hdlr_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
1720 avio_wb32(pb
, 33); /* size */
1721 ffio_wfourcc(pb
, "hdlr");
1724 ffio_wfourcc(pb
, "mdir");
1725 ffio_wfourcc(pb
, "appl");
1732 /* helper function to write a data tag with the specified string as data */
1733 static int mov_write_string_data_tag(AVIOContext
*pb
, const char *data
, int lang
, int long_style
)
1736 int size
= 16 + strlen(data
);
1737 avio_wb32(pb
, size
); /* size */
1738 ffio_wfourcc(pb
, "data");
1741 avio_write(pb
, data
, strlen(data
));
1745 lang
= ff_mov_iso639_to_lang("und", 1);
1746 avio_wb16(pb
, strlen(data
)); /* string length */
1747 avio_wb16(pb
, lang
);
1748 avio_write(pb
, data
, strlen(data
));
1749 return strlen(data
) + 4;
1753 static int mov_write_string_tag(AVIOContext
*pb
, const char *name
,
1754 const char *value
, int lang
, int long_style
)
1757 if (value
&& value
[0]) {
1758 int64_t pos
= avio_tell(pb
);
1759 avio_wb32(pb
, 0); /* size */
1760 ffio_wfourcc(pb
, name
);
1761 mov_write_string_data_tag(pb
, value
, lang
, long_style
);
1762 size
= update_size(pb
, pos
);
1767 static int mov_write_string_metadata(AVFormatContext
*s
, AVIOContext
*pb
,
1768 const char *name
, const char *tag
,
1771 int l
, lang
= 0, len
, len2
;
1772 AVDictionaryEntry
*t
, *t2
= NULL
;
1775 if (!(t
= av_dict_get(s
->metadata
, tag
, NULL
, 0)))
1778 len
= strlen(t
->key
);
1779 snprintf(tag2
, sizeof(tag2
), "%s-", tag
);
1780 while ((t2
= av_dict_get(s
->metadata
, tag2
, t2
, AV_DICT_IGNORE_SUFFIX
))) {
1781 len2
= strlen(t2
->key
);
1782 if (len2
== len
+ 4 && !strcmp(t
->value
, t2
->value
)
1783 && (l
= ff_mov_iso639_to_lang(&t2
->key
[len2
- 3], 1)) >= 0) {
1788 return mov_write_string_tag(pb
, name
, t
->value
, lang
, long_style
);
1791 /* iTunes track number */
1792 static int mov_write_trkn_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
1795 AVDictionaryEntry
*t
= av_dict_get(s
->metadata
, "track", NULL
, 0);
1796 int size
= 0, track
= t ?
atoi(t
->value
) : 0;
1798 avio_wb32(pb
, 32); /* size */
1799 ffio_wfourcc(pb
, "trkn");
1800 avio_wb32(pb
, 24); /* size */
1801 ffio_wfourcc(pb
, "data");
1802 avio_wb32(pb
, 0); // 8 bytes empty
1804 avio_wb16(pb
, 0); // empty
1805 avio_wb16(pb
, track
); // track number
1806 avio_wb16(pb
, 0); // total track number
1807 avio_wb16(pb
, 0); // empty
1813 /* iTunes meta data list */
1814 static int mov_write_ilst_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
1817 int64_t pos
= avio_tell(pb
);
1818 avio_wb32(pb
, 0); /* size */
1819 ffio_wfourcc(pb
, "ilst");
1820 mov_write_string_metadata(s
, pb
, "\251nam", "title" , 1);
1821 mov_write_string_metadata(s
, pb
, "\251ART", "artist" , 1);
1822 mov_write_string_metadata(s
, pb
, "aART", "album_artist", 1);
1823 mov_write_string_metadata(s
, pb
, "\251wrt", "composer" , 1);
1824 mov_write_string_metadata(s
, pb
, "\251alb", "album" , 1);
1825 mov_write_string_metadata(s
, pb
, "\251day", "date" , 1);
1826 mov_write_string_tag(pb
, "\251too", LIBAVFORMAT_IDENT
, 0, 1);
1827 mov_write_string_metadata(s
, pb
, "\251cmt", "comment" , 1);
1828 mov_write_string_metadata(s
, pb
, "\251gen", "genre" , 1);
1829 mov_write_string_metadata(s
, pb
, "\251cpy", "copyright", 1);
1830 mov_write_string_metadata(s
, pb
, "\251grp", "grouping" , 1);
1831 mov_write_string_metadata(s
, pb
, "\251lyr", "lyrics" , 1);
1832 mov_write_string_metadata(s
, pb
, "desc", "description",1);
1833 mov_write_string_metadata(s
, pb
, "ldes", "synopsis" , 1);
1834 mov_write_string_metadata(s
, pb
, "tvsh", "show" , 1);
1835 mov_write_string_metadata(s
, pb
, "tven", "episode_id",1);
1836 mov_write_string_metadata(s
, pb
, "tvnn", "network" , 1);
1837 mov_write_trkn_tag(pb
, mov
, s
);
1838 return update_size(pb
, pos
);
1841 /* iTunes meta data tag */
1842 static int mov_write_meta_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
1846 int64_t pos
= avio_tell(pb
);
1847 avio_wb32(pb
, 0); /* size */
1848 ffio_wfourcc(pb
, "meta");
1850 mov_write_itunes_hdlr_tag(pb
, mov
, s
);
1851 mov_write_ilst_tag(pb
, mov
, s
);
1852 size
= update_size(pb
, pos
);
1856 static int utf8len(const uint8_t *b
)
1861 GET_UTF8(val
, *b
++, return -1;)
1867 static int ascii_to_wc(AVIOContext
*pb
, const uint8_t *b
)
1871 GET_UTF8(val
, *b
++, return -1;)
1874 avio_wb16(pb
, 0x00);
1878 static uint16_t language_code(const char *str
)
1880 return (((str
[0] - 0x60) & 0x1F) << 10) +
1881 (((str
[1] - 0x60) & 0x1F) << 5) +
1882 (( str
[2] - 0x60) & 0x1F);
1885 static int mov_write_3gp_udta_tag(AVIOContext
*pb
, AVFormatContext
*s
,
1886 const char *tag
, const char *str
)
1888 int64_t pos
= avio_tell(pb
);
1889 AVDictionaryEntry
*t
= av_dict_get(s
->metadata
, str
, NULL
, 0);
1890 if (!t
|| !utf8len(t
->value
))
1892 avio_wb32(pb
, 0); /* size */
1893 ffio_wfourcc(pb
, tag
); /* type */
1894 avio_wb32(pb
, 0); /* version + flags */
1895 if (!strcmp(tag
, "yrrc"))
1896 avio_wb16(pb
, atoi(t
->value
));
1898 avio_wb16(pb
, language_code("eng")); /* language */
1899 avio_write(pb
, t
->value
, strlen(t
->value
) + 1); /* UTF8 string value */
1900 if (!strcmp(tag
, "albm") &&
1901 (t
= av_dict_get(s
->metadata
, "track", NULL
, 0)))
1902 avio_w8(pb
, atoi(t
->value
));
1904 return update_size(pb
, pos
);
1907 static int mov_write_chpl_tag(AVIOContext
*pb
, AVFormatContext
*s
)
1909 int64_t pos
= avio_tell(pb
);
1910 int i
, nb_chapters
= FFMIN(s
->nb_chapters
, 255);
1912 avio_wb32(pb
, 0); // size
1913 ffio_wfourcc(pb
, "chpl");
1914 avio_wb32(pb
, 0x01000000); // version + flags
1915 avio_wb32(pb
, 0); // unknown
1916 avio_w8(pb
, nb_chapters
);
1918 for (i
= 0; i
< nb_chapters
; i
++) {
1919 AVChapter
*c
= s
->chapters
[i
];
1920 AVDictionaryEntry
*t
;
1921 avio_wb64(pb
, av_rescale_q(c
->start
, c
->time_base
, (AVRational
){1,10000000}));
1923 if ((t
= av_dict_get(c
->metadata
, "title", NULL
, 0))) {
1924 int len
= FFMIN(strlen(t
->value
), 255);
1926 avio_write(pb
, t
->value
, len
);
1930 return update_size(pb
, pos
);
1933 static int mov_write_udta_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
1936 AVIOContext
*pb_buf
;
1940 for (i
= 0; i
< s
->nb_streams
; i
++)
1941 if (mov
->tracks
[i
].enc
->flags
& CODEC_FLAG_BITEXACT
) {
1945 ret
= avio_open_dyn_buf(&pb_buf
);
1949 if (mov
->mode
& MODE_3GP
) {
1950 mov_write_3gp_udta_tag(pb_buf
, s
, "perf", "artist");
1951 mov_write_3gp_udta_tag(pb_buf
, s
, "titl", "title");
1952 mov_write_3gp_udta_tag(pb_buf
, s
, "auth", "author");
1953 mov_write_3gp_udta_tag(pb_buf
, s
, "gnre", "genre");
1954 mov_write_3gp_udta_tag(pb_buf
, s
, "dscp", "comment");
1955 mov_write_3gp_udta_tag(pb_buf
, s
, "albm", "album");
1956 mov_write_3gp_udta_tag(pb_buf
, s
, "cprt", "copyright");
1957 mov_write_3gp_udta_tag(pb_buf
, s
, "yrrc", "date");
1958 } else if (mov
->mode
== MODE_MOV
) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
1959 mov_write_string_metadata(s
, pb_buf
, "\251ART", "artist", 0);
1960 mov_write_string_metadata(s
, pb_buf
, "\251nam", "title", 0);
1961 mov_write_string_metadata(s
, pb_buf
, "\251aut", "author", 0);
1962 mov_write_string_metadata(s
, pb_buf
, "\251alb", "album", 0);
1963 mov_write_string_metadata(s
, pb_buf
, "\251day", "date", 0);
1964 mov_write_string_metadata(s
, pb_buf
, "\251swr", "encoder", 0);
1965 mov_write_string_metadata(s
, pb_buf
, "\251des", "comment", 0);
1966 mov_write_string_metadata(s
, pb_buf
, "\251gen", "genre", 0);
1967 mov_write_string_metadata(s
, pb_buf
, "\251cpy", "copyright", 0);
1969 /* iTunes meta data */
1970 mov_write_meta_tag(pb_buf
, mov
, s
);
1974 mov_write_chpl_tag(pb_buf
, s
);
1976 if ((size
= avio_close_dyn_buf(pb_buf
, &buf
)) > 0) {
1977 avio_wb32(pb
, size
+ 8);
1978 ffio_wfourcc(pb
, "udta");
1979 avio_write(pb
, buf
, size
);
1986 static void mov_write_psp_udta_tag(AVIOContext
*pb
,
1987 const char *str
, const char *lang
, int type
)
1989 int len
= utf8len(str
) + 1;
1992 avio_wb16(pb
, len
* 2 + 10); /* size */
1993 avio_wb32(pb
, type
); /* type */
1994 avio_wb16(pb
, language_code(lang
)); /* language */
1995 avio_wb16(pb
, 0x01); /* ? */
1996 ascii_to_wc(pb
, str
);
1999 static int mov_write_uuidusmt_tag(AVIOContext
*pb
, AVFormatContext
*s
)
2001 AVDictionaryEntry
*title
= av_dict_get(s
->metadata
, "title", NULL
, 0);
2005 pos
= avio_tell(pb
);
2006 avio_wb32(pb
, 0); /* size placeholder*/
2007 ffio_wfourcc(pb
, "uuid");
2008 ffio_wfourcc(pb
, "USMT");
2009 avio_wb32(pb
, 0x21d24fce); /* 96 bit UUID */
2010 avio_wb32(pb
, 0xbb88695c);
2011 avio_wb32(pb
, 0xfac9c740);
2013 pos2
= avio_tell(pb
);
2014 avio_wb32(pb
, 0); /* size placeholder*/
2015 ffio_wfourcc(pb
, "MTDT");
2019 avio_wb16(pb
, 0x0C); /* size */
2020 avio_wb32(pb
, 0x0B); /* type */
2021 avio_wb16(pb
, language_code("und")); /* language */
2022 avio_wb16(pb
, 0x0); /* ? */
2023 avio_wb16(pb
, 0x021C); /* data */
2025 mov_write_psp_udta_tag(pb
, LIBAVCODEC_IDENT
, "eng", 0x04);
2026 mov_write_psp_udta_tag(pb
, title
->value
, "eng", 0x01);
2027 mov_write_psp_udta_tag(pb
, "2006/04/01 11:11:11", "und", 0x03);
2029 update_size(pb
, pos2
);
2030 return update_size(pb
, pos
);
2036 static int mov_write_moov_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
2040 int64_t pos
= avio_tell(pb
);
2041 avio_wb32(pb
, 0); /* size placeholder*/
2042 ffio_wfourcc(pb
, "moov");
2044 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2045 if (mov
->tracks
[i
].entry
<= 0 && !(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
2048 mov
->tracks
[i
].time
= mov
->time
;
2049 mov
->tracks
[i
].track_id
= i
+ 1;
2052 if (mov
->chapter_track
)
2053 for (i
= 0; i
< s
->nb_streams
; i
++) {
2054 mov
->tracks
[i
].tref_tag
= MKTAG('c','h','a','p');
2055 mov
->tracks
[i
].tref_id
= mov
->tracks
[mov
->chapter_track
].track_id
;
2057 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2058 if (mov
->tracks
[i
].tag
== MKTAG('r','t','p',' ')) {
2059 mov
->tracks
[i
].tref_tag
= MKTAG('h','i','n','t');
2060 mov
->tracks
[i
].tref_id
=
2061 mov
->tracks
[mov
->tracks
[i
].src_track
].track_id
;
2065 mov_write_mvhd_tag(pb
, mov
);
2066 if (mov
->mode
!= MODE_MOV
&& !mov
->iods_skip
)
2067 mov_write_iods_tag(pb
, mov
);
2068 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2069 if (mov
->tracks
[i
].entry
> 0 || mov
->flags
& FF_MOV_FLAG_FRAGMENT
) {
2070 mov_write_trak_tag(pb
, mov
, &(mov
->tracks
[i
]), i
< s
->nb_streams ? s
->streams
[i
] : NULL
);
2073 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
)
2074 mov_write_mvex_tag(pb
, mov
); /* QuickTime requires trak to precede this */
2076 if (mov
->mode
== MODE_PSP
)
2077 mov_write_uuidusmt_tag(pb
, s
);
2079 mov_write_udta_tag(pb
, mov
, s
);
2081 return update_size(pb
, pos
);
2084 static void param_write_int(AVIOContext
*pb
, const char *name
, int value
)
2086 avio_printf(pb
, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name
, value
);
2089 static void param_write_string(AVIOContext
*pb
, const char *name
, const char *value
)
2091 avio_printf(pb
, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name
, value
);
2094 static void param_write_hex(AVIOContext
*pb
, const char *name
, const uint8_t *value
, int len
)
2097 len
= FFMIN(sizeof(buf
) / 2 - 1, len
);
2098 ff_data_to_hex(buf
, value
, len
, 0);
2099 buf
[2 * len
] = '\0';
2100 avio_printf(pb
, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name
, buf
);
2103 static int mov_write_isml_manifest(AVIOContext
*pb
, MOVMuxContext
*mov
)
2105 int64_t pos
= avio_tell(pb
);
2107 const uint8_t uuid
[] = {
2108 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd,
2109 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66
2113 ffio_wfourcc(pb
, "uuid");
2114 avio_write(pb
, uuid
, sizeof(uuid
));
2117 avio_printf(pb
, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
2118 avio_printf(pb
, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
2119 avio_printf(pb
, "<head>\n");
2120 avio_printf(pb
, "<meta name=\"creator\" content=\"%s\" />\n",
2122 avio_printf(pb
, "</head>\n");
2123 avio_printf(pb
, "<body>\n");
2124 avio_printf(pb
, "<switch>\n");
2125 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2126 MOVTrack
*track
= &mov
->tracks
[i
];
2128 /* track->track_id is initialized in write_moov, and thus isn't known
2130 int track_id
= i
+ 1;
2132 if (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
2134 } else if (track
->enc
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
2139 avio_printf(pb
, "<%s systemBitrate=\"%d\">\n", type
,
2140 track
->enc
->bit_rate
);
2141 param_write_int(pb
, "systemBitrate", track
->enc
->bit_rate
);
2142 param_write_int(pb
, "trackID", track_id
);
2143 if (track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
2144 if (track
->enc
->codec_id
== AV_CODEC_ID_H264
) {
2146 int size
= track
->enc
->extradata_size
;
2147 if (!ff_avc_write_annexb_extradata(track
->enc
->extradata
, &ptr
,
2149 param_write_hex(pb
, "CodecPrivateData",
2150 ptr ? ptr
: track
->enc
->extradata
,
2154 param_write_string(pb
, "FourCC", "H264");
2155 } else if (track
->enc
->codec_id
== AV_CODEC_ID_VC1
) {
2156 param_write_string(pb
, "FourCC", "WVC1");
2157 param_write_hex(pb
, "CodecPrivateData", track
->enc
->extradata
,
2158 track
->enc
->extradata_size
);
2160 param_write_int(pb
, "MaxWidth", track
->enc
->width
);
2161 param_write_int(pb
, "MaxHeight", track
->enc
->height
);
2162 param_write_int(pb
, "DisplayWidth", track
->enc
->width
);
2163 param_write_int(pb
, "DisplayHeight", track
->enc
->height
);
2165 if (track
->enc
->codec_id
== AV_CODEC_ID_AAC
) {
2166 param_write_string(pb
, "FourCC", "AACL");
2167 } else if (track
->enc
->codec_id
== AV_CODEC_ID_WMAPRO
) {
2168 param_write_string(pb
, "FourCC", "WMAP");
2170 param_write_hex(pb
, "CodecPrivateData", track
->enc
->extradata
,
2171 track
->enc
->extradata_size
);
2172 param_write_int(pb
, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags
,
2173 track
->enc
->codec_id
));
2174 param_write_int(pb
, "Channels", track
->enc
->channels
);
2175 param_write_int(pb
, "SamplingRate", track
->enc
->sample_rate
);
2176 param_write_int(pb
, "BitsPerSample", 16);
2177 param_write_int(pb
, "PacketSize", track
->enc
->block_align ?
2178 track
->enc
->block_align
: 4);
2180 avio_printf(pb
, "</%s>\n", type
);
2182 avio_printf(pb
, "</switch>\n");
2183 avio_printf(pb
, "</body>\n");
2184 avio_printf(pb
, "</smil>\n");
2186 return update_size(pb
, pos
);
2189 static int mov_write_mfhd_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
2192 ffio_wfourcc(pb
, "mfhd");
2194 avio_wb32(pb
, mov
->fragments
);
2198 static int mov_write_tfhd_tag(AVIOContext
*pb
, MOVTrack
*track
,
2199 int64_t moof_offset
)
2201 int64_t pos
= avio_tell(pb
);
2202 uint32_t flags
= MOV_TFHD_DEFAULT_SIZE
| MOV_TFHD_DEFAULT_DURATION
|
2203 MOV_TFHD_BASE_DATA_OFFSET
;
2204 if (!track
->entry
) {
2205 flags
|= MOV_TFHD_DURATION_IS_EMPTY
;
2207 flags
|= MOV_TFHD_DEFAULT_FLAGS
;
2210 /* Don't set a default sample size, the silverlight player refuses
2211 * to play files with that set. Don't set a default sample duration,
2212 * WMP freaks out if it is set. Don't set a base data offset, PIFF
2213 * file format says it MUST NOT be set. */
2214 if (track
->mode
== MODE_ISM
)
2215 flags
&= ~(MOV_TFHD_DEFAULT_SIZE
| MOV_TFHD_DEFAULT_DURATION
|
2216 MOV_TFHD_BASE_DATA_OFFSET
);
2218 avio_wb32(pb
, 0); /* size placeholder */
2219 ffio_wfourcc(pb
, "tfhd");
2220 avio_w8(pb
, 0); /* version */
2221 avio_wb24(pb
, flags
);
2223 avio_wb32(pb
, track
->track_id
); /* track-id */
2224 if (flags
& MOV_TFHD_BASE_DATA_OFFSET
)
2225 avio_wb64(pb
, moof_offset
);
2226 if (flags
& MOV_TFHD_DEFAULT_DURATION
) {
2227 track
->default_duration
= get_cluster_duration(track
, 0);
2228 avio_wb32(pb
, track
->default_duration
);
2230 if (flags
& MOV_TFHD_DEFAULT_SIZE
) {
2231 track
->default_size
= track
->entry ? track
->cluster
[0].size
: 1;
2232 avio_wb32(pb
, track
->default_size
);
2234 track
->default_size
= -1;
2236 if (flags
& MOV_TFHD_DEFAULT_FLAGS
) {
2237 track
->default_sample_flags
=
2238 track
->enc
->codec_type
== AVMEDIA_TYPE_VIDEO ?
2239 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES
| MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC
) :
2240 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO
;
2241 avio_wb32(pb
, track
->default_sample_flags
);
2244 return update_size(pb
, pos
);
2247 static uint32_t get_sample_flags(MOVTrack
*track
, MOVIentry
*entry
)
2249 return entry
->flags
& MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO
:
2250 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES
| MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC
);
2253 static int mov_write_trun_tag(AVIOContext
*pb
, MOVTrack
*track
)
2255 int64_t pos
= avio_tell(pb
);
2256 uint32_t flags
= MOV_TRUN_DATA_OFFSET
;
2259 for (i
= 0; i
< track
->entry
; i
++) {
2260 if (get_cluster_duration(track
, i
) != track
->default_duration
)
2261 flags
|= MOV_TRUN_SAMPLE_DURATION
;
2262 if (track
->cluster
[i
].size
!= track
->default_size
)
2263 flags
|= MOV_TRUN_SAMPLE_SIZE
;
2264 if (i
> 0 && get_sample_flags(track
, &track
->cluster
[i
]) != track
->default_sample_flags
)
2265 flags
|= MOV_TRUN_SAMPLE_FLAGS
;
2267 if (!(flags
& MOV_TRUN_SAMPLE_FLAGS
))
2268 flags
|= MOV_TRUN_FIRST_SAMPLE_FLAGS
;
2269 if (track
->flags
& MOV_TRACK_CTTS
)
2270 flags
|= MOV_TRUN_SAMPLE_CTS
;
2272 avio_wb32(pb
, 0); /* size placeholder */
2273 ffio_wfourcc(pb
, "trun");
2274 avio_w8(pb
, 0); /* version */
2275 avio_wb24(pb
, flags
);
2277 avio_wb32(pb
, track
->entry
); /* sample count */
2278 track
->moof_size_offset
= avio_tell(pb
);
2279 avio_wb32(pb
, 0); /* data offset */
2280 if (flags
& MOV_TRUN_FIRST_SAMPLE_FLAGS
)
2281 avio_wb32(pb
, get_sample_flags(track
, &track
->cluster
[0]));
2283 for (i
= 0; i
< track
->entry
; i
++) {
2284 if (flags
& MOV_TRUN_SAMPLE_DURATION
)
2285 avio_wb32(pb
, get_cluster_duration(track
, i
));
2286 if (flags
& MOV_TRUN_SAMPLE_SIZE
)
2287 avio_wb32(pb
, track
->cluster
[i
].size
);
2288 if (flags
& MOV_TRUN_SAMPLE_FLAGS
)
2289 avio_wb32(pb
, get_sample_flags(track
, &track
->cluster
[i
]));
2290 if (flags
& MOV_TRUN_SAMPLE_CTS
)
2291 avio_wb32(pb
, track
->cluster
[i
].cts
);
2294 return update_size(pb
, pos
);
2297 static int mov_write_tfxd_tag(AVIOContext
*pb
, MOVTrack
*track
)
2299 int64_t pos
= avio_tell(pb
);
2300 const uint8_t uuid
[] = {
2301 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
2302 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
2305 avio_wb32(pb
, 0); /* size placeholder */
2306 ffio_wfourcc(pb
, "uuid");
2307 avio_write(pb
, uuid
, sizeof(uuid
));
2310 avio_wb64(pb
, track
->frag_start
);
2311 avio_wb64(pb
, track
->start_dts
+ track
->track_duration
-
2312 track
->cluster
[0].dts
);
2314 return update_size(pb
, pos
);
2317 static int mov_write_tfrf_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
2318 MOVTrack
*track
, int entry
)
2320 int n
= track
->nb_frag_info
- 1 - entry
, i
;
2321 int size
= 8 + 16 + 4 + 1 + 16*n
;
2322 const uint8_t uuid
[] = {
2323 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95,
2324 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f
2330 avio_seek(pb
, track
->frag_info
[entry
].tfrf_offset
, SEEK_SET
);
2331 avio_wb32(pb
, size
);
2332 ffio_wfourcc(pb
, "uuid");
2333 avio_write(pb
, uuid
, sizeof(uuid
));
2337 for (i
= 0; i
< n
; i
++) {
2338 int index
= entry
+ 1 + i
;
2339 avio_wb64(pb
, track
->frag_info
[index
].time
);
2340 avio_wb64(pb
, track
->frag_info
[index
].duration
);
2342 if (n
< mov
->ism_lookahead
) {
2343 int free_size
= 16 * (mov
->ism_lookahead
- n
);
2344 avio_wb32(pb
, free_size
);
2345 ffio_wfourcc(pb
, "free");
2346 for (i
= 0; i
< free_size
- 8; i
++)
2353 static int mov_write_tfrf_tags(AVIOContext
*pb
, MOVMuxContext
*mov
,
2356 int64_t pos
= avio_tell(pb
);
2358 for (i
= 0; i
< mov
->ism_lookahead
; i
++) {
2359 /* Update the tfrf tag for the last ism_lookahead fragments,
2360 * nb_frag_info - 1 is the next fragment to be written. */
2361 mov_write_tfrf_tag(pb
, mov
, track
, track
->nb_frag_info
- 2 - i
);
2363 avio_seek(pb
, pos
, SEEK_SET
);
2367 static int mov_write_traf_tag(AVIOContext
*pb
, MOVMuxContext
*mov
,
2368 MOVTrack
*track
, int64_t moof_offset
)
2370 int64_t pos
= avio_tell(pb
);
2371 avio_wb32(pb
, 0); /* size placeholder */
2372 ffio_wfourcc(pb
, "traf");
2374 mov_write_tfhd_tag(pb
, track
, moof_offset
);
2375 mov_write_trun_tag(pb
, track
);
2376 if (mov
->mode
== MODE_ISM
) {
2377 mov_write_tfxd_tag(pb
, track
);
2379 if (mov
->ism_lookahead
) {
2380 int i
, size
= 16 + 4 + 1 + 16 * mov
->ism_lookahead
;
2382 track
->tfrf_offset
= avio_tell(pb
);
2383 avio_wb32(pb
, 8 + size
);
2384 ffio_wfourcc(pb
, "free");
2385 for (i
= 0; i
< size
; i
++)
2390 return update_size(pb
, pos
);
2393 static int mov_write_moof_tag(AVIOContext
*pb
, MOVMuxContext
*mov
, int tracks
)
2395 int64_t pos
= avio_tell(pb
), end
;
2398 avio_wb32(pb
, 0); /* size placeholder */
2399 ffio_wfourcc(pb
, "moof");
2401 mov_write_mfhd_tag(pb
, mov
);
2402 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2403 MOVTrack
*track
= &mov
->tracks
[i
];
2404 if (tracks
>= 0 && i
!= tracks
)
2408 mov_write_traf_tag(pb
, mov
, track
, pos
);
2411 end
= avio_tell(pb
);
2412 moof_size
= end
- pos
;
2413 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2414 MOVTrack
*track
= &mov
->tracks
[i
];
2415 if (tracks
>= 0 && i
!= tracks
)
2419 avio_seek(pb
, mov
->tracks
[i
].moof_size_offset
, SEEK_SET
);
2420 avio_wb32(pb
, moof_size
+ 8 + mov
->tracks
[i
].data_offset
);
2422 avio_seek(pb
, end
, SEEK_SET
);
2424 return update_size(pb
, pos
);
2427 static int mov_write_tfra_tag(AVIOContext
*pb
, MOVTrack
*track
)
2429 int64_t pos
= avio_tell(pb
);
2432 avio_wb32(pb
, 0); /* size placeholder */
2433 ffio_wfourcc(pb
, "tfra");
2434 avio_w8(pb
, 1); /* version */
2437 avio_wb32(pb
, track
->track_id
);
2438 avio_wb32(pb
, 0); /* length of traf/trun/sample num */
2439 avio_wb32(pb
, track
->nb_frag_info
);
2440 for (i
= 0; i
< track
->nb_frag_info
; i
++) {
2441 avio_wb64(pb
, track
->frag_info
[i
].time
);
2442 avio_wb64(pb
, track
->frag_info
[i
].offset
);
2443 avio_w8(pb
, 1); /* traf number */
2444 avio_w8(pb
, 1); /* trun number */
2445 avio_w8(pb
, 1); /* sample number */
2448 return update_size(pb
, pos
);
2451 static int mov_write_mfra_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
2453 int64_t pos
= avio_tell(pb
);
2456 avio_wb32(pb
, 0); /* size placeholder */
2457 ffio_wfourcc(pb
, "mfra");
2458 /* An empty mfra atom is enough to indicate to the publishing point that
2459 * the stream has ended. */
2460 if (mov
->flags
& FF_MOV_FLAG_ISML
)
2461 return update_size(pb
, pos
);
2463 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2464 MOVTrack
*track
= &mov
->tracks
[i
];
2465 if (track
->nb_frag_info
)
2466 mov_write_tfra_tag(pb
, track
);
2470 ffio_wfourcc(pb
, "mfro");
2471 avio_wb32(pb
, 0); /* version + flags */
2472 avio_wb32(pb
, avio_tell(pb
) + 4 - pos
);
2474 return update_size(pb
, pos
);
2477 static int mov_write_mdat_tag(AVIOContext
*pb
, MOVMuxContext
*mov
)
2479 avio_wb32(pb
, 8); // placeholder for extended size field (64 bit)
2480 ffio_wfourcc(pb
, mov
->mode
== MODE_MOV ?
"wide" : "free");
2482 mov
->mdat_pos
= avio_tell(pb
);
2483 avio_wb32(pb
, 0); /* size placeholder*/
2484 ffio_wfourcc(pb
, "mdat");
2488 /* TODO: This needs to be more general */
2489 static int mov_write_ftyp_tag(AVIOContext
*pb
, AVFormatContext
*s
)
2491 MOVMuxContext
*mov
= s
->priv_data
;
2492 int64_t pos
= avio_tell(pb
);
2493 int has_h264
= 0, has_video
= 0;
2497 for (i
= 0; i
< s
->nb_streams
; i
++) {
2498 AVStream
*st
= s
->streams
[i
];
2499 if (st
->codec
->codec_type
== AVMEDIA_TYPE_VIDEO
)
2501 if (st
->codec
->codec_id
== AV_CODEC_ID_H264
)
2505 avio_wb32(pb
, 0); /* size */
2506 ffio_wfourcc(pb
, "ftyp");
2508 if (mov
->mode
== MODE_3GP
) {
2509 ffio_wfourcc(pb
, has_h264 ?
"3gp6" : "3gp4");
2510 minor
= has_h264 ?
0x100 : 0x200;
2511 } else if (mov
->mode
& MODE_3G2
) {
2512 ffio_wfourcc(pb
, has_h264 ?
"3g2b" : "3g2a");
2513 minor
= has_h264 ?
0x20000 : 0x10000;
2514 } else if (mov
->mode
== MODE_PSP
)
2515 ffio_wfourcc(pb
, "MSNV");
2516 else if (mov
->mode
== MODE_MP4
)
2517 ffio_wfourcc(pb
, "isom");
2518 else if (mov
->mode
== MODE_IPOD
)
2519 ffio_wfourcc(pb
, has_video ?
"M4V ":"M4A ");
2520 else if (mov
->mode
== MODE_ISM
)
2521 ffio_wfourcc(pb
, "isml");
2523 ffio_wfourcc(pb
, "qt ");
2525 avio_wb32(pb
, minor
);
2527 if (mov
->mode
== MODE_MOV
)
2528 ffio_wfourcc(pb
, "qt ");
2529 else if (mov
->mode
== MODE_ISM
) {
2530 ffio_wfourcc(pb
, "piff");
2531 ffio_wfourcc(pb
, "iso2");
2533 ffio_wfourcc(pb
, "isom");
2534 ffio_wfourcc(pb
, "iso2");
2536 ffio_wfourcc(pb
, "avc1");
2539 if (mov
->mode
== MODE_3GP
)
2540 ffio_wfourcc(pb
, has_h264 ?
"3gp6":"3gp4");
2541 else if (mov
->mode
& MODE_3G2
)
2542 ffio_wfourcc(pb
, has_h264 ?
"3g2b":"3g2a");
2543 else if (mov
->mode
== MODE_PSP
)
2544 ffio_wfourcc(pb
, "MSNV");
2545 else if (mov
->mode
== MODE_MP4
)
2546 ffio_wfourcc(pb
, "mp41");
2547 return update_size(pb
, pos
);
2550 static void mov_write_uuidprof_tag(AVIOContext
*pb
, AVFormatContext
*s
)
2552 AVCodecContext
*video_codec
= s
->streams
[0]->codec
;
2553 AVCodecContext
*audio_codec
= s
->streams
[1]->codec
;
2554 int audio_rate
= audio_codec
->sample_rate
;
2555 int frame_rate
= ((video_codec
->time_base
.den
) * (0x10000)) / (video_codec
->time_base
.num
);
2556 int audio_kbitrate
= audio_codec
->bit_rate
/ 1000;
2557 int video_kbitrate
= FFMIN(video_codec
->bit_rate
/ 1000, 800 - audio_kbitrate
);
2559 avio_wb32(pb
, 0x94); /* size */
2560 ffio_wfourcc(pb
, "uuid");
2561 ffio_wfourcc(pb
, "PROF");
2563 avio_wb32(pb
, 0x21d24fce); /* 96 bit UUID */
2564 avio_wb32(pb
, 0xbb88695c);
2565 avio_wb32(pb
, 0xfac9c740);
2567 avio_wb32(pb
, 0x0); /* ? */
2568 avio_wb32(pb
, 0x3); /* 3 sections ? */
2570 avio_wb32(pb
, 0x14); /* size */
2571 ffio_wfourcc(pb
, "FPRF");
2572 avio_wb32(pb
, 0x0); /* ? */
2573 avio_wb32(pb
, 0x0); /* ? */
2574 avio_wb32(pb
, 0x0); /* ? */
2576 avio_wb32(pb
, 0x2c); /* size */
2577 ffio_wfourcc(pb
, "APRF"); /* audio */
2579 avio_wb32(pb
, 0x2); /* TrackID */
2580 ffio_wfourcc(pb
, "mp4a");
2581 avio_wb32(pb
, 0x20f);
2583 avio_wb32(pb
, audio_kbitrate
);
2584 avio_wb32(pb
, audio_kbitrate
);
2585 avio_wb32(pb
, audio_rate
);
2586 avio_wb32(pb
, audio_codec
->channels
);
2588 avio_wb32(pb
, 0x34); /* size */
2589 ffio_wfourcc(pb
, "VPRF"); /* video */
2591 avio_wb32(pb
, 0x1); /* TrackID */
2592 if (video_codec
->codec_id
== AV_CODEC_ID_H264
) {
2593 ffio_wfourcc(pb
, "avc1");
2594 avio_wb16(pb
, 0x014D);
2595 avio_wb16(pb
, 0x0015);
2597 ffio_wfourcc(pb
, "mp4v");
2598 avio_wb16(pb
, 0x0000);
2599 avio_wb16(pb
, 0x0103);
2602 avio_wb32(pb
, video_kbitrate
);
2603 avio_wb32(pb
, video_kbitrate
);
2604 avio_wb32(pb
, frame_rate
);
2605 avio_wb32(pb
, frame_rate
);
2606 avio_wb16(pb
, video_codec
->width
);
2607 avio_wb16(pb
, video_codec
->height
);
2608 avio_wb32(pb
, 0x010001); /* ? */
2611 static int mov_parse_mpeg2_frame(AVPacket
*pkt
, uint32_t *flags
)
2614 int i
, closed_gop
= 0;
2616 for (i
= 0; i
< pkt
->size
- 4; i
++) {
2617 c
= (c
<< 8) + pkt
->data
[i
];
2618 if (c
== 0x1b8) { // gop
2619 closed_gop
= pkt
->data
[i
+ 4] >> 6 & 0x01;
2620 } else if (c
== 0x100) { // pic
2621 int temp_ref
= (pkt
->data
[i
+ 1] << 2) | (pkt
->data
[i
+ 2] >> 6);
2622 if (!temp_ref
|| closed_gop
) // I picture is not reordered
2623 *flags
= MOV_SYNC_SAMPLE
;
2625 *flags
= MOV_PARTIAL_SYNC_SAMPLE
;
2632 static void mov_parse_vc1_frame(AVPacket
*pkt
, MOVTrack
*trk
, int fragment
)
2634 const uint8_t *start
, *next
, *end
= pkt
->data
+ pkt
->size
;
2635 int seq
= 0, entry
= 0;
2636 int key
= pkt
->flags
& AV_PKT_FLAG_KEY
;
2637 start
= find_next_marker(pkt
->data
, end
);
2638 for (next
= start
; next
< end
; start
= next
) {
2639 next
= find_next_marker(start
+ 4, end
);
2640 switch (AV_RB32(start
)) {
2641 case VC1_CODE_SEQHDR
:
2644 case VC1_CODE_ENTRYPOINT
:
2647 case VC1_CODE_SLICE
:
2648 trk
->vc1_info
.slices
= 1;
2652 if (!trk
->entry
&& !fragment
) {
2653 /* First packet in first fragment */
2654 trk
->vc1_info
.first_packet_seq
= seq
;
2655 trk
->vc1_info
.first_packet_entry
= entry
;
2656 } else if ((seq
&& !trk
->vc1_info
.packet_seq
) ||
2657 (entry
&& !trk
->vc1_info
.packet_entry
)) {
2659 for (i
= 0; i
< trk
->entry
; i
++)
2660 trk
->cluster
[i
].flags
&= ~MOV_SYNC_SAMPLE
;
2661 trk
->has_keyframes
= 0;
2663 trk
->vc1_info
.packet_seq
= 1;
2665 trk
->vc1_info
.packet_entry
= 1;
2667 /* First fragment */
2668 if ((!seq
|| trk
->vc1_info
.first_packet_seq
) &&
2669 (!entry
|| trk
->vc1_info
.first_packet_entry
)) {
2670 /* First packet had the same headers as this one, readd the
2671 * sync sample flag. */
2672 trk
->cluster
[0].flags
|= MOV_SYNC_SAMPLE
;
2673 trk
->has_keyframes
= 1;
2677 if (trk
->vc1_info
.packet_seq
&& trk
->vc1_info
.packet_entry
)
2679 else if (trk
->vc1_info
.packet_seq
)
2681 else if (trk
->vc1_info
.packet_entry
)
2684 trk
->cluster
[trk
->entry
].flags
|= MOV_SYNC_SAMPLE
;
2685 trk
->has_keyframes
++;
2689 static int mov_flush_fragment(AVFormatContext
*s
)
2691 MOVMuxContext
*mov
= s
->priv_data
;
2692 int i
, first_track
= -1;
2693 int64_t mdat_size
= 0;
2695 if (!(mov
->flags
& FF_MOV_FLAG_FRAGMENT
))
2698 if (!(mov
->flags
& FF_MOV_FLAG_EMPTY_MOOV
) && mov
->fragments
== 0) {
2699 int64_t pos
= avio_tell(s
->pb
);
2701 AVIOContext
*moov_buf
;
2705 for (i
= 0; i
< mov
->nb_streams
; i
++)
2706 if (!mov
->tracks
[i
].entry
)
2708 /* Don't write the initial moov unless all tracks have data */
2709 if (i
< mov
->nb_streams
)
2712 if ((ret
= avio_open_dyn_buf(&moov_buf
)) < 0)
2714 mov_write_moov_tag(moov_buf
, mov
, s
);
2715 buf_size
= avio_close_dyn_buf(moov_buf
, &buf
);
2717 for (i
= 0; i
< mov
->nb_streams
; i
++)
2718 mov
->tracks
[i
].data_offset
= pos
+ buf_size
+ 8;
2720 mov_write_moov_tag(s
->pb
, mov
, s
);
2722 buf_size
= avio_close_dyn_buf(mov
->mdat_buf
, &buf
);
2723 mov
->mdat_buf
= NULL
;
2724 avio_wb32(s
->pb
, buf_size
+ 8);
2725 ffio_wfourcc(s
->pb
, "mdat");
2726 avio_write(s
->pb
, buf
, buf_size
);
2731 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2732 if (mov
->tracks
[i
].entry
)
2733 mov
->tracks
[i
].frag_start
+= mov
->tracks
[i
].start_dts
+
2734 mov
->tracks
[i
].track_duration
-
2735 mov
->tracks
[i
].cluster
[0].dts
;
2736 mov
->tracks
[i
].entry
= 0;
2742 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2743 MOVTrack
*track
= &mov
->tracks
[i
];
2744 if (mov
->flags
& FF_MOV_FLAG_SEPARATE_MOOF
)
2745 track
->data_offset
= 0;
2747 track
->data_offset
= mdat_size
;
2748 if (!track
->mdat_buf
)
2750 mdat_size
+= avio_tell(track
->mdat_buf
);
2751 if (first_track
< 0)
2758 for (i
= 0; i
< mov
->nb_streams
; i
++) {
2759 MOVTrack
*track
= &mov
->tracks
[i
];
2760 int buf_size
, write_moof
= 1, moof_tracks
= -1;
2762 int64_t duration
= 0;
2765 duration
= track
->start_dts
+ track
->track_duration
-
2766 track
->cluster
[0].dts
;
2767 if (mov
->flags
& FF_MOV_FLAG_SEPARATE_MOOF
) {
2768 if (!track
->mdat_buf
)
2770 mdat_size
= avio_tell(track
->mdat_buf
);
2773 write_moof
= i
== first_track
;
2777 MOVFragmentInfo
*info
;
2779 track
->nb_frag_info
++;
2780 if (track
->nb_frag_info
>= track
->frag_info_capacity
) {
2781 unsigned new_capacity
= track
->nb_frag_info
+ MOV_FRAG_INFO_ALLOC_INCREMENT
;
2782 if (av_reallocp_array(&track
->frag_info
,
2784 sizeof(*track
->frag_info
)))
2785 return AVERROR(ENOMEM
);
2786 track
->frag_info_capacity
= new_capacity
;
2788 info
= &track
->frag_info
[track
->nb_frag_info
- 1];
2789 info
->offset
= avio_tell(s
->pb
);
2790 info
->time
= mov
->tracks
[i
].frag_start
;
2791 info
->duration
= duration
;
2792 mov_write_tfrf_tags(s
->pb
, mov
, track
);
2794 mov_write_moof_tag(s
->pb
, mov
, moof_tracks
);
2795 info
->tfrf_offset
= track
->tfrf_offset
;
2798 avio_wb32(s
->pb
, mdat_size
+ 8);
2799 ffio_wfourcc(s
->pb
, "mdat");
2803 track
->frag_start
+= duration
;
2805 if (!track
->mdat_buf
)
2807 buf_size
= avio_close_dyn_buf(track
->mdat_buf
, &buf
);
2808 track
->mdat_buf
= NULL
;
2810 avio_write(s
->pb
, buf
, buf_size
);
2820 int ff_mov_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
2822 MOVMuxContext
*mov
= s
->priv_data
;
2823 AVIOContext
*pb
= s
->pb
;
2824 MOVTrack
*trk
= &mov
->tracks
[pkt
->stream_index
];
2825 AVCodecContext
*enc
= trk
->enc
;
2826 unsigned int samples_in_chunk
= 0;
2827 int size
= pkt
->size
;
2828 uint8_t *reformatted_data
= NULL
;
2830 if (mov
->flags
& FF_MOV_FLAG_FRAGMENT
) {
2832 if (mov
->fragments
> 0) {
2833 if (!trk
->mdat_buf
) {
2834 if ((ret
= avio_open_dyn_buf(&trk
->mdat_buf
)) < 0)
2839 if (!mov
->mdat_buf
) {
2840 if ((ret
= avio_open_dyn_buf(&mov
->mdat_buf
)) < 0)
2847 if (enc
->codec_id
== AV_CODEC_ID_AMR_NB
) {
2848 /* We must find out how many AMR blocks there are in one packet */
2849 static uint16_t packed_size
[16] =
2850 {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
2853 while (len
< size
&& samples_in_chunk
< 100) {
2854 len
+= packed_size
[(pkt
->data