blob: 9280dc8d236baf2f9c07395c1074f20de95216dd
1 | /* |
2 | * MOV, 3GP, MP4 muxer |
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> |
6 | * |
7 | * This file is part of FFmpeg. |
8 | * |
9 | * FFmpeg 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. |
13 | * |
14 | * FFmpeg 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. |
18 | * |
19 | * You should have received a copy of the GNU Lesser General Public |
20 | * License along with FFmpeg; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | */ |
23 | |
24 | #include <stdint.h> |
25 | #include <inttypes.h> |
26 | |
27 | #include "movenc.h" |
28 | #include "avformat.h" |
29 | #include "avio_internal.h" |
30 | #include "riff.h" |
31 | #include "avio.h" |
32 | #include "isom.h" |
33 | #include "avc.h" |
34 | #include "libavcodec/ac3_parser.h" |
35 | #include "libavcodec/dnxhddata.h" |
36 | #include "libavcodec/flac.h" |
37 | #include "libavcodec/get_bits.h" |
38 | #include "libavcodec/put_bits.h" |
39 | #include "libavcodec/vc1_common.h" |
40 | #include "libavcodec/raw.h" |
41 | #include "internal.h" |
42 | #include "libavutil/avstring.h" |
43 | #include "libavutil/intfloat.h" |
44 | #include "libavutil/mathematics.h" |
45 | #include "libavutil/libm.h" |
46 | #include "libavutil/opt.h" |
47 | #include "libavutil/dict.h" |
48 | #include "libavutil/pixdesc.h" |
49 | #include "libavutil/stereo3d.h" |
50 | #include "libavutil/timecode.h" |
51 | #include "libavutil/color_utils.h" |
52 | #include "hevc.h" |
53 | #include "rtpenc.h" |
54 | #include "mov_chan.h" |
55 | #include "vpcc.h" |
56 | |
57 | static const AVOption options[] = { |
58 | { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
59 | { "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" }, |
60 | { "moov_size", "maximum moov size so it can be placed at the begin", offsetof(MOVMuxContext, reserved_moov_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 0 }, |
61 | { "empty_moov", "Make the initial moov atom empty", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
62 | { "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" }, |
63 | { "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" }, |
64 | { "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" }, |
65 | { "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" }, |
66 | { "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" }, |
67 | { "omit_tfhd_offset", "Omit the base data offset in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_OMIT_TFHD_OFFSET}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
68 | { "disable_chpl", "Disable Nero chapter atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DISABLE_CHPL}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
69 | { "default_base_moof", "Set the default-base-is-moof flag in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DEFAULT_BASE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
70 | { "dash", "Write DASH compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DASH}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
71 | { "frag_discont", "Signal that the next fragment is discontinuous from earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
72 | { "delay_moov", "Delay writing the initial moov until the first fragment is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
73 | { "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
74 | { "write_colr", "Write colr atom (Experimental, may be renamed or changed, do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
75 | { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
76 | { "use_metadata_tags", "Use mdta atom for metadata.", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
77 | { "skip_trailer", "Skip writing the mfra/tfra/mfro trailer for fragmented files", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_TRAILER}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, |
78 | FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags), |
79 | { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, |
80 | { "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}, |
81 | { "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}, |
82 | { "frag_duration", "Maximum fragment duration", offsetof(MOVMuxContext, max_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, |
83 | { "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}, |
84 | { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, |
85 | { "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}, |
86 | { "video_track_timescale", "set timescale of all video tracks", offsetof(MOVMuxContext, video_track_timescale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, |
87 | { "brand", "Override major brand", offsetof(MOVMuxContext, major_brand), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, |
88 | { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, |
89 | { "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext, fragments), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, |
90 | { "mov_gamma", "gamma value for gama atom", offsetof(MOVMuxContext, gamma), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, 0.0, 10, AV_OPT_FLAG_ENCODING_PARAM}, |
91 | { "frag_interleave", "Interleave samples within fragments (max number of consecutive samples, lower is tighter interleaving, but with more overhead)", offsetof(MOVMuxContext, frag_interleave), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, |
92 | { "encryption_scheme", "Configures the encryption scheme, allowed values are none, cenc-aes-ctr", offsetof(MOVMuxContext, encryption_scheme_str), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, |
93 | { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM }, |
94 | { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM }, |
95 | { "use_stream_ids_as_track_ids", "use stream ids as track ids", offsetof(MOVMuxContext, use_stream_ids_as_track_ids), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, |
96 | { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, |
97 | { NULL }, |
98 | }; |
99 | |
100 | #define MOV_CLASS(flavor)\ |
101 | static const AVClass flavor ## _muxer_class = {\ |
102 | .class_name = #flavor " muxer",\ |
103 | .item_name = av_default_item_name,\ |
104 | .option = options,\ |
105 | .version = LIBAVUTIL_VERSION_INT,\ |
106 | }; |
107 | |
108 | static int get_moov_size(AVFormatContext *s); |
109 | |
110 | static int utf8len(const uint8_t *b) |
111 | { |
112 | int len = 0; |
113 | int val; |
114 | while (*b) { |
115 | GET_UTF8(val, *b++, return -1;) |
116 | len++; |
117 | } |
118 | return len; |
119 | } |
120 | |
121 | //FIXME support 64 bit variant with wide placeholders |
122 | static int64_t update_size(AVIOContext *pb, int64_t pos) |
123 | { |
124 | int64_t curpos = avio_tell(pb); |
125 | avio_seek(pb, pos, SEEK_SET); |
126 | avio_wb32(pb, curpos - pos); /* rewrite size */ |
127 | avio_seek(pb, curpos, SEEK_SET); |
128 | |
129 | return curpos - pos; |
130 | } |
131 | |
132 | static int co64_required(const MOVTrack *track) |
133 | { |
134 | if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX) |
135 | return 1; |
136 | return 0; |
137 | } |
138 | |
139 | /* Chunk offset atom */ |
140 | static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track) |
141 | { |
142 | int i; |
143 | int mode64 = co64_required(track); // use 32 bit size variant if possible |
144 | int64_t pos = avio_tell(pb); |
145 | avio_wb32(pb, 0); /* size */ |
146 | if (mode64) |
147 | ffio_wfourcc(pb, "co64"); |
148 | else |
149 | ffio_wfourcc(pb, "stco"); |
150 | avio_wb32(pb, 0); /* version & flags */ |
151 | avio_wb32(pb, track->chunkCount); /* entry count */ |
152 | for (i = 0; i < track->entry; i++) { |
153 | if (!track->cluster[i].chunkNum) |
154 | continue; |
155 | if (mode64 == 1) |
156 | avio_wb64(pb, track->cluster[i].pos + track->data_offset); |
157 | else |
158 | avio_wb32(pb, track->cluster[i].pos + track->data_offset); |
159 | } |
160 | return update_size(pb, pos); |
161 | } |
162 | |
163 | /* Sample size atom */ |
164 | static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track) |
165 | { |
166 | int equalChunks = 1; |
167 | int i, j, entries = 0, tst = -1, oldtst = -1; |
168 | |
169 | int64_t pos = avio_tell(pb); |
170 | avio_wb32(pb, 0); /* size */ |
171 | ffio_wfourcc(pb, "stsz"); |
172 | avio_wb32(pb, 0); /* version & flags */ |
173 | |
174 | for (i = 0; i < track->entry; i++) { |
175 | tst = track->cluster[i].size / track->cluster[i].entries; |
176 | if (oldtst != -1 && tst != oldtst) |
177 | equalChunks = 0; |
178 | oldtst = tst; |
179 | entries += track->cluster[i].entries; |
180 | } |
181 | if (equalChunks && track->entry) { |
182 | int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0; |
183 | sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0 |
184 | avio_wb32(pb, sSize); // sample size |
185 | avio_wb32(pb, entries); // sample count |
186 | } else { |
187 | avio_wb32(pb, 0); // sample size |
188 | avio_wb32(pb, entries); // sample count |
189 | for (i = 0; i < track->entry; i++) { |
190 | for (j = 0; j < track->cluster[i].entries; j++) { |
191 | avio_wb32(pb, track->cluster[i].size / |
192 | track->cluster[i].entries); |
193 | } |
194 | } |
195 | } |
196 | return update_size(pb, pos); |
197 | } |
198 | |
199 | /* Sample to chunk atom */ |
200 | static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track) |
201 | { |
202 | int index = 0, oldval = -1, i; |
203 | int64_t entryPos, curpos; |
204 | |
205 | int64_t pos = avio_tell(pb); |
206 | avio_wb32(pb, 0); /* size */ |
207 | ffio_wfourcc(pb, "stsc"); |
208 | avio_wb32(pb, 0); // version & flags |
209 | entryPos = avio_tell(pb); |
210 | avio_wb32(pb, track->chunkCount); // entry count |
211 | for (i = 0; i < track->entry; i++) { |
212 | if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) { |
213 | avio_wb32(pb, track->cluster[i].chunkNum); // first chunk |
214 | avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk |
215 | avio_wb32(pb, 0x1); // sample description index |
216 | oldval = track->cluster[i].samples_in_chunk; |
217 | index++; |
218 | } |
219 | } |
220 | curpos = avio_tell(pb); |
221 | avio_seek(pb, entryPos, SEEK_SET); |
222 | avio_wb32(pb, index); // rewrite size |
223 | avio_seek(pb, curpos, SEEK_SET); |
224 | |
225 | return update_size(pb, pos); |
226 | } |
227 | |
228 | /* Sync sample atom */ |
229 | static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag) |
230 | { |
231 | int64_t curpos, entryPos; |
232 | int i, index = 0; |
233 | int64_t pos = avio_tell(pb); |
234 | avio_wb32(pb, 0); // size |
235 | ffio_wfourcc(pb, flag == MOV_SYNC_SAMPLE ? "stss" : "stps"); |
236 | avio_wb32(pb, 0); // version & flags |
237 | entryPos = avio_tell(pb); |
238 | avio_wb32(pb, track->entry); // entry count |
239 | for (i = 0; i < track->entry; i++) { |
240 | if (track->cluster[i].flags & flag) { |
241 | avio_wb32(pb, i + 1); |
242 | index++; |
243 | } |
244 | } |
245 | curpos = avio_tell(pb); |
246 | avio_seek(pb, entryPos, SEEK_SET); |
247 | avio_wb32(pb, index); // rewrite size |
248 | avio_seek(pb, curpos, SEEK_SET); |
249 | return update_size(pb, pos); |
250 | } |
251 | |
252 | static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track) |
253 | { |
254 | avio_wb32(pb, 0x11); /* size */ |
255 | if (track->mode == MODE_MOV) ffio_wfourcc(pb, "samr"); |
256 | else ffio_wfourcc(pb, "damr"); |
257 | ffio_wfourcc(pb, "FFMP"); |
258 | avio_w8(pb, 0); /* decoder version */ |
259 | |
260 | avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */ |
261 | avio_w8(pb, 0x00); /* Mode change period (no restriction) */ |
262 | avio_w8(pb, 0x01); /* Frames per sample */ |
263 | return 0x11; |
264 | } |
265 | |
266 | static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track) |
267 | { |
268 | GetBitContext gbc; |
269 | PutBitContext pbc; |
270 | uint8_t buf[3]; |
271 | int fscod, bsid, bsmod, acmod, lfeon, frmsizecod; |
272 | |
273 | if (track->vos_len < 7) |
274 | return -1; |
275 | |
276 | avio_wb32(pb, 11); |
277 | ffio_wfourcc(pb, "dac3"); |
278 | |
279 | init_get_bits(&gbc, track->vos_data + 4, (track->vos_len - 4) * 8); |
280 | fscod = get_bits(&gbc, 2); |
281 | frmsizecod = get_bits(&gbc, 6); |
282 | bsid = get_bits(&gbc, 5); |
283 | bsmod = get_bits(&gbc, 3); |
284 | acmod = get_bits(&gbc, 3); |
285 | if (acmod == 2) { |
286 | skip_bits(&gbc, 2); // dsurmod |
287 | } else { |
288 | if ((acmod & 1) && acmod != 1) |
289 | skip_bits(&gbc, 2); // cmixlev |
290 | if (acmod & 4) |
291 | skip_bits(&gbc, 2); // surmixlev |
292 | } |
293 | lfeon = get_bits1(&gbc); |
294 | |
295 | init_put_bits(&pbc, buf, sizeof(buf)); |
296 | put_bits(&pbc, 2, fscod); |
297 | put_bits(&pbc, 5, bsid); |
298 | put_bits(&pbc, 3, bsmod); |
299 | put_bits(&pbc, 3, acmod); |
300 | put_bits(&pbc, 1, lfeon); |
301 | put_bits(&pbc, 5, frmsizecod >> 1); // bit_rate_code |
302 | put_bits(&pbc, 5, 0); // reserved |
303 | |
304 | flush_put_bits(&pbc); |
305 | avio_write(pb, buf, sizeof(buf)); |
306 | |
307 | return 11; |
308 | } |
309 | |
310 | struct eac3_info { |
311 | AVPacket pkt; |
312 | uint8_t ec3_done; |
313 | uint8_t num_blocks; |
314 | |
315 | /* Layout of the EC3SpecificBox */ |
316 | /* maximum bitrate */ |
317 | uint16_t data_rate; |
318 | /* number of independent substreams */ |
319 | uint8_t num_ind_sub; |
320 | struct { |
321 | /* sample rate code (see ff_ac3_sample_rate_tab) 2 bits */ |
322 | uint8_t fscod; |
323 | /* bit stream identification 5 bits */ |
324 | uint8_t bsid; |
325 | /* one bit reserved */ |
326 | /* audio service mixing (not supported yet) 1 bit */ |
327 | /* bit stream mode 3 bits */ |
328 | uint8_t bsmod; |
329 | /* audio coding mode 3 bits */ |
330 | uint8_t acmod; |
331 | /* sub woofer on 1 bit */ |
332 | uint8_t lfeon; |
333 | /* 3 bits reserved */ |
334 | /* number of dependent substreams associated with this substream 4 bits */ |
335 | uint8_t num_dep_sub; |
336 | /* channel locations of the dependent substream(s), if any, 9 bits */ |
337 | uint16_t chan_loc; |
338 | /* if there is no dependent substream, then one bit reserved instead */ |
339 | } substream[1]; /* TODO: support 8 independent substreams */ |
340 | }; |
341 | |
342 | #if CONFIG_AC3_PARSER |
343 | static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) |
344 | { |
345 | GetBitContext gbc; |
346 | AC3HeaderInfo tmp, *hdr = &tmp; |
347 | struct eac3_info *info; |
348 | int num_blocks; |
349 | |
350 | if (!track->eac3_priv && !(track->eac3_priv = av_mallocz(sizeof(*info)))) |
351 | return AVERROR(ENOMEM); |
352 | info = track->eac3_priv; |
353 | |
354 | init_get_bits(&gbc, pkt->data, pkt->size * 8); |
355 | if (avpriv_ac3_parse_header(&gbc, &hdr) < 0) { |
356 | /* drop the packets until we see a good one */ |
357 | if (!track->entry) { |
358 | av_log(mov, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n"); |
359 | return 0; |
360 | } |
361 | return AVERROR_INVALIDDATA; |
362 | } |
363 | |
364 | info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000); |
365 | num_blocks = hdr->num_blocks; |
366 | |
367 | if (!info->ec3_done) { |
368 | /* AC-3 substream must be the first one */ |
369 | if (hdr->bitstream_id <= 10 && hdr->substreamid != 0) |
370 | return AVERROR(EINVAL); |
371 | |
372 | /* this should always be the case, given that our AC-3 parser |
373 | * concatenates dependent frames to their independent parent */ |
374 | if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT) { |
375 | /* substream ids must be incremental */ |
376 | if (hdr->substreamid > info->num_ind_sub + 1) |
377 | return AVERROR(EINVAL); |
378 | |
379 | if (hdr->substreamid == info->num_ind_sub + 1) { |
380 | //info->num_ind_sub++; |
381 | avpriv_request_sample(track->par, "Multiple independent substreams"); |
382 | return AVERROR_PATCHWELCOME; |
383 | } else if (hdr->substreamid < info->num_ind_sub || |
384 | hdr->substreamid == 0 && info->substream[0].bsid) { |
385 | info->ec3_done = 1; |
386 | goto concatenate; |
387 | } |
388 | } |
389 | |
390 | /* fill the info needed for the "dec3" atom */ |
391 | info->substream[hdr->substreamid].fscod = hdr->sr_code; |
392 | info->substream[hdr->substreamid].bsid = hdr->bitstream_id; |
393 | info->substream[hdr->substreamid].bsmod = hdr->bitstream_mode; |
394 | info->substream[hdr->substreamid].acmod = hdr->channel_mode; |
395 | info->substream[hdr->substreamid].lfeon = hdr->lfe_on; |
396 | |
397 | /* Parse dependent substream(s), if any */ |
398 | if (pkt->size != hdr->frame_size) { |
399 | int cumul_size = hdr->frame_size; |
400 | int parent = hdr->substreamid; |
401 | |
402 | while (cumul_size != pkt->size) { |
403 | int i; |
404 | init_get_bits(&gbc, pkt->data + cumul_size, (pkt->size - cumul_size) * 8); |
405 | if (avpriv_ac3_parse_header(&gbc, &hdr) < 0) |
406 | return AVERROR_INVALIDDATA; |
407 | if (hdr->frame_type != EAC3_FRAME_TYPE_DEPENDENT) |
408 | return AVERROR(EINVAL); |
409 | cumul_size += hdr->frame_size; |
410 | info->substream[parent].num_dep_sub++; |
411 | |
412 | /* header is parsed up to lfeon, but custom channel map may be needed */ |
413 | /* skip bsid */ |
414 | skip_bits(&gbc, 5); |
415 | /* skip volume control params */ |
416 | for (i = 0; i < (hdr->channel_mode ? 1 : 2); i++) { |
417 | skip_bits(&gbc, 5); // skip dialog normalization |
418 | if (get_bits1(&gbc)) { |
419 | skip_bits(&gbc, 8); // skip compression gain word |
420 | } |
421 | } |
422 | /* get the dependent stream channel map, if exists */ |
423 | if (get_bits1(&gbc)) |
424 | info->substream[parent].chan_loc |= (get_bits(&gbc, 16) >> 5) & 0x1f; |
425 | else |
426 | info->substream[parent].chan_loc |= hdr->channel_mode; |
427 | } |
428 | } |
429 | } |
430 | |
431 | concatenate: |
432 | if (!info->num_blocks && num_blocks == 6) |
433 | return pkt->size; |
434 | else if (info->num_blocks + num_blocks > 6) |
435 | return AVERROR_INVALIDDATA; |
436 | |
437 | if (!info->num_blocks) { |
438 | int ret; |
439 | if ((ret = av_copy_packet(&info->pkt, pkt)) < 0) |
440 | return ret; |
441 | info->num_blocks = num_blocks; |
442 | return 0; |
443 | } else { |
444 | int ret; |
445 | if ((ret = av_grow_packet(&info->pkt, pkt->size)) < 0) |
446 | return ret; |
447 | memcpy(info->pkt.data + info->pkt.size - pkt->size, pkt->data, pkt->size); |
448 | info->num_blocks += num_blocks; |
449 | info->pkt.duration += pkt->duration; |
450 | if ((ret = av_copy_packet_side_data(&info->pkt, pkt)) < 0) |
451 | return ret; |
452 | if (info->num_blocks != 6) |
453 | return 0; |
454 | av_packet_unref(pkt); |
455 | if ((ret = av_copy_packet(pkt, &info->pkt)) < 0) |
456 | return ret; |
457 | av_packet_unref(&info->pkt); |
458 | info->num_blocks = 0; |
459 | } |
460 | |
461 | return pkt->size; |
462 | } |
463 | #endif |
464 | |
465 | static int mov_write_eac3_tag(AVIOContext *pb, MOVTrack *track) |
466 | { |
467 | PutBitContext pbc; |
468 | uint8_t *buf; |
469 | struct eac3_info *info; |
470 | int size, i; |
471 | |
472 | if (!track->eac3_priv) |
473 | return AVERROR(EINVAL); |
474 | |
475 | info = track->eac3_priv; |
476 | size = 2 + 4 * (info->num_ind_sub + 1); |
477 | buf = av_malloc(size); |
478 | if (!buf) { |
479 | size = AVERROR(ENOMEM); |
480 | goto end; |
481 | } |
482 | |
483 | init_put_bits(&pbc, buf, size); |
484 | put_bits(&pbc, 13, info->data_rate); |
485 | put_bits(&pbc, 3, info->num_ind_sub); |
486 | for (i = 0; i <= info->num_ind_sub; i++) { |
487 | put_bits(&pbc, 2, info->substream[i].fscod); |
488 | put_bits(&pbc, 5, info->substream[i].bsid); |
489 | put_bits(&pbc, 1, 0); /* reserved */ |
490 | put_bits(&pbc, 1, 0); /* asvc */ |
491 | put_bits(&pbc, 3, info->substream[i].bsmod); |
492 | put_bits(&pbc, 3, info->substream[i].acmod); |
493 | put_bits(&pbc, 1, info->substream[i].lfeon); |
494 | put_bits(&pbc, 5, 0); /* reserved */ |
495 | put_bits(&pbc, 4, info->substream[i].num_dep_sub); |
496 | if (!info->substream[i].num_dep_sub) { |
497 | put_bits(&pbc, 1, 0); /* reserved */ |
498 | size--; |
499 | } else { |
500 | put_bits(&pbc, 9, info->substream[i].chan_loc); |
501 | } |
502 | } |
503 | flush_put_bits(&pbc); |
504 | |
505 | avio_wb32(pb, size + 8); |
506 | ffio_wfourcc(pb, "dec3"); |
507 | avio_write(pb, buf, size); |
508 | |
509 | av_free(buf); |
510 | |
511 | end: |
512 | av_packet_unref(&info->pkt); |
513 | av_freep(&track->eac3_priv); |
514 | |
515 | return size; |
516 | } |
517 | |
518 | /** |
519 | * This function writes extradata "as is". |
520 | * Extradata must be formatted like a valid atom (with size and tag). |
521 | */ |
522 | static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track) |
523 | { |
524 | avio_write(pb, track->par->extradata, track->par->extradata_size); |
525 | return track->par->extradata_size; |
526 | } |
527 | |
528 | static int mov_write_enda_tag(AVIOContext *pb) |
529 | { |
530 | avio_wb32(pb, 10); |
531 | ffio_wfourcc(pb, "enda"); |
532 | avio_wb16(pb, 1); /* little endian */ |
533 | return 10; |
534 | } |
535 | |
536 | static int mov_write_enda_tag_be(AVIOContext *pb) |
537 | { |
538 | avio_wb32(pb, 10); |
539 | ffio_wfourcc(pb, "enda"); |
540 | avio_wb16(pb, 0); /* big endian */ |
541 | return 10; |
542 | } |
543 | |
544 | static void put_descr(AVIOContext *pb, int tag, unsigned int size) |
545 | { |
546 | int i = 3; |
547 | avio_w8(pb, tag); |
548 | for (; i > 0; i--) |
549 | avio_w8(pb, (size >> (7 * i)) | 0x80); |
550 | avio_w8(pb, size & 0x7F); |
551 | } |
552 | |
553 | static unsigned compute_avg_bitrate(MOVTrack *track) |
554 | { |
555 | uint64_t size = 0; |
556 | int i; |
557 | if (!track->track_duration) |
558 | return 0; |
559 | for (i = 0; i < track->entry; i++) |
560 | size += track->cluster[i].size; |
561 | return size * 8 * track->timescale / track->track_duration; |
562 | } |
563 | |
564 | static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic |
565 | { |
566 | AVCPBProperties *props; |
567 | int64_t pos = avio_tell(pb); |
568 | int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0; |
569 | unsigned avg_bitrate; |
570 | |
571 | avio_wb32(pb, 0); // size |
572 | ffio_wfourcc(pb, "esds"); |
573 | avio_wb32(pb, 0); // Version |
574 | |
575 | // ES descriptor |
576 | put_descr(pb, 0x03, 3 + 5+13 + decoder_specific_info_len + 5+1); |
577 | avio_wb16(pb, track->track_id); |
578 | avio_w8(pb, 0x00); // flags (= no flags) |
579 | |
580 | // DecoderConfig descriptor |
581 | put_descr(pb, 0x04, 13 + decoder_specific_info_len); |
582 | |
583 | // Object type indication |
584 | if ((track->par->codec_id == AV_CODEC_ID_MP2 || |
585 | track->par->codec_id == AV_CODEC_ID_MP3) && |
586 | track->par->sample_rate > 24000) |
587 | avio_w8(pb, 0x6B); // 11172-3 |
588 | else |
589 | avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id)); |
590 | |
591 | // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio) |
592 | // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved) |
593 | if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) |
594 | avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream) |
595 | else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) |
596 | avio_w8(pb, 0x15); // flags (= Audiostream) |
597 | else |
598 | avio_w8(pb, 0x11); // flags (= Visualstream) |
599 | |
600 | props = (AVCPBProperties*)av_stream_get_side_data(track->st, AV_PKT_DATA_CPB_PROPERTIES, |
601 | NULL); |
602 | |
603 | avio_wb24(pb, props ? props->buffer_size / 8 : 0); // Buffersize DB |
604 | |
605 | avg_bitrate = compute_avg_bitrate(track); |
606 | avio_wb32(pb, props ? FFMAX3(props->max_bitrate, props->avg_bitrate, avg_bitrate) : FFMAX(track->par->bit_rate, avg_bitrate)); // maxbitrate (FIXME should be max rate in any 1 sec window) |
607 | avio_wb32(pb, avg_bitrate); |
608 | |
609 | if (track->vos_len) { |
610 | // DecoderSpecific info descriptor |
611 | put_descr(pb, 0x05, track->vos_len); |
612 | avio_write(pb, track->vos_data, track->vos_len); |
613 | } |
614 | |
615 | // SL descriptor |
616 | put_descr(pb, 0x06, 1); |
617 | avio_w8(pb, 0x02); |
618 | return update_size(pb, pos); |
619 | } |
620 | |
621 | static int mov_pcm_le_gt16(enum AVCodecID codec_id) |
622 | { |
623 | return codec_id == AV_CODEC_ID_PCM_S24LE || |
624 | codec_id == AV_CODEC_ID_PCM_S32LE || |
625 | codec_id == AV_CODEC_ID_PCM_F32LE || |
626 | codec_id == AV_CODEC_ID_PCM_F64LE; |
627 | } |
628 | |
629 | static int mov_pcm_be_gt16(enum AVCodecID codec_id) |
630 | { |
631 | return codec_id == AV_CODEC_ID_PCM_S24BE || |
632 | codec_id == AV_CODEC_ID_PCM_S32BE || |
633 | codec_id == AV_CODEC_ID_PCM_F32BE || |
634 | codec_id == AV_CODEC_ID_PCM_F64BE; |
635 | } |
636 | |
637 | static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) |
638 | { |
639 | int ret; |
640 | int64_t pos = avio_tell(pb); |
641 | avio_wb32(pb, 0); |
642 | avio_wl32(pb, track->tag); // store it byteswapped |
643 | track->par->codec_tag = av_bswap16(track->tag >> 16); |
644 | if ((ret = ff_put_wav_header(s, pb, track->par, 0)) < 0) |
645 | return ret; |
646 | return update_size(pb, pos); |
647 | } |
648 | |
649 | static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) |
650 | { |
651 | int ret; |
652 | int64_t pos = avio_tell(pb); |
653 | avio_wb32(pb, 0); |
654 | ffio_wfourcc(pb, "wfex"); |
655 | if ((ret = ff_put_wav_header(s, pb, track->st->codecpar, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0) |
656 | return ret; |
657 | return update_size(pb, pos); |
658 | } |
659 | |
660 | static int mov_write_dfla_tag(AVIOContext *pb, MOVTrack *track) |
661 | { |
662 | int64_t pos = avio_tell(pb); |
663 | avio_wb32(pb, 0); |
664 | ffio_wfourcc(pb, "dfLa"); |
665 | avio_w8(pb, 0); /* version */ |
666 | avio_wb24(pb, 0); /* flags */ |
667 | |
668 | /* Expect the encoder to pass a METADATA_BLOCK_TYPE_STREAMINFO. */ |
669 | if (track->par->extradata_size != FLAC_STREAMINFO_SIZE) |
670 | return AVERROR_INVALIDDATA; |
671 | |
672 | /* TODO: Write other METADATA_BLOCK_TYPEs if the encoder makes them available. */ |
673 | avio_w8(pb, 1 << 7 | FLAC_METADATA_TYPE_STREAMINFO); /* LastMetadataBlockFlag << 7 | BlockType */ |
674 | avio_wb24(pb, track->par->extradata_size); /* Length */ |
675 | avio_write(pb, track->par->extradata, track->par->extradata_size); /* BlockData[Length] */ |
676 | |
677 | return update_size(pb, pos); |
678 | } |
679 | |
680 | static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) |
681 | { |
682 | uint32_t layout_tag, bitmap; |
683 | int64_t pos = avio_tell(pb); |
684 | |
685 | layout_tag = ff_mov_get_channel_layout_tag(track->par->codec_id, |
686 | track->par->channel_layout, |
687 | &bitmap); |
688 | if (!layout_tag) { |
689 | av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to " |
690 | "lack of channel information\n"); |
691 | return 0; |
692 | } |
693 | |
694 | if (track->multichannel_as_mono) |
695 | return 0; |
696 | |
697 | avio_wb32(pb, 0); // Size |
698 | ffio_wfourcc(pb, "chan"); // Type |
699 | avio_w8(pb, 0); // Version |
700 | avio_wb24(pb, 0); // Flags |
701 | avio_wb32(pb, layout_tag); // mChannelLayoutTag |
702 | avio_wb32(pb, bitmap); // mChannelBitmap |
703 | avio_wb32(pb, 0); // mNumberChannelDescriptions |
704 | |
705 | return update_size(pb, pos); |
706 | } |
707 | |
708 | static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) |
709 | { |
710 | int64_t pos = avio_tell(pb); |
711 | |
712 | avio_wb32(pb, 0); /* size */ |
713 | ffio_wfourcc(pb, "wave"); |
714 | |
715 | if (track->par->codec_id != AV_CODEC_ID_QDM2) { |
716 | avio_wb32(pb, 12); /* size */ |
717 | ffio_wfourcc(pb, "frma"); |
718 | avio_wl32(pb, track->tag); |
719 | } |
720 | |
721 | if (track->par->codec_id == AV_CODEC_ID_AAC) { |
722 | /* useless atom needed by mplayer, ipod, not needed by quicktime */ |
723 | avio_wb32(pb, 12); /* size */ |
724 | ffio_wfourcc(pb, "mp4a"); |
725 | avio_wb32(pb, 0); |
726 | mov_write_esds_tag(pb, track); |
727 | } else if (mov_pcm_le_gt16(track->par->codec_id)) { |
728 | mov_write_enda_tag(pb); |
729 | } else if (mov_pcm_be_gt16(track->par->codec_id)) { |
730 | mov_write_enda_tag_be(pb); |
731 | } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) { |
732 | mov_write_amr_tag(pb, track); |
733 | } else if (track->par->codec_id == AV_CODEC_ID_AC3) { |
734 | mov_write_ac3_tag(pb, track); |
735 | } else if (track->par->codec_id == AV_CODEC_ID_EAC3) { |
736 | mov_write_eac3_tag(pb, track); |
737 | } else if (track->par->codec_id == AV_CODEC_ID_ALAC || |
738 | track->par->codec_id == AV_CODEC_ID_QDM2) { |
739 | mov_write_extradata_tag(pb, track); |
740 | } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS || |
741 | track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { |
742 | mov_write_ms_tag(s, pb, track); |
743 | } |
744 | |
745 | avio_wb32(pb, 8); /* size */ |
746 | avio_wb32(pb, 0); /* null tag */ |
747 | |
748 | return update_size(pb, pos); |
749 | } |
750 | |
751 | static int mov_write_dvc1_structs(MOVTrack *track, uint8_t *buf) |
752 | { |
753 | uint8_t *unescaped; |
754 | const uint8_t *start, *next, *end = track->vos_data + track->vos_len; |
755 | int unescaped_size, seq_found = 0; |
756 | int level = 0, interlace = 0; |
757 | int packet_seq = track->vc1_info.packet_seq; |
758 | int packet_entry = track->vc1_info.packet_entry; |
759 | int slices = track->vc1_info.slices; |
760 | PutBitContext pbc; |
761 | |
762 | if (track->start_dts == AV_NOPTS_VALUE) { |
763 | /* No packets written yet, vc1_info isn't authoritative yet. */ |
764 | /* Assume inline sequence and entry headers. */ |
765 | packet_seq = packet_entry = 1; |
766 | av_log(NULL, AV_LOG_WARNING, |
767 | "moov atom written before any packets, unable to write correct " |
768 | "dvc1 atom. Set the delay_moov flag to fix this.\n"); |
769 | } |
770 | |
771 | unescaped = av_mallocz(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE); |
772 | if (!unescaped) |
773 | return AVERROR(ENOMEM); |
774 | start = find_next_marker(track->vos_data, end); |
775 | for (next = start; next < end; start = next) { |
776 | GetBitContext gb; |
777 | int size; |
778 | next = find_next_marker(start + 4, end); |
779 | size = next - start - 4; |
780 | if (size <= 0) |
781 | continue; |
782 | unescaped_size = vc1_unescape_buffer(start + 4, size, unescaped); |
783 | init_get_bits(&gb, unescaped, 8 * unescaped_size); |
784 | if (AV_RB32(start) == VC1_CODE_SEQHDR) { |
785 | int profile = get_bits(&gb, 2); |
786 | if (profile != PROFILE_ADVANCED) { |
787 | av_free(unescaped); |
788 | return AVERROR(ENOSYS); |
789 | } |
790 | seq_found = 1; |
791 | level = get_bits(&gb, 3); |
792 | /* chromaformat, frmrtq_postproc, bitrtq_postproc, postprocflag, |
793 | * width, height */ |
794 | skip_bits_long(&gb, 2 + 3 + 5 + 1 + 2*12); |
795 | skip_bits(&gb, 1); /* broadcast */ |
796 | interlace = get_bits1(&gb); |
797 | skip_bits(&gb, 4); /* tfcntrflag, finterpflag, reserved, psf */ |
798 | } |
799 | } |
800 | if (!seq_found) { |
801 | av_free(unescaped); |
802 | return AVERROR(ENOSYS); |
803 | } |
804 | |
805 | init_put_bits(&pbc, buf, 7); |
806 | /* VC1DecSpecStruc */ |
807 | put_bits(&pbc, 4, 12); /* profile - advanced */ |
808 | put_bits(&pbc, 3, level); |
809 | put_bits(&pbc, 1, 0); /* reserved */ |
810 | /* VC1AdvDecSpecStruc */ |
811 | put_bits(&pbc, 3, level); |
812 | put_bits(&pbc, 1, 0); /* cbr */ |
813 | put_bits(&pbc, 6, 0); /* reserved */ |
814 | put_bits(&pbc, 1, !interlace); /* no interlace */ |
815 | put_bits(&pbc, 1, !packet_seq); /* no multiple seq */ |
816 | put_bits(&pbc, 1, !packet_entry); /* no multiple entry */ |
817 | put_bits(&pbc, 1, !slices); /* no slice code */ |
818 | put_bits(&pbc, 1, 0); /* no bframe */ |
819 | put_bits(&pbc, 1, 0); /* reserved */ |
820 | |
821 | /* framerate */ |
822 | if (track->st->avg_frame_rate.num > 0 && track->st->avg_frame_rate.den > 0) |
823 | put_bits32(&pbc, track->st->avg_frame_rate.num / track->st->avg_frame_rate.den); |
824 | else |
825 | put_bits32(&pbc, 0xffffffff); |
826 | |
827 | flush_put_bits(&pbc); |
828 | |
829 | av_free(unescaped); |
830 | |
831 | return 0; |
832 | } |
833 | |
834 | static int mov_write_dvc1_tag(AVIOContext *pb, MOVTrack *track) |
835 | { |
836 | uint8_t buf[7] = { 0 }; |
837 | int ret; |
838 | |
839 | if ((ret = mov_write_dvc1_structs(track, buf)) < 0) |
840 | return ret; |
841 | |
842 | avio_wb32(pb, track->vos_len + 8 + sizeof(buf)); |
843 | ffio_wfourcc(pb, "dvc1"); |
844 | avio_write(pb, buf, sizeof(buf)); |
845 | avio_write(pb, track->vos_data, track->vos_len); |
846 | |
847 | return 0; |
848 | } |
849 | |
850 | static int mov_write_glbl_tag(AVIOContext *pb, MOVTrack *track) |
851 | { |
852 | avio_wb32(pb, track->vos_len + 8); |
853 | ffio_wfourcc(pb, "glbl"); |
854 | avio_write(pb, track->vos_data, track->vos_len); |
855 | return 8 + track->vos_len; |
856 | } |
857 | |
858 | /** |
859 | * Compute flags for 'lpcm' tag. |
860 | * See CoreAudioTypes and AudioStreamBasicDescription at Apple. |
861 | */ |
862 | static int mov_get_lpcm_flags(enum AVCodecID codec_id) |
863 | { |
864 | switch (codec_id) { |
865 | case AV_CODEC_ID_PCM_F32BE: |
866 | case AV_CODEC_ID_PCM_F64BE: |
867 | return 11; |
868 | case AV_CODEC_ID_PCM_F32LE: |
869 | case AV_CODEC_ID_PCM_F64LE: |
870 | return 9; |
871 | case AV_CODEC_ID_PCM_U8: |
872 | return 10; |
873 | case AV_CODEC_ID_PCM_S16BE: |
874 | case AV_CODEC_ID_PCM_S24BE: |
875 | case AV_CODEC_ID_PCM_S32BE: |
876 | return 14; |
877 | case AV_CODEC_ID_PCM_S8: |
878 | case AV_CODEC_ID_PCM_S16LE: |
879 | case AV_CODEC_ID_PCM_S24LE: |
880 | case AV_CODEC_ID_PCM_S32LE: |
881 | return 12; |
882 | default: |
883 | return 0; |
884 | } |
885 | } |
886 | |
887 | static int get_cluster_duration(MOVTrack *track, int cluster_idx) |
888 | { |
889 | int64_t next_dts; |
890 | |
891 | if (cluster_idx >= track->entry) |
892 | return 0; |
893 | |
894 | if (cluster_idx + 1 == track->entry) |
895 | next_dts = track->track_duration + track->start_dts; |
896 | else |
897 | next_dts = track->cluster[cluster_idx + 1].dts; |
898 | |
899 | next_dts -= track->cluster[cluster_idx].dts; |
900 | |
901 | av_assert0(next_dts >= 0); |
902 | av_assert0(next_dts <= INT_MAX); |
903 | |
904 | return next_dts; |
905 | } |
906 | |
907 | static int get_samples_per_packet(MOVTrack *track) |
908 | { |
909 | int i, first_duration; |
910 | |
911 | // return track->par->frame_size; |
912 | |
913 | /* use 1 for raw PCM */ |
914 | if (!track->audio_vbr) |
915 | return 1; |
916 | |
917 | /* check to see if duration is constant for all clusters */ |
918 | if (!track->entry) |
919 | return 0; |
920 | first_duration = get_cluster_duration(track, 0); |
921 | for (i = 1; i < track->entry; i++) { |
922 | if (get_cluster_duration(track, i) != first_duration) |
923 | return 0; |
924 | } |
925 | return first_duration; |
926 | } |
927 | |
928 | static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) |
929 | { |
930 | int64_t pos = avio_tell(pb); |
931 | int version = 0; |
932 | uint32_t tag = track->tag; |
933 | |
934 | if (track->mode == MODE_MOV) { |
935 | if (track->timescale > UINT16_MAX) { |
936 | if (mov_get_lpcm_flags(track->par->codec_id)) |
937 | tag = AV_RL32("lpcm"); |
938 | version = 2; |
939 | } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) || |
940 | mov_pcm_be_gt16(track->par->codec_id) || |
941 | track->par->codec_id == AV_CODEC_ID_ADPCM_MS || |
942 | track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV || |
943 | track->par->codec_id == AV_CODEC_ID_QDM2) { |
944 | version = 1; |
945 | } |
946 | } |
947 | |
948 | avio_wb32(pb, 0); /* size */ |
949 | if (mov->encryption_scheme != MOV_ENC_NONE) { |
950 | ffio_wfourcc(pb, "enca"); |
951 | } else { |
952 | avio_wl32(pb, tag); // store it byteswapped |
953 | } |
954 | avio_wb32(pb, 0); /* Reserved */ |
955 | avio_wb16(pb, 0); /* Reserved */ |
956 | avio_wb16(pb, 1); /* Data-reference index, XXX == 1 */ |
957 | |
958 | /* SoundDescription */ |
959 | avio_wb16(pb, version); /* Version */ |
960 | avio_wb16(pb, 0); /* Revision level */ |
961 | avio_wb32(pb, 0); /* Reserved */ |
962 | |
963 | if (version == 2) { |
964 | avio_wb16(pb, 3); |
965 | avio_wb16(pb, 16); |
966 | avio_wb16(pb, 0xfffe); |
967 | avio_wb16(pb, 0); |
968 | avio_wb32(pb, 0x00010000); |
969 | avio_wb32(pb, 72); |
970 | avio_wb64(pb, av_double2int(track->par->sample_rate)); |
971 | avio_wb32(pb, track->par->channels); |
972 | avio_wb32(pb, 0x7F000000); |
973 | avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id)); |
974 | avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id)); |
975 | avio_wb32(pb, track->sample_size); |
976 | avio_wb32(pb, get_samples_per_packet(track)); |
977 | } else { |
978 | if (track->mode == MODE_MOV) { |
979 | avio_wb16(pb, track->par->channels); |
980 | if (track->par->codec_id == AV_CODEC_ID_PCM_U8 || |
981 | track->par->codec_id == AV_CODEC_ID_PCM_S8) |
982 | avio_wb16(pb, 8); /* bits per sample */ |
983 | else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726) |
984 | avio_wb16(pb, track->par->bits_per_coded_sample); |
985 | else |
986 | avio_wb16(pb, 16); |
987 | avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */ |
988 | } else { /* reserved for mp4/3gp */ |
989 | if (track->par->codec_id == AV_CODEC_ID_FLAC) { |
990 | avio_wb16(pb, track->par->channels); |
991 | avio_wb16(pb, track->par->bits_per_raw_sample); |
992 | } else { |
993 | avio_wb16(pb, 2); |
994 | avio_wb16(pb, 16); |
995 | } |
996 | avio_wb16(pb, 0); |
997 | } |
998 | |
999 | avio_wb16(pb, 0); /* packet size (= 0) */ |
1000 | avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ? |
1001 | track->par->sample_rate : 0); |
1002 | avio_wb16(pb, 0); /* Reserved */ |
1003 | } |
1004 | |
1005 | if (version == 1) { /* SoundDescription V1 extended info */ |
1006 | if (mov_pcm_le_gt16(track->par->codec_id) || |
1007 | mov_pcm_be_gt16(track->par->codec_id)) |
1008 | avio_wb32(pb, 1); /* must be 1 for uncompressed formats */ |
1009 | else |
1010 | avio_wb32(pb, track->par->frame_size); /* Samples per packet */ |
1011 | avio_wb32(pb, track->sample_size / track->par->channels); /* Bytes per packet */ |
1012 | avio_wb32(pb, track->sample_size); /* Bytes per frame */ |
1013 | avio_wb32(pb, 2); /* Bytes per sample */ |
1014 | } |
1015 | |
1016 | if (track->mode == MODE_MOV && |
1017 | (track->par->codec_id == AV_CODEC_ID_AAC || |
1018 | track->par->codec_id == AV_CODEC_ID_AC3 || |
1019 | track->par->codec_id == AV_CODEC_ID_EAC3 || |
1020 | track->par->codec_id == AV_CODEC_ID_AMR_NB || |
1021 | track->par->codec_id == AV_CODEC_ID_ALAC || |
1022 | track->par->codec_id == AV_CODEC_ID_ADPCM_MS || |
1023 | track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV || |
1024 | track->par->codec_id == AV_CODEC_ID_QDM2 || |
1025 | (mov_pcm_le_gt16(track->par->codec_id) && version==1) || |
1026 | (mov_pcm_be_gt16(track->par->codec_id) && version==1))) |
1027 | mov_write_wave_tag(s, pb, track); |
1028 | else if (track->tag == MKTAG('m','p','4','a')) |
1029 | mov_write_esds_tag(pb, track); |
1030 | else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) |
1031 | mov_write_amr_tag(pb, track); |
1032 | else if (track->par->codec_id == AV_CODEC_ID_AC3) |
1033 | mov_write_ac3_tag(pb, track); |
1034 | else if (track->par->codec_id == AV_CODEC_ID_EAC3) |
1035 | mov_write_eac3_tag(pb, track); |
1036 | else if (track->par->codec_id == AV_CODEC_ID_ALAC) |
1037 | mov_write_extradata_tag(pb, track); |
1038 | else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) |
1039 | mov_write_wfex_tag(s, pb, track); |
1040 | else if (track->par->codec_id == AV_CODEC_ID_FLAC) |
1041 | mov_write_dfla_tag(pb, track); |
1042 | else if (track->vos_len > 0) |
1043 | mov_write_glbl_tag(pb, track); |
1044 | |
1045 | if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO) |
1046 | mov_write_chan_tag(s, pb, track); |
1047 | |
1048 | if (mov->encryption_scheme != MOV_ENC_NONE) { |
1049 | ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid); |
1050 | } |
1051 | |
1052 | return update_size(pb, pos); |
1053 | } |
1054 | |
1055 | static int mov_write_d263_tag(AVIOContext *pb) |
1056 | { |
1057 | avio_wb32(pb, 0xf); /* size */ |
1058 | ffio_wfourcc(pb, "d263"); |
1059 | ffio_wfourcc(pb, "FFMP"); |
1060 | avio_w8(pb, 0); /* decoder version */ |
1061 | /* FIXME use AVCodecContext level/profile, when encoder will set values */ |
1062 | avio_w8(pb, 0xa); /* level */ |
1063 | avio_w8(pb, 0); /* profile */ |
1064 | return 0xf; |
1065 | } |
1066 | |
1067 | static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track) |
1068 | { |
1069 | int64_t pos = avio_tell(pb); |
1070 | |
1071 | avio_wb32(pb, 0); |
1072 | ffio_wfourcc(pb, "avcC"); |
1073 | ff_isom_write_avcc(pb, track->vos_data, track->vos_len); |
1074 | return update_size(pb, pos); |
1075 | } |
1076 | |
1077 | static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) |
1078 | { |
1079 | int64_t pos = avio_tell(pb); |
1080 | |
1081 | avio_wb32(pb, 0); |
1082 | ffio_wfourcc(pb, "vpcC"); |
1083 | avio_wb32(pb, 0); /* version & flags */ |
1084 | ff_isom_write_vpcc(s, pb, track->par); |
1085 | return update_size(pb, pos); |
1086 | } |
1087 | |
1088 | static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track) |
1089 | { |
1090 | int64_t pos = avio_tell(pb); |
1091 | |
1092 | avio_wb32(pb, 0); |
1093 | ffio_wfourcc(pb, "hvcC"); |
1094 | ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0); |
1095 | return update_size(pb, pos); |
1096 | } |
1097 | |
1098 | /* also used by all avid codecs (dv, imx, meridien) and their variants */ |
1099 | static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) |
1100 | { |
1101 | int i; |
1102 | int interlaced; |
1103 | int cid; |
1104 | int display_width = track->par->width; |
1105 | |
1106 | if (track->vos_data && track->vos_len > 0x29) { |
1107 | if (ff_dnxhd_parse_header_prefix(track->vos_data) != 0) { |
1108 | /* looks like a DNxHD bit stream */ |
1109 | interlaced = (track->vos_data[5] & 2); |
1110 | cid = AV_RB32(track->vos_data + 0x28); |
1111 | } else { |
1112 | av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream in vos_data\n"); |
1113 | return 0; |
1114 | } |
1115 | } else { |
1116 | av_log(NULL, AV_LOG_WARNING, "Could not locate DNxHD bit stream, vos_data too small\n"); |
1117 | return 0; |
1118 | } |
1119 | |
1120 | avio_wb32(pb, 24); /* size */ |
1121 | ffio_wfourcc(pb, "ACLR"); |
1122 | ffio_wfourcc(pb, "ACLR"); |
1123 | ffio_wfourcc(pb, "0001"); |
1124 | if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */ |
1125 | track->par->color_range == AVCOL_RANGE_UNSPECIFIED) { |
1126 | avio_wb32(pb, 1); /* Corresponds to 709 in official encoder */ |
1127 | } else { /* Full range (0-255) */ |
1128 | avio_wb32(pb, 2); /* Corresponds to RGB in official encoder */ |
1129 | } |
1130 | avio_wb32(pb, 0); /* unknown */ |
1131 | |
1132 | if (track->tag == MKTAG('A','V','d','h')) { |
1133 | avio_wb32(pb, 32); |
1134 | ffio_wfourcc(pb, "ADHR"); |
1135 | ffio_wfourcc(pb, "0001"); |
1136 | avio_wb32(pb, cid); |
1137 | avio_wb32(pb, 0); /* unknown */ |
1138 | avio_wb32(pb, 1); /* unknown */ |
1139 | avio_wb32(pb, 0); /* unknown */ |
1140 | avio_wb32(pb, 0); /* unknown */ |
1141 | return 0; |
1142 | } |
1143 | |
1144 | avio_wb32(pb, 24); /* size */ |
1145 | ffio_wfourcc(pb, "APRG"); |
1146 | ffio_wfourcc(pb, "APRG"); |
1147 | ffio_wfourcc(pb, "0001"); |
1148 | avio_wb32(pb, 1); /* unknown */ |
1149 | avio_wb32(pb, 0); /* unknown */ |
1150 | |
1151 | avio_wb32(pb, 120); /* size */ |
1152 | ffio_wfourcc(pb, "ARES"); |
1153 | ffio_wfourcc(pb, "ARES"); |
1154 | ffio_wfourcc(pb, "0001"); |
1155 | avio_wb32(pb, cid); /* dnxhd cid, some id ? */ |
1156 | if ( track->par->sample_aspect_ratio.num > 0 |
1157 | && track->par->sample_aspect_ratio.den > 0) |
1158 | display_width = display_width * track->par->sample_aspect_ratio.num / track->par->sample_aspect_ratio.den; |
1159 | avio_wb32(pb, display_width); |
1160 | /* values below are based on samples created with quicktime and avid codecs */ |
1161 | if (interlaced) { |
1162 | avio_wb32(pb, track->par->height / 2); |
1163 | avio_wb32(pb, 2); /* unknown */ |
1164 | avio_wb32(pb, 0); /* unknown */ |
1165 | avio_wb32(pb, 4); /* unknown */ |
1166 | } else { |
1167 | avio_wb32(pb, track->par->height); |
1168 | avio_wb32(pb, 1); /* unknown */ |
1169 | avio_wb32(pb, 0); /* unknown */ |
1170 | if (track->par->height == 1080) |
1171 | avio_wb32(pb, 5); /* unknown */ |
1172 | else |
1173 | avio_wb32(pb, 6); /* unknown */ |
1174 | } |
1175 | /* padding */ |
1176 | for (i = 0; i < 10; i++) |
1177 | avio_wb64(pb, 0); |
1178 | |
1179 | return 0; |
1180 | } |
1181 | |
1182 | static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track) |
1183 | { |
1184 | avio_wb32(pb, 12); |
1185 | ffio_wfourcc(pb, "DpxE"); |
1186 | if (track->par->extradata_size >= 12 && |
1187 | !memcmp(&track->par->extradata[4], "DpxE", 4)) { |
1188 | avio_wb32(pb, track->par->extradata[11]); |
1189 | } else { |
1190 | avio_wb32(pb, 1); |
1191 | } |
1192 | return 0; |
1193 | } |
1194 | |
1195 | static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track) |
1196 | { |
1197 | int tag = track->par->codec_tag; |
1198 | |
1199 | if (!ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id)) |
1200 | return 0; |
1201 | |
1202 | if (track->par->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1'); |
1203 | else if (track->par->codec_id == AV_CODEC_ID_HEVC) tag = MKTAG('h','e','v','1'); |
1204 | else if (track->par->codec_id == AV_CODEC_ID_VP9) tag = MKTAG('v','p','0','9'); |
1205 | else if (track->par->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3'); |
1206 | else if (track->par->codec_id == AV_CODEC_ID_EAC3) tag = MKTAG('e','c','-','3'); |
1207 | else if (track->par->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); |
1208 | else if (track->par->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g'); |
1209 | else if (track->par->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1'); |
1210 | else if (track->par->codec_id == AV_CODEC_ID_FLAC) tag = MKTAG('f','L','a','C'); |
1211 | else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); |
1212 | else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); |
1213 | else if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) tag = MKTAG('m','p','4','s'); |
1214 | |
1215 | return tag; |
1216 | } |
1217 | |
1218 | static const AVCodecTag codec_ipod_tags[] = { |
1219 | { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, |
1220 | { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, |
1221 | { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, |
1222 | { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') }, |
1223 | { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') }, |
1224 | { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, |
1225 | { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') }, |
1226 | { AV_CODEC_ID_NONE, 0 }, |
1227 | }; |
1228 | |
1229 | static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track) |
1230 | { |
1231 | int tag = track->par->codec_tag; |
1232 | |
1233 | // keep original tag for subs, ipod supports both formats |
1234 | if (!(track->par->codec_type == AVMEDIA_TYPE_SUBTITLE && |
1235 | (tag == MKTAG('t', 'x', '3', 'g') || |
1236 | tag == MKTAG('t', 'e', 'x', 't')))) |
1237 | tag = ff_codec_get_tag(codec_ipod_tags, track->par->codec_id); |
1238 | |
1239 | if (!av_match_ext(s->filename, "m4a") && |
1240 | !av_match_ext(s->filename, "m4b") && |
1241 | !av_match_ext(s->filename, "m4v")) |
1242 | av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a, .m4v nor .m4b " |
1243 | "Quicktime/Ipod might not play the file\n"); |
1244 | |
1245 | return tag; |
1246 | } |
1247 | |
1248 | static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track) |
1249 | { |
1250 | int tag; |
1251 | |
1252 | if (track->par->width == 720) { /* SD */ |
1253 | if (track->par->height == 480) { /* NTSC */ |
1254 | if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n'); |
1255 | else tag = MKTAG('d','v','c',' '); |
1256 | }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p'); |
1257 | else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p'); |
1258 | else tag = MKTAG('d','v','p','p'); |
1259 | } else if (track->par->height == 720) { /* HD 720 line */ |
1260 | if (track->st->time_base.den == 50) tag = MKTAG('d','v','h','q'); |
1261 | else tag = MKTAG('d','v','h','p'); |
1262 | } else if (track->par->height == 1080) { /* HD 1080 line */ |
1263 | if (track->st->time_base.den == 25) tag = MKTAG('d','v','h','5'); |
1264 | else tag = MKTAG('d','v','h','6'); |
1265 | } else { |
1266 | av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n"); |
1267 | return 0; |
1268 | } |
1269 | |
1270 | return tag; |
1271 | } |
1272 | |
1273 | static AVRational find_fps(AVFormatContext *s, AVStream *st) |
1274 | { |
1275 | AVRational rate = st->avg_frame_rate; |
1276 | |
1277 | #if FF_API_LAVF_AVCTX |
1278 | FF_DISABLE_DEPRECATION_WARNINGS |
1279 | rate = av_inv_q(st->codec->time_base); |
1280 | if (av_timecode_check_frame_rate(rate) < 0) { |
1281 | av_log(s, AV_LOG_DEBUG, "timecode: tbc=%d/%d invalid, fallback on %d/%d\n", |
1282 | rate.num, rate.den, st->avg_frame_rate.num, st->avg_frame_rate.den); |
1283 | rate = st->avg_frame_rate; |
1284 | } |
1285 | FF_ENABLE_DEPRECATION_WARNINGS |
1286 | #endif |
1287 | |
1288 | return rate; |
1289 | } |
1290 | |
1291 | static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track) |
1292 | { |
1293 | int tag = track->par->codec_tag; |
1294 | int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE; |
1295 | AVStream *st = track->st; |
1296 | int rate = av_q2d(find_fps(s, st)); |
1297 | |
1298 | if (!tag) |
1299 | tag = MKTAG('m', '2', 'v', '1'); //fallback tag |
1300 | |
1301 | if (track->par->format == AV_PIX_FMT_YUV420P) { |
1302 | if (track->par->width == 1280 && track->par->height == 720) { |
1303 | if (!interlaced) { |
1304 | if (rate == 24) tag = MKTAG('x','d','v','4'); |
1305 | else if (rate == 25) tag = MKTAG('x','d','v','5'); |
1306 | else if (rate == 30) tag = MKTAG('x','d','v','1'); |
1307 | else if (rate == 50) tag = MKTAG('x','d','v','a'); |
1308 | else if (rate == 60) tag = MKTAG('x','d','v','9'); |
1309 | } |
1310 | } else if (track->par->width == 1440 && track->par->height == 1080) { |
1311 | if (!interlaced) { |
1312 | if (rate == 24) tag = MKTAG('x','d','v','6'); |
1313 | else if (rate == 25) tag = MKTAG('x','d','v','7'); |
1314 | else if (rate == 30) tag = MKTAG('x','d','v','8'); |
1315 | } else { |
1316 | if (rate == 25) tag = MKTAG('x','d','v','3'); |
1317 | else if (rate == 30) tag = MKTAG('x','d','v','2'); |
1318 | } |
1319 | } else if (track->par->width == 1920 && track->par->height == 1080) { |
1320 | if (!interlaced) { |
1321 | if (rate == 24) tag = MKTAG('x','d','v','d'); |
1322 | else if (rate == 25) tag = MKTAG('x','d','v','e'); |
1323 | else if (rate == 30) tag = MKTAG('x','d','v','f'); |
1324 | } else { |
1325 | if (rate == 25) tag = MKTAG('x','d','v','c'); |
1326 | else if (rate == 30) tag = MKTAG('x','d','v','b'); |
1327 | } |
1328 | } |
1329 | } else if (track->par->format == AV_PIX_FMT_YUV422P) { |
1330 | if (track->par->width == 1280 && track->par->height == 720) { |
1331 | if (!interlaced) { |
1332 | if (rate == 24) tag = MKTAG('x','d','5','4'); |
1333 | else if (rate == 25) tag = MKTAG('x','d','5','5'); |
1334 | else if (rate == 30) tag = MKTAG('x','d','5','1'); |
1335 | else if (rate == 50) tag = MKTAG('x','d','5','a'); |
1336 | else if (rate == 60) tag = MKTAG('x','d','5','9'); |
1337 | } |
1338 | } else if (track->par->width == 1920 && track->par->height == 1080) { |
1339 | if (!interlaced) { |
1340 | if (rate == 24) tag = MKTAG('x','d','5','d'); |
1341 | else if (rate == 25) tag = MKTAG('x','d','5','e'); |
1342 | else if (rate == 30) tag = MKTAG('x','d','5','f'); |
1343 | } else { |
1344 | if (rate == 25) tag = MKTAG('x','d','5','c'); |
1345 | else if (rate == 30) tag = MKTAG('x','d','5','b'); |
1346 | } |
1347 | } |
1348 | } |
1349 | |
1350 | return tag; |
1351 | } |
1352 | |
1353 | static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track) |
1354 | { |
1355 | int tag = track->par->codec_tag; |
1356 | int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE; |
1357 | AVStream *st = track->st; |
1358 | int rate = av_q2d(find_fps(s, st)); |
1359 | |
1360 | if (!tag) |
1361 | tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag |
1362 | |
1363 | if (track->par->format == AV_PIX_FMT_YUV420P10) { |
1364 | if (track->par->width == 960 && track->par->height == 720) { |
1365 | if (!interlaced) { |
1366 | if (rate == 24) tag = MKTAG('a','i','5','p'); |
1367 | else if (rate == 25) tag = MKTAG('a','i','5','q'); |
1368 | else if (rate == 30) tag = MKTAG('a','i','5','p'); |
1369 | else if (rate == 50) tag = MKTAG('a','i','5','q'); |
1370 | else if (rate == 60) tag = MKTAG('a','i','5','p'); |
1371 | } |
1372 | } else if (track->par->width == 1440 && track->par->height == 1080) { |
1373 | if (!interlaced) { |
1374 | if (rate == 24) tag = MKTAG('a','i','5','3'); |
1375 | else if (rate == 25) tag = MKTAG('a','i','5','2'); |
1376 | else if (rate == 30) tag = MKTAG('a','i','5','3'); |
1377 | } else { |
1378 | if (rate == 50) tag = MKTAG('a','i','5','5'); |
1379 | else if (rate == 60) tag = MKTAG('a','i','5','6'); |
1380 | } |
1381 | } |
1382 | } else if (track->par->format == AV_PIX_FMT_YUV422P10) { |
1383 | if (track->par->width == 1280 && track->par->height == 720) { |
1384 | if (!interlaced) { |
1385 | if (rate == 24) tag = MKTAG('a','i','1','p'); |
1386 | else if (rate == 25) tag = MKTAG('a','i','1','q'); |
1387 | else if (rate == 30) tag = MKTAG('a','i','1','p'); |
1388 | else if (rate == 50) tag = MKTAG('a','i','1','q'); |
1389 | else if (rate == 60) tag = MKTAG('a','i','1','p'); |
1390 | } |
1391 | } else if (track->par->width == 1920 && track->par->height == 1080) { |
1392 | if (!interlaced) { |
1393 | if (rate == 24) tag = MKTAG('a','i','1','3'); |
1394 | else if (rate == 25) tag = MKTAG('a','i','1','2'); |
1395 | else if (rate == 30) tag = MKTAG('a','i','1','3'); |
1396 | } else { |
1397 | if (rate == 25) tag = MKTAG('a','i','1','5'); |
1398 | else if (rate == 50) tag = MKTAG('a','i','1','5'); |
1399 | else if (rate == 60) tag = MKTAG('a','i','1','6'); |
1400 | } |
1401 | } else if ( track->par->width == 4096 && track->par->height == 2160 |
1402 | || track->par->width == 3840 && track->par->height == 2160 |
1403 | || track->par->width == 2048 && track->par->height == 1080) { |
1404 | tag = MKTAG('a','i','v','x'); |
1405 | } |
1406 | } |
1407 | |
1408 | return tag; |
1409 | } |
1410 | |
1411 | static const struct { |
1412 | enum AVPixelFormat pix_fmt; |
1413 | uint32_t tag; |
1414 | unsigned bps; |
1415 | } mov_pix_fmt_tags[] = { |
1416 | { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','2'), 0 }, |
1417 | { AV_PIX_FMT_YUYV422, MKTAG('y','u','v','s'), 0 }, |
1418 | { AV_PIX_FMT_UYVY422, MKTAG('2','v','u','y'), 0 }, |
1419 | { AV_PIX_FMT_RGB555BE,MKTAG('r','a','w',' '), 16 }, |
1420 | { AV_PIX_FMT_RGB555LE,MKTAG('L','5','5','5'), 16 }, |
1421 | { AV_PIX_FMT_RGB565LE,MKTAG('L','5','6','5'), 16 }, |
1422 | { AV_PIX_FMT_RGB565BE,MKTAG('B','5','6','5'), 16 }, |
1423 | { AV_PIX_FMT_GRAY16BE,MKTAG('b','1','6','g'), 16 }, |
1424 | { AV_PIX_FMT_RGB24, MKTAG('r','a','w',' '), 24 }, |
1425 | { AV_PIX_FMT_BGR24, MKTAG('2','4','B','G'), 24 }, |
1426 | { AV_PIX_FMT_ARGB, MKTAG('r','a','w',' '), 32 }, |
1427 | { AV_PIX_FMT_BGRA, MKTAG('B','G','R','A'), 32 }, |
1428 | { AV_PIX_FMT_RGBA, MKTAG('R','G','B','A'), 32 }, |
1429 | { AV_PIX_FMT_ABGR, MKTAG('A','B','G','R'), 32 }, |
1430 | { AV_PIX_FMT_RGB48BE, MKTAG('b','4','8','r'), 48 }, |
1431 | }; |
1432 | |
1433 | static int mov_get_dnxhd_codec_tag(AVFormatContext *s, MOVTrack *track) |
1434 | { |
1435 | int tag = MKTAG('A','V','d','n'); |
1436 | if (track->par->profile != FF_PROFILE_UNKNOWN && |
1437 | track->par->profile != FF_PROFILE_DNXHD) |
1438 | tag = MKTAG('A','V','d','h'); |
1439 | return tag; |
1440 | } |
1441 | |
1442 | static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) |
1443 | { |
1444 | int tag = track->par->codec_tag; |
1445 | int i; |
1446 | enum AVPixelFormat pix_fmt; |
1447 | |
1448 | for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) { |
1449 | if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) { |
1450 | tag = mov_pix_fmt_tags[i].tag; |
1451 | track->par->bits_per_coded_sample = mov_pix_fmt_tags[i].bps; |
1452 | if (track->par->codec_tag == mov_pix_fmt_tags[i].tag) |
1453 | break; |
1454 | } |
1455 | } |
1456 | |
1457 | pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, |
1458 | track->par->bits_per_coded_sample); |
1459 | if (tag == MKTAG('r','a','w',' ') && |
1460 | track->par->format != pix_fmt && |
1461 | track->par->format != AV_PIX_FMT_GRAY8 && |
1462 | track->par->format != AV_PIX_FMT_NONE) |
1463 | av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n", |
1464 | av_get_pix_fmt_name(track->par->format)); |
1465 | return tag; |
1466 | } |
1467 | |
1468 | static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track) |
1469 | { |
1470 | int tag = track->par->codec_tag; |
1471 | |
1472 | if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL && |
1473 | (track->par->codec_id == AV_CODEC_ID_DVVIDEO || |
1474 | track->par->codec_id == AV_CODEC_ID_RAWVIDEO || |
1475 | track->par->codec_id == AV_CODEC_ID_H263 || |
1476 | track->par->codec_id == AV_CODEC_ID_H264 || |
1477 | track->par->codec_id == AV_CODEC_ID_DNXHD || |
1478 | track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO || |
1479 | av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio |
1480 | if (track->par->codec_id == AV_CODEC_ID_DVVIDEO) |
1481 | tag = mov_get_dv_codec_tag(s, track); |
1482 | else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO) |
1483 | tag = mov_get_rawvideo_codec_tag(s, track); |
1484 | else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO) |
1485 | tag = mov_get_mpeg2_xdcam_codec_tag(s, track); |
1486 | else if (track->par->codec_id == AV_CODEC_ID_H264) |
1487 | tag = mov_get_h264_codec_tag(s, track); |
1488 | else if (track->par->codec_id == AV_CODEC_ID_DNXHD) |
1489 | tag = mov_get_dnxhd_codec_tag(s, track); |
1490 | else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { |
1491 | tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->par->codec_id); |
1492 | if (!tag) { // if no mac fcc found, try with Microsoft tags |
1493 | tag = ff_codec_get_tag(ff_codec_bmp_tags, track->par->codec_id); |
1494 | if (tag) |
1495 | av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, " |
1496 | "the file may be unplayable!\n"); |
1497 | } |
1498 | } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { |
1499 | tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->par->codec_id); |
1500 | if (!tag) { // if no mac fcc found, try with Microsoft tags |
1501 | int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id); |
1502 | if (ms_tag) { |
1503 | tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff)); |
1504 | av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, " |
1505 | "the file may be unplayable!\n"); |
1506 | } |
1507 | } |
1508 | } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) |
1509 | tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->par->codec_id); |
1510 | } |
1511 | |
1512 | return tag; |
1513 | } |
1514 | |
1515 | static const AVCodecTag codec_3gp_tags[] = { |
1516 | { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, |
1517 | { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, |
1518 | { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, |
1519 | { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, |
1520 | { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, |
1521 | { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') }, |
1522 | { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, |
1523 | { AV_CODEC_ID_NONE, 0 }, |
1524 | }; |
1525 | |
1526 | static const AVCodecTag codec_f4v_tags[] = { // XXX: add GIF/PNG/JPEG? |
1527 | { AV_CODEC_ID_MP3, MKTAG('.','m','p','3') }, |
1528 | { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, |
1529 | { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, |
1530 | { AV_CODEC_ID_VP6A, MKTAG('V','P','6','A') }, |
1531 | { AV_CODEC_ID_VP6F, MKTAG('V','P','6','F') }, |
1532 | { AV_CODEC_ID_NONE, 0 }, |
1533 | }; |
1534 | |
1535 | static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track) |
1536 | { |
1537 | int tag; |
1538 | |
1539 | if (track->mode == MODE_MP4 || track->mode == MODE_PSP) |
1540 | tag = mp4_get_codec_tag(s, track); |
1541 | else if (track->mode == MODE_ISM) { |
1542 | tag = mp4_get_codec_tag(s, track); |
1543 | if (!tag && track->par->codec_id == AV_CODEC_ID_WMAPRO) |
1544 | tag = MKTAG('w', 'm', 'a', ' '); |
1545 | } else if (track->mode == MODE_IPOD) |
1546 | tag = ipod_get_codec_tag(s, track); |
1547 | else if (track->mode & MODE_3GP) |
1548 | tag = ff_codec_get_tag(codec_3gp_tags, track->par->codec_id); |
1549 | else if (track->mode == MODE_F4V) |
1550 | tag = ff_codec_get_tag(codec_f4v_tags, track->par->codec_id); |
1551 | else |
1552 | tag = mov_get_codec_tag(s, track); |
1553 | |
1554 | return tag; |
1555 | } |
1556 | |
1557 | /** Write uuid atom. |
1558 | * Needed to make file play in iPods running newest firmware |
1559 | * goes after avcC atom in moov.trak.mdia.minf.stbl.stsd.avc1 |
1560 | */ |
1561 | static int mov_write_uuid_tag_ipod(AVIOContext *pb) |
1562 | { |
1563 | avio_wb32(pb, 28); |
1564 | ffio_wfourcc(pb, "uuid"); |
1565 | avio_wb32(pb, 0x6b6840f2); |
1566 | avio_wb32(pb, 0x5f244fc5); |
1567 | avio_wb32(pb, 0xba39a51b); |
1568 | avio_wb32(pb, 0xcf0323f3); |
1569 | avio_wb32(pb, 0x0); |
1570 | return 28; |
1571 | } |
1572 | |
1573 | static const uint16_t fiel_data[] = { |
1574 | 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e |
1575 | }; |
1576 | |
1577 | static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order) |
1578 | { |
1579 | unsigned mov_field_order = 0; |
1580 | if (field_order < FF_ARRAY_ELEMS(fiel_data)) |
1581 | mov_field_order = fiel_data[field_order]; |
1582 | else |
1583 | return 0; |
1584 | avio_wb32(pb, 10); |
1585 | ffio_wfourcc(pb, "fiel"); |
1586 | avio_wb16(pb, mov_field_order); |
1587 | return 10; |
1588 | } |
1589 | |
1590 | static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track) |
1591 | { |
1592 | int64_t pos = avio_tell(pb); |
1593 | avio_wb32(pb, 0); /* size */ |
1594 | avio_wl32(pb, track->tag); // store it byteswapped |
1595 | avio_wb32(pb, 0); /* Reserved */ |
1596 | avio_wb16(pb, 0); /* Reserved */ |
1597 | avio_wb16(pb, 1); /* Data-reference index */ |
1598 | |
1599 | if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE) |
1600 | mov_write_esds_tag(pb, track); |
1601 | else if (track->par->extradata_size) |
1602 | avio_write(pb, track->par->extradata, track->par->extradata_size); |
1603 | |
1604 | return update_size(pb, pos); |
1605 | } |
1606 | |
1607 | static int mov_write_st3d_tag(AVIOContext *pb, AVStereo3D *stereo_3d) |
1608 | { |
1609 | int8_t stereo_mode; |
1610 | |
1611 | if (stereo_3d->flags != 0) { |
1612 | av_log(pb, AV_LOG_WARNING, "Unsupported stereo_3d flags %x. st3d not written.\n", stereo_3d->flags); |
1613 | return 0; |
1614 | } |
1615 | |
1616 | switch (stereo_3d->type) { |
1617 | case AV_STEREO3D_2D: |
1618 | stereo_mode = 0; |
1619 | break; |
1620 | case AV_STEREO3D_TOPBOTTOM: |
1621 | stereo_mode = 1; |
1622 | break; |
1623 | case AV_STEREO3D_SIDEBYSIDE: |
1624 | stereo_mode = 2; |
1625 | break; |
1626 | default: |
1627 | av_log(pb, AV_LOG_WARNING, "Unsupported stereo_3d type %s. st3d not written.\n", av_stereo3d_type_name(stereo_3d->type)); |
1628 | return 0; |
1629 | } |
1630 | avio_wb32(pb, 13); /* size */ |
1631 | ffio_wfourcc(pb, "st3d"); |
1632 | avio_wb32(pb, 0); /* version = 0 & flags = 0 */ |
1633 | avio_w8(pb, stereo_mode); |
1634 | return 13; |
1635 | } |
1636 | |
1637 | static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMapping *spherical_mapping) |
1638 | { |
1639 | int64_t sv3d_pos, svhd_pos, proj_pos; |
1640 | const char* metadata_source = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : LIBAVFORMAT_IDENT; |
1641 | |
1642 | if (spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR && |
1643 | spherical_mapping->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE && |
1644 | spherical_mapping->projection != AV_SPHERICAL_CUBEMAP) { |
1645 | av_log(pb, AV_LOG_WARNING, "Unsupported projection %d. sv3d not written.\n", spherical_mapping->projection); |
1646 | return 0; |
1647 | } |
1648 | |
1649 | sv3d_pos = avio_tell(pb); |
1650 | avio_wb32(pb, 0); /* size */ |
1651 | ffio_wfourcc(pb, "sv3d"); |
1652 | |
1653 | svhd_pos = avio_tell(pb); |
1654 | avio_wb32(pb, 0); /* size */ |
1655 | ffio_wfourcc(pb, "svhd"); |
1656 | avio_wb32(pb, 0); /* version = 0 & flags = 0 */ |
1657 | avio_put_str(pb, metadata_source); |
1658 | update_size(pb, svhd_pos); |
1659 | |
1660 | proj_pos = avio_tell(pb); |
1661 | avio_wb32(pb, 0); /* size */ |
1662 | ffio_wfourcc(pb, "proj"); |
1663 | |
1664 | avio_wb32(pb, 24); /* size */ |
1665 | ffio_wfourcc(pb, "prhd"); |
1666 | avio_wb32(pb, 0); /* version = 0 & flags = 0 */ |
1667 | avio_wb32(pb, spherical_mapping->yaw); |
1668 | avio_wb32(pb, spherical_mapping->pitch); |
1669 | avio_wb32(pb, spherical_mapping->roll); |
1670 | |
1671 | switch (spherical_mapping->projection) { |
1672 | case AV_SPHERICAL_EQUIRECTANGULAR: |
1673 | case AV_SPHERICAL_EQUIRECTANGULAR_TILE: |
1674 | avio_wb32(pb, 28); /* size */ |
1675 | ffio_wfourcc(pb, "equi"); |
1676 | avio_wb32(pb, 0); /* version = 0 & flags = 0 */ |
1677 | avio_wb32(pb, spherical_mapping->bound_top); |
1678 | avio_wb32(pb, spherical_mapping->bound_bottom); |
1679 | avio_wb32(pb, spherical_mapping->bound_left); |
1680 | avio_wb32(pb, spherical_mapping->bound_right); |
1681 | break; |
1682 | case AV_SPHERICAL_CUBEMAP: |
1683 | avio_wb32(pb, 20); /* size */ |
1684 | ffio_wfourcc(pb, "cbmp"); |
1685 | avio_wb32(pb, 0); /* version = 0 & flags = 0 */ |
1686 | avio_wb32(pb, 0); /* layout */ |
1687 | avio_wb32(pb, spherical_mapping->padding); /* padding */ |
1688 | break; |
1689 | } |
1690 | update_size(pb, proj_pos); |
1691 | |
1692 | return update_size(pb, sv3d_pos); |
1693 | } |
1694 | |
1695 | static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track) |
1696 | { |
1697 | AVRational sar; |
1698 | av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num, |
1699 | track->par->sample_aspect_ratio.den, INT_MAX); |
1700 | |
1701 | avio_wb32(pb, 16); |
1702 | ffio_wfourcc(pb, "pasp"); |
1703 | avio_wb32(pb, sar.num); |
1704 | avio_wb32(pb, sar.den); |
1705 | return 16; |
1706 | } |
1707 | |
1708 | static int mov_write_gama_tag(AVIOContext *pb, MOVTrack *track, double gamma) |
1709 | { |
1710 | uint32_t gama = 0; |
1711 | if (gamma <= 0.0) |
1712 | { |
1713 | gamma = avpriv_get_gamma_from_trc(track->par->color_trc); |
1714 | } |
1715 | av_log(pb, AV_LOG_DEBUG, "gamma value %g\n", gamma); |
1716 | |
1717 | if (gamma > 1e-6) { |
1718 | gama = (uint32_t)lrint((double)(1<<16) * gamma); |
1719 | av_log(pb, AV_LOG_DEBUG, "writing gama value %"PRId32"\n", gama); |
1720 | |
1721 | av_assert0(track->mode == MODE_MOV); |
1722 | avio_wb32(pb, 12); |
1723 | ffio_wfourcc(pb, "gama"); |
1724 | avio_wb32(pb, gama); |
1725 | return 12; |
1726 | } |
1727 | else { |
1728 | av_log(pb, AV_LOG_WARNING, "gamma value unknown, unable to write gama atom\n"); |
1729 | } |
1730 | return 0; |
1731 | } |
1732 | |
1733 | static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track) |
1734 | { |
1735 | // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9 |
1736 | // Ref (MP4): ISO/IEC 14496-12:2012 |
1737 | |
1738 | if (track->par->color_primaries == AVCOL_PRI_UNSPECIFIED && |
1739 | track->par->color_trc == AVCOL_TRC_UNSPECIFIED && |
1740 | track->par->color_space == AVCOL_SPC_UNSPECIFIED) { |
1741 | if ((track->par->width >= 1920 && track->par->height >= 1080) |
1742 | || (track->par->width == 1280 && track->par->height == 720)) { |
1743 | av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt709\n"); |
1744 | track->par->color_primaries = AVCOL_PRI_BT709; |
1745 | } else if (track->par->width == 720 && track->height == 576) { |
1746 | av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt470bg\n"); |
1747 | track->par->color_primaries = AVCOL_PRI_BT470BG; |
1748 | } else if (track->par->width == 720 && |
1749 | (track->height == 486 || track->height == 480)) { |
1750 | av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming smpte170\n"); |
1751 | track->par->color_primaries = AVCOL_PRI_SMPTE170M; |
1752 | } else { |
1753 | av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, unable to assume anything\n"); |
1754 | } |
1755 | switch (track->par->color_primaries) { |
1756 | case AVCOL_PRI_BT709: |
1757 | track->par->color_trc = AVCOL_TRC_BT709; |
1758 | track->par->color_space = AVCOL_SPC_BT709; |
1759 | break; |
1760 | case AVCOL_PRI_SMPTE170M: |
1761 | case AVCOL_PRI_BT470BG: |
1762 | track->par->color_trc = AVCOL_TRC_BT709; |
1763 | track->par->color_space = AVCOL_SPC_SMPTE170M; |
1764 | break; |
1765 | } |
1766 | } |
1767 | |
1768 | /* We should only ever be called by MOV or MP4. */ |
1769 | av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4); |
1770 | |
1771 | avio_wb32(pb, 18 + (track->mode == MODE_MP4)); |
1772 | ffio_wfourcc(pb, "colr"); |
1773 | if (track->mode == MODE_MP4) |
1774 | ffio_wfourcc(pb, "nclx"); |
1775 | else |
1776 | ffio_wfourcc(pb, "nclc"); |
1777 | switch (track->par->color_primaries) { |
1778 | case AVCOL_PRI_BT709: avio_wb16(pb, 1); break; |
1779 | case AVCOL_PRI_SMPTE170M: |
1780 | case AVCOL_PRI_SMPTE240M: avio_wb16(pb, 6); break; |
1781 | case AVCOL_PRI_BT470BG: avio_wb16(pb, 5); break; |
1782 | default: avio_wb16(pb, 2); |
1783 | } |
1784 | switch (track->par->color_trc) { |
1785 | case AVCOL_TRC_BT709: avio_wb16(pb, 1); break; |
1786 | case AVCOL_TRC_SMPTE170M: avio_wb16(pb, 1); break; // remapped |
1787 | case AVCOL_TRC_SMPTE240M: avio_wb16(pb, 7); break; |
1788 | default: avio_wb16(pb, 2); |
1789 | } |
1790 | switch (track->par->color_space) { |
1791 | case AVCOL_SPC_BT709: avio_wb16(pb, 1); break; |
1792 | case AVCOL_SPC_BT470BG: |
1793 | case AVCOL_SPC_SMPTE170M: avio_wb16(pb, 6); break; |
1794 | case AVCOL_SPC_SMPTE240M: avio_wb16(pb, 7); break; |
1795 | default: avio_wb16(pb, 2); |
1796 | } |
1797 | |
1798 | if (track->mode == MODE_MP4) { |
1799 | int full_range = track->par->color_range == AVCOL_RANGE_JPEG; |
1800 | avio_w8(pb, full_range << 7); |
1801 | return 19; |
1802 | } else { |
1803 | return 18; |
1804 | } |
1805 | } |
1806 | |
1807 | static void find_compressor(char * compressor_name, int len, MOVTrack *track) |
1808 | { |
1809 | AVDictionaryEntry *encoder; |
1810 | int xdcam_res = (track->par->width == 1280 && track->par->height == 720) |
1811 | || (track->par->width == 1440 && track->par->height == 1080) |
1812 | || (track->par->width == 1920 && track->par->height == 1080); |
1813 | |
1814 | if (track->mode == MODE_MOV && |
1815 | (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) { |
1816 | av_strlcpy(compressor_name, encoder->value, 32); |
1817 | } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) { |
1818 | int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE; |
1819 | AVStream *st = track->st; |
1820 | int rate = av_q2d(find_fps(NULL, st)); |
1821 | av_strlcatf(compressor_name, len, "XDCAM"); |
1822 | if (track->par->format == AV_PIX_FMT_YUV422P) { |
1823 | av_strlcatf(compressor_name, len, " HD422"); |
1824 | } else if(track->par->width == 1440) { |
1825 | av_strlcatf(compressor_name, len, " HD"); |
1826 | } else |
1827 | av_strlcatf(compressor_name, len, " EX"); |
1828 | |
1829 | av_strlcatf(compressor_name, len, " %d%c", track->par->height, interlaced ? 'i' : 'p'); |
1830 | |
1831 | av_strlcatf(compressor_name, len, "%d", rate * (interlaced + 1)); |
1832 | } |
1833 | } |
1834 | |
1835 | static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) |
1836 | { |
1837 | int64_t pos = avio_tell(pb); |
1838 | char compressor_name[32] = { 0 }; |
1839 | int avid = 0; |
1840 | |
1841 | avio_wb32(pb, 0); /* size */ |
1842 | if (mov->encryption_scheme != MOV_ENC_NONE) { |
1843 | ffio_wfourcc(pb, "encv"); |
1844 | } else { |
1845 | avio_wl32(pb, track->tag); // store it byteswapped |
1846 | } |
1847 | avio_wb32(pb, 0); /* Reserved */ |
1848 | avio_wb16(pb, 0); /* Reserved */ |
1849 | avio_wb16(pb, 1); /* Data-reference index */ |
1850 | |
1851 | avio_wb16(pb, 0); /* Codec stream version */ |
1852 | avio_wb16(pb, 0); /* Codec stream revision (=0) */ |
1853 | if (track->mode == MODE_MOV) { |
1854 | ffio_wfourcc(pb, "FFMP"); /* Vendor */ |
1855 | if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO) { |
1856 | avio_wb32(pb, 0); /* Temporal Quality */ |
1857 | avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/ |
1858 | } else { |
1859 | avio_wb32(pb, 0x200); /* Temporal Quality = normal */ |
1860 | avio_wb32(pb, 0x200); /* Spatial Quality = normal */ |
1861 | } |
1862 | } else { |
1863 | avio_wb32(pb, 0); /* Reserved */ |
1864 | avio_wb32(pb, 0); /* Reserved */ |
1865 | avio_wb32(pb, 0); /* Reserved */ |
1866 | } |
1867 | avio_wb16(pb, track->par->width); /* Video width */ |
1868 | avio_wb16(pb, track->height); /* Video height */ |
1869 | avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */ |
1870 | avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */ |
1871 | avio_wb32(pb, 0); /* Data size (= 0) */ |
1872 | avio_wb16(pb, 1); /* Frame count (= 1) */ |
1873 | |
1874 | /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */ |
1875 | find_compressor(compressor_name, 32, track); |
1876 | avio_w8(pb, strlen(compressor_name)); |
1877 | avio_write(pb, compressor_name, 31); |
1878 | |
1879 | if (track->mode == MODE_MOV && track->par->bits_per_coded_sample) |
1880 | avio_wb16(pb, track->par->bits_per_coded_sample | |
1881 | (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0)); |
1882 | else |
1883 | avio_wb16(pb, 0x18); /* Reserved */ |
1884 | |
1885 | if (track->mode == MODE_MOV && track->par->format == AV_PIX_FMT_PAL8) { |
1886 | int pal_size = 1 << track->par->bits_per_coded_sample; |
1887 | int i; |
1888 | avio_wb16(pb, 0); /* Color table ID */ |
1889 | avio_wb32(pb, 0); /* Color table seed */ |
1890 | avio_wb16(pb, 0x8000); /* Color table flags */ |
1891 | avio_wb16(pb, pal_size - 1); /* Color table size (zero-relative) */ |
1892 | for (i = 0; i < pal_size; i++) { |
1893 | uint32_t rgb = track->palette[i]; |
1894 | uint16_t r = (rgb >> 16) & 0xff; |
1895 | uint16_t g = (rgb >> 8) & 0xff; |
1896 | uint16_t b = rgb & 0xff; |
1897 | avio_wb16(pb, 0); |
1898 | avio_wb16(pb, (r << 8) | r); |
1899 | avio_wb16(pb, (g << 8) | g); |
1900 | avio_wb16(pb, (b << 8) | b); |
1901 | } |
1902 | } else |
1903 | avio_wb16(pb, 0xffff); /* Reserved */ |
1904 | |
1905 | if (track->tag == MKTAG('m','p','4','v')) |
1906 | mov_write_esds_tag(pb, track); |
1907 | else if (track->par->codec_id == AV_CODEC_ID_H263) |
1908 | mov_write_d263_tag(pb); |
1909 | else if (track->par->codec_id == AV_CODEC_ID_AVUI || |
1910 | track->par->codec_id == AV_CODEC_ID_SVQ3) { |
1911 | mov_write_extradata_tag(pb, track); |
1912 | avio_wb32(pb, 0); |
1913 | } else if (track->par->codec_id == AV_CODEC_ID_DNXHD) { |
1914 | mov_write_avid_tag(pb, track); |
1915 | avid = 1; |
1916 | } else if (track->par->codec_id == AV_CODEC_ID_HEVC) |
1917 | mov_write_hvcc_tag(pb, track); |
1918 | else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) { |
1919 | mov_write_avcc_tag(pb, track); |
1920 | if (track->mode == MODE_IPOD) |
1921 | mov_write_uuid_tag_ipod(pb); |
1922 | } else if (track->par->codec_id == AV_CODEC_ID_VP9) { |
1923 | mov_write_vpcc_tag(mov->fc, pb, track); |
1924 | } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0) |
1925 | mov_write_dvc1_tag(pb, track); |
1926 | else if (track->par->codec_id == AV_CODEC_ID_VP6F || |
1927 | track->par->codec_id == AV_CODEC_ID_VP6A) { |
1928 | /* Don't write any potential extradata here - the cropping |
1929 | * is signalled via the normal width/height fields. */ |
1930 | } else if (track->par->codec_id == AV_CODEC_ID_R10K) { |
1931 | if (track->par->codec_tag == MKTAG('R','1','0','k')) |
1932 | mov_write_dpxe_tag(pb, track); |
1933 | } else if (track->vos_len > 0) |
1934 | mov_write_glbl_tag(pb, track); |
1935 | |
1936 | if (track->par->codec_id != AV_CODEC_ID_H264 && |
1937 | track->par->codec_id != AV_CODEC_ID_MPEG4 && |
1938 | track->par->codec_id != AV_CODEC_ID_DNXHD) { |
1939 | int field_order = track->par->field_order; |
1940 | |
1941 | #if FF_API_LAVF_AVCTX |
1942 | FF_DISABLE_DEPRECATION_WARNINGS |
1943 | if (field_order != track->st->codec->field_order && track->st->codec->field_order != AV_FIELD_UNKNOWN) |
1944 | field_order = track->st->codec->field_order; |
1945 | FF_ENABLE_DEPRECATION_WARNINGS |
1946 | #endif |
1947 | |
1948 | if (field_order != AV_FIELD_UNKNOWN) |
1949 | mov_write_fiel_tag(pb, track, field_order); |
1950 | } |
1951 | |
1952 | if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) { |
1953 | if (track->mode == MODE_MOV) |
1954 | mov_write_gama_tag(pb, track, mov->gamma); |
1955 | else |
1956 | av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n"); |
1957 | } |
1958 | if (mov->flags & FF_MOV_FLAG_WRITE_COLR) { |
1959 | if (track->mode == MODE_MOV || track->mode == MODE_MP4) |
1960 | mov_write_colr_tag(pb, track); |
1961 | else |
1962 | av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4.\n"); |
1963 | } |
1964 | |
1965 | if (track->mode == MODE_MP4 && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { |
1966 | AVStereo3D* stereo_3d = (AVStereo3D*) av_stream_get_side_data(track->st, AV_PKT_DATA_STEREO3D, NULL); |
1967 | AVSphericalMapping* spherical_mapping = (AVSphericalMapping*)av_stream_get_side_data(track->st, AV_PKT_DATA_SPHERICAL, NULL); |
1968 | |
1969 | if (stereo_3d) |
1970 | mov_write_st3d_tag(pb, stereo_3d); |
1971 | if (spherical_mapping) |
1972 | mov_write_sv3d_tag(mov->fc, pb, spherical_mapping); |
1973 | } |
1974 | |
1975 | if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) { |
1976 | mov_write_pasp_tag(pb, track); |
1977 | } |
1978 | |
1979 | if (mov->encryption_scheme != MOV_ENC_NONE) { |
1980 | ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid); |
1981 | } |
1982 | |
1983 | /* extra padding for avid stsd */ |
1984 | /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */ |
1985 | if (avid) |
1986 | avio_wb32(pb, 0); |
1987 | |
1988 | return update_size(pb, pos); |
1989 | } |
1990 | |
1991 | static int mov_write_rtp_tag(AVIOContext *pb, MOVTrack *track) |
1992 | { |
1993 | int64_t pos = avio_tell(pb); |
1994 | avio_wb32(pb, 0); /* size */ |
1995 | ffio_wfourcc(pb, "rtp "); |
1996 | avio_wb32(pb, 0); /* Reserved */ |
1997 | avio_wb16(pb, 0); /* Reserved */ |
1998 | avio_wb16(pb, 1); /* Data-reference index */ |
1999 | |
2000 | avio_wb16(pb, 1); /* Hint track version */ |
2001 | avio_wb16(pb, 1); /* Highest compatible version */ |
2002 | avio_wb32(pb, track->max_packet_size); /* Max packet size */ |
2003 | |
2004 | avio_wb32(pb, 12); /* size */ |
2005 | ffio_wfourcc(pb, "tims"); |
2006 | avio_wb32(pb, track->timescale); |
2007 | |
2008 | return update_size(pb, pos); |
2009 | } |
2010 | |
2011 | static int mov_write_source_reference_tag(AVIOContext *pb, MOVTrack *track, const char *reel_name) |
2012 | { |
2013 | uint64_t str_size =strlen(reel_name); |
2014 | int64_t pos = avio_tell(pb); |
2015 | |
2016 | if (str_size >= UINT16_MAX){ |
2017 | av_log(NULL, AV_LOG_ERROR, "reel_name length %"PRIu64" is too large\n", str_size); |
2018 | avio_wb16(pb, 0); |
2019 | return AVERROR(EINVAL); |
2020 | } |
2021 | |
2022 | avio_wb32(pb, 0); /* size */ |
2023 | ffio_wfourcc(pb, "name"); /* Data format */ |
2024 | avio_wb16(pb, str_size); /* string size */ |
2025 | avio_wb16(pb, track->language); /* langcode */ |
2026 | avio_write(pb, reel_name, str_size); /* reel name */ |
2027 | return update_size(pb,pos); |
2028 | } |
2029 | |
2030 | static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track) |
2031 | { |
2032 | int64_t pos = avio_tell(pb); |
2033 | #if 1 |
2034 | int frame_duration; |
2035 | int nb_frames; |
2036 | AVDictionaryEntry *t = NULL; |
2037 | |
2038 | if (!track->st->avg_frame_rate.num || !track->st->avg_frame_rate.den) { |
2039 | #if FF_API_LAVF_AVCTX |
2040 | FF_DISABLE_DEPRECATION_WARNINGS |
2041 | frame_duration = av_rescale(track->timescale, track->st->codec->time_base.num, track->st->codec->time_base.den); |
2042 | nb_frames = ROUNDED_DIV(track->st->codec->time_base.den, track->st->codec->time_base.num); |
2043 | FF_ENABLE_DEPRECATION_WARNINGS |
2044 | #else |
2045 | av_log(NULL, AV_LOG_ERROR, "avg_frame_rate not set for tmcd track.\n"); |
2046 | return AVERROR(EINVAL); |
2047 | #endif |
2048 | } else { |
2049 | frame_duration = av_rescale(track->timescale, track->st->avg_frame_rate.num, track->st->avg_frame_rate.den); |
2050 | nb_frames = ROUNDED_DIV(track->st->avg_frame_rate.den, track->st->avg_frame_rate.num); |
2051 | } |
2052 | |
2053 | if (nb_frames > 255) { |
2054 | av_log(NULL, AV_LOG_ERROR, "fps %d is too large\n", nb_frames); |
2055 | return AVERROR(EINVAL); |
2056 | } |
2057 | |
2058 | avio_wb32(pb, 0); /* size */ |
2059 | ffio_wfourcc(pb, "tmcd"); /* Data format */ |
2060 | avio_wb32(pb, 0); /* Reserved */ |
2061 | avio_wb32(pb, 1); /* Data reference index */ |
2062 | avio_wb32(pb, 0); /* Flags */ |
2063 | avio_wb32(pb, track->timecode_flags); /* Flags (timecode) */ |
2064 | avio_wb32(pb, track->timescale); /* Timescale */ |
2065 | avio_wb32(pb, frame_duration); /* Frame duration */ |
2066 | avio_w8(pb, nb_frames); /* Number of frames */ |
2067 | avio_w8(pb, 0); /* Reserved */ |
2068 | |
2069 | t = av_dict_get(track->st->metadata, "reel_name", NULL, 0); |
2070 | if (t && utf8len(t->value) && track->mode != MODE_MP4) |
2071 | mov_write_source_reference_tag(pb, track, t->value); |
2072 | else |
2073 | avio_wb16(pb, 0); /* zero size */ |
2074 | #else |
2075 | |
2076 | avio_wb32(pb, 0); /* size */ |
2077 | ffio_wfourcc(pb, "tmcd"); /* Data format */ |
2078 | avio_wb32(pb, 0); /* Reserved */ |
2079 | avio_wb32(pb, 1); /* Data reference index */ |
2080 | if (track->par->extradata_size) |
2081 | avio_write(pb, track->par->extradata, track->par->extradata_size); |
2082 | #endif |
2083 | return update_size(pb, pos); |
2084 | } |
2085 | |
2086 | static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) |
2087 | { |
2088 | int64_t pos = avio_tell(pb); |
2089 | avio_wb32(pb, 0); /* size */ |
2090 | ffio_wfourcc(pb, "stsd"); |
2091 | avio_wb32(pb, 0); /* version & flags */ |
2092 | avio_wb32(pb, 1); /* entry count */ |
2093 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) |
2094 | mov_write_video_tag(pb, mov, track); |
2095 | else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) |
2096 | mov_write_audio_tag(s, pb, mov, track); |
2097 | else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) |
2098 | mov_write_subtitle_tag(pb, track); |
2099 | else if (track->par->codec_tag == MKTAG('r','t','p',' ')) |
2100 | mov_write_rtp_tag(pb, track); |
2101 | else if (track->par->codec_tag == MKTAG('t','m','c','d')) |
2102 | mov_write_tmcd_tag(pb, track); |
2103 | return update_size(pb, pos); |
2104 | } |
2105 | |
2106 | static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) |
2107 | { |
2108 | MOVStts *ctts_entries; |
2109 | uint32_t entries = 0; |
2110 | uint32_t atom_size; |
2111 | int i; |
2112 | |
2113 | ctts_entries = av_malloc_array((track->entry + 1), sizeof(*ctts_entries)); /* worst case */ |
2114 | if (!ctts_entries) |
2115 | return AVERROR(ENOMEM); |
2116 | ctts_entries[0].count = 1; |
2117 | ctts_entries[0].duration = track->cluster[0].cts; |
2118 | for (i = 1; i < track->entry; i++) { |
2119 | if (track->cluster[i].cts == ctts_entries[entries].duration) { |
2120 | ctts_entries[entries].count++; /* compress */ |
2121 | } else { |
2122 | entries++; |
2123 | ctts_entries[entries].duration = track->cluster[i].cts; |
2124 | ctts_entries[entries].count = 1; |
2125 | } |
2126 | } |
2127 | entries++; /* last one */ |
2128 | atom_size = 16 + (entries * 8); |
2129 | avio_wb32(pb, atom_size); /* size */ |
2130 | ffio_wfourcc(pb, "ctts"); |
2131 | avio_wb32(pb, 0); /* version & flags */ |
2132 | avio_wb32(pb, entries); /* entry count */ |
2133 | for (i = 0; i < entries; i++) { |
2134 | avio_wb32(pb, ctts_entries[i].count); |
2135 | avio_wb32(pb, ctts_entries[i].duration); |
2136 | } |
2137 | av_free(ctts_entries); |
2138 | return atom_size; |
2139 | } |
2140 | |
2141 | /* Time to sample atom */ |
2142 | static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track) |
2143 | { |
2144 | MOVStts *stts_entries = NULL; |
2145 | uint32_t entries = -1; |
2146 | uint32_t atom_size; |
2147 | int i; |
2148 | |
2149 | if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) { |
2150 | stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */ |
2151 | if (!stts_entries) |
2152 | return AVERROR(ENOMEM); |
2153 | stts_entries[0].count = track->sample_count; |
2154 | stts_entries[0].duration = 1; |
2155 | entries = 1; |
2156 | } else { |
2157 | if (track->entry) { |
2158 | stts_entries = av_malloc_array(track->entry, sizeof(*stts_entries)); /* worst case */ |
2159 | if (!stts_entries) |
2160 | return AVERROR(ENOMEM); |
2161 | } |
2162 | for (i = 0; i < track->entry; i++) { |
2163 | int duration = get_cluster_duration(track, i); |
2164 | if (i && duration == stts_entries[entries].duration) { |
2165 | stts_entries[entries].count++; /* compress */ |
2166 | } else { |
2167 | entries++; |
2168 | stts_entries[entries].duration = duration; |
2169 | stts_entries[entries].count = 1; |
2170 | } |
2171 | } |
2172 | entries++; /* last one */ |
2173 | } |
2174 | atom_size = 16 + (entries * 8); |
2175 | avio_wb32(pb, atom_size); /* size */ |
2176 | ffio_wfourcc(pb, "stts"); |
2177 | avio_wb32(pb, 0); /* version & flags */ |
2178 | avio_wb32(pb, entries); /* entry count */ |
2179 | for (i = 0; i < entries; i++) { |
2180 | avio_wb32(pb, stts_entries[i].count); |
2181 | avio_wb32(pb, stts_entries[i].duration); |
2182 | } |
2183 | av_free(stts_entries); |
2184 | return atom_size; |
2185 | } |
2186 | |
2187 | static int mov_write_dref_tag(AVIOContext *pb) |
2188 | { |
2189 | avio_wb32(pb, 28); /* size */ |
2190 | ffio_wfourcc(pb, "dref"); |
2191 | avio_wb32(pb, 0); /* version & flags */ |
2192 | avio_wb32(pb, 1); /* entry count */ |
2193 | |
2194 | avio_wb32(pb, 0xc); /* size */ |
2195 | //FIXME add the alis and rsrc atom |
2196 | ffio_wfourcc(pb, "url "); |
2197 | avio_wb32(pb, 1); /* version & flags */ |
2198 | |
2199 | return 28; |
2200 | } |
2201 | |
2202 | static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) |
2203 | { |
2204 | int64_t pos = avio_tell(pb); |
2205 | int ret; |
2206 | |
2207 | avio_wb32(pb, 0); /* size */ |
2208 | ffio_wfourcc(pb, "stbl"); |
2209 | mov_write_stsd_tag(s, pb, mov, track); |
2210 | mov_write_stts_tag(pb, track); |
2211 | if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO || |
2212 | track->par->codec_tag == MKTAG('r','t','p',' ')) && |
2213 | track->has_keyframes && track->has_keyframes < track->entry) |
2214 | mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); |
2215 | if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS) |
2216 | mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE); |
2217 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && |
2218 | track->flags & MOV_TRACK_CTTS && track->entry) { |
2219 | |
2220 | if ((ret = mov_write_ctts_tag(pb, track)) < 0) |
2221 | return ret; |
2222 | } |
2223 | mov_write_stsc_tag(pb, track); |
2224 | mov_write_stsz_tag(pb, track); |
2225 | mov_write_stco_tag(pb, track); |
2226 | if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { |
2227 | ff_mov_cenc_write_stbl_atoms(&track->cenc, pb); |
2228 | } |
2229 | return update_size(pb, pos); |
2230 | } |
2231 | |
2232 | static int mov_write_dinf_tag(AVIOContext *pb) |
2233 | { |
2234 | int64_t pos = avio_tell(pb); |
2235 | avio_wb32(pb, 0); /* size */ |
2236 | ffio_wfourcc(pb, "dinf"); |
2237 | mov_write_dref_tag(pb); |
2238 | return update_size(pb, pos); |
2239 | } |
2240 | |
2241 | static int mov_write_nmhd_tag(AVIOContext *pb) |
2242 | { |
2243 | avio_wb32(pb, 12); |
2244 | ffio_wfourcc(pb, "nmhd"); |
2245 | avio_wb32(pb, 0); |
2246 | return 12; |
2247 | } |
2248 | |
2249 | static int mov_write_tcmi_tag(AVIOContext *pb, MOVTrack *track) |
2250 | { |
2251 | int64_t pos = avio_tell(pb); |
2252 | const char *font = "Lucida Grande"; |
2253 | avio_wb32(pb, 0); /* size */ |
2254 | ffio_wfourcc(pb, "tcmi"); /* timecode media information atom */ |
2255 | avio_wb32(pb, 0); /* version & flags */ |
2256 | avio_wb16(pb, 0); /* text font */ |
2257 | avio_wb16(pb, 0); /* text face */ |
2258 | avio_wb16(pb, 12); /* text size */ |
2259 | avio_wb16(pb, 0); /* (unknown, not in the QT specs...) */ |
2260 | avio_wb16(pb, 0x0000); /* text color (red) */ |
2261 | avio_wb16(pb, 0x0000); /* text color (green) */ |
2262 | avio_wb16(pb, 0x0000); /* text color (blue) */ |
2263 | avio_wb16(pb, 0xffff); /* background color (red) */ |
2264 | avio_wb16(pb, 0xffff); /* background color (green) */ |
2265 | avio_wb16(pb, 0xffff); /* background color (blue) */ |
2266 | avio_w8(pb, strlen(font)); /* font len (part of the pascal string) */ |
2267 | avio_write(pb, font, strlen(font)); /* font name */ |
2268 | return update_size(pb, pos); |
2269 | } |
2270 | |
2271 | static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track) |
2272 | { |
2273 | int64_t pos = avio_tell(pb); |
2274 | avio_wb32(pb, 0); /* size */ |
2275 | ffio_wfourcc(pb, "gmhd"); |
2276 | avio_wb32(pb, 0x18); /* gmin size */ |
2277 | ffio_wfourcc(pb, "gmin");/* generic media info */ |
2278 | avio_wb32(pb, 0); /* version & flags */ |
2279 | avio_wb16(pb, 0x40); /* graphics mode = */ |
2280 | avio_wb16(pb, 0x8000); /* opColor (r?) */ |
2281 | avio_wb16(pb, 0x8000); /* opColor (g?) */ |
2282 | avio_wb16(pb, 0x8000); /* opColor (b?) */ |
2283 | avio_wb16(pb, 0); /* balance */ |
2284 | avio_wb16(pb, 0); /* reserved */ |
2285 | |
2286 | /* |
2287 | * This special text atom is required for |
2288 | * Apple Quicktime chapters. The contents |
2289 | * don't appear to be documented, so the |
2290 | * bytes are copied verbatim. |
2291 | */ |
2292 | if (track->tag != MKTAG('c','6','0','8')) { |
2293 | avio_wb32(pb, 0x2C); /* size */ |
2294 | ffio_wfourcc(pb, "text"); |
2295 | avio_wb16(pb, 0x01); |
2296 | avio_wb32(pb, 0x00); |
2297 | avio_wb32(pb, 0x00); |
2298 | avio_wb32(pb, 0x00); |
2299 | avio_wb32(pb, 0x01); |
2300 | avio_wb32(pb, 0x00); |
2301 | avio_wb32(pb, 0x00); |
2302 | avio_wb32(pb, 0x00); |
2303 | avio_wb32(pb, 0x00004000); |
2304 | avio_wb16(pb, 0x0000); |
2305 | } |
2306 | |
2307 | if (track->par->codec_tag == MKTAG('t','m','c','d')) { |
2308 | int64_t tmcd_pos = avio_tell(pb); |
2309 | avio_wb32(pb, 0); /* size */ |
2310 | ffio_wfourcc(pb, "tmcd"); |
2311 | mov_write_tcmi_tag(pb, track); |
2312 | update_size(pb, tmcd_pos); |
2313 | } |
2314 | return update_size(pb, pos); |
2315 | } |
2316 | |
2317 | static int mov_write_smhd_tag(AVIOContext *pb) |
2318 | { |
2319 | avio_wb32(pb, 16); /* size */ |
2320 | ffio_wfourcc(pb, "smhd"); |
2321 | avio_wb32(pb, 0); /* version & flags */ |
2322 | avio_wb16(pb, 0); /* reserved (balance, normally = 0) */ |
2323 | avio_wb16(pb, 0); /* reserved */ |
2324 | return 16; |
2325 | } |
2326 | |
2327 | static int mov_write_vmhd_tag(AVIOContext *pb) |
2328 | { |
2329 | avio_wb32(pb, 0x14); /* size (always 0x14) */ |
2330 | ffio_wfourcc(pb, "vmhd"); |
2331 | avio_wb32(pb, 0x01); /* version & flags */ |
2332 | avio_wb64(pb, 0); /* reserved (graphics mode = copy) */ |
2333 | return 0x14; |
2334 | } |
2335 | |
2336 | static int is_clcp_track(MOVTrack *track) |
2337 | { |
2338 | return track->tag == MKTAG('c','7','0','8') || |
2339 | track->tag == MKTAG('c','6','0','8'); |
2340 | } |
2341 | |
2342 | static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) |
2343 | { |
2344 | const char *hdlr, *descr = NULL, *hdlr_type = NULL; |
2345 | int64_t pos = avio_tell(pb); |
2346 | |
2347 | hdlr = "dhlr"; |
2348 | hdlr_type = "url "; |
2349 | descr = "DataHandler"; |
2350 | |
2351 | if (track) { |
2352 | hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0"; |
2353 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { |
2354 | hdlr_type = "vide"; |
2355 | descr = "VideoHandler"; |
2356 | } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { |
2357 | hdlr_type = "soun"; |
2358 | descr = "SoundHandler"; |
2359 | } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) { |
2360 | if (is_clcp_track(track)) { |
2361 | hdlr_type = "clcp"; |
2362 | descr = "ClosedCaptionHandler"; |
2363 | } else { |
2364 | if (track->tag == MKTAG('t','x','3','g')) { |
2365 | hdlr_type = "sbtl"; |
2366 | } else if (track->tag == MKTAG('m','p','4','s')) { |
2367 | hdlr_type = "subp"; |
2368 | } else { |
2369 | hdlr_type = "text"; |
2370 | } |
2371 | descr = "SubtitleHandler"; |
2372 | } |
2373 | } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) { |
2374 | hdlr_type = "hint"; |
2375 | descr = "HintHandler"; |
2376 | } else if (track->par->codec_tag == MKTAG('t','m','c','d')) { |
2377 | hdlr_type = "tmcd"; |
2378 | descr = "TimeCodeHandler"; |
2379 | } else { |
2380 | av_log(s, AV_LOG_WARNING, |
2381 | "Unknown hldr_type for %s, writing dummy values\n", |
2382 | av_fourcc2str(track->par->codec_tag)); |
2383 | } |
2384 | if (track->st) { |
2385 | // hdlr.name is used by some players to identify the content title |
2386 | // of the track. So if an alternate handler description is |
2387 | // specified, use it. |
2388 | AVDictionaryEntry *t; |
2389 | t = av_dict_get(track->st->metadata, "handler", NULL, 0); |
2390 | if (t && utf8len(t->value)) |
2391 | descr = t->value; |
2392 | } |
2393 | } |
2394 | |
2395 | avio_wb32(pb, 0); /* size */ |
2396 | ffio_wfourcc(pb, "hdlr"); |
2397 | avio_wb32(pb, 0); /* Version & flags */ |
2398 | avio_write(pb, hdlr, 4); /* handler */ |
2399 | ffio_wfourcc(pb, hdlr_type); /* handler type */ |
2400 | avio_wb32(pb, 0); /* reserved */ |
2401 | avio_wb32(pb, 0); /* reserved */ |
2402 | avio_wb32(pb, 0); /* reserved */ |
2403 | if (!track || track->mode == MODE_MOV) |
2404 | avio_w8(pb, strlen(descr)); /* pascal string */ |
2405 | avio_write(pb, descr, strlen(descr)); /* handler description */ |
2406 | if (track && track->mode != MODE_MOV) |
2407 | avio_w8(pb, 0); /* c string */ |
2408 | return update_size(pb, pos); |
2409 | } |
2410 | |
2411 | static int mov_write_hmhd_tag(AVIOContext *pb) |
2412 | { |
2413 | /* This atom must be present, but leaving the values at zero |
2414 | * seems harmless. */ |
2415 | avio_wb32(pb, 28); /* size */ |
2416 | ffio_wfourcc(pb, "hmhd"); |
2417 | avio_wb32(pb, 0); /* version, flags */ |
2418 | avio_wb16(pb, 0); /* maxPDUsize */ |
2419 | avio_wb16(pb, 0); /* avgPDUsize */ |
2420 | avio_wb32(pb, 0); /* maxbitrate */ |
2421 | avio_wb32(pb, 0); /* avgbitrate */ |
2422 | avio_wb32(pb, 0); /* reserved */ |
2423 | return 28; |
2424 | } |
2425 | |
2426 | static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) |
2427 | { |
2428 | int64_t pos = avio_tell(pb); |
2429 | int ret; |
2430 | |
2431 | avio_wb32(pb, 0); /* size */ |
2432 | ffio_wfourcc(pb, "minf"); |
2433 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) |
2434 | mov_write_vmhd_tag(pb); |
2435 | else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) |
2436 | mov_write_smhd_tag(pb); |
2437 | else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) { |
2438 | if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) { |
2439 | mov_write_gmhd_tag(pb, track); |
2440 | } else { |
2441 | mov_write_nmhd_tag(pb); |
2442 | } |
2443 | } else if (track->tag == MKTAG('r','t','p',' ')) { |
2444 | mov_write_hmhd_tag(pb); |
2445 | } else if (track->tag == MKTAG('t','m','c','d')) { |
2446 | if (track->mode != MODE_MOV) |
2447 | mov_write_nmhd_tag(pb); |
2448 | else |
2449 | mov_write_gmhd_tag(pb, track); |
2450 | } |
2451 | if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */ |
2452 | mov_write_hdlr_tag(s, pb, NULL); |
2453 | mov_write_dinf_tag(pb); |
2454 | if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0) |
2455 | return ret; |
2456 | return update_size(pb, pos); |
2457 | } |
2458 | |
2459 | static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov, |
2460 | MOVTrack *track) |
2461 | { |
2462 | int version = track->track_duration < INT32_MAX ? 0 : 1; |
2463 | |
2464 | if (track->mode == MODE_ISM) |
2465 | version = 1; |
2466 | |
2467 | (version == 1) ? avio_wb32(pb, 44) : avio_wb32(pb, 32); /* size */ |
2468 | ffio_wfourcc(pb, "mdhd"); |
2469 | avio_w8(pb, version); |
2470 | avio_wb24(pb, 0); /* flags */ |
2471 | if (version == 1) { |
2472 | avio_wb64(pb, track->time); |
2473 | avio_wb64(pb, track->time); |
2474 | } else { |
2475 | avio_wb32(pb, track->time); /* creation time */ |
2476 | avio_wb32(pb, track->time); /* modification time */ |
2477 | } |
2478 | avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */ |
2479 | if (!track->entry && mov->mode == MODE_ISM) |
2480 | (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff); |
2481 | else if (!track->entry) |
2482 | (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0); |
2483 | else |
2484 | (version == 1) ? avio_wb64(pb, track->track_duration) : avio_wb32(pb, track->track_duration); /* duration */ |
2485 | avio_wb16(pb, track->language); /* language */ |
2486 | avio_wb16(pb, 0); /* reserved (quality) */ |
2487 | |
2488 | if (version != 0 && track->mode == MODE_MOV) { |
2489 | av_log(NULL, AV_LOG_ERROR, |
2490 | "FATAL error, file duration too long for timebase, this file will not be\n" |
2491 | "playable with quicktime. Choose a different timebase or a different\n" |
2492 | "container format\n"); |
2493 | } |
2494 | |
2495 | return 32; |
2496 | } |
2497 | |
2498 | static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb, |
2499 | MOVMuxContext *mov, MOVTrack *track) |
2500 | { |
2501 | int64_t pos = avio_tell(pb); |
2502 | int ret; |
2503 | |
2504 | avio_wb32(pb, 0); /* size */ |
2505 | ffio_wfourcc(pb, "mdia"); |
2506 | mov_write_mdhd_tag(pb, mov, track); |
2507 | mov_write_hdlr_tag(s, pb, track); |
2508 | if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0) |
2509 | return ret; |
2510 | return update_size(pb, pos); |
2511 | } |
2512 | |
2513 | /* transformation matrix |
2514 | |a b u| |
2515 | |c d v| |
2516 | |tx ty w| */ |
2517 | static void write_matrix(AVIOContext *pb, int16_t a, int16_t b, int16_t c, |
2518 | int16_t d, int16_t tx, int16_t ty) |
2519 | { |
2520 | avio_wb32(pb, a << 16); /* 16.16 format */ |
2521 | avio_wb32(pb, b << 16); /* 16.16 format */ |
2522 | avio_wb32(pb, 0); /* u in 2.30 format */ |
2523 | avio_wb32(pb, c << 16); /* 16.16 format */ |
2524 | avio_wb32(pb, d << 16); /* 16.16 format */ |
2525 | avio_wb32(pb, 0); /* v in 2.30 format */ |
2526 | avio_wb32(pb, tx << 16); /* 16.16 format */ |
2527 | avio_wb32(pb, ty << 16); /* 16.16 format */ |
2528 | avio_wb32(pb, 1 << 30); /* w in 2.30 format */ |
2529 | } |
2530 | |
2531 | static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, |
2532 | MOVTrack *track, AVStream *st) |
2533 | { |
2534 | int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE, |
2535 | track->timescale, AV_ROUND_UP); |
2536 | int version = duration < INT32_MAX ? 0 : 1; |
2537 | int flags = MOV_TKHD_FLAG_IN_MOVIE; |
2538 | int rotation = 0; |
2539 | int group = 0; |
2540 | |
2541 | uint32_t *display_matrix = NULL; |
2542 | int display_matrix_size, i; |
2543 | |
2544 | if (st) { |
2545 | if (mov->per_stream_grouping) |
2546 | group = st->index; |
2547 | else |
2548 | group = st->codecpar->codec_type; |
2549 | |
2550 | display_matrix = (uint32_t*)av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, |
2551 | &display_matrix_size); |
2552 | if (display_matrix && display_matrix_size < 9 * sizeof(*display_matrix)) |
2553 | display_matrix = NULL; |
2554 | } |
2555 | |
2556 | if (track->flags & MOV_TRACK_ENABLED) |
2557 | flags |= MOV_TKHD_FLAG_ENABLED; |
2558 | |
2559 | if (track->mode == MODE_ISM) |
2560 | version = 1; |
2561 | |
2562 | (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */ |
2563 | ffio_wfourcc(pb, "tkhd"); |
2564 | avio_w8(pb, version); |
2565 | avio_wb24(pb, flags); |
2566 | if (version == 1) { |
2567 | avio_wb64(pb, track->time); |
2568 | avio_wb64(pb, track->time); |
2569 | } else { |
2570 | avio_wb32(pb, track->time); /* creation time */ |
2571 | avio_wb32(pb, track->time); /* modification time */ |
2572 | } |
2573 | avio_wb32(pb, track->track_id); /* track-id */ |
2574 | avio_wb32(pb, 0); /* reserved */ |
2575 | if (!track->entry && mov->mode == MODE_ISM) |
2576 | (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff); |
2577 | else if (!track->entry) |
2578 | (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0); |
2579 | else |
2580 | (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); |
2581 | |
2582 | avio_wb32(pb, 0); /* reserved */ |
2583 | avio_wb32(pb, 0); /* reserved */ |
2584 | avio_wb16(pb, 0); /* layer */ |
2585 | avio_wb16(pb, group); /* alternate group) */ |
2586 | /* Volume, only for audio */ |
2587 | if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) |
2588 | avio_wb16(pb, 0x0100); |
2589 | else |
2590 | avio_wb16(pb, 0); |
2591 | avio_wb16(pb, 0); /* reserved */ |
2592 | |
2593 | /* Matrix structure */ |
2594 | #if FF_API_OLD_ROTATE_API |
2595 | if (st && st->metadata) { |
2596 | AVDictionaryEntry *rot = av_dict_get(st->metadata, "rotate", NULL, 0); |
2597 | rotation = (rot && rot->value) ? atoi(rot->value) : 0; |
2598 | } |
2599 | #endif |
2600 | if (display_matrix) { |
2601 | for (i = 0; i < 9; i++) |
2602 | avio_wb32(pb, display_matrix[i]); |
2603 | #if FF_API_OLD_ROTATE_API |
2604 | } else if (rotation == 90) { |
2605 | write_matrix(pb, 0, 1, -1, 0, track->par->height, 0); |
2606 | } else if (rotation == 180) { |
2607 | write_matrix(pb, -1, 0, 0, -1, track->par->width, track->par->height); |
2608 | } else if (rotation == 270) { |
2609 | write_matrix(pb, 0, -1, 1, 0, 0, track->par->width); |
2610 | #endif |
2611 | } else { |
2612 | write_matrix(pb, 1, 0, 0, 1, 0, 0); |
2613 | } |
2614 | /* Track width and height, for visual only */ |
2615 | if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO || |
2616 | track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) { |
2617 | int64_t track_width_1616; |
2618 | if (track->mode == MODE_MOV) { |
2619 | track_width_1616 = track->par->width * 0x10000ULL; |
2620 | } else { |
2621 | track_width_1616 = av_rescale(st->sample_aspect_ratio.num, |
2622 | track->par->width * 0x10000LL, |
2623 | st->sample_aspect_ratio.den); |
2624 | if (!track_width_1616 || |
2625 | track->height != track->par->height || |
2626 | track_width_1616 > UINT32_MAX) |
2627 | track_width_1616 = track->par->width * 0x10000ULL; |
2628 | } |
2629 | if (track_width_1616 > UINT32_MAX) { |
2630 | av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n"); |
2631 | track_width_1616 = 0; |
2632 | } |
2633 | avio_wb32(pb, track_width_1616); |
2634 | if (track->height > 0xFFFF) { |
2635 | av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n"); |
2636 | avio_wb32(pb, 0); |
2637 | } else |
2638 | avio_wb32(pb, track->height * 0x10000U); |
2639 | } else { |
2640 | avio_wb32(pb, 0); |
2641 | avio_wb32(pb, 0); |
2642 | } |
2643 | return 0x5c; |
2644 | } |
2645 | |
2646 | static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track) |
2647 | { |
2648 | int32_t width = av_rescale(track->par->sample_aspect_ratio.num, track->par->width, |
2649 | track->par->sample_aspect_ratio.den); |
2650 | |
2651 | int64_t pos = avio_tell(pb); |
2652 | |
2653 | avio_wb32(pb, 0); /* size */ |
2654 | ffio_wfourcc(pb, "tapt"); |
2655 | |
2656 | avio_wb32(pb, 20); |
2657 | ffio_wfourcc(pb, "clef"); |
2658 | avio_wb32(pb, 0); |
2659 | avio_wb32(pb, width << 16); |
2660 | avio_wb32(pb, track->par->height << 16); |
2661 | |
2662 | avio_wb32(pb, 20); |
2663 | ffio_wfourcc(pb, "prof"); |
2664 | avio_wb32(pb, 0); |
2665 | avio_wb32(pb, width << 16); |
2666 | avio_wb32(pb, track->par->height << 16); |
2667 | |
2668 | avio_wb32(pb, 20); |
2669 | ffio_wfourcc(pb, "enof"); |
2670 | avio_wb32(pb, 0); |
2671 | avio_wb32(pb, track->par->width << 16); |
2672 | avio_wb32(pb, track->par->height << 16); |
2673 | |
2674 | return update_size(pb, pos); |
2675 | } |
2676 | |
2677 | // This box seems important for the psp playback ... without it the movie seems to hang |
2678 | static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, |
2679 | MOVTrack *track) |
2680 | { |
2681 | int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE, |
2682 | track->timescale, AV_ROUND_UP); |
2683 | int version = duration < INT32_MAX ? 0 : 1; |
2684 | int entry_size, entry_count, size; |
2685 | int64_t delay, start_ct = track->start_cts; |
2686 | int64_t start_dts = track->start_dts; |
2687 | |
2688 | if (track->entry) { |
2689 | if (start_dts != track->cluster[0].dts || start_ct != track->cluster[0].cts) { |
2690 | |
2691 | av_log(mov->fc, AV_LOG_DEBUG, |
2692 | "EDTS using dts:%"PRId64" cts:%d instead of dts:%"PRId64" cts:%"PRId64" tid:%d\n", |
2693 | track->cluster[0].dts, track->cluster[0].cts, |
2694 | start_dts, start_ct, track->track_id); |
2695 | start_dts = track->cluster[0].dts; |
2696 | start_ct = track->cluster[0].cts; |
2697 | } |
2698 | } |
2699 | |
2700 | delay = av_rescale_rnd(start_dts + start_ct, MOV_TIMESCALE, |
2701 | track->timescale, AV_ROUND_DOWN); |
2702 | version |= delay < INT32_MAX ? 0 : 1; |
2703 | |
2704 | entry_size = (version == 1) ? 20 : 12; |
2705 | entry_count = 1 + (delay > 0); |
2706 | size = 24 + entry_count * entry_size; |
2707 | |
2708 | /* write the atom data */ |
2709 | avio_wb32(pb, size); |
2710 | ffio_wfourcc(pb, "edts"); |
2711 | avio_wb32(pb, size - 8); |
2712 | ffio_wfourcc(pb, "elst"); |
2713 | avio_w8(pb, version); |
2714 | avio_wb24(pb, 0); /* flags */ |
2715 | |
2716 | avio_wb32(pb, entry_count); |
2717 | if (delay > 0) { /* add an empty edit to delay presentation */ |
2718 | /* In the positive delay case, the delay includes the cts |
2719 | * offset, and the second edit list entry below trims out |
2720 | * the same amount from the actual content. This makes sure |
2721 | * that the offset last sample is included in the edit |
2722 | * list duration as well. */ |
2723 | if (version == 1) { |
2724 | avio_wb64(pb, delay); |
2725 | avio_wb64(pb, -1); |
2726 | } else { |
2727 | avio_wb32(pb, delay); |
2728 | avio_wb32(pb, -1); |
2729 | } |
2730 | avio_wb32(pb, 0x00010000); |
2731 | } else { |
2732 | /* Avoid accidentally ending up with start_ct = -1 which has got a |
2733 | * special meaning. Normally start_ct should end up positive or zero |
2734 | * here, but use FFMIN in case dts is a small positive integer |
2735 | * rounded to 0 when represented in MOV_TIMESCALE units. */ |
2736 | av_assert0(av_rescale_rnd(start_dts, MOV_TIMESCALE, track->timescale, AV_ROUND_DOWN) <= 0); |
2737 | start_ct = -FFMIN(start_dts, 0); |
2738 | /* Note, this delay is calculated from the pts of the first sample, |
2739 | * ensuring that we don't reduce the duration for cases with |
2740 | * dts<0 pts=0. */ |
2741 | duration += delay; |
2742 | } |
2743 | |
2744 | /* For fragmented files, we don't know the full length yet. Setting |
2745 | * duration to 0 allows us to only specify the offset, including |
2746 | * the rest of the content (from all future fragments) without specifying |
2747 | * an explicit duration. */ |
2748 | if (mov->flags & FF_MOV_FLAG_FRAGMENT) |
2749 | duration = 0; |
2750 | |
2751 | /* duration */ |
2752 | if (version == 1) { |
2753 | avio_wb64(pb, duration); |
2754 | avio_wb64(pb, start_ct); |
2755 | } else { |
2756 | avio_wb32(pb, duration); |
2757 | avio_wb32(pb, start_ct); |
2758 | } |
2759 | avio_wb32(pb, 0x00010000); |
2760 | return size; |
2761 | } |
2762 | |
2763 | static int mov_write_tref_tag(AVIOContext *pb, MOVTrack *track) |
2764 | { |
2765 | avio_wb32(pb, 20); // size |
2766 | ffio_wfourcc(pb, "tref"); |
2767 | avio_wb32(pb, 12); // size (subatom) |
2768 | avio_wl32(pb, track->tref_tag); |
2769 | avio_wb32(pb, track->tref_id); |
2770 | return 20; |
2771 | } |
2772 | |
2773 | // goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it) |
2774 | static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov) |
2775 | { |
2776 | avio_wb32(pb, 0x34); /* size ... reports as 28 in mp4box! */ |
2777 | ffio_wfourcc(pb, "uuid"); |
2778 | ffio_wfourcc(pb, "USMT"); |
2779 | avio_wb32(pb, 0x21d24fce); |
2780 | avio_wb32(pb, 0xbb88695c); |
2781 | avio_wb32(pb, 0xfac9c740); |
2782 | avio_wb32(pb, 0x1c); // another size here! |
2783 | ffio_wfourcc(pb, "MTDT"); |
2784 | avio_wb32(pb, 0x00010012); |
2785 | avio_wb32(pb, 0x0a); |
2786 | avio_wb32(pb, 0x55c40000); |
2787 | avio_wb32(pb, 0x1); |
2788 | avio_wb32(pb, 0x0); |
2789 | return 0x34; |
2790 | } |
2791 | |
2792 | static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track) |
2793 | { |
2794 | AVFormatContext *ctx = track->rtp_ctx; |
2795 | char buf[1000] = ""; |
2796 | int len; |
2797 | |
2798 | ff_sdp_write_media(buf, sizeof(buf), ctx->streams[0], track->src_track, |
2799 | NULL, NULL, 0, 0, ctx); |
2800 | av_strlcatf(buf, sizeof(buf), "a=control:streamid=%d\r\n", track->track_id); |
2801 | len = strlen(buf); |
2802 | |
2803 | avio_wb32(pb, len + 24); |
2804 | ffio_wfourcc(pb, "udta"); |
2805 | avio_wb32(pb, len + 16); |
2806 | ffio_wfourcc(pb, "hnti"); |
2807 | avio_wb32(pb, len + 8); |
2808 | ffio_wfourcc(pb, "sdp "); |
2809 | avio_write(pb, buf, len); |
2810 | return len + 24; |
2811 | } |
2812 | |
2813 | static int mov_write_track_metadata(AVIOContext *pb, AVStream *st, |
2814 | const char *tag, const char *str) |
2815 | { |
2816 | int64_t pos = avio_tell(pb); |
2817 | AVDictionaryEntry *t = av_dict_get(st->metadata, str, NULL, 0); |
2818 | if (!t || !utf8len(t->value)) |
2819 | return 0; |
2820 | |
2821 | avio_wb32(pb, 0); /* size */ |
2822 | ffio_wfourcc(pb, tag); /* type */ |
2823 | avio_write(pb, t->value, strlen(t->value)); /* UTF8 string value */ |
2824 | return update_size(pb, pos); |
2825 | } |
2826 | |
2827 | static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov, |
2828 | AVStream *st) |
2829 | { |
2830 | AVIOContext *pb_buf; |
2831 | int ret, size; |
2832 | uint8_t *buf; |
2833 | |
2834 | if (!st) |
2835 | return 0; |
2836 | |
2837 | ret = avio_open_dyn_buf(&pb_buf); |
2838 | if (ret < 0) |
2839 | return ret; |
2840 | |
2841 | if (mov->mode & MODE_MP4) |
2842 | mov_write_track_metadata(pb_buf, st, "name", "title"); |
2843 | |
2844 | if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) { |
2845 | avio_wb32(pb, size + 8); |
2846 | ffio_wfourcc(pb, "udta"); |
2847 | avio_write(pb, buf, size); |
2848 | } |
2849 | av_free(buf); |
2850 | |
2851 | return 0; |
2852 | } |
2853 | |
2854 | static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, |
2855 | MOVTrack *track, AVStream *st) |
2856 | { |
2857 | int64_t pos = avio_tell(pb); |
2858 | int entry_backup = track->entry; |
2859 | int chunk_backup = track->chunkCount; |
2860 | int ret; |
2861 | |
2862 | /* If we want to have an empty moov, but some samples already have been |
2863 | * buffered (delay_moov), pretend that no samples have been written yet. */ |
2864 | if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) |
2865 | track->chunkCount = track->entry = 0; |
2866 | |
2867 | avio_wb32(pb, 0); /* size */ |
2868 | ffio_wfourcc(pb, "trak"); |
2869 | mov_write_tkhd_tag(pb, mov, track, st); |
2870 | |
2871 | av_assert2(mov->use_editlist >= 0); |
2872 | |
2873 | if (track->start_dts != AV_NOPTS_VALUE) { |
2874 | if (mov->use_editlist) |
2875 | mov_write_edts_tag(pb, mov, track); // PSP Movies and several other cases require edts box |
2876 | else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track)) |
2877 | av_log(mov->fc, AV_LOG_WARNING, |
2878 | "Not writing any edit list even though one would have been required\n"); |
2879 | } |
2880 | |
2881 | if (track->tref_tag) |
2882 | mov_write_tref_tag(pb, track); |
2883 | |
2884 | if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0) |
2885 | return ret; |
2886 | if (track->mode == MODE_PSP) |
2887 | mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box |
2888 | if (track->tag == MKTAG('r','t','p',' ')) |
2889 | mov_write_udta_sdp(pb, track); |
2890 | if (track->mode == MODE_MOV) { |
2891 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { |
2892 | double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); |
2893 | if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) { |
2894 | mov_write_tapt_tag(pb, track); |
2895 | } |
2896 | } |
2897 | if (is_clcp_track(track) && st->sample_aspect_ratio.num) { |
2898 | mov_write_tapt_tag(pb, track); |
2899 | } |
2900 | } |
2901 | mov_write_track_udta_tag(pb, mov, st); |
2902 | track->entry = entry_backup; |
2903 | track->chunkCount = chunk_backup; |
2904 | return update_size(pb, pos); |
2905 | } |
2906 | |
2907 | static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov) |
2908 | { |
2909 | int i, has_audio = 0, has_video = 0; |
2910 | int64_t pos = avio_tell(pb); |
2911 | int audio_profile = mov->iods_audio_profile; |
2912 | int video_profile = mov->iods_video_profile; |
2913 | for (i = 0; i < mov->nb_streams; i++) { |
2914 | if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) { |
2915 | has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO; |
2916 | has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO; |
2917 | } |
2918 | } |
2919 | if (audio_profile < 0) |
2920 | audio_profile = 0xFF - has_audio; |
2921 | if (video_profile < 0) |
2922 | video_profile = 0xFF - has_video; |
2923 | avio_wb32(pb, 0x0); /* size */ |
2924 | ffio_wfourcc(pb, "iods"); |
2925 | avio_wb32(pb, 0); /* version & flags */ |
2926 | put_descr(pb, 0x10, 7); |
2927 | avio_wb16(pb, 0x004f); |
2928 | avio_w8(pb, 0xff); |
2929 | avio_w8(pb, 0xff); |
2930 | avio_w8(pb, audio_profile); |
2931 | avio_w8(pb, video_profile); |
2932 | avio_w8(pb, 0xff); |
2933 | return update_size(pb, pos); |
2934 | } |
2935 | |
2936 | static int mov_write_trex_tag(AVIOContext *pb, MOVTrack *track) |
2937 | { |
2938 | avio_wb32(pb, 0x20); /* size */ |
2939 | ffio_wfourcc(pb, "trex"); |
2940 | avio_wb32(pb, 0); /* version & flags */ |
2941 | avio_wb32(pb, track->track_id); /* track ID */ |
2942 | avio_wb32(pb, 1); /* default sample description index */ |
2943 | avio_wb32(pb, 0); /* default sample duration */ |
2944 | avio_wb32(pb, 0); /* default sample size */ |
2945 | avio_wb32(pb, 0); /* default sample flags */ |
2946 | return 0; |
2947 | } |
2948 | |
2949 | static int mov_write_mvex_tag(AVIOContext *pb, MOVMuxContext *mov) |
2950 | { |
2951 | int64_t pos = avio_tell(pb); |
2952 | int i; |
2953 | avio_wb32(pb, 0x0); /* size */ |
2954 | ffio_wfourcc(pb, "mvex"); |
2955 | for (i = 0; i < mov->nb_streams; i++) |
2956 | mov_write_trex_tag(pb, &mov->tracks[i]); |
2957 | return update_size(pb, pos); |
2958 | } |
2959 | |
2960 | static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov) |
2961 | { |
2962 | int max_track_id = 1, i; |
2963 | int64_t max_track_len = 0; |
2964 | int version; |
2965 | |
2966 | for (i = 0; i < mov->nb_streams; i++) { |
2967 | if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) { |
2968 | int64_t max_track_len_temp = av_rescale_rnd(mov->tracks[i].track_duration, |
2969 | MOV_TIMESCALE, |
2970 | mov->tracks[i].timescale, |
2971 | AV_ROUND_UP); |
2972 | if (max_track_len < max_track_len_temp) |
2973 | max_track_len = max_track_len_temp; |
2974 | if (max_track_id < mov->tracks[i].track_id) |
2975 | max_track_id = mov->tracks[i].track_id; |
2976 | } |
2977 | } |
2978 | /* If using delay_moov, make sure the output is the same as if no |
2979 | * samples had been written yet. */ |
2980 | if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) { |
2981 | max_track_len = 0; |
2982 | max_track_id = 1; |
2983 | } |
2984 | |
2985 | version = max_track_len < UINT32_MAX ? 0 : 1; |
2986 | avio_wb32(pb, version == 1 ? 120 : 108); /* size */ |
2987 | |
2988 | ffio_wfourcc(pb, "mvhd"); |
2989 | avio_w8(pb, version); |
2990 | avio_wb24(pb, 0); /* flags */ |
2991 | if (version == 1) { |
2992 | avio_wb64(pb, mov->time); |
2993 | avio_wb64(pb, mov->time); |
2994 | } else { |
2995 | avio_wb32(pb, mov->time); /* creation time */ |
2996 | avio_wb32(pb, mov->time); /* modification time */ |
2997 | } |
2998 | avio_wb32(pb, MOV_TIMESCALE); |
2999 | (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */ |
3000 | |
3001 | avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */ |
3002 | avio_wb16(pb, 0x0100); /* reserved (preferred volume) 1.0 = normal */ |
3003 | avio_wb16(pb, 0); /* reserved */ |
3004 | avio_wb32(pb, 0); /* reserved */ |
3005 | avio_wb32(pb, 0); /* reserved */ |
3006 | |
3007 | /* Matrix structure */ |
3008 | write_matrix(pb, 1, 0, 0, 1, 0, 0); |
3009 | |
3010 | avio_wb32(pb, 0); /* reserved (preview time) */ |
3011 | avio_wb32(pb, 0); /* reserved (preview duration) */ |
3012 | avio_wb32(pb, 0); /* reserved (poster time) */ |
3013 | avio_wb32(pb, 0); /* reserved (selection time) */ |
3014 | avio_wb32(pb, 0); /* reserved (selection duration) */ |
3015 | avio_wb32(pb, 0); /* reserved (current time) */ |
3016 | avio_wb32(pb, max_track_id + 1); /* Next track id */ |
3017 | return 0x6c; |
3018 | } |
3019 | |
3020 | static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov, |
3021 | AVFormatContext *s) |
3022 | { |
3023 | avio_wb32(pb, 33); /* size */ |
3024 | ffio_wfourcc(pb, "hdlr"); |
3025 | avio_wb32(pb, 0); |
3026 | avio_wb32(pb, 0); |
3027 | ffio_wfourcc(pb, "mdir"); |
3028 | ffio_wfourcc(pb, "appl"); |
3029 | avio_wb32(pb, 0); |
3030 | avio_wb32(pb, 0); |
3031 | avio_w8(pb, 0); |
3032 | return 33; |
3033 | } |
3034 | |
3035 | /* helper function to write a data tag with the specified string as data */ |
3036 | static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style) |
3037 | { |
3038 | if (long_style) { |
3039 | int size = 16 + strlen(data); |
3040 | avio_wb32(pb, size); /* size */ |
3041 | ffio_wfourcc(pb, "data"); |
3042 | avio_wb32(pb, 1); |
3043 | avio_wb32(pb, 0); |
3044 | avio_write(pb, data, strlen(data)); |
3045 | return size; |
3046 | } else { |
3047 | if (!lang) |
3048 | lang = ff_mov_iso639_to_lang("und", 1); |
3049 | avio_wb16(pb, strlen(data)); /* string length */ |
3050 | avio_wb16(pb, lang); |
3051 | avio_write(pb, data, strlen(data)); |
3052 | return strlen(data) + 4; |
3053 | } |
3054 | } |
3055 | |
3056 | static int mov_write_string_tag(AVIOContext *pb, const char *name, |
3057 | const char *value, int lang, int long_style) |
3058 | { |
3059 | int size = 0; |
3060 | if (value && value[0]) { |
3061 | int64_t pos = avio_tell(pb); |
3062 | avio_wb32(pb, 0); /* size */ |
3063 | ffio_wfourcc(pb, name); |
3064 | mov_write_string_data_tag(pb, value, lang, long_style); |
3065 | size = update_size(pb, pos); |
3066 | } |
3067 | return size; |
3068 | } |
3069 | |
3070 | static AVDictionaryEntry *get_metadata_lang(AVFormatContext *s, |
3071 | const char *tag, int *lang) |
3072 | { |
3073 | int l, len, len2; |
3074 | AVDictionaryEntry *t, *t2 = NULL; |
3075 | char tag2[16]; |
3076 | |
3077 | *lang = 0; |
3078 | |
3079 | if (!(t = av_dict_get(s->metadata, tag, NULL, 0))) |
3080 | return NULL; |
3081 | |
3082 | len = strlen(t->key); |
3083 | snprintf(tag2, sizeof(tag2), "%s-", tag); |
3084 | while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) { |
3085 | len2 = strlen(t2->key); |
3086 | if (len2 == len + 4 && !strcmp(t->value, t2->value) |
3087 | && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) { |
3088 | *lang = l; |
3089 | return t; |
3090 | } |
3091 | } |
3092 | return t; |
3093 | } |
3094 | |
3095 | static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb, |
3096 | const char *name, const char *tag, |
3097 | int long_style) |
3098 | { |
3099 | int lang; |
3100 | AVDictionaryEntry *t = get_metadata_lang(s, tag, &lang); |
3101 | if (!t) |
3102 | return 0; |
3103 | return mov_write_string_tag(pb, name, t->value, lang, long_style); |
3104 | } |
3105 | |
3106 | /* iTunes bpm number */ |
3107 | static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s) |
3108 | { |
3109 | AVDictionaryEntry *t = av_dict_get(s->metadata, "tmpo", NULL, 0); |
3110 | int size = 0, tmpo = t ? atoi(t->value) : 0; |
3111 | if (tmpo) { |
3112 | size = 26; |
3113 | avio_wb32(pb, size); |
3114 | ffio_wfourcc(pb, "tmpo"); |
3115 | avio_wb32(pb, size-8); /* size */ |
3116 | ffio_wfourcc(pb, "data"); |
3117 | avio_wb32(pb, 0x15); //type specifier |
3118 | avio_wb32(pb, 0); |
3119 | avio_wb16(pb, tmpo); // data |
3120 | } |
3121 | return size; |
3122 | } |
3123 | |
3124 | /* 3GPP TS 26.244 */ |
3125 | static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb) |
3126 | { |
3127 | int lang; |
3128 | int64_t pos = avio_tell(pb); |
3129 | double latitude, longitude, altitude; |
3130 | int32_t latitude_fix, longitude_fix, altitude_fix; |
3131 | AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang); |
3132 | const char *ptr, *place = ""; |
3133 | char *end; |
3134 | static const char *astronomical_body = "earth"; |
3135 | if (!t) |
3136 | return 0; |
3137 | |
3138 | ptr = t->value; |
3139 | longitude = strtod(ptr, &end); |
3140 | if (end == ptr) { |
3141 | av_log(s, AV_LOG_WARNING, "malformed location metadata\n"); |
3142 | return 0; |
3143 | } |
3144 | ptr = end; |
3145 | latitude = strtod(ptr, &end); |
3146 | if (end == ptr) { |
3147 | av_log(s, AV_LOG_WARNING, "malformed location metadata\n"); |
3148 | return 0; |
3149 | } |
3150 | ptr = end; |
3151 | altitude = strtod(ptr, &end); |
3152 | /* If no altitude was present, the default 0 should be fine */ |
3153 | if (*end == '/') |
3154 | place = end + 1; |
3155 | |
3156 | latitude_fix = (int32_t) ((1 << 16) * latitude); |
3157 | longitude_fix = (int32_t) ((1 << 16) * longitude); |
3158 | altitude_fix = (int32_t) ((1 << 16) * altitude); |
3159 | |
3160 | avio_wb32(pb, 0); /* size */ |
3161 | ffio_wfourcc(pb, "loci"); /* type */ |
3162 | avio_wb32(pb, 0); /* version + flags */ |
3163 | avio_wb16(pb, lang); |
3164 | avio_write(pb, place, strlen(place) + 1); |
3165 | avio_w8(pb, 0); /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */ |
3166 | avio_wb32(pb, latitude_fix); |
3167 | avio_wb32(pb, longitude_fix); |
3168 | avio_wb32(pb, altitude_fix); |
3169 | avio_write(pb, astronomical_body, strlen(astronomical_body) + 1); |
3170 | avio_w8(pb, 0); /* additional notes, null terminated string */ |
3171 | |
3172 | return update_size(pb, pos); |
3173 | } |
3174 | |
3175 | /* iTunes track or disc number */ |
3176 | static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov, |
3177 | AVFormatContext *s, int disc) |
3178 | { |
3179 | AVDictionaryEntry *t = av_dict_get(s->metadata, |
3180 | disc ? "disc" : "track", |
3181 | NULL, 0); |
3182 | int size = 0, track = t ? atoi(t->value) : 0; |
3183 | if (track) { |
3184 | int tracks = 0; |
3185 | char *slash = strchr(t->value, '/'); |
3186 | if (slash) |
3187 | tracks = atoi(slash + 1); |
3188 | avio_wb32(pb, 32); /* size */ |
3189 | ffio_wfourcc(pb, disc ? "disk" : "trkn"); |
3190 | avio_wb32(pb, 24); /* size */ |
3191 | ffio_wfourcc(pb, "data"); |
3192 | avio_wb32(pb, 0); // 8 bytes empty |
3193 | avio_wb32(pb, 0); |
3194 | avio_wb16(pb, 0); // empty |
3195 | avio_wb16(pb, track); // track / disc number |
3196 | avio_wb16(pb, tracks); // total track / disc number |
3197 | avio_wb16(pb, 0); // empty |
3198 | size = 32; |
3199 | } |
3200 | return size; |
3201 | } |
3202 | |
3203 | static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb, |
3204 | const char *name, const char *tag, |
3205 | int len) |
3206 | { |
3207 | AVDictionaryEntry *t = NULL; |
3208 | uint8_t num; |
3209 | int size = 24 + len; |
3210 | |
3211 | if (len != 1 && len != 4) |
3212 | return -1; |
3213 | |
3214 | if (!(t = av_dict_get(s->metadata, tag, NULL, 0))) |
3215 | return 0; |
3216 | num = atoi(t->value); |
3217 | |
3218 | avio_wb32(pb, size); |
3219 | ffio_wfourcc(pb, name); |
3220 | avio_wb32(pb, size - 8); |
3221 | ffio_wfourcc(pb, "data"); |
3222 | avio_wb32(pb, 0x15); |
3223 | avio_wb32(pb, 0); |
3224 | if (len==4) avio_wb32(pb, num); |
3225 | else avio_w8 (pb, num); |
3226 | |
3227 | return size; |
3228 | } |
3229 | |
3230 | /* iTunes meta data list */ |
3231 | static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, |
3232 | AVFormatContext *s) |
3233 | { |
3234 | int64_t pos = avio_tell(pb); |
3235 | avio_wb32(pb, 0); /* size */ |
3236 | ffio_wfourcc(pb, "ilst"); |
3237 | mov_write_string_metadata(s, pb, "\251nam", "title" , 1); |
3238 | mov_write_string_metadata(s, pb, "\251ART", "artist" , 1); |
3239 | mov_write_string_metadata(s, pb, "aART", "album_artist", 1); |
3240 | mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1); |
3241 | mov_write_string_metadata(s, pb, "\251alb", "album" , 1); |
3242 | mov_write_string_metadata(s, pb, "\251day", "date" , 1); |
3243 | if (!mov_write_string_metadata(s, pb, "\251too", "encoding_tool", 1)) { |
3244 | if (!(s->flags & AVFMT_FLAG_BITEXACT)) |
3245 | mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1); |
3246 | } |
3247 | mov_write_string_metadata(s, pb, "\251cmt", "comment" , 1); |
3248 | mov_write_string_metadata(s, pb, "\251gen", "genre" , 1); |
3249 | mov_write_string_metadata(s, pb, "\251cpy", "copyright", 1); |
3250 | mov_write_string_metadata(s, pb, "\251grp", "grouping" , 1); |
3251 | mov_write_string_metadata(s, pb, "\251lyr", "lyrics" , 1); |
3252 | mov_write_string_metadata(s, pb, "desc", "description",1); |
3253 | mov_write_string_metadata(s, pb, "ldes", "synopsis" , 1); |
3254 | mov_write_string_metadata(s, pb, "tvsh", "show" , 1); |
3255 | mov_write_string_metadata(s, pb, "tven", "episode_id",1); |
3256 | mov_write_string_metadata(s, pb, "tvnn", "network" , 1); |
3257 | mov_write_int8_metadata (s, pb, "tves", "episode_sort",4); |
3258 | mov_write_int8_metadata (s, pb, "tvsn", "season_number",4); |
3259 | mov_write_int8_metadata (s, pb, "stik", "media_type",1); |
3260 | mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1); |
3261 | mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1); |
3262 | mov_write_int8_metadata (s, pb, "cpil", "compilation", 1); |
3263 | mov_write_trkn_tag(pb, mov, s, 0); // track number |
3264 | mov_write_trkn_tag(pb, mov, s, 1); // disc number |
3265 | mov_write_tmpo_tag(pb, s); |
3266 | return update_size(pb, pos); |
3267 | } |
3268 | |
3269 | static int mov_write_mdta_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov, |
3270 | AVFormatContext *s) |
3271 | { |
3272 | avio_wb32(pb, 33); /* size */ |
3273 | ffio_wfourcc(pb, "hdlr"); |
3274 | avio_wb32(pb, 0); |
3275 | avio_wb32(pb, 0); |
3276 | ffio_wfourcc(pb, "mdta"); |
3277 | avio_wb32(pb, 0); |
3278 | avio_wb32(pb, 0); |
3279 | avio_wb32(pb, 0); |
3280 | avio_w8(pb, 0); |
3281 | return 33; |
3282 | } |
3283 | |
3284 | static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov, |
3285 | AVFormatContext *s) |
3286 | { |
3287 | AVDictionaryEntry *t = NULL; |
3288 | int64_t pos = avio_tell(pb); |
3289 | int64_t curpos, entry_pos; |
3290 | int count = 0; |
3291 | |
3292 | avio_wb32(pb, 0); /* size */ |
3293 | ffio_wfourcc(pb, "keys"); |
3294 | avio_wb32(pb, 0); |
3295 | entry_pos = avio_tell(pb); |
3296 | avio_wb32(pb, 0); /* entry count */ |
3297 | |
3298 | while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) { |
3299 | avio_wb32(pb, strlen(t->key) + 8); |
3300 | ffio_wfourcc(pb, "mdta"); |
3301 | avio_write(pb, t->key, strlen(t->key)); |
3302 | count += 1; |
3303 | } |
3304 | curpos = avio_tell(pb); |
3305 | avio_seek(pb, entry_pos, SEEK_SET); |
3306 | avio_wb32(pb, count); // rewrite entry count |
3307 | avio_seek(pb, curpos, SEEK_SET); |
3308 | |
3309 | return update_size(pb, pos); |
3310 | } |
3311 | |
3312 | static int mov_write_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, |
3313 | AVFormatContext *s) |
3314 | { |
3315 | AVDictionaryEntry *t = NULL; |
3316 | int64_t pos = avio_tell(pb); |
3317 | int count = 1; /* keys are 1-index based */ |
3318 | |
3319 | avio_wb32(pb, 0); /* size */ |
3320 | ffio_wfourcc(pb, "ilst"); |
3321 | |
3322 | while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) { |
3323 | int64_t entry_pos = avio_tell(pb); |
3324 | avio_wb32(pb, 0); /* size */ |
3325 | avio_wb32(pb, count); /* key */ |
3326 | mov_write_string_data_tag(pb, t->value, 0, 1); |
3327 | update_size(pb, entry_pos); |
3328 | count += 1; |
3329 | } |
3330 | return update_size(pb, pos); |
3331 | } |
3332 | |
3333 | /* meta data tags */ |
3334 | static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov, |
3335 | AVFormatContext *s) |
3336 | { |
3337 | int size = 0; |
3338 | int64_t pos = avio_tell(pb); |
3339 | avio_wb32(pb, 0); /* size */ |
3340 | ffio_wfourcc(pb, "meta"); |
3341 | avio_wb32(pb, 0); |
3342 | if (mov->flags & FF_MOV_FLAG_USE_MDTA) { |
3343 | mov_write_mdta_hdlr_tag(pb, mov, s); |
3344 | mov_write_mdta_keys_tag(pb, mov, s); |
3345 | mov_write_mdta_ilst_tag(pb, mov, s); |
3346 | } |
3347 | else { |
3348 | /* iTunes metadata tag */ |
3349 | mov_write_itunes_hdlr_tag(pb, mov, s); |
3350 | mov_write_ilst_tag(pb, mov, s); |
3351 | } |
3352 | size = update_size(pb, pos); |
3353 | return size; |
3354 | } |
3355 | |
3356 | static int mov_write_raw_metadata_tag(AVFormatContext *s, AVIOContext *pb, |
3357 | const char *name, const char *key) |
3358 | { |
3359 | int len; |
3360 | AVDictionaryEntry *t; |
3361 | |
3362 | if (!(t = av_dict_get(s->metadata, key, NULL, 0))) |
3363 | return 0; |
3364 | |
3365 | len = strlen(t->value); |
3366 | if (len > 0) { |
3367 | int size = len + 8; |
3368 | avio_wb32(pb, size); |
3369 | ffio_wfourcc(pb, name); |
3370 | avio_write(pb, t->value, len); |
3371 | return size; |
3372 | } |
3373 | return 0; |
3374 | } |
3375 | |
3376 | static int ascii_to_wc(AVIOContext *pb, const uint8_t *b) |
3377 | { |
3378 | int val; |
3379 | while (*b) { |
3380 | GET_UTF8(val, *b++, return -1;) |
3381 | avio_wb16(pb, val); |
3382 | } |
3383 | avio_wb16(pb, 0x00); |
3384 | return 0; |
3385 | } |
3386 | |
3387 | static uint16_t language_code(const char *str) |
3388 | { |
3389 | return (((str[0] - 0x60) & 0x1F) << 10) + |
3390 | (((str[1] - 0x60) & 0x1F) << 5) + |
3391 | (( str[2] - 0x60) & 0x1F); |
3392 | } |
3393 | |
3394 | static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s, |
3395 | const char *tag, const char *str) |
3396 | { |
3397 | int64_t pos = avio_tell(pb); |
3398 | AVDictionaryEntry *t = av_dict_get(s->metadata, str, NULL, 0); |
3399 | if (!t || !utf8len(t->value)) |
3400 | return 0; |
3401 | avio_wb32(pb, 0); /* size */ |
3402 | ffio_wfourcc(pb, tag); /* type */ |
3403 | avio_wb32(pb, 0); /* version + flags */ |
3404 | if (!strcmp(tag, "yrrc")) |
3405 | avio_wb16(pb, atoi(t->value)); |
3406 | else { |
3407 | avio_wb16(pb, language_code("eng")); /* language */ |
3408 | avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */ |
3409 | if (!strcmp(tag, "albm") && |
3410 | (t = av_dict_get(s->metadata, "track", NULL, 0))) |
3411 | avio_w8(pb, atoi(t->value)); |
3412 | } |
3413 | return update_size(pb, pos); |
3414 | } |
3415 | |
3416 | static int mov_write_chpl_tag(AVIOContext *pb, AVFormatContext *s) |
3417 | { |
3418 | int64_t pos = avio_tell(pb); |
3419 | int i, nb_chapters = FFMIN(s->nb_chapters, 255); |
3420 | |
3421 | avio_wb32(pb, 0); // size |
3422 | ffio_wfourcc(pb, "chpl"); |
3423 | avio_wb32(pb, 0x01000000); // version + flags |
3424 | avio_wb32(pb, 0); // unknown |
3425 | avio_w8(pb, nb_chapters); |
3426 | |
3427 | for (i = 0; i < nb_chapters; i++) { |
3428 | AVChapter *c = s->chapters[i]; |
3429 | AVDictionaryEntry *t; |
3430 | avio_wb64(pb, av_rescale_q(c->start, c->time_base, (AVRational){1,10000000})); |
3431 | |
3432 | if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { |
3433 | int len = FFMIN(strlen(t->value), 255); |
3434 | avio_w8(pb, len); |
3435 | avio_write(pb, t->value, len); |
3436 | } else |
3437 | avio_w8(pb, 0); |
3438 | } |
3439 | return update_size(pb, pos); |
3440 | } |
3441 | |
3442 | static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, |
3443 | AVFormatContext *s) |
3444 | { |
3445 | AVIOContext *pb_buf; |
3446 | int ret, size; |
3447 | uint8_t *buf; |
3448 | |
3449 | ret = avio_open_dyn_buf(&pb_buf); |
3450 | if (ret < 0) |
3451 | return ret; |
3452 | |
3453 | if (mov->mode & MODE_3GP) { |
3454 | mov_write_3gp_udta_tag(pb_buf, s, "perf", "artist"); |
3455 | mov_write_3gp_udta_tag(pb_buf, s, "titl", "title"); |
3456 | mov_write_3gp_udta_tag(pb_buf, s, "auth", "author"); |
3457 | mov_write_3gp_udta_tag(pb_buf, s, "gnre", "genre"); |
3458 | mov_write_3gp_udta_tag(pb_buf, s, "dscp", "comment"); |
3459 | mov_write_3gp_udta_tag(pb_buf, s, "albm", "album"); |
3460 | mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright"); |
3461 | mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date"); |
3462 | mov_write_loci_tag(s, pb_buf); |
3463 | } else if (mov->mode == MODE_MOV && !(mov->flags & FF_MOV_FLAG_USE_MDTA)) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4 |
3464 | mov_write_string_metadata(s, pb_buf, "\251ART", "artist", 0); |
3465 | mov_write_string_metadata(s, pb_buf, "\251nam", "title", 0); |
3466 | mov_write_string_metadata(s, pb_buf, "\251aut", "author", 0); |
3467 | mov_write_string_metadata(s, pb_buf, "\251alb", "album", 0); |
3468 | mov_write_string_metadata(s, pb_buf, "\251day", "date", 0); |
3469 | mov_write_string_metadata(s, pb_buf, "\251swr", "encoder", 0); |
3470 | // currently ignored by mov.c |
3471 | mov_write_string_metadata(s, pb_buf, "\251des", "comment", 0); |
3472 | // add support for libquicktime, this atom is also actually read by mov.c |
3473 | mov_write_string_metadata(s, pb_buf, "\251cmt", "comment", 0); |
3474 | mov_write_string_metadata(s, pb_buf, "\251gen", "genre", 0); |
3475 | mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright", 0); |
3476 | mov_write_string_metadata(s, pb_buf, "\251mak", "make", 0); |
3477 | mov_write_string_metadata(s, pb_buf, "\251mod", "model", 0); |
3478 | mov_write_string_metadata(s, pb_buf, "\251xyz", "location", 0); |
3479 | mov_write_raw_metadata_tag(s, pb_buf, "XMP_", "xmp"); |
3480 | } else { |
3481 | /* iTunes meta data */ |
3482 | mov_write_meta_tag(pb_buf, mov, s); |
3483 | mov_write_loci_tag(s, pb_buf); |
3484 | } |
3485 | |
3486 | if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL)) |
3487 | mov_write_chpl_tag(pb_buf, s); |
3488 | |
3489 | if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) { |
3490 | avio_wb32(pb, size + 8); |
3491 | ffio_wfourcc(pb, "udta"); |
3492 | avio_write(pb, buf, size); |
3493 | } |
3494 | av_free(buf); |
3495 | |
3496 | return 0; |
3497 | } |
3498 | |
3499 | static void mov_write_psp_udta_tag(AVIOContext *pb, |
3500 | const char *str, const char *lang, int type) |
3501 | { |
3502 | int len = utf8len(str) + 1; |
3503 | if (len <= 0) |
3504 | return; |
3505 | avio_wb16(pb, len * 2 + 10); /* size */ |
3506 | avio_wb32(pb, type); /* type */ |
3507 | avio_wb16(pb, language_code(lang)); /* language */ |
3508 | avio_wb16(pb, 0x01); /* ? */ |
3509 | ascii_to_wc(pb, str); |
3510 | } |
3511 | |
3512 | static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s) |
3513 | { |
3514 | AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0); |
3515 | int64_t pos, pos2; |
3516 | |
3517 | if (title) { |
3518 | pos = avio_tell(pb); |
3519 | avio_wb32(pb, 0); /* size placeholder*/ |
3520 | ffio_wfourcc(pb, "uuid"); |
3521 | ffio_wfourcc(pb, "USMT"); |
3522 | avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */ |
3523 | avio_wb32(pb, 0xbb88695c); |
3524 | avio_wb32(pb, 0xfac9c740); |
3525 | |
3526 | pos2 = avio_tell(pb); |
3527 | avio_wb32(pb, 0); /* size placeholder*/ |
3528 | ffio_wfourcc(pb, "MTDT"); |
3529 | avio_wb16(pb, 4); |
3530 | |
3531 | // ? |
3532 | avio_wb16(pb, 0x0C); /* size */ |
3533 | avio_wb32(pb, 0x0B); /* type */ |
3534 | avio_wb16(pb, language_code("und")); /* language */ |
3535 | avio_wb16(pb, 0x0); /* ? */ |
3536 | avio_wb16(pb, 0x021C); /* data */ |
3537 | |
3538 | if (!(s->flags & AVFMT_FLAG_BITEXACT)) |
3539 | mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT, "eng", 0x04); |
3540 | mov_write_psp_udta_tag(pb, title->value, "eng", 0x01); |
3541 | mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03); |
3542 | |
3543 | update_size(pb, pos2); |
3544 | return update_size(pb, pos); |
3545 | } |
3546 | |
3547 | return 0; |
3548 | } |
3549 | |
3550 | static void build_chunks(MOVTrack *trk) |
3551 | { |
3552 | int i; |
3553 | MOVIentry *chunk = &trk->cluster[0]; |
3554 | uint64_t chunkSize = chunk->size; |
3555 | chunk->chunkNum = 1; |
3556 | if (trk->chunkCount) |
3557 | return; |
3558 | trk->chunkCount = 1; |
3559 | for (i = 1; i<trk->entry; i++){ |
3560 | if (chunk->pos + chunkSize == trk->cluster[i].pos && |
3561 | chunkSize + trk->cluster[i].size < (1<<20)){ |
3562 | chunkSize += trk->cluster[i].size; |
3563 | chunk->samples_in_chunk += trk->cluster[i].entries; |
3564 | } else { |
3565 | trk->cluster[i].chunkNum = chunk->chunkNum+1; |
3566 | chunk=&trk->cluster[i]; |
3567 | chunkSize = chunk->size; |
3568 | trk->chunkCount++; |
3569 | } |
3570 | } |
3571 | } |
3572 | |
3573 | /** |
3574 | * Assign track ids. If option "use_stream_ids_as_track_ids" is set, |
3575 | * the stream ids are used as track ids. |
3576 | * |
3577 | * This assumes mov->tracks and s->streams are in the same order and |
3578 | * there are no gaps in either of them (so mov->tracks[n] refers to |
3579 | * s->streams[n]). |
3580 | * |
3581 | * As an exception, there can be more entries in |
3582 | * s->streams than in mov->tracks, in which case new track ids are |
3583 | * generated (starting after the largest found stream id). |
3584 | */ |
3585 | static int mov_setup_track_ids(MOVMuxContext *mov, AVFormatContext *s) |
3586 | { |
3587 | int i; |
3588 | |
3589 | if (mov->track_ids_ok) |
3590 | return 0; |
3591 | |
3592 | if (mov->use_stream_ids_as_track_ids) { |
3593 | int next_generated_track_id = 0; |
3594 | for (i = 0; i < s->nb_streams; i++) { |
3595 | if (s->streams[i]->id > next_generated_track_id) |
3596 | next_generated_track_id = s->streams[i]->id; |
3597 | } |
3598 | |
3599 | for (i = 0; i < mov->nb_streams; i++) { |
3600 | if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) |
3601 | continue; |
3602 | |
3603 | mov->tracks[i].track_id = i >= s->nb_streams ? ++next_generated_track_id : s->streams[i]->id; |
3604 | } |
3605 | } else { |
3606 | for (i = 0; i < mov->nb_streams; i++) { |
3607 | if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) |
3608 | continue; |
3609 | |
3610 | mov->tracks[i].track_id = i + 1; |
3611 | } |
3612 | } |
3613 | |
3614 | mov->track_ids_ok = 1; |
3615 | |
3616 | return 0; |
3617 | } |
3618 | |
3619 | static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, |
3620 | AVFormatContext *s) |
3621 | { |
3622 | int i; |
3623 | int64_t pos = avio_tell(pb); |
3624 | avio_wb32(pb, 0); /* size placeholder*/ |
3625 | ffio_wfourcc(pb, "moov"); |
3626 | |
3627 | mov_setup_track_ids(mov, s); |
3628 | |
3629 | for (i = 0; i < mov->nb_streams; i++) { |
3630 | if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) |
3631 | continue; |
3632 | |
3633 | mov->tracks[i].time = mov->time; |
3634 | |
3635 | if (mov->tracks[i].entry) |
3636 | build_chunks(&mov->tracks[i]); |
3637 | } |
3638 | |
3639 | if (mov->chapter_track) |
3640 | for (i = 0; i < s->nb_streams; i++) { |
3641 | mov->tracks[i].tref_tag = MKTAG('c','h','a','p'); |
3642 | mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].track_id; |
3643 | } |
3644 | for (i = 0; i < mov->nb_streams; i++) { |
3645 | MOVTrack *track = &mov->tracks[i]; |
3646 | if (track->tag == MKTAG('r','t','p',' ')) { |
3647 | track->tref_tag = MKTAG('h','i','n','t'); |
3648 | track->tref_id = mov->tracks[track->src_track].track_id; |
3649 | } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { |
3650 | int * fallback, size; |
3651 | fallback = (int*)av_stream_get_side_data(track->st, |
3652 | AV_PKT_DATA_FALLBACK_TRACK, |
3653 | &size); |
3654 | if (fallback != NULL && size == sizeof(int)) { |
3655 | if (*fallback >= 0 && *fallback < mov->nb_streams) { |
3656 | track->tref_tag = MKTAG('f','a','l','l'); |
3657 | track->tref_id = mov->tracks[*fallback].track_id; |
3658 | } |
3659 | } |
3660 | } |
3661 | } |
3662 | for (i = 0; i < mov->nb_streams; i++) { |
3663 | if (mov->tracks[i].tag == MKTAG('t','m','c','d')) { |
3664 | int src_trk = mov->tracks[i].src_track; |
3665 | mov->tracks[src_trk].tref_tag = mov->tracks[i].tag; |
3666 | mov->tracks[src_trk].tref_id = mov->tracks[i].track_id; |
3667 | //src_trk may have a different timescale than the tmcd track |
3668 | mov->tracks[i].track_duration = av_rescale(mov->tracks[src_trk].track_duration, |
3669 | mov->tracks[i].timescale, |
3670 | mov->tracks[src_trk].timescale); |
3671 | } |
3672 | } |
3673 | |
3674 | mov_write_mvhd_tag(pb, mov); |
3675 | if (mov->mode != MODE_MOV && !mov->iods_skip) |
3676 | mov_write_iods_tag(pb, mov); |
3677 | for (i = 0; i < mov->nb_streams; i++) { |
3678 | if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT) { |
3679 | int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL); |
3680 | if (ret < 0) |
3681 | return ret; |
3682 | } |
3683 | } |
3684 | if (mov->flags & FF_MOV_FLAG_FRAGMENT) |
3685 | mov_write_mvex_tag(pb, mov); /* QuickTime requires trak to precede this */ |
3686 | |
3687 | if (mov->mode == MODE_PSP) |
3688 | mov_write_uuidusmt_tag(pb, s); |
3689 | else |
3690 | mov_write_udta_tag(pb, mov, s); |
3691 | |
3692 | return update_size(pb, pos); |
3693 | } |
3694 | |
3695 | static void param_write_int(AVIOContext *pb, const char *name, int value) |
3696 | { |
3697 | avio_printf(pb, "<param name=\"%s\" value=\"%d\" valuetype=\"data\"/>\n", name, value); |
3698 | } |
3699 | |
3700 | static void param_write_string(AVIOContext *pb, const char *name, const char *value) |
3701 | { |
3702 | avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, value); |
3703 | } |
3704 | |
3705 | static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len) |
3706 | { |
3707 | char buf[150]; |
3708 | len = FFMIN(sizeof(buf) / 2 - 1, len); |
3709 | ff_data_to_hex(buf, value, len, 0); |
3710 | buf[2 * len] = '\0'; |
3711 | avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf); |
3712 | } |
3713 | |
3714 | static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) |
3715 | { |
3716 | int64_t pos = avio_tell(pb); |
3717 | int i; |
3718 | int64_t manifest_bit_rate = 0; |
3719 | AVCPBProperties *props = NULL; |
3720 | |
3721 | static const uint8_t uuid[] = { |
3722 | 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd, |
3723 | 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 |
3724 | }; |
3725 | |
3726 | avio_wb32(pb, 0); |
3727 | ffio_wfourcc(pb, "uuid"); |
3728 | avio_write(pb, uuid, sizeof(uuid)); |
3729 | avio_wb32(pb, 0); |
3730 | |
3731 | avio_printf(pb, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); |
3732 | avio_printf(pb, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n"); |
3733 | avio_printf(pb, "<head>\n"); |
3734 | if (!(mov->fc->flags & AVFMT_FLAG_BITEXACT)) |
3735 | avio_printf(pb, "<meta name=\"creator\" content=\"%s\" />\n", |
3736 | LIBAVFORMAT_IDENT); |
3737 | avio_printf(pb, "</head>\n"); |
3738 | avio_printf(pb, "<body>\n"); |
3739 | avio_printf(pb, "<switch>\n"); |
3740 | |
3741 | mov_setup_track_ids(mov, s); |
3742 | |
3743 | for (i = 0; i < mov->nb_streams; i++) { |
3744 | MOVTrack *track = &mov->tracks[i]; |
3745 | const char *type; |
3746 | int track_id = track->track_id; |
3747 | char track_name_buf[32] = { 0 }; |
3748 | |
3749 | AVStream *st = track->st; |
3750 | AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0); |
3751 | |
3752 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { |
3753 | type = "video"; |
3754 | } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { |
3755 | type = "audio"; |
3756 | } else { |
3757 | continue; |
3758 | } |
3759 | |
3760 | props = (AVCPBProperties*)av_stream_get_side_data(track->st, AV_PKT_DATA_CPB_PROPERTIES, NULL); |
3761 | |
3762 | if (track->par->bit_rate) { |
3763 | manifest_bit_rate = track->par->bit_rate; |
3764 | } else if (props) { |
3765 | manifest_bit_rate = props->max_bitrate; |
3766 | } |
3767 | |
3768 | avio_printf(pb, "<%s systemBitrate=\"%"PRId64"\">\n", type, |
3769 | manifest_bit_rate); |
3770 | param_write_int(pb, "systemBitrate", manifest_bit_rate); |
3771 | param_write_int(pb, "trackID", track_id); |
3772 | param_write_string(pb, "systemLanguage", lang ? lang->value : "und"); |
3773 | |
3774 | /* Build track name piece by piece: */ |
3775 | /* 1. track type */ |
3776 | av_strlcat(track_name_buf, type, sizeof(track_name_buf)); |
3777 | /* 2. track language, if available */ |
3778 | if (lang) |
3779 | av_strlcatf(track_name_buf, sizeof(track_name_buf), |
3780 | "_%s", lang->value); |
3781 | /* 3. special type suffix */ |
3782 | /* "_cc" = closed captions, "_ad" = audio_description */ |
3783 | if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) |
3784 | av_strlcat(track_name_buf, "_cc", sizeof(track_name_buf)); |
3785 | else if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED) |
3786 | av_strlcat(track_name_buf, "_ad", sizeof(track_name_buf)); |
3787 | |
3788 | param_write_string(pb, "trackName", track_name_buf); |
3789 | |
3790 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { |
3791 | if (track->par->codec_id == AV_CODEC_ID_H264) { |
3792 | uint8_t *ptr; |
3793 | int size = track->par->extradata_size; |
3794 | if (!ff_avc_write_annexb_extradata(track->par->extradata, &ptr, |
3795 | &size)) { |
3796 | param_write_hex(pb, "CodecPrivateData", |
3797 | ptr ? ptr : track->par->extradata, |
3798 | size); |
3799 | av_free(ptr); |
3800 | } |
3801 | param_write_string(pb, "FourCC", "H264"); |
3802 | } else if (track->par->codec_id == AV_CODEC_ID_VC1) { |
3803 | param_write_string(pb, "FourCC", "WVC1"); |
3804 | param_write_hex(pb, "CodecPrivateData", track->par->extradata, |
3805 | track->par->extradata_size); |
3806 | } |
3807 | param_write_int(pb, "MaxWidth", track->par->width); |
3808 | param_write_int(pb, "MaxHeight", track->par->height); |
3809 | param_write_int(pb, "DisplayWidth", track->par->width); |
3810 | param_write_int(pb, "DisplayHeight", track->par->height); |
3811 | } else { |
3812 | if (track->par->codec_id == AV_CODEC_ID_AAC) { |
3813 | switch (track->par->profile) |
3814 | { |
3815 | case FF_PROFILE_AAC_HE_V2: |
3816 | param_write_string(pb, "FourCC", "AACP"); |
3817 | break; |
3818 | case FF_PROFILE_AAC_HE: |
3819 | param_write_string(pb, "FourCC", "AACH"); |
3820 | break; |
3821 | default: |
3822 | param_write_string(pb, "FourCC", "AACL"); |
3823 | } |
3824 | } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) { |
3825 | param_write_string(pb, "FourCC", "WMAP"); |
3826 | } |
3827 | param_write_hex(pb, "CodecPrivateData", track->par->extradata, |
3828 | track->par->extradata_size); |
3829 | param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags, |
3830 | track->par->codec_id)); |
3831 | param_write_int(pb, "Channels", track->par->channels); |
3832 | param_write_int(pb, "SamplingRate", track->par->sample_rate); |
3833 | param_write_int(pb, "BitsPerSample", 16); |
3834 | param_write_int(pb, "PacketSize", track->par->block_align ? |
3835 | track->par->block_align : 4); |
3836 | } |
3837 | avio_printf(pb, "</%s>\n", type); |
3838 | } |
3839 | avio_printf(pb, "</switch>\n"); |
3840 | avio_printf(pb, "</body>\n"); |
3841 | avio_printf(pb, "</smil>\n"); |
3842 | |
3843 | return update_size(pb, pos); |
3844 | } |
3845 | |
3846 | static int mov_write_mfhd_tag(AVIOContext *pb, MOVMuxContext *mov) |
3847 | { |
3848 | avio_wb32(pb, 16); |
3849 | ffio_wfourcc(pb, "mfhd"); |
3850 | avio_wb32(pb, 0); |
3851 | avio_wb32(pb, mov->fragments); |
3852 | return 0; |
3853 | } |
3854 | |
3855 | static uint32_t get_sample_flags(MOVTrack *track, MOVIentry *entry) |
3856 | { |
3857 | return entry->flags & MOV_SYNC_SAMPLE ? MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO : |
3858 | (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC); |
3859 | } |
3860 | |
3861 | static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov, |
3862 | MOVTrack *track, int64_t moof_offset) |
3863 | { |
3864 | int64_t pos = avio_tell(pb); |
3865 | uint32_t flags = MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION | |
3866 | MOV_TFHD_BASE_DATA_OFFSET; |
3867 | if (!track->entry) { |
3868 | flags |= MOV_TFHD_DURATION_IS_EMPTY; |
3869 | } else { |
3870 | flags |= MOV_TFHD_DEFAULT_FLAGS; |
3871 | } |
3872 | if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET) |
3873 | flags &= ~MOV_TFHD_BASE_DATA_OFFSET; |
3874 | if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) { |
3875 | flags &= ~MOV_TFHD_BASE_DATA_OFFSET; |
3876 | flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF; |
3877 | } |
3878 | |
3879 | /* Don't set a default sample size, the silverlight player refuses |
3880 | * to play files with that set. Don't set a default sample duration, |
3881 | * WMP freaks out if it is set. Don't set a base data offset, PIFF |
3882 | * file format says it MUST NOT be set. */ |
3883 | if (track->mode == MODE_ISM) |
3884 | flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION | |
3885 | MOV_TFHD_BASE_DATA_OFFSET); |
3886 | |
3887 | avio_wb32(pb, 0); /* size placeholder */ |
3888 | ffio_wfourcc(pb, "tfhd"); |
3889 | avio_w8(pb, 0); /* version */ |
3890 | avio_wb24(pb, flags); |
3891 | |
3892 | avio_wb32(pb, track->track_id); /* track-id */ |
3893 | if (flags & MOV_TFHD_BASE_DATA_OFFSET) |
3894 | avio_wb64(pb, moof_offset); |
3895 | if (flags & MOV_TFHD_DEFAULT_DURATION) { |
3896 | track->default_duration = get_cluster_duration(track, 0); |
3897 | avio_wb32(pb, track->default_duration); |
3898 | } |
3899 | if (flags & MOV_TFHD_DEFAULT_SIZE) { |
3900 | track->default_size = track->entry ? track->cluster[0].size : 1; |
3901 | avio_wb32(pb, track->default_size); |
3902 | } else |
3903 | track->default_size = -1; |
3904 | |
3905 | if (flags & MOV_TFHD_DEFAULT_FLAGS) { |
3906 | /* Set the default flags based on the second sample, if available. |
3907 | * If the first sample is different, that can be signaled via a separate field. */ |
3908 | if (track->entry > 1) |
3909 | track->default_sample_flags = get_sample_flags(track, &track->cluster[1]); |
3910 | else |
3911 | track->default_sample_flags = |
3912 | track->par->codec_type == AVMEDIA_TYPE_VIDEO ? |
3913 | (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) : |
3914 | MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO; |
3915 | avio_wb32(pb, track->default_sample_flags); |
3916 | } |
3917 | |
3918 | return update_size(pb, pos); |
3919 | } |
3920 | |
3921 | static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov, |
3922 | MOVTrack *track, int moof_size, |
3923 | int first, int end) |
3924 | { |
3925 | int64_t pos = avio_tell(pb); |
3926 | uint32_t flags = MOV_TRUN_DATA_OFFSET; |
3927 | int i; |
3928 | |
3929 | for (i = first; i < end; i++) { |
3930 | if (get_cluster_duration(track, i) != track->default_duration) |
3931 | flags |= MOV_TRUN_SAMPLE_DURATION; |
3932 | if (track->cluster[i].size != track->default_size) |
3933 | flags |= MOV_TRUN_SAMPLE_SIZE; |
3934 | if (i > first && get_sample_flags(track, &track->cluster[i]) != track->default_sample_flags) |
3935 | flags |= MOV_TRUN_SAMPLE_FLAGS; |
3936 | } |
3937 | if (!(flags & MOV_TRUN_SAMPLE_FLAGS) && track->entry > 0 && |
3938 | get_sample_flags(track, &track->cluster[0]) != track->default_sample_flags) |
3939 | flags |= MOV_TRUN_FIRST_SAMPLE_FLAGS; |
3940 | if (track->flags & MOV_TRACK_CTTS) |
3941 | flags |= MOV_TRUN_SAMPLE_CTS; |
3942 | |
3943 | avio_wb32(pb, 0); /* size placeholder */ |
3944 | ffio_wfourcc(pb, "trun"); |
3945 | avio_w8(pb, 0); /* version */ |
3946 | avio_wb24(pb, flags); |
3947 | |
3948 | avio_wb32(pb, end - first); /* sample count */ |
3949 | if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET && |
3950 | !(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) && |
3951 | !mov->first_trun) |
3952 | avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */ |
3953 | else |
3954 | avio_wb32(pb, moof_size + 8 + track->data_offset + |
3955 | track->cluster[first].pos); /* data offset */ |
3956 | if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) |
3957 | avio_wb32(pb, get_sample_flags(track, &track->cluster[first])); |
3958 | |
3959 | for (i = first; i < end; i++) { |
3960 | if (flags & MOV_TRUN_SAMPLE_DURATION) |
3961 | avio_wb32(pb, get_cluster_duration(track, i)); |
3962 | if (flags & MOV_TRUN_SAMPLE_SIZE) |
3963 | avio_wb32(pb, track->cluster[i].size); |
3964 | if (flags & MOV_TRUN_SAMPLE_FLAGS) |
3965 | avio_wb32(pb, get_sample_flags(track, &track->cluster[i])); |
3966 | if (flags & MOV_TRUN_SAMPLE_CTS) |
3967 | avio_wb32(pb, track->cluster[i].cts); |
3968 | } |
3969 | |
3970 | mov->first_trun = 0; |
3971 | return update_size(pb, pos); |
3972 | } |
3973 | |
3974 | static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track) |
3975 | { |
3976 | int64_t pos = avio_tell(pb); |
3977 | static const uint8_t uuid[] = { |
3978 | 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6, |
3979 | 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2 |
3980 | }; |
3981 | |
3982 | avio_wb32(pb, 0); /* size placeholder */ |
3983 | ffio_wfourcc(pb, "uuid"); |
3984 | avio_write(pb, uuid, sizeof(uuid)); |
3985 | avio_w8(pb, 1); |
3986 | avio_wb24(pb, 0); |
3987 | avio_wb64(pb, track->start_dts + track->frag_start + |
3988 | track->cluster[0].cts); |
3989 | avio_wb64(pb, track->end_pts - |
3990 | (track->cluster[0].dts + track->cluster[0].cts)); |
3991 | |
3992 | return update_size(pb, pos); |
3993 | } |
3994 | |
3995 | static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov, |
3996 | MOVTrack *track, int entry) |
3997 | { |
3998 | int n = track->nb_frag_info - 1 - entry, i; |
3999 | int size = 8 + 16 + 4 + 1 + 16*n; |
4000 | static const uint8_t uuid[] = { |
4001 | 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95, |
4002 | 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f |
4003 | }; |
4004 | |
4005 | if (entry < 0) |
4006 | return 0; |
4007 | |
4008 | avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET); |
4009 | avio_wb32(pb, size); |
4010 | ffio_wfourcc(pb, "uuid"); |
4011 | avio_write(pb, uuid, sizeof(uuid)); |
4012 | avio_w8(pb, 1); |
4013 | avio_wb24(pb, 0); |
4014 | avio_w8(pb, n); |
4015 | for (i = 0; i < n; i++) { |
4016 | int index = entry + 1 + i; |
4017 | avio_wb64(pb, track->frag_info[index].time); |
4018 | avio_wb64(pb, track->frag_info[index].duration); |
4019 | } |
4020 | if (n < mov->ism_lookahead) { |
4021 | int free_size = 16 * (mov->ism_lookahead - n); |
4022 | avio_wb32(pb, free_size); |
4023 | ffio_wfourcc(pb, "free"); |
4024 | ffio_fill(pb, 0, free_size - 8); |
4025 | } |
4026 | |
4027 | return 0; |
4028 | } |
4029 | |
4030 | static int mov_write_tfrf_tags(AVIOContext *pb, MOVMuxContext *mov, |
4031 | MOVTrack *track) |
4032 | { |
4033 | int64_t pos = avio_tell(pb); |
4034 | int i; |
4035 | for (i = 0; i < mov->ism_lookahead; i++) { |
4036 | /* Update the tfrf tag for the last ism_lookahead fragments, |
4037 | * nb_frag_info - 1 is the next fragment to be written. */ |
4038 | mov_write_tfrf_tag(pb, mov, track, track->nb_frag_info - 2 - i); |
4039 | } |
4040 | avio_seek(pb, pos, SEEK_SET); |
4041 | return 0; |
4042 | } |
4043 | |
4044 | static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks, |
4045 | int size) |
4046 | { |
4047 | int i; |
4048 | for (i = 0; i < mov->nb_streams; i++) { |
4049 | MOVTrack *track = &mov->tracks[i]; |
4050 | MOVFragmentInfo *info; |
4051 | if ((tracks >= 0 && i != tracks) || !track->entry) |
4052 | continue; |
4053 | track->nb_frag_info++; |
4054 | if (track->nb_frag_info >= track->frag_info_capacity) { |
4055 | unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT; |
4056 | if (av_reallocp_array(&track->frag_info, |
4057 | new_capacity, |
4058 | sizeof(*track->frag_info))) |
4059 | return AVERROR(ENOMEM); |
4060 | track->frag_info_capacity = new_capacity; |
4061 | } |
4062 | info = &track->frag_info[track->nb_frag_info - 1]; |
4063 | info->offset = avio_tell(pb); |
4064 | info->size = size; |
4065 | // Try to recreate the original pts for the first packet |
4066 | // from the fields we have stored |
4067 | info->time = track->start_dts + track->frag_start + |
4068 | track->cluster[0].cts; |
4069 | info->duration = track->end_pts - |
4070 | (track->cluster[0].dts + track->cluster[0].cts); |
4071 | // If the pts is less than zero, we will have trimmed |
4072 | // away parts of the media track using an edit list, |
4073 | // and the corresponding start presentation time is zero. |
4074 | if (info->time < 0) { |
4075 | info->duration += info->time; |
4076 | info->time = 0; |
4077 | } |
4078 | info->tfrf_offset = 0; |
4079 | mov_write_tfrf_tags(pb, mov, track); |
4080 | } |
4081 | return 0; |
4082 | } |
4083 | |
4084 | static void mov_prune_frag_info(MOVMuxContext *mov, int tracks, int max) |
4085 | { |
4086 | int i; |
4087 | for (i = 0; i < mov->nb_streams; i++) { |
4088 | MOVTrack *track = &mov->tracks[i]; |
4089 | if ((tracks >= 0 && i != tracks) || !track->entry) |
4090 | continue; |
4091 | if (track->nb_frag_info > max) { |
4092 | memmove(track->frag_info, track->frag_info + (track->nb_frag_info - max), max * sizeof(*track->frag_info)); |
4093 | track->nb_frag_info = max; |
4094 | } |
4095 | } |
4096 | } |
4097 | |
4098 | static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track) |
4099 | { |
4100 | int64_t pos = avio_tell(pb); |
4101 | |
4102 | avio_wb32(pb, 0); /* size */ |
4103 | ffio_wfourcc(pb, "tfdt"); |
4104 | avio_w8(pb, 1); /* version */ |
4105 | avio_wb24(pb, 0); |
4106 | avio_wb64(pb, track->frag_start); |
4107 | return update_size(pb, pos); |
4108 | } |
4109 | |
4110 | static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov, |
4111 | MOVTrack *track, int64_t moof_offset, |
4112 | int moof_size) |
4113 | { |
4114 | int64_t pos = avio_tell(pb); |
4115 | int i, start = 0; |
4116 | avio_wb32(pb, 0); /* size placeholder */ |
4117 | ffio_wfourcc(pb, "traf"); |
4118 | |
4119 | mov_write_tfhd_tag(pb, mov, track, moof_offset); |
4120 | if (mov->mode != MODE_ISM) |
4121 | mov_write_tfdt_tag(pb, track); |
4122 | for (i = 1; i < track->entry; i++) { |
4123 | if (track->cluster[i].pos != track->cluster[i - 1].pos + track->cluster[i - 1].size) { |
4124 | mov_write_trun_tag(pb, mov, track, moof_size, start, i); |
4125 | start = i; |
4126 | } |
4127 | } |
4128 | mov_write_trun_tag(pb, mov, track, moof_size, start, track->entry); |
4129 | if (mov->mode == MODE_ISM) { |
4130 | mov_write_tfxd_tag(pb, track); |
4131 | |
4132 | if (mov->ism_lookahead) { |
4133 | int i, size = 16 + 4 + 1 + 16 * mov->ism_lookahead; |
4134 | |
4135 | if (track->nb_frag_info > 0) { |
4136 | MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1]; |
4137 | if (!info->tfrf_offset) |
4138 | info->tfrf_offset = avio_tell(pb); |
4139 | } |
4140 | avio_wb32(pb, 8 + size); |
4141 | ffio_wfourcc(pb, "free"); |
4142 | for (i = 0; i < size; i++) |
4143 | avio_w8(pb, 0); |
4144 | } |
4145 | } |
4146 | |
4147 | return update_size(pb, pos); |
4148 | } |
4149 | |
4150 | static int mov_write_moof_tag_internal(AVIOContext *pb, MOVMuxContext *mov, |
4151 | int tracks, int moof_size) |
4152 | { |
4153 | int64_t pos = avio_tell(pb); |
4154 | int i; |
4155 | |
4156 | avio_wb32(pb, 0); /* size placeholder */ |
4157 | ffio_wfourcc(pb, "moof"); |
4158 | mov->first_trun = 1; |
4159 | |
4160 | mov_write_mfhd_tag(pb, mov); |
4161 | for (i = 0; i < mov->nb_streams; i++) { |
4162 | MOVTrack *track = &mov->tracks[i]; |
4163 | if (tracks >= 0 && i != tracks) |
4164 | continue; |
4165 | if (!track->entry) |
4166 | continue; |
4167 | mov_write_traf_tag(pb, mov, track, pos, moof_size); |
4168 | } |
4169 | |
4170 | return update_size(pb, pos); |
4171 | } |
4172 | |
4173 | static int mov_write_sidx_tag(AVIOContext *pb, |
4174 | MOVTrack *track, int ref_size, int total_sidx_size) |
4175 | { |
4176 | int64_t pos = avio_tell(pb), offset_pos, end_pos; |
4177 | int64_t presentation_time, duration, offset; |
4178 | int starts_with_SAP, i, entries; |
4179 | |
4180 | if (track->entry) { |
4181 | entries = 1; |
4182 | presentation_time = track->start_dts + track->frag_start + |
4183 | track->cluster[0].cts; |
4184 | duration = track->end_pts - |
4185 | (track->cluster[0].dts + track->cluster[0].cts); |
4186 | starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE; |
4187 | |
4188 | // pts<0 should be cut away using edts |
4189 | if (presentation_time < 0) { |
4190 | duration += presentation_time; |
4191 | presentation_time = 0; |
4192 | } |
4193 | } else { |
4194 | entries = track->nb_frag_info; |
4195 | if (entries <= 0) |
4196 | return 0; |
4197 | presentation_time = track->frag_info[0].time; |
4198 | } |
4199 | |
4200 | avio_wb32(pb, 0); /* size */ |
4201 | ffio_wfourcc(pb, "sidx"); |
4202 | avio_w8(pb, 1); /* version */ |
4203 | avio_wb24(pb, 0); |
4204 | avio_wb32(pb, track->track_id); /* reference_ID */ |
4205 | avio_wb32(pb, track->timescale); /* timescale */ |
4206 | avio_wb64(pb, presentation_time); /* earliest_presentation_time */ |
4207 | offset_pos = avio_tell(pb); |
4208 | avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */ |
4209 | avio_wb16(pb, 0); /* reserved */ |
4210 | |
4211 | avio_wb16(pb, entries); /* reference_count */ |
4212 | for (i = 0; i < entries; i++) { |
4213 | if (!track->entry) { |
4214 | if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) { |
4215 | av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n"); |
4216 | } |
4217 | duration = track->frag_info[i].duration; |
4218 | ref_size = track->frag_info[i].size; |
4219 | starts_with_SAP = 1; |
4220 | } |
4221 | avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */ |
4222 | avio_wb32(pb, duration); /* subsegment_duration */ |
4223 | avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */ |
4224 | } |
4225 | |
4226 | end_pos = avio_tell(pb); |
4227 | offset = pos + total_sidx_size - end_pos; |
4228 | avio_seek(pb, offset_pos, SEEK_SET); |
4229 | avio_wb64(pb, offset); |
4230 | avio_seek(pb, end_pos, SEEK_SET); |
4231 | return update_size(pb, pos); |
4232 | } |
4233 | |
4234 | static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov, |
4235 | int tracks, int ref_size) |
4236 | { |
4237 | int i, round, ret; |
4238 | AVIOContext *avio_buf; |
4239 | int total_size = 0; |
4240 | for (round = 0; round < 2; round++) { |
4241 | // First run one round to calculate the total size of all |
4242 | // sidx atoms. |
4243 | // This would be much simpler if we'd only write one sidx |
4244 | // atom, for the first track in the moof. |
4245 | if (round == 0) { |
4246 | if ((ret = ffio_open_null_buf(&avio_buf)) < 0) |
4247 | return ret; |
4248 | } else { |
4249 | avio_buf = pb; |
4250 | } |
4251 | for (i = 0; i < mov->nb_streams; i++) { |
4252 | MOVTrack *track = &mov->tracks[i]; |
4253 | if (tracks >= 0 && i != tracks) |
4254 | continue; |
4255 | // When writing a sidx for the full file, entry is 0, but |
4256 | // we want to include all tracks. ref_size is 0 in this case, |
4257 | // since we read it from frag_info instead. |
4258 | if (!track->entry && ref_size > 0) |
4259 | continue; |
4260 | total_size -= mov_write_sidx_tag(avio_buf, track, ref_size, |
4261 | total_size); |
4262 | } |
4263 | if (round == 0) |
4264 | total_size = ffio_close_null_buf(avio_buf); |
4265 | } |
4266 | return 0; |
4267 | } |
4268 | |
4269 | static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks, |
4270 | int64_t mdat_size) |
4271 | { |
4272 | AVIOContext *avio_buf; |
4273 | int ret, moof_size; |
4274 | |
4275 | if ((ret = ffio_open_null_buf(&avio_buf)) < 0) |
4276 | return ret; |
4277 | mov_write_moof_tag_internal(avio_buf, mov, tracks, 0); |
4278 | moof_size = ffio_close_null_buf(avio_buf); |
4279 | |
4280 | if (mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)) |
4281 | mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size); |
4282 | |
4283 | if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX || |
4284 | !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) || |
4285 | mov->ism_lookahead) { |
4286 | if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0) |
4287 | return ret; |
4288 | if (!(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) && |
4289 | mov->flags & FF_MOV_FLAG_SKIP_TRAILER) { |
4290 | mov_prune_frag_info(mov, tracks, mov->ism_lookahead + 1); |
4291 | } |
4292 | } |
4293 | |
4294 | return mov_write_moof_tag_internal(pb, mov, tracks, moof_size); |
4295 | } |
4296 | |
4297 | static int mov_write_tfra_tag(AVIOContext *pb, MOVTrack *track) |
4298 | { |
4299 | int64_t pos = avio_tell(pb); |
4300 | int i; |
4301 | |
4302 | avio_wb32(pb, 0); /* size placeholder */ |
4303 | ffio_wfourcc(pb, "tfra"); |
4304 | avio_w8(pb, 1); /* version */ |
4305 | avio_wb24(pb, 0); |
4306 | |
4307 | avio_wb32(pb, track->track_id); |
4308 | avio_wb32(pb, 0); /* length of traf/trun/sample num */ |
4309 | avio_wb32(pb, track->nb_frag_info); |
4310 | for (i = 0; i < track->nb_frag_info; i++) { |
4311 | avio_wb64(pb, track->frag_info[i].time); |
4312 | avio_wb64(pb, track->frag_info[i].offset + track->data_offset); |
4313 | avio_w8(pb, 1); /* traf number */ |
4314 | avio_w8(pb, 1); /* trun number */ |
4315 | avio_w8(pb, 1); /* sample number */ |
4316 | } |
4317 | |
4318 | return update_size(pb, pos); |
4319 | } |
4320 | |
4321 | static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov) |
4322 | { |
4323 | int64_t pos = avio_tell(pb); |
4324 | int i; |
4325 | |
4326 | avio_wb32(pb, 0); /* size placeholder */ |
4327 | ffio_wfourcc(pb, "mfra"); |
4328 | /* An empty mfra atom is enough to indicate to the publishing point that |
4329 | * the stream has ended. */ |
4330 | if (mov->flags & FF_MOV_FLAG_ISML) |
4331 | return update_size(pb, pos); |
4332 | |
4333 | for (i = 0; i < mov->nb_streams; i++) { |
4334 | MOVTrack *track = &mov->tracks[i]; |
4335 | if (track->nb_frag_info) |
4336 | mov_write_tfra_tag(pb, track); |
4337 | } |
4338 | |
4339 | avio_wb32(pb, 16); |
4340 | ffio_wfourcc(pb, "mfro"); |
4341 | avio_wb32(pb, 0); /* version + flags */ |
4342 | avio_wb32(pb, avio_tell(pb) + 4 - pos); |
4343 | |
4344 | return update_size(pb, pos); |
4345 | } |
4346 | |
4347 | static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov) |
4348 | { |
4349 | avio_wb32(pb, 8); // placeholder for extended size field (64 bit) |
4350 | ffio_wfourcc(pb, mov->mode == MODE_MOV ? "wide" : "free"); |
4351 | |
4352 | mov->mdat_pos = avio_tell(pb); |
4353 | avio_wb32(pb, 0); /* size placeholder*/ |
4354 | ffio_wfourcc(pb, "mdat"); |
4355 | return 0; |
4356 | } |
4357 | |
4358 | /* TODO: This needs to be more general */ |
4359 | static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) |
4360 | { |
4361 | MOVMuxContext *mov = s->priv_data; |
4362 | int64_t pos = avio_tell(pb); |
4363 | int has_h264 = 0, has_video = 0; |
4364 | int minor = 0x200; |
4365 | int i; |
4366 | |
4367 | for (i = 0; i < s->nb_streams; i++) { |
4368 | AVStream *st = s->streams[i]; |
4369 | if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) |
4370 | has_video = 1; |
4371 | if (st->codecpar->codec_id == AV_CODEC_ID_H264) |
4372 | has_h264 = 1; |
4373 | } |
4374 | |
4375 | avio_wb32(pb, 0); /* size */ |
4376 | ffio_wfourcc(pb, "ftyp"); |
4377 | |
4378 | if (mov->major_brand && strlen(mov->major_brand) >= 4) |
4379 | ffio_wfourcc(pb, mov->major_brand); |
4380 | else if (mov->mode == MODE_3GP) { |
4381 | ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4"); |
4382 | minor = has_h264 ? 0x100 : 0x200; |
4383 | } else if (mov->mode & MODE_3G2) { |
4384 | ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a"); |
4385 | minor = has_h264 ? 0x20000 : 0x10000; |
4386 | } else if (mov->mode == MODE_PSP) |
4387 | ffio_wfourcc(pb, "MSNV"); |
4388 | else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) |
4389 | ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof |
4390 | else if (mov->mode == MODE_MP4) |
4391 | ffio_wfourcc(pb, "isom"); |
4392 | else if (mov->mode == MODE_IPOD) |
4393 | ffio_wfourcc(pb, has_video ? "M4V ":"M4A "); |
4394 | else if (mov->mode == MODE_ISM) |
4395 | ffio_wfourcc(pb, "isml"); |
4396 | else if (mov->mode == MODE_F4V) |
4397 | ffio_wfourcc(pb, "f4v "); |
4398 | else |
4399 | ffio_wfourcc(pb, "qt "); |
4400 | |
4401 | avio_wb32(pb, minor); |
4402 | |
4403 | if (mov->mode == MODE_MOV) |
4404 | ffio_wfourcc(pb, "qt "); |
4405 | else if (mov->mode == MODE_ISM) { |
4406 | ffio_wfourcc(pb, "piff"); |
4407 | } else if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) { |
4408 | ffio_wfourcc(pb, "isom"); |
4409 | ffio_wfourcc(pb, "iso2"); |
4410 | if (has_h264) |
4411 | ffio_wfourcc(pb, "avc1"); |
4412 | } |
4413 | |
4414 | // We add tfdt atoms when fragmenting, signal this with the iso6 compatible |
4415 | // brand. This is compatible with users that don't understand tfdt. |
4416 | if (mov->flags & FF_MOV_FLAG_FRAGMENT && mov->mode != MODE_ISM) |
4417 | ffio_wfourcc(pb, "iso6"); |
4418 | |
4419 | if (mov->mode == MODE_3GP) |
4420 | ffio_wfourcc(pb, has_h264 ? "3gp6":"3gp4"); |
4421 | else if (mov->mode & MODE_3G2) |
4422 | ffio_wfourcc(pb, has_h264 ? "3g2b":"3g2a"); |
4423 | else if (mov->mode == MODE_PSP) |
4424 | ffio_wfourcc(pb, "MSNV"); |
4425 | else if (mov->mode == MODE_MP4) |
4426 | ffio_wfourcc(pb, "mp41"); |
4427 | |
4428 | if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) |
4429 | ffio_wfourcc(pb, "dash"); |
4430 | |
4431 | return update_size(pb, pos); |
4432 | } |
4433 | |
4434 | static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s) |
4435 | { |
4436 | AVStream *video_st = s->streams[0]; |
4437 | AVCodecParameters *video_par = s->streams[0]->codecpar; |
4438 | AVCodecParameters *audio_par = s->streams[1]->codecpar; |
4439 | int audio_rate = audio_par->sample_rate; |
4440 | int64_t frame_rate = video_st->avg_frame_rate.den ? |
4441 | (video_st->avg_frame_rate.num * 0x10000LL) / video_st->avg_frame_rate.den : |
4442 | 0; |
4443 | int audio_kbitrate = audio_par->bit_rate / 1000; |
4444 | int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate); |
4445 | |
4446 | if (frame_rate < 0 || frame_rate > INT32_MAX) { |
4447 | av_log(s, AV_LOG_ERROR, "Frame rate %f outside supported range\n", frame_rate / (double)0x10000); |
4448 | return AVERROR(EINVAL); |
4449 | } |
4450 | |
4451 | avio_wb32(pb, 0x94); /* size */ |
4452 | ffio_wfourcc(pb, "uuid"); |
4453 | ffio_wfourcc(pb, "PROF"); |
4454 | |
4455 | avio_wb32(pb, 0x21d24fce); /* 96 bit UUID */ |
4456 | avio_wb32(pb, 0xbb88695c); |
4457 | avio_wb32(pb, 0xfac9c740); |
4458 | |
4459 | avio_wb32(pb, 0x0); /* ? */ |
4460 | avio_wb32(pb, 0x3); /* 3 sections ? */ |
4461 | |
4462 | avio_wb32(pb, 0x14); /* size */ |
4463 | ffio_wfourcc(pb, "FPRF"); |
4464 | avio_wb32(pb, 0x0); /* ? */ |
4465 | avio_wb32(pb, 0x0); /* ? */ |
4466 | avio_wb32(pb, 0x0); /* ? */ |
4467 | |
4468 | avio_wb32(pb, 0x2c); /* size */ |
4469 | ffio_wfourcc(pb, "APRF"); /* audio */ |
4470 | avio_wb32(pb, 0x0); |
4471 | avio_wb32(pb, 0x2); /* TrackID */ |
4472 | ffio_wfourcc(pb, "mp4a"); |
4473 | avio_wb32(pb, 0x20f); |
4474 | avio_wb32(pb, 0x0); |
4475 | avio_wb32(pb, audio_kbitrate); |
4476 | avio_wb32(pb, audio_kbitrate); |
4477 | avio_wb32(pb, audio_rate); |
4478 | avio_wb32(pb, audio_par->channels); |
4479 | |
4480 | avio_wb32(pb, 0x34); /* size */ |
4481 | ffio_wfourcc(pb, "VPRF"); /* video */ |
4482 | avio_wb32(pb, 0x0); |
4483 | avio_wb32(pb, 0x1); /* TrackID */ |
4484 | if (video_par->codec_id == AV_CODEC_ID_H264) { |
4485 | ffio_wfourcc(pb, "avc1"); |
4486 | avio_wb16(pb, 0x014D); |
4487 | avio_wb16(pb, 0x0015); |
4488 | } else { |
4489 | ffio_wfourcc(pb, "mp4v"); |
4490 | avio_wb16(pb, 0x0000); |
4491 | avio_wb16(pb, 0x0103); |
4492 | } |
4493 | avio_wb32(pb, 0x0); |
4494 | avio_wb32(pb, video_kbitrate); |
4495 | avio_wb32(pb, video_kbitrate); |
4496 | avio_wb32(pb, frame_rate); |
4497 | avio_wb32(pb, frame_rate); |
4498 | avio_wb16(pb, video_par->width); |
4499 | avio_wb16(pb, video_par->height); |
4500 | avio_wb32(pb, 0x010001); /* ? */ |
4501 | |
4502 | return 0; |
4503 | } |
4504 | |
4505 | static int mov_write_identification(AVIOContext *pb, AVFormatContext *s) |
4506 | { |
4507 | MOVMuxContext *mov = s->priv_data; |
4508 | int i; |
4509 | |
4510 | mov_write_ftyp_tag(pb,s); |
4511 | if (mov->mode == MODE_PSP) { |
4512 | int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0; |
4513 | for (i = 0; i < s->nb_streams; i++) { |
4514 | AVStream *st = s->streams[i]; |
4515 | if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) |
4516 | video_streams_nb++; |
4517 | else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) |
4518 | audio_streams_nb++; |
4519 | else |
4520 | other_streams_nb++; |
4521 | } |
4522 | |
4523 | if (video_streams_nb != 1 || audio_streams_nb != 1 || other_streams_nb) { |
4524 | av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n"); |
4525 | return AVERROR(EINVAL); |
4526 | } |
4527 | return mov_write_uuidprof_tag(pb, s); |
4528 | } |
4529 | return 0; |
4530 | } |
4531 | |
4532 | static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags) |
4533 | { |
4534 | uint32_t c = -1; |
4535 | int i, closed_gop = 0; |
4536 | |
4537 | for (i = 0; i < pkt->size - 4; i++) { |
4538 | c = (c << 8) + pkt->data[i]; |
4539 | if (c == 0x1b8) { // gop |
4540 | closed_gop = pkt->data[i + 4] >> 6 & 0x01; |
4541 | } else if (c == 0x100) { // pic |
4542 | int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6); |
4543 | if (!temp_ref || closed_gop) // I picture is not reordered |
4544 | *flags = MOV_SYNC_SAMPLE; |
4545 | else |
4546 | *flags = MOV_PARTIAL_SYNC_SAMPLE; |
4547 | break; |
4548 | } |
4549 | } |
4550 | return 0; |
4551 | } |
4552 | |
4553 | static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk) |
4554 | { |
4555 | const uint8_t *start, *next, *end = pkt->data + pkt->size; |
4556 | int seq = 0, entry = 0; |
4557 | int key = pkt->flags & AV_PKT_FLAG_KEY; |
4558 | start = find_next_marker(pkt->data, end); |
4559 | for (next = start; next < end; start = next) { |
4560 | next = find_next_marker(start + 4, end); |
4561 | switch (AV_RB32(start)) { |
4562 | case VC1_CODE_SEQHDR: |
4563 | seq = 1; |
4564 | break; |
4565 | case VC1_CODE_ENTRYPOINT: |
4566 | entry = 1; |
4567 | break; |
4568 | case VC1_CODE_SLICE: |
4569 | trk->vc1_info.slices = 1; |
4570 | break; |
4571 | } |
4572 | } |
4573 | if (!trk->entry && trk->vc1_info.first_packet_seen) |
4574 | trk->vc1_info.first_frag_written = 1; |
4575 | if (!trk->entry && !trk->vc1_info.first_frag_written) { |
4576 | /* First packet in first fragment */ |
4577 | trk->vc1_info.first_packet_seq = seq; |
4578 | trk->vc1_info.first_packet_entry = entry; |
4579 | trk->vc1_info.first_packet_seen = 1; |
4580 | } else if ((seq && !trk->vc1_info.packet_seq) || |
4581 | (entry && !trk->vc1_info.packet_entry)) { |
4582 | int i; |
4583 | for (i = 0; i < trk->entry; i++) |
4584 | trk->cluster[i].flags &= ~MOV_SYNC_SAMPLE; |
4585 | trk->has_keyframes = 0; |
4586 | if (seq) |
4587 | trk->vc1_info.packet_seq = 1; |
4588 | if (entry) |
4589 | trk->vc1_info.packet_entry = 1; |
4590 | if (!trk->vc1_info.first_frag_written) { |
4591 | /* First fragment */ |
4592 | if ((!seq || trk->vc1_info.first_packet_seq) && |
4593 | (!entry || trk->vc1_info.first_packet_entry)) { |
4594 | /* First packet had the same headers as this one, readd the |
4595 | * sync sample flag. */ |
4596 | trk->cluster[0].flags |= MOV_SYNC_SAMPLE; |
4597 | trk->has_keyframes = 1; |
4598 | } |
4599 | } |
4600 | } |
4601 | if (trk->vc1_info.packet_seq && trk->vc1_info.packet_entry) |
4602 | key = seq && entry; |
4603 | else if (trk->vc1_info.packet_seq) |
4604 | key = seq; |
4605 | else if (trk->vc1_info.packet_entry) |
4606 | key = entry; |
4607 | if (key) { |
4608 | trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE; |
4609 | trk->has_keyframes++; |
4610 | } |
4611 | } |
4612 | |
4613 | static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track) |
4614 | { |
4615 | MOVMuxContext *mov = s->priv_data; |
4616 | int ret, buf_size; |
4617 | uint8_t *buf; |
4618 | int i, offset; |
4619 | |
4620 | if (!track->mdat_buf) |
4621 | return 0; |
4622 | if (!mov->mdat_buf) { |
4623 | if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0) |
4624 | return ret; |
4625 | } |
4626 | buf_size = avio_close_dyn_buf(track->mdat_buf, &buf); |
4627 | track->mdat_buf = NULL; |
4628 | |
4629 | offset = avio_tell(mov->mdat_buf); |
4630 | avio_write(mov->mdat_buf, buf, buf_size); |
4631 | av_free(buf); |
4632 | |
4633 | for (i = track->entries_flushed; i < track->entry; i++) |
4634 | track->cluster[i].pos += offset; |
4635 | track->entries_flushed = track->entry; |
4636 | return 0; |
4637 | } |
4638 | |
4639 | static int mov_flush_fragment(AVFormatContext *s, int force) |
4640 | { |
4641 | MOVMuxContext *mov = s->priv_data; |
4642 | int i, first_track = -1; |
4643 | int64_t mdat_size = 0; |
4644 | int ret; |
4645 | int has_video = 0, starts_with_key = 0, first_video_track = 1; |
4646 | |
4647 | if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) |
4648 | return 0; |
4649 | |
4650 | // Try to fill in the duration of the last packet in each stream |
4651 | // from queued packets in the interleave queues. If the flushing |
4652 | // of fragments was triggered automatically by an AVPacket, we |
4653 | // already have reliable info for the end of that track, but other |
4654 | // tracks may need to be filled in. |
4655 | for (i = 0; i < s->nb_streams; i++) { |
4656 | MOVTrack *track = &mov->tracks[i]; |
4657 | if (!track->end_reliable) { |
4658 | AVPacket pkt; |
4659 | if (!ff_interleaved_peek(s, i, &pkt, 1)) { |
4660 | track->track_duration = pkt.dts - track->start_dts; |
4661 | if (pkt.pts != AV_NOPTS_VALUE) |
4662 | track->end_pts = pkt.pts; |
4663 | else |
4664 | track->end_pts = pkt.dts; |
4665 | } |
4666 | } |
4667 | } |
4668 | |
4669 | for (i = 0; i < mov->nb_streams; i++) { |
4670 | MOVTrack *track = &mov->tracks[i]; |
4671 | if (track->entry <= 1) |
4672 | continue; |
4673 | // Sample durations are calculated as the diff of dts values, |
4674 | // but for the last sample in a fragment, we don't know the dts |
4675 | // of the first sample in the next fragment, so we have to rely |
4676 | // on what was set as duration in the AVPacket. Not all callers |
4677 | // set this though, so we might want to replace it with an |
4678 | // estimate if it currently is zero. |
4679 | if (get_cluster_duration(track, track->entry - 1) != 0) |
4680 | continue; |
4681 | // Use the duration (i.e. dts diff) of the second last sample for |
4682 | // the last one. This is a wild guess (and fatal if it turns out |
4683 | // to be too long), but probably the best we can do - having a zero |
4684 | // duration is bad as well. |
4685 | track->track_duration += get_cluster_duration(track, track->entry - 2); |
4686 | track->end_pts += get_cluster_duration(track, track->entry - 2); |
4687 | if (!mov->missing_duration_warned) { |
4688 | av_log(s, AV_LOG_WARNING, |
4689 | "Estimating the duration of the last packet in a " |
4690 | "fragment, consider setting the duration field in " |
4691 | "AVPacket instead.\n"); |
4692 | mov->missing_duration_warned = 1; |
4693 | } |
4694 | } |
4695 | |
4696 | if (!mov->moov_written) { |
4697 | int64_t pos = avio_tell(s->pb); |
4698 | uint8_t *buf; |
4699 | int buf_size, moov_size; |
4700 | |
4701 | for (i = 0; i < mov->nb_streams; i++) |
4702 | if (!mov->tracks[i].entry) |
4703 | break; |
4704 | /* Don't write the initial moov unless all tracks have data */ |
4705 | if (i < mov->nb_streams && !force) |
4706 | return 0; |
4707 | |
4708 | moov_size = get_moov_size(s); |
4709 | for (i = 0; i < mov->nb_streams; i++) |
4710 | mov->tracks[i].data_offset = pos + moov_size + 8; |
4711 | |
4712 | avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER); |
4713 | if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) |
4714 | mov_write_identification(s->pb, s); |
4715 | if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0) |
4716 | return ret; |
4717 | |
4718 | if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) { |
4719 | if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) |
4720 | mov->reserved_header_pos = avio_tell(s->pb); |
4721 | avio_flush(s->pb); |
4722 | mov->moov_written = 1; |
4723 | return 0; |
4724 | } |
4725 | |
4726 | buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf); |
4727 | mov->mdat_buf = NULL; |
4728 | avio_wb32(s->pb, buf_size + 8); |
4729 | ffio_wfourcc(s->pb, "mdat"); |
4730 | avio_write(s->pb, buf, buf_size); |
4731 | av_free(buf); |
4732 | |
4733 | if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) |
4734 | mov->reserved_header_pos = avio_tell(s->pb); |
4735 | |
4736 | mov->moov_written = 1; |
4737 | mov->mdat_size = 0; |
4738 | for (i = 0; i < mov->nb_streams; i++) { |
4739 | if (mov->tracks[i].entry) |
4740 | mov->tracks[i].frag_start += mov->tracks[i].start_dts + |
4741 | mov->tracks[i].track_duration - |
4742 | mov->tracks[i].cluster[0].dts; |
4743 | mov->tracks[i].entry = 0; |
4744 | mov->tracks[i].end_reliable = 0; |
4745 | } |
4746 | avio_flush(s->pb); |
4747 | return 0; |
4748 | } |
4749 | |
4750 | if (mov->frag_interleave) { |
4751 | for (i = 0; i < mov->nb_streams; i++) { |
4752 | MOVTrack *track = &mov->tracks[i]; |
4753 | int ret; |
4754 | if ((ret = mov_flush_fragment_interleaving(s, track)) < 0) |
4755 | return ret; |
4756 | } |
4757 | |
4758 | if (!mov->mdat_buf) |
4759 | return 0; |
4760 | mdat_size = avio_tell(mov->mdat_buf); |
4761 | } |
4762 | |
4763 | for (i = 0; i < mov->nb_streams; i++) { |
4764 | MOVTrack *track = &mov->tracks[i]; |
4765 | if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF || mov->frag_interleave) |
4766 | track->data_offset = 0; |
4767 | else |
4768 | track->data_offset = mdat_size; |
4769 | if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { |
4770 | has_video = 1; |
4771 | if (first_video_track) { |
4772 | if (track->entry) |
4773 | starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE; |
4774 | first_video_track = 0; |
4775 | } |
4776 | } |
4777 | if (!track->entry) |
4778 | continue; |
4779 | if (track->mdat_buf) |
4780 | mdat_size += avio_tell(track->mdat_buf); |
4781 | if (first_track < 0) |
4782 | first_track = i; |
4783 | } |
4784 | |
4785 | if (!mdat_size) |
4786 | return 0; |
4787 | |
4788 | avio_write_marker(s->pb, |
4789 | av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale), |
4790 | (has_video ? starts_with_key : mov->tracks[first_track].cluster[0].flags & MOV_SYNC_SAMPLE) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT); |
4791 | |
4792 | for (i = 0; i < mov->nb_streams; i++) { |
4793 | MOVTrack *track = &mov->tracks[i]; |
4794 | int buf_size, write_moof = 1, moof_tracks = -1; |
4795 | uint8_t *buf; |
4796 | int64_t duration = 0; |
4797 | |
4798 | if (track->entry) |
4799 | duration = track->start_dts + track->track_duration - |
4800 | track->cluster[0].dts; |
4801 | if (mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) { |
4802 | if (!track->mdat_buf) |
4803 | continue; |
4804 | mdat_size = avio_tell(track->mdat_buf); |
4805 | moof_tracks = i; |
4806 | } else { |
4807 | write_moof = i == first_track; |
4808 | } |
4809 | |
4810 | if (write_moof) { |
4811 | avio_flush(s->pb); |
4812 | |
4813 | mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size); |
4814 | mov->fragments++; |
4815 | |
4816 | avio_wb32(s->pb, mdat_size + 8); |
4817 | ffio_wfourcc(s->pb, "mdat"); |
4818 | } |
4819 | |
4820 | if (track->entry) |
4821 | track->frag_start += duration; |
4822 | track->entry = 0; |
4823 | track->entries_flushed = 0; |
4824 | track->end_reliable = 0; |
4825 | if (!mov->frag_interleave) { |
4826 | if (!track->mdat_buf) |
4827 | continue; |
4828 | buf_size = avio_close_dyn_buf(track->mdat_buf, &buf); |
4829 | track->mdat_buf = NULL; |
4830 | } else { |
4831 | if (!mov->mdat_buf) |
4832 | continue; |
4833 | buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf); |
4834 | mov->mdat_buf = NULL; |
4835 | } |
4836 | |
4837 | avio_write(s->pb, buf, buf_size); |
4838 | av_free(buf); |
4839 | } |
4840 | |
4841 | mov->mdat_size = 0; |
4842 | |
4843 | avio_flush(s->pb); |
4844 | return 0; |
4845 | } |
4846 | |
4847 | static int mov_auto_flush_fragment(AVFormatContext *s, int force) |
4848 | { |
4849 | MOVMuxContext *mov = s->priv_data; |
4850 | int had_moov = mov->moov_written; |
4851 | int ret = mov_flush_fragment(s, force); |
4852 | if (ret < 0) |
4853 | return ret; |
4854 | // If using delay_moov, the first flush only wrote the moov, |
4855 | // not the actual moof+mdat pair, thus flush once again. |
4856 | if (!had_moov && mov->flags & FF_MOV_FLAG_DELAY_MOOV) |
4857 | ret = mov_flush_fragment(s, force); |
4858 | return ret; |
4859 | } |
4860 | |
4861 | static int check_pkt(AVFormatContext *s, AVPacket *pkt) |
4862 | { |
4863 | MOVMuxContext *mov = s->priv_data; |
4864 | MOVTrack *trk = &mov->tracks[pkt->stream_index]; |
4865 | int64_t ref; |
4866 | uint64_t duration; |
4867 | |
4868 | if (trk->entry) { |
4869 | ref = trk->cluster[trk->entry - 1].dts; |
4870 | } else if ( trk->start_dts != AV_NOPTS_VALUE |
4871 | && !trk->frag_discont) { |
4872 | ref = trk->start_dts + trk->track_duration; |
4873 | } else |
4874 | ref = pkt->dts; // Skip tests for the first packet |
4875 | |
4876 | duration = pkt->dts - ref; |
4877 | if (pkt->dts < ref || duration >= INT_MAX) { |
4878 | av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" / timestamp: %"PRId64" is out of range for mov/mp4 format\n", |
4879 | duration, pkt->dts |
4880 | ); |
4881 | |
4882 | pkt->dts = ref + 1; |
4883 | pkt->pts = AV_NOPTS_VALUE; |
4884 | } |
4885 | |
4886 | if (pkt->duration < 0 || pkt->duration > INT_MAX) { |
4887 | av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" is invalid\n", pkt->duration); |
4888 | return AVERROR(EINVAL); |
4889 | } |
4890 | return 0; |
4891 | } |
4892 | |
4893 | int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) |
4894 | { |
4895 | MOVMuxContext *mov = s->priv_data; |
4896 | AVIOContext *pb = s->pb; |
4897 | MOVTrack *trk = &mov->tracks[pkt->stream_index]; |
4898 | AVCodecParameters *par = trk->par; |
4899 | unsigned int samples_in_chunk = 0; |
4900 | int size = pkt->size, ret = 0; |
4901 | uint8_t *reformatted_data = NULL; |
4902 | |
4903 | ret = check_pkt(s, pkt); |
4904 | if (ret < 0) |
4905 | return ret; |
4906 | |
4907 | if (mov->flags & FF_MOV_FLAG_FRAGMENT) { |
4908 | int ret; |
4909 | if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) { |
4910 | if (mov->frag_interleave && mov->fragments > 0) { |
4911 | if (trk->entry - trk->entries_flushed >= mov->frag_interleave) { |
4912 | if ((ret = mov_flush_fragment_interleaving(s, trk)) < 0) |
4913 | return ret; |
4914 | } |
4915 | } |
4916 | |
4917 | if (!trk->mdat_buf) { |
4918 | if ((ret = avio_open_dyn_buf(&trk->mdat_buf)) < 0) |
4919 | return ret; |
4920 | } |
4921 | pb = trk->mdat_buf; |
4922 | } else { |
4923 | if (!mov->mdat_buf) { |
4924 | if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0) |
4925 | return ret; |
4926 | } |
4927 | pb = mov->mdat_buf; |
4928 | } |
4929 | } |
4930 | |
4931 | if (par->codec_id == AV_CODEC_ID_AMR_NB) { |
4932 | /* We must find out how many AMR blocks there are in one packet */ |
4933 | static const uint16_t packed_size[16] = |
4934 | {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1}; |
4935 | int len = 0; |
4936 | |
4937 | while (len < size && samples_in_chunk < 100) { |
4938 | len += packed_size[(pkt->data[len] >> 3) & 0x0F]; |
4939 | samples_in_chunk++; |
4940 | } |
4941 | if (samples_in_chunk > 1) { |
4942 | av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n"); |
4943 | return -1; |
4944 | } |
4945 | } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS || |
4946 | par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { |
4947 | samples_in_chunk = trk->par->frame_size; |
4948 | } else if (trk->sample_size) |
4949 | samples_in_chunk = size / trk->sample_size; |
4950 | else |
4951 | samples_in_chunk = 1; |
4952 | |
4953 | /* copy extradata if it exists */ |
4954 | if (trk->vos_len == 0 && par->extradata_size > 0 && |
4955 | !TAG_IS_AVCI(trk->tag) && |
4956 | (par->codec_id != AV_CODEC_ID_DNXHD)) { |
4957 | trk->vos_len = par->extradata_size; |
4958 | trk->vos_data = av_malloc(trk->vos_len); |
4959 | if (!trk->vos_data) { |
4960 | ret = AVERROR(ENOMEM); |
4961 | goto err; |
4962 | } |
4963 | memcpy(trk->vos_data, par->extradata, trk->vos_len); |
4964 | } |
4965 | |
4966 | if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && |
4967 | (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { |
4968 | if (!s->streams[pkt->stream_index]->nb_frames) { |
4969 | av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: " |
4970 | "use the audio bitstream filter 'aac_adtstoasc' to fix it " |
4971 | "('-bsf:a aac_adtstoasc' option with ffmpeg)\n"); |
4972 | return -1; |
4973 | } |
4974 | av_log(s, AV_LOG_WARNING, "aac bitstream error\n"); |
4975 | } |
4976 | if (par->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1 && !TAG_IS_AVCI(trk->tag)) { |
4977 | /* from x264 or from bytestream H.264 */ |
4978 | /* NAL reformatting needed */ |
4979 | if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) { |
4980 | ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data, |
4981 | &size); |
4982 | avio_write(pb, reformatted_data, size); |
4983 | } else { |
4984 | if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { |
4985 | size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size); |
4986 | if (size < 0) { |
4987 | ret = size; |
4988 | goto err; |
4989 | } |
4990 | } else { |
4991 | size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size); |
4992 | } |
4993 | } |
4994 | } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 && |
4995 | (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) { |
4996 | /* extradata is Annex B, assume the bitstream is too and convert it */ |
4997 | if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) { |
4998 | ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data, &size, 0, NULL); |
4999 | avio_write(pb, reformatted_data, size); |
5000 | } else { |
5001 | size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL); |
5002 | } |
5003 | #if CONFIG_AC3_PARSER |
5004 | } else if (par->codec_id == AV_CODEC_ID_EAC3) { |
5005 | size = handle_eac3(mov, pkt, trk); |
5006 | if (size < 0) |
5007 | return size; |
5008 | else if (!size) |
5009 | goto end; |
5010 | avio_write(pb, pkt->data, size); |
5011 | #endif |
5012 | } else { |
5013 | if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { |
5014 | if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) { |
5015 | int nal_size_length = (par->extradata[4] & 0x3) + 1; |
5016 | ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size); |
5017 | } else { |
5018 | ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size); |
5019 | } |
5020 | |
5021 | if (ret) { |
5022 | goto err; |
5023 | } |
5024 | } else { |
5025 | avio_write(pb, pkt->data, size); |
5026 | } |
5027 | } |
5028 | |
5029 | if ((par->codec_id == AV_CODEC_ID_DNXHD || |
5030 | par->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) { |
5031 | /* copy frame to create needed atoms */ |
5032 | trk->vos_len = size; |
5033 | trk->vos_data = av_malloc(size); |
5034 | if (!trk->vos_data) { |
5035 | ret = AVERROR(ENOMEM); |
5036 | goto err; |
5037 | } |
5038 | memcpy(trk->vos_data, pkt->data, size); |
5039 | } |
5040 | |
5041 | if (trk->entry >= trk->cluster_capacity) { |
5042 | unsigned new_capacity = 2 * (trk->entry + MOV_INDEX_CLUSTER_SIZE); |
5043 | if (av_reallocp_array(&trk->cluster, new_capacity, |
5044 | sizeof(*trk->cluster))) { |
5045 | ret = AVERROR(ENOMEM); |
5046 | goto err; |
5047 | } |
5048 | trk->cluster_capacity = new_capacity; |
5049 | } |
5050 | |
5051 | trk->cluster[trk->entry].pos = avio_tell(pb) - size; |
5052 | trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk; |
5053 | trk->cluster[trk->entry].chunkNum = 0; |
5054 | trk->cluster[trk->entry].size = size; |
5055 | trk->cluster[trk->entry].entries = samples_in_chunk; |
5056 | trk->cluster[trk->entry].dts = pkt->dts; |
5057 | if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) { |
5058 | if (!trk->frag_discont) { |
5059 | /* First packet of a new fragment. We already wrote the duration |
5060 | * of the last packet of the previous fragment based on track_duration, |
5061 | * which might not exactly match our dts. Therefore adjust the dts |
5062 | * of this packet to be what the previous packets duration implies. */ |
5063 | trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration; |
5064 | /* We also may have written the pts and the corresponding duration |
5065 | * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with |
5066 | * the next fragment. This means the cts of the first sample must |
5067 | * be the same in all fragments, unless end_pts was updated by |
5068 | * the packet causing the fragment to be written. */ |
5069 | if ((mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)) || |
5070 | mov->mode == MODE_ISM) |
5071 | pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts; |
5072 | } else { |
5073 | /* New fragment, but discontinuous from previous fragments. |
5074 | * Pretend the duration sum of the earlier fragments is |
5075 | * pkt->dts - trk->start_dts. */ |
5076 | trk->frag_start = pkt->dts - trk->start_dts; |
5077 | trk->end_pts = AV_NOPTS_VALUE; |
5078 | trk->frag_discont = 0; |
5079 | } |
5080 | } |
5081 | |
5082 | if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist && |
5083 | s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) { |
5084 | /* Not using edit lists and shifting the first track to start from zero. |
5085 | * If the other streams start from a later timestamp, we won't be able |
5086 | * to signal the difference in starting time without an edit list. |
5087 | * Thus move the timestamp for this first sample to 0, increasing |
5088 | * its duration instead. */ |
5089 | trk->cluster[trk->entry].dts = trk->start_dts = 0; |
5090 | } |
5091 | if (trk->start_dts == AV_NOPTS_VALUE) { |
5092 | trk->start_dts = pkt->dts; |
5093 | if (trk->frag_discont) { |
5094 | if (mov->use_editlist) { |
5095 | /* Pretend the whole stream started at pts=0, with earlier fragments |
5096 | * already written. If the stream started at pts=0, the duration sum |
5097 | * of earlier fragments would have been pkt->pts. */ |
5098 | trk->frag_start = pkt->pts; |
5099 | trk->start_dts = pkt->dts - pkt->pts; |
5100 | } else { |
5101 | /* Pretend the whole stream started at dts=0, with earlier fragments |
5102 | * already written, with a duration summing up to pkt->dts. */ |
5103 | trk->frag_start = pkt->dts; |
5104 | trk->start_dts = 0; |
5105 | } |
5106 | trk->frag_discont = 0; |
5107 | } else if (pkt->dts && mov->moov_written) |
5108 | av_log(s, AV_LOG_WARNING, |
5109 | "Track %d starts with a nonzero dts %"PRId64", while the moov " |
5110 | "already has been written. Set the delay_moov flag to handle " |
5111 | "this case.\n", |
5112 | pkt->stream_index, pkt->dts); |
5113 | } |
5114 | trk->track_duration = pkt->dts - trk->start_dts + pkt->duration; |
5115 | trk->last_sample_is_subtitle_end = 0; |
5116 | |
5117 | if (pkt->pts == AV_NOPTS_VALUE) { |
5118 | av_log(s, AV_LOG_WARNING, "pts has no value\n"); |
5119 | pkt->pts = pkt->dts; |
5120 | } |
5121 | if (pkt->dts != pkt->pts) |
5122 | trk->flags |= MOV_TRACK_CTTS; |
5123 | trk->cluster[trk->entry].cts = pkt->pts - pkt->dts; |
5124 | trk->cluster[trk->entry].flags = 0; |
5125 | if (trk->start_cts == AV_NOPTS_VALUE) |
5126 | trk->start_cts = pkt->pts - pkt->dts; |
5127 | if (trk->end_pts == AV_NOPTS_VALUE) |
5128 | trk->end_pts = trk->cluster[trk->entry].dts + |
5129 | trk->cluster[trk->entry].cts + pkt->duration; |
5130 | else |
5131 | trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts + |
5132 | trk->cluster[trk->entry].cts + |
5133 | pkt->duration); |
5134 | |
5135 | if (par->codec_id == AV_CODEC_ID_VC1) { |
5136 | mov_parse_vc1_frame(pkt, trk); |
5137 | } else if (pkt->flags & AV_PKT_FLAG_KEY) { |
5138 | if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO && |
5139 | trk->entry > 0) { // force sync sample for the first key frame |
5140 | mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags); |
5141 | if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE) |
5142 | trk->flags |= MOV_TRACK_STPS; |
5143 | } else { |
5144 | trk->cluster[trk->entry].flags = MOV_SYNC_SAMPLE; |
5145 | } |
5146 | if (trk->cluster[trk->entry].flags & MOV_SYNC_SAMPLE) |
5147 | trk->has_keyframes++; |
5148 | } |
5149 | trk->entry++; |
5150 | trk->sample_count += samples_in_chunk; |
5151 | mov->mdat_size += size; |
5152 | |
5153 | if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) |
5154 | ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry, |
5155 | reformatted_data, size); |
5156 | |
5157 | end: |
5158 | err: |
5159 | |
5160 | av_free(reformatted_data); |
5161 | return ret; |
5162 | } |
5163 | |
5164 | static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) |
5165 | { |
5166 | MOVMuxContext *mov = s->priv_data; |
5167 | MOVTrack *trk = &mov->tracks[pkt->stream_index]; |
5168 | AVCodecParameters *par = trk->par; |
5169 | int64_t frag_duration = 0; |
5170 | int size = pkt->size; |
5171 | |
5172 | int ret = check_pkt(s, pkt); |
5173 | if (ret < 0) |
5174 | return ret; |
5175 | |
5176 | if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) { |
5177 | int i; |
5178 | for (i = 0; i < s->nb_streams; i++) |
5179 | mov->tracks[i].frag_discont = 1; |
5180 | mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT; |
5181 | } |
5182 | |
5183 | if (!pkt->size) { |
5184 | if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) { |
5185 | trk->start_dts = pkt->dts; |
5186 | if (pkt->pts != AV_NOPTS_VALUE) |
5187 | trk->start_cts = pkt->pts - pkt->dts; |
5188 | else |
5189 | trk->start_cts = 0; |
5190 | } |
5191 | |
5192 | if (trk->par->codec_id == AV_CODEC_ID_MP4ALS || |
5193 | trk->par->codec_id == AV_CODEC_ID_FLAC) { |
5194 | int side_size = 0; |
5195 | uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); |
5196 | if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { |
5197 | void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE); |
5198 | if (!newextra) |
5199 | return AVERROR(ENOMEM); |
5200 | av_free(par->extradata); |
5201 | par->extradata = newextra; |
5202 | memcpy(par->extradata, side, side_size); |
5203 | par->extradata_size = side_size; |
5204 | mov->need_rewrite_extradata = 1; |
5205 | } |
5206 | } |
5207 | |
5208 | return 0; /* Discard 0 sized packets */ |
5209 | } |
5210 | |
5211 | if (trk->entry && pkt->stream_index < s->nb_streams) |
5212 | frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts, |
5213 | s->streams[pkt->stream_index]->time_base, |
5214 | AV_TIME_BASE_Q); |
5215 | if ((mov->max_fragment_duration && |
5216 | frag_duration >= mov->max_fragment_duration) || |
5217 | (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) || |
5218 | (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME && |
5219 | par->codec_type == AVMEDIA_TYPE_VIDEO && |
5220 | trk->entry && pkt->flags & AV_PKT_FLAG_KEY)) { |
5221 | if (frag_duration >= mov->min_fragment_duration) { |
5222 | // Set the duration of this track to line up with the next |
5223 | // sample in this track. This avoids relying on AVPacket |
5224 | // duration, but only helps for this particular track, not |
5225 | // for the other ones that are flushed at the same time. |
5226 | trk->track_duration = pkt->dts - trk->start_dts; |
5227 | if (pkt->pts != AV_NOPTS_VALUE) |
5228 | trk->end_pts = pkt->pts; |
5229 | else |
5230 | trk->end_pts = pkt->dts; |
5231 | trk->end_reliable = 1; |
5232 | mov_auto_flush_fragment(s, 0); |
5233 | } |
5234 | } |
5235 | |
5236 | return ff_mov_write_packet(s, pkt); |
5237 | } |
5238 | |
5239 | static int mov_write_subtitle_end_packet(AVFormatContext *s, |
5240 | int stream_index, |
5241 | int64_t dts) { |
5242 | AVPacket end; |
5243 | uint8_t data[2] = {0}; |
5244 | int ret; |
5245 | |
5246 | av_init_packet(&end); |
5247 | end.size = sizeof(data); |
5248 | end.data = data; |
5249 | end.pts = dts; |
5250 | end.dts = dts; |
5251 | end.duration = 0; |
5252 | end.stream_index = stream_index; |
5253 | |
5254 | ret = mov_write_single_packet(s, &end); |
5255 | av_packet_unref(&end); |
5256 | |
5257 | return ret; |
5258 | } |
5259 | |
5260 | static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) |
5261 | { |
5262 | if (!pkt) { |
5263 | mov_flush_fragment(s, 1); |
5264 | return 1; |
5265 | } else { |
5266 | int i; |
5267 | MOVMuxContext *mov = s->priv_data; |
5268 | MOVTrack *trk = &mov->tracks[pkt->stream_index]; |
5269 | |
5270 | if (!pkt->size) |
5271 | return mov_write_single_packet(s, pkt); /* Passthrough. */ |
5272 | |
5273 | /* |
5274 | * Subtitles require special handling. |
5275 | * |
5276 | * 1) For full complaince, every track must have a sample at |
5277 | * dts == 0, which is rarely true for subtitles. So, as soon |
5278 | * as we see any packet with dts > 0, write an empty subtitle |
5279 | * at dts == 0 for any subtitle track with no samples in it. |
5280 | * |
5281 | * 2) For each subtitle track, check if the current packet's |
5282 | * dts is past the duration of the last subtitle sample. If |
5283 | * so, we now need to write an end sample for that subtitle. |
5284 | * |
5285 | * This must be done conditionally to allow for subtitles that |
5286 | * immediately replace each other, in which case an end sample |
5287 | * is not needed, and is, in fact, actively harmful. |
5288 | * |
5289 | * 3) See mov_write_trailer for how the final end sample is |
5290 | * handled. |
5291 | */ |
5292 | for (i = 0; i < mov->nb_streams; i++) { |
5293 | MOVTrack *trk = &mov->tracks[i]; |
5294 | int ret; |
5295 | |
5296 | if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT && |
5297 | trk->track_duration < pkt->dts && |
5298 | (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) { |
5299 | ret = mov_write_subtitle_end_packet(s, i, trk->track_duration); |
5300 | if (ret < 0) return ret; |
5301 | trk->last_sample_is_subtitle_end = 1; |
5302 | } |
5303 | } |
5304 | |
5305 | if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) { |
5306 | AVPacket *opkt = pkt; |
5307 | int reshuffle_ret, ret; |
5308 | if (trk->is_unaligned_qt_rgb) { |
5309 | int64_t bpc = trk->par->bits_per_coded_sample != 15 ? trk->par->bits_per_coded_sample : 16; |
5310 | int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2; |
5311 | reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride); |
5312 | if (reshuffle_ret < 0) |
5313 | return reshuffle_ret; |
5314 | } else |
5315 | reshuffle_ret = 0; |
5316 | if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) { |
5317 | ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette); |
5318 | if (ret < 0) |
5319 | goto fail; |
5320 | if (ret) |
5321 | trk->pal_done++; |
5322 | } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO && |
5323 | (trk->par->format == AV_PIX_FMT_GRAY8 || |
5324 | trk->par->format == AV_PIX_FMT_MONOBLACK)) { |
5325 | for (i = 0; i < pkt->size; i++) |
5326 | pkt->data[i] = ~pkt->data[i]; |
5327 | } |
5328 | if (reshuffle_ret) { |
5329 | ret = mov_write_single_packet(s, pkt); |
5330 | fail: |
5331 | if (reshuffle_ret) |
5332 | av_packet_free(&pkt); |
5333 | return ret; |
5334 | } |
5335 | } |
5336 | |
5337 | return mov_write_single_packet(s, pkt); |
5338 | } |
5339 | } |
5340 | |
5341 | // QuickTime chapters involve an additional text track with the chapter names |
5342 | // as samples, and a tref pointing from the other tracks to the chapter one. |
5343 | static int mov_create_chapter_track(AVFormatContext *s, int tracknum) |
5344 | { |
5345 | AVIOContext *pb; |
5346 | |
5347 | MOVMuxContext *mov = s->priv_data; |
5348 | MOVTrack *track = &mov->tracks[tracknum]; |
5349 | AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY }; |
5350 | int i, len; |
5351 | |
5352 | track->mode = mov->mode; |
5353 | track->tag = MKTAG('t','e','x','t'); |
5354 | track->timescale = MOV_TIMESCALE; |
5355 | track->par = avcodec_parameters_alloc(); |
5356 | if (!track->par) |
5357 | return AVERROR(ENOMEM); |
5358 | track->par->codec_type = AVMEDIA_TYPE_SUBTITLE; |
5359 | #if 0 |
5360 | // These properties are required to make QT recognize the chapter track |
5361 | uint8_t chapter_properties[43] = { 0, 0, 0, 0, 0, 0, 0, 1, }; |
5362 | if (ff_alloc_extradata(track->par, sizeof(chapter_properties))) |
5363 | return AVERROR(ENOMEM); |
5364 | memcpy(track->par->extradata, chapter_properties, sizeof(chapter_properties)); |
5365 | #else |
5366 | if (avio_open_dyn_buf(&pb) >= 0) { |
5367 | int size; |
5368 | uint8_t *buf; |
5369 | |
5370 | /* Stub header (usually for Quicktime chapter track) */ |
5371 | // TextSampleEntry |
5372 | avio_wb32(pb, 0x01); // displayFlags |
5373 | avio_w8(pb, 0x00); // horizontal justification |
5374 | avio_w8(pb, 0x00); // vertical justification |
5375 | avio_w8(pb, 0x00); // bgColourRed |
5376 | avio_w8(pb, 0x00); // bgColourGreen |
5377 | avio_w8(pb, 0x00); // bgColourBlue |
5378 | avio_w8(pb, 0x00); // bgColourAlpha |
5379 | // BoxRecord |
5380 | avio_wb16(pb, 0x00); // defTextBoxTop |
5381 | avio_wb16(pb, 0x00); // defTextBoxLeft |
5382 | avio_wb16(pb, 0x00); // defTextBoxBottom |
5383 | avio_wb16(pb, 0x00); // defTextBoxRight |
5384 | // StyleRecord |
5385 | avio_wb16(pb, 0x00); // startChar |
5386 | avio_wb16(pb, 0x00); // endChar |
5387 | avio_wb16(pb, 0x01); // fontID |
5388 | avio_w8(pb, 0x00); // fontStyleFlags |
5389 | avio_w8(pb, 0x00); // fontSize |
5390 | avio_w8(pb, 0x00); // fgColourRed |
5391 | avio_w8(pb, 0x00); // fgColourGreen |
5392 | avio_w8(pb, 0x00); // fgColourBlue |
5393 | avio_w8(pb, 0x00); // fgColourAlpha |
5394 | // FontTableBox |
5395 | avio_wb32(pb, 0x0D); // box size |
5396 | ffio_wfourcc(pb, "ftab"); // box atom name |
5397 | avio_wb16(pb, 0x01); // entry count |
5398 | // FontRecord |
5399 | avio_wb16(pb, 0x01); // font ID |
5400 | avio_w8(pb, 0x00); // font name length |
5401 | |
5402 | if ((size = avio_close_dyn_buf(pb, &buf)) > 0) { |
5403 | track->par->extradata = buf; |
5404 | track->par->extradata_size = size; |
5405 | } else { |
5406 | av_freep(&buf); |
5407 | } |
5408 | } |
5409 | #endif |
5410 | |
5411 | for (i = 0; i < s->nb_chapters; i++) { |
5412 | AVChapter *c = s->chapters[i]; |
5413 | AVDictionaryEntry *t; |
5414 | |
5415 | int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE}); |
5416 | pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE}); |
5417 | pkt.duration = end - pkt.dts; |
5418 | |
5419 | if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { |
5420 | static const char encd[12] = { |
5421 | 0x00, 0x00, 0x00, 0x0C, |
5422 | 'e', 'n', 'c', 'd', |
5423 | 0x00, 0x00, 0x01, 0x00 }; |
5424 | len = strlen(t->value); |
5425 | pkt.size = len + 2 + 12; |
5426 | pkt.data = av_malloc(pkt.size); |
5427 | if (!pkt.data) |
5428 | return AVERROR(ENOMEM); |
5429 | AV_WB16(pkt.data, len); |
5430 | memcpy(pkt.data + 2, t->value, len); |
5431 | memcpy(pkt.data + len + 2, encd, sizeof(encd)); |
5432 | ff_mov_write_packet(s, &pkt); |
5433 | av_freep(&pkt.data); |
5434 | } |
5435 | } |
5436 | |
5437 | return 0; |
5438 | } |
5439 | |
5440 | |
5441 | static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, int src_index, const char *tcstr) |
5442 | { |
5443 | int ret; |
5444 | |
5445 | /* compute the frame number */ |
5446 | ret = av_timecode_init_from_string(tc, find_fps(s, s->streams[src_index]), tcstr, s); |
5447 | return ret; |
5448 | } |
5449 | |
5450 | static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc) |
5451 | { |
5452 | int ret; |
5453 | MOVMuxContext *mov = s->priv_data; |
5454 | MOVTrack *track = &mov->tracks[index]; |
5455 | AVStream *src_st = s->streams[src_index]; |
5456 | AVPacket pkt = {.stream_index = index, .flags = AV_PKT_FLAG_KEY, .size = 4}; |
5457 | AVRational rate = find_fps(s, src_st); |
5458 | |
5459 | /* tmcd track based on video stream */ |
5460 | track->mode = mov->mode; |
5461 | track->tag = MKTAG('t','m','c','d'); |
5462 | track->src_track = src_index; |
5463 | track->timescale = mov->tracks[src_index].timescale; |
5464 | if (tc.flags & AV_TIMECODE_FLAG_DROPFRAME) |
5465 | track->timecode_flags |= MOV_TIMECODE_FLAG_DROPFRAME; |
5466 | |
5467 | /* set st to src_st for metadata access*/ |
5468 | track->st = src_st; |
5469 | |
5470 | /* encode context: tmcd data stream */ |
5471 | track->par = avcodec_parameters_alloc(); |
5472 | if (!track->par) |
5473 | return AVERROR(ENOMEM); |
5474 | track->par->codec_type = AVMEDIA_TYPE_DATA; |
5475 | track->par->codec_tag = track->tag; |
5476 | track->st->avg_frame_rate = av_inv_q(rate); |
5477 | |
5478 | /* the tmcd track just contains one packet with the frame number */ |
5479 | pkt.data = av_malloc(pkt.size); |
5480 | if (!pkt.data) |
5481 | return AVERROR(ENOMEM); |
5482 | AV_WB32(pkt.data, tc.start); |
5483 | ret = ff_mov_write_packet(s, &pkt); |
5484 | av_free(pkt.data); |
5485 | return ret; |
5486 | } |
5487 | |
5488 | /* |
5489 | * st->disposition controls the "enabled" flag in the tkhd tag. |
5490 | * QuickTime will not play a track if it is not enabled. So make sure |
5491 | * that one track of each type (audio, video, subtitle) is enabled. |
5492 | * |
5493 | * Subtitles are special. For audio and video, setting "enabled" also |
5494 | * makes the track "default" (i.e. it is rendered when played). For |
5495 | * subtitles, an "enabled" subtitle is not rendered by default, but |
5496 | * if no subtitle is enabled, the subtitle menu in QuickTime will be |
5497 | * empty! |
5498 | */ |
5499 | static void enable_tracks(AVFormatContext *s) |
5500 | { |
5501 | MOVMuxContext *mov = s->priv_data; |
5502 | int i; |
5503 | int enabled[AVMEDIA_TYPE_NB]; |
5504 | int first[AVMEDIA_TYPE_NB]; |
5505 | |
5506 | for (i = 0; i < AVMEDIA_TYPE_NB; i++) { |
5507 | enabled[i] = 0; |
5508 | first[i] = -1; |
5509 | } |
5510 | |
5511 | for (i = 0; i < s->nb_streams; i++) { |
5512 | AVStream *st = s->streams[i]; |
5513 | |
5514 | if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN || |
5515 | st->codecpar->codec_type >= AVMEDIA_TYPE_NB) |
5516 | continue; |
5517 | |
5518 | if (first[st->codecpar->codec_type] < 0) |
5519 | first[st->codecpar->codec_type] = i; |
5520 | if (st->disposition & AV_DISPOSITION_DEFAULT) { |
5521 | mov->tracks[i].flags |= MOV_TRACK_ENABLED; |
5522 | enabled[st->codecpar->codec_type]++; |
5523 | } |
5524 | } |
5525 | |
5526 | for (i = 0; i < AVMEDIA_TYPE_NB; i++) { |
5527 | switch (i) { |
5528 | case AVMEDIA_TYPE_VIDEO: |
5529 | case AVMEDIA_TYPE_AUDIO: |
5530 | case AVMEDIA_TYPE_SUBTITLE: |
5531 | if (enabled[i] > 1) |
5532 | mov->per_stream_grouping = 1; |
5533 | if (!enabled[i] && first[i] >= 0) |
5534 | mov->tracks[first[i]].flags |= MOV_TRACK_ENABLED; |
5535 | break; |
5536 | } |
5537 | } |
5538 | } |
5539 | |
5540 | static void mov_free(AVFormatContext *s) |
5541 | { |
5542 | MOVMuxContext *mov = s->priv_data; |
5543 | int i; |
5544 | |
5545 | if (mov->chapter_track) { |
5546 | if (mov->tracks[mov->chapter_track].par) |
5547 | av_freep(&mov->tracks[mov->chapter_track].par->extradata); |
5548 | av_freep(&mov->tracks[mov->chapter_track].par); |
5549 | } |
5550 | |
5551 | for (i = 0; i < mov->nb_streams; i++) { |
5552 | if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) |
5553 | ff_mov_close_hinting(&mov->tracks[i]); |
5554 | else if (mov->tracks[i].tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) |
5555 | av_freep(&mov->tracks[i].par); |
5556 | av_freep(&mov->tracks[i].cluster); |
5557 | av_freep(&mov->tracks[i].frag_info); |
5558 | |
5559 | if (mov->tracks[i].vos_len) |
5560 | av_freep(&mov->tracks[i].vos_data); |
5561 | |
5562 | ff_mov_cenc_free(&mov->tracks[i].cenc); |
5563 | } |
5564 | |
5565 | av_freep(&mov->tracks); |
5566 | } |
5567 | |
5568 | static uint32_t rgb_to_yuv(uint32_t rgb) |
5569 | { |
5570 | uint8_t r, g, b; |
5571 | int y, cb, cr; |
5572 | |
5573 | r = (rgb >> 16) & 0xFF; |
5574 | g = (rgb >> 8) & 0xFF; |
5575 | b = (rgb ) & 0xFF; |
5576 | |
5577 | y = av_clip_uint8(( 16000 + 257 * r + 504 * g + 98 * b)/1000); |
5578 | cb = av_clip_uint8((128000 - 148 * r - 291 * g + 439 * b)/1000); |
5579 | cr = av_clip_uint8((128000 + 439 * r - 368 * g - 71 * b)/1000); |
5580 | |
5581 | return (y << 16) | (cr << 8) | cb; |
5582 | } |
5583 | |
5584 | static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, |
5585 | AVStream *st) |
5586 | { |
5587 | int i, width = 720, height = 480; |
5588 | int have_palette = 0, have_size = 0; |
5589 | uint32_t palette[16]; |
5590 | char *cur = st->codecpar->extradata; |
5591 | |
5592 | while (cur && *cur) { |
5593 | if (strncmp("palette:", cur, 8) == 0) { |
5594 | int i, count; |
5595 | count = sscanf(cur + 8, |
5596 | "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", " |
5597 | "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", " |
5598 | "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32", " |
5599 | "%06"PRIx32", %06"PRIx32", %06"PRIx32", %06"PRIx32"", |
5600 | &palette[ 0], &palette[ 1], &palette[ 2], &palette[ 3], |
5601 | &palette[ 4], &palette[ 5], &palette[ 6], &palette[ 7], |
5602 | &palette[ 8], &palette[ 9], &palette[10], &palette[11], |
5603 | &palette[12], &palette[13], &palette[14], &palette[15]); |
5604 | |
5605 | for (i = 0; i < count; i++) { |
5606 | palette[i] = rgb_to_yuv(palette[i]); |
5607 | } |
5608 | have_palette = 1; |
5609 | } else if (!strncmp("size:", cur, 5)) { |
5610 | sscanf(cur + 5, "%dx%d", &width, &height); |
5611 | have_size = 1; |
5612 | } |
5613 | if (have_palette && have_size) |
5614 | break; |
5615 | cur += strcspn(cur, "\n\r"); |
5616 | cur += strspn(cur, "\n\r"); |
5617 | } |
5618 | if (have_palette) { |
5619 | track->vos_data = av_malloc(16*4); |
5620 | if (!track->vos_data) |
5621 | return AVERROR(ENOMEM); |
5622 | for (i = 0; i < 16; i++) { |
5623 | AV_WB32(track->vos_data + i * 4, palette[i]); |
5624 | } |
5625 | track->vos_len = 16 * 4; |
5626 | } |
5627 | st->codecpar->width = width; |
5628 | st->codecpar->height = track->height = height; |
5629 | |
5630 | return 0; |
5631 | } |
5632 | |
5633 | static int mov_init(AVFormatContext *s) |
5634 | { |
5635 | MOVMuxContext *mov = s->priv_data; |
5636 | AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0); |
5637 | int i, ret; |
5638 | |
5639 | mov->fc = s; |
5640 | |
5641 | /* Default mode == MP4 */ |
5642 | mov->mode = MODE_MP4; |
5643 | |
5644 | if (s->oformat) { |
5645 | if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP; |
5646 | else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2; |
5647 | else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV; |
5648 | else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP; |
5649 | else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD; |
5650 | else if (!strcmp("ismv",s->oformat->name)) mov->mode = MODE_ISM; |
5651 | else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V; |
5652 | } |
5653 | |
5654 | if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) |
5655 | mov->flags |= FF_MOV_FLAG_EMPTY_MOOV; |
5656 | |
5657 | /* Set the FRAGMENT flag if any of the fragmentation methods are |
5658 | * enabled. */ |
5659 | if (mov->max_fragment_duration || mov->max_fragment_size || |
5660 | mov->flags & (FF_MOV_FLAG_EMPTY_MOOV | |
5661 | FF_MOV_FLAG_FRAG_KEYFRAME | |
5662 | FF_MOV_FLAG_FRAG_CUSTOM)) |
5663 | mov->flags |= FF_MOV_FLAG_FRAGMENT; |
5664 | |
5665 | /* Set other implicit flags immediately */ |
5666 | if (mov->mode == MODE_ISM) |
5667 | mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF | |
5668 | FF_MOV_FLAG_FRAGMENT; |
5669 | if (mov->flags & FF_MOV_FLAG_DASH) |
5670 | mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV | |
5671 | FF_MOV_FLAG_DEFAULT_BASE_MOOF; |
5672 | |
5673 | if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) { |
5674 | av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n"); |
5675 | s->flags &= ~AVFMT_FLAG_AUTO_BSF; |
5676 | } |
5677 | |
5678 | if (mov->flags & FF_MOV_FLAG_FASTSTART) { |
5679 | mov->reserved_moov_size = -1; |
5680 | } |
5681 | |
5682 | if (mov->use_editlist < 0) { |
5683 | mov->use_editlist = 1; |
5684 | if (mov->flags & FF_MOV_FLAG_FRAGMENT && |
5685 | !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { |
5686 | // If we can avoid needing an edit list by shifting the |
5687 | // tracks, prefer that over (trying to) write edit lists |
5688 | // in fragmented output. |
5689 | if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO || |
5690 | s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) |
5691 | mov->use_editlist = 0; |
5692 | } |
5693 | } |
5694 | if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && |
5695 | !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist) |
5696 | av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n"); |
5697 | |
5698 | if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO) |
5699 | s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO; |
5700 | |
5701 | /* Clear the omit_tfhd_offset flag if default_base_moof is set; |
5702 | * if the latter is set that's enough and omit_tfhd_offset doesn't |
5703 | * add anything extra on top of that. */ |
5704 | if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET && |
5705 | mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) |
5706 | mov->flags &= ~FF_MOV_FLAG_OMIT_TFHD_OFFSET; |
5707 | |
5708 | if (mov->frag_interleave && |
5709 | mov->flags & (FF_MOV_FLAG_OMIT_TFHD_OFFSET | FF_MOV_FLAG_SEPARATE_MOOF)) { |
5710 | av_log(s, AV_LOG_ERROR, |
5711 | "Sample interleaving in fragments is mutually exclusive with " |
5712 | "omit_tfhd_offset and separate_moof\n"); |
5713 | return AVERROR(EINVAL); |
5714 | } |
5715 | |
5716 | /* Non-seekable output is ok if using fragmentation. If ism_lookahead |
5717 | * is enabled, we don't support non-seekable output at all. */ |
5718 | if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && |
5719 | (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead)) { |
5720 | av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n"); |
5721 | return AVERROR(EINVAL); |
5722 | } |
5723 | |
5724 | mov->nb_streams = s->nb_streams; |
5725 | if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) |
5726 | mov->chapter_track = mov->nb_streams++; |
5727 | |
5728 | if (mov->flags & FF_MOV_FLAG_RTP_HINT) { |
5729 | /* Add hint tracks for each audio and video stream */ |
5730 | for (i = 0; i < s->nb_streams; i++) { |
5731 | AVStream *st = s->streams[i]; |
5732 | if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || |
5733 | st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
5734 | mov->nb_streams++; |
5735 | } |
5736 | } |
5737 | } |
5738 | |
5739 | if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4) |
5740 | || mov->write_tmcd == 1) { |
5741 | /* +1 tmcd track for each video stream with a timecode */ |
5742 | for (i = 0; i < s->nb_streams; i++) { |
5743 | AVStream *st = s->streams[i]; |
5744 | AVDictionaryEntry *t = global_tcr; |
5745 | if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && |
5746 | (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) { |
5747 | AVTimecode tc; |
5748 | ret = mov_check_timecode_track(s, &tc, i, t->value); |
5749 | if (ret >= 0) |
5750 | mov->nb_meta_tmcd++; |
5751 | } |
5752 | } |
5753 | |
5754 | /* check if there is already a tmcd track to remux */ |
5755 | if (mov->nb_meta_tmcd) { |
5756 | for (i = 0; i < s->nb_streams; i++) { |
5757 | AVStream *st = s->streams[i]; |
5758 | if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) { |
5759 | av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track " |
5760 | "so timecode metadata are now ignored\n"); |
5761 | mov->nb_meta_tmcd = 0; |
5762 | } |
5763 | } |
5764 | } |
5765 | |
5766 | mov->nb_streams += mov->nb_meta_tmcd; |
5767 | } |
5768 | |
5769 | // Reserve an extra stream for chapters for the case where chapters |
5770 | // are written in the trailer |
5771 | mov->tracks = av_mallocz_array((mov->nb_streams + 1), sizeof(*mov->tracks)); |
5772 | if (!mov->tracks) |
5773 | return AVERROR(ENOMEM); |
5774 | |
5775 | if (mov->encryption_scheme_str != NULL && strcmp(mov->encryption_scheme_str, "none") != 0) { |
5776 | if (strcmp(mov->encryption_scheme_str, "cenc-aes-ctr") == 0) { |
5777 | mov->encryption_scheme = MOV_ENC_CENC_AES_CTR; |
5778 | |
5779 | if (mov->encryption_key_len != AES_CTR_KEY_SIZE) { |
5780 | av_log(s, AV_LOG_ERROR, "Invalid encryption key len %d expected %d\n", |
5781 | mov->encryption_key_len, AES_CTR_KEY_SIZE); |
5782 | return AVERROR(EINVAL); |
5783 | } |
5784 | |
5785 | if (mov->encryption_kid_len != CENC_KID_SIZE) { |
5786 | av_log(s, AV_LOG_ERROR, "Invalid encryption kid len %d expected %d\n", |
5787 | mov->encryption_kid_len, CENC_KID_SIZE); |
5788 | return AVERROR(EINVAL); |
5789 | } |
5790 | } else { |
5791 | av_log(s, AV_LOG_ERROR, "unsupported encryption scheme %s\n", |
5792 | mov->encryption_scheme_str); |
5793 | return AVERROR(EINVAL); |
5794 | } |
5795 | } |
5796 | |
5797 | for (i = 0; i < s->nb_streams; i++) { |
5798 | AVStream *st= s->streams[i]; |
5799 | MOVTrack *track= &mov->tracks[i]; |
5800 | AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0); |
5801 | |
5802 | track->st = st; |
5803 | track->par = st->codecpar; |
5804 | track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV); |
5805 | if (track->language < 0) |
5806 | track->language = 0; |
5807 | track->mode = mov->mode; |
5808 | track->tag = mov_find_codec_tag(s, track); |
5809 | if (!track->tag) { |
5810 | av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, " |
5811 | "codec not currently supported in container\n", |
5812 | avcodec_get_name(st->codecpar->codec_id), i); |
5813 | return AVERROR(EINVAL); |
5814 | } |
5815 | /* If hinting of this track is enabled by a later hint track, |
5816 | * this is updated. */ |
5817 | track->hint_track = -1; |
5818 | track->start_dts = AV_NOPTS_VALUE; |
5819 | track->start_cts = AV_NOPTS_VALUE; |
5820 | track->end_pts = AV_NOPTS_VALUE; |
5821 | if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { |
5822 | if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') || |
5823 | track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') || |
5824 | track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) { |
5825 | if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) { |
5826 | av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n"); |
5827 | return AVERROR(EINVAL); |
5828 | } |
5829 | track->height = track->tag >> 24 == 'n' ? 486 : 576; |
5830 | } |
5831 | if (mov->video_track_timescale) { |
5832 | track->timescale = mov->video_track_timescale; |
5833 | } else { |
5834 | track->timescale = st->time_base.den; |
5835 | while(track->timescale < 10000) |
5836 | track->timescale *= 2; |
5837 | } |
5838 | if (st->codecpar->width > 65535 || st->codecpar->height > 65535) { |
5839 | av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height); |
5840 | return AVERROR(EINVAL); |
5841 | } |
5842 | if (track->mode == MODE_MOV && track->timescale > 100000) |
5843 | av_log(s, AV_LOG_WARNING, |
5844 | "WARNING codec timebase is very high. If duration is too long,\n" |
5845 | "file may not be playable by quicktime. Specify a shorter timebase\n" |
5846 | "or choose different container.\n"); |
5847 | if (track->mode == MODE_MOV && |
5848 | track->par->codec_id == AV_CODEC_ID_RAWVIDEO && |
5849 | track->tag == MKTAG('r','a','w',' ')) { |
5850 | enum AVPixelFormat pix_fmt = track->par->format; |
5851 | if (pix_fmt == AV_PIX_FMT_NONE && track->par->bits_per_coded_sample == 1) |
5852 | pix_fmt = AV_PIX_FMT_MONOWHITE; |
5853 | track->is_unaligned_qt_rgb = |
5854 | pix_fmt == AV_PIX_FMT_RGB24 || |
5855 | pix_fmt == AV_PIX_FMT_BGR24 || |
5856 | pix_fmt == AV_PIX_FMT_PAL8 || |
5857 | pix_fmt == AV_PIX_FMT_GRAY8 || |
5858 | pix_fmt == AV_PIX_FMT_MONOWHITE || |
5859 | pix_fmt == AV_PIX_FMT_MONOBLACK; |
5860 | } |
5861 | if (track->par->codec_id == AV_CODEC_ID_VP9) { |
5862 | if (track->mode != MODE_MP4) { |
5863 | av_log(s, AV_LOG_ERROR, "VP9 only supported in MP4.\n"); |
5864 | return AVERROR(EINVAL); |
5865 | } |
5866 | if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { |
5867 | av_log(s, AV_LOG_ERROR, |
5868 | "VP9 in MP4 support is experimental, add " |
5869 | "'-strict %d' if you want to use it.\n", |
5870 | FF_COMPLIANCE_EXPERIMENTAL); |
5871 | return AVERROR_EXPERIMENTAL; |
5872 | } |
5873 | } |
5874 | } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
5875 | track->timescale = st->codecpar->sample_rate; |
5876 | if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) { |
5877 | av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i); |
5878 | track->audio_vbr = 1; |
5879 | }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS || |
5880 | st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV || |
5881 | st->codecpar->codec_id == AV_CODEC_ID_ILBC){ |
5882 | if (!st->codecpar->block_align) { |
5883 | av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i); |
5884 | return AVERROR(EINVAL); |
5885 | } |
5886 | track->sample_size = st->codecpar->block_align; |
5887 | }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */ |
5888 | track->audio_vbr = 1; |
5889 | }else{ |
5890 | track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) * st->codecpar->channels; |
5891 | } |
5892 | if (st->codecpar->codec_id == AV_CODEC_ID_ILBC || |
5893 | st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) { |
5894 | track->audio_vbr = 1; |
5895 | } |
5896 | if (track->mode != MODE_MOV && |
5897 | track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) { |
5898 | if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) { |
5899 | av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n", |
5900 | i, track->par->sample_rate); |
5901 | return AVERROR(EINVAL); |
5902 | } else { |
5903 | av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n", |
5904 | i, track->par->sample_rate); |
5905 | } |
5906 | } |
5907 | if (track->par->codec_id == AV_CODEC_ID_FLAC) { |
5908 | if (track->mode != MODE_MP4) { |
5909 | av_log(s, AV_LOG_ERROR, "FLAC only supported in MP4.\n"); |
5910 | return AVERROR(EINVAL); |
5911 | } |
5912 | if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { |
5913 | av_log(s, AV_LOG_ERROR, |
5914 | "FLAC in MP4 support is experimental, add " |
5915 | "'-strict %d' if you want to use it.\n", |
5916 | FF_COMPLIANCE_EXPERIMENTAL); |
5917 | return AVERROR_EXPERIMENTAL; |
5918 | } |
5919 | } |
5920 | } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { |
5921 | track->timescale = st->time_base.den; |
5922 | } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { |
5923 | track->timescale = st->time_base.den; |
5924 | } else { |
5925 | track->timescale = MOV_TIMESCALE; |
5926 | } |
5927 | if (!track->height) |
5928 | track->height = st->codecpar->height; |
5929 | /* The ism specific timescale isn't mandatory, but is assumed by |
5930 | * some tools, such as mp4split. */ |
5931 | if (mov->mode == MODE_ISM) |
5932 | track->timescale = 10000000; |
5933 | |
5934 | avpriv_set_pts_info(st, 64, 1, track->timescale); |
5935 | |
5936 | if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) { |
5937 | ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key, |
5938 | track->par->codec_id == AV_CODEC_ID_H264, s->flags & AVFMT_FLAG_BITEXACT); |
5939 | if (ret) |
5940 | return ret; |
5941 | } |
5942 | } |
5943 | |
5944 | enable_tracks(s); |
5945 | return 0; |
5946 | } |
5947 | |
5948 | static int mov_write_header(AVFormatContext *s) |
5949 | { |
5950 | AVIOContext *pb = s->pb; |
5951 | MOVMuxContext *mov = s->priv_data; |
5952 | AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0); |
5953 | int i, ret, hint_track = 0, tmcd_track = 0, nb_tracks = s->nb_streams; |
5954 | |
5955 | if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) |
5956 | nb_tracks++; |
5957 | |
5958 | if (mov->flags & FF_MOV_FLAG_RTP_HINT) { |
5959 | /* Add hint tracks for each audio and video stream */ |
5960 | hint_track = nb_tracks; |
5961 | for (i = 0; i < s->nb_streams; i++) { |
5962 | AVStream *st = s->streams[i]; |
5963 | if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || |
5964 | st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
5965 | nb_tracks++; |
5966 | } |
5967 | } |
5968 | } |
5969 | |
5970 | if (mov->mode == MODE_MOV || mov->mode == MODE_MP4) |
5971 | tmcd_track = nb_tracks; |
5972 | |
5973 | for (i = 0; i < s->nb_streams; i++) { |
5974 | int j; |
5975 | AVStream *st= s->streams[i]; |
5976 | MOVTrack *track= &mov->tracks[i]; |
5977 | |
5978 | /* copy extradata if it exists */ |
5979 | if (st->codecpar->extradata_size) { |
5980 | if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) |
5981 | mov_create_dvd_sub_decoder_specific_info(track, st); |
5982 | else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) { |
5983 | track->vos_len = st->codecpar->extradata_size; |
5984 | track->vos_data = av_malloc(track->vos_len); |
5985 | if (!track->vos_data) { |
5986 | return AVERROR(ENOMEM); |
5987 | } |
5988 | memcpy(track->vos_data, st->codecpar->extradata, track->vos_len); |
5989 | } |
5990 | } |
5991 | |
5992 | if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || |
5993 | track->par->channel_layout != AV_CH_LAYOUT_MONO) |
5994 | continue; |
5995 | |
5996 | for (j = 0; j < s->nb_streams; j++) { |
5997 | AVStream *stj= s->streams[j]; |
5998 | MOVTrack *trackj= &mov->tracks[j]; |
5999 | if (j == i) |
6000 | continue; |
6001 | |
6002 | if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || |
6003 | trackj->par->channel_layout != AV_CH_LAYOUT_MONO || |
6004 | trackj->language != track->language || |
6005 | trackj->tag != track->tag |
6006 | ) |
6007 | continue; |
6008 | track->multichannel_as_mono++; |
6009 | } |
6010 | } |
6011 | |
6012 | if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { |
6013 | if ((ret = mov_write_identification(pb, s)) < 0) |
6014 | return ret; |
6015 | } |
6016 | |
6017 | if (mov->reserved_moov_size){ |
6018 | mov->reserved_header_pos = avio_tell(pb); |
6019 | if (mov->reserved_moov_size > 0) |
6020 | avio_skip(pb, mov->reserved_moov_size); |
6021 | } |
6022 | |
6023 | if (mov->flags & FF_MOV_FLAG_FRAGMENT) { |
6024 | /* If no fragmentation options have been set, set a default. */ |
6025 | if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME | |
6026 | FF_MOV_FLAG_FRAG_CUSTOM)) && |
6027 | !mov->max_fragment_duration && !mov->max_fragment_size) |
6028 | mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME; |
6029 | } else { |
6030 | if (mov->flags & FF_MOV_FLAG_FASTSTART) |
6031 | mov->reserved_header_pos = avio_tell(pb); |
6032 | mov_write_mdat_tag(pb, mov); |
6033 | } |
6034 | |
6035 | ff_parse_creation_time_metadata(s, &mov->time, 1); |
6036 | if (mov->time) |
6037 | mov->time += 0x7C25B080; // 1970 based -> 1904 based |
6038 | |
6039 | if (mov->chapter_track) |
6040 | if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0) |
6041 | return ret; |
6042 | |
6043 | if (mov->flags & FF_MOV_FLAG_RTP_HINT) { |
6044 | /* Initialize the hint tracks for each audio and video stream */ |
6045 | for (i = 0; i < s->nb_streams; i++) { |
6046 | AVStream *st = s->streams[i]; |
6047 | if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || |
6048 | st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
6049 | if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0) |
6050 | return ret; |
6051 | hint_track++; |
6052 | } |
6053 | } |
6054 | } |
6055 | |
6056 | if (mov->nb_meta_tmcd) { |
6057 | /* Initialize the tmcd tracks */ |
6058 | for (i = 0; i < s->nb_streams; i++) { |
6059 | AVStream *st = s->streams[i]; |
6060 | t = global_tcr; |
6061 | |
6062 | if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { |
6063 | AVTimecode tc; |
6064 | if (!t) |
6065 | t = av_dict_get(st->metadata, "timecode", NULL, 0); |
6066 | if (!t) |
6067 | continue; |
6068 | if (mov_check_timecode_track(s, &tc, i, t->value) < 0) |
6069 | continue; |
6070 | if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0) |
6071 | return ret; |
6072 | tmcd_track++; |
6073 | } |
6074 | } |
6075 | } |
6076 | |
6077 | avio_flush(pb); |
6078 | |
6079 | if (mov->flags & FF_MOV_FLAG_ISML) |
6080 | mov_write_isml_manifest(pb, mov, s); |
6081 | |
6082 | if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && |
6083 | !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { |
6084 | if ((ret = mov_write_moov_tag(pb, mov, s)) < 0) |
6085 | return ret; |
6086 | avio_flush(pb); |
6087 | mov->moov_written = 1; |
6088 | if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) |
6089 | mov->reserved_header_pos = avio_tell(pb); |
6090 | } |
6091 | |
6092 | return 0; |
6093 | } |
6094 | |
6095 | static int get_moov_size(AVFormatContext *s) |
6096 | { |
6097 | int ret; |
6098 | AVIOContext *moov_buf; |
6099 | MOVMuxContext *mov = s->priv_data; |
6100 | |
6101 | if ((ret = ffio_open_null_buf(&moov_buf)) < 0) |
6102 | return ret; |
6103 | if ((ret = mov_write_moov_tag(moov_buf, mov, s)) < 0) |
6104 | return ret; |
6105 | return ffio_close_null_buf(moov_buf); |
6106 | } |
6107 | |
6108 | static int get_sidx_size(AVFormatContext *s) |
6109 | { |
6110 | int ret; |
6111 | AVIOContext *buf; |
6112 | MOVMuxContext *mov = s->priv_data; |
6113 | |
6114 | if ((ret = ffio_open_null_buf(&buf)) < 0) |
6115 | return ret; |
6116 | mov_write_sidx_tags(buf, mov, -1, 0); |
6117 | return ffio_close_null_buf(buf); |
6118 | } |
6119 | |
6120 | /* |
6121 | * This function gets the moov size if moved to the top of the file: the chunk |
6122 | * offset table can switch between stco (32-bit entries) to co64 (64-bit |
6123 | * entries) when the moov is moved to the beginning, so the size of the moov |
6124 | * would change. It also updates the chunk offset tables. |
6125 | */ |
6126 | static int compute_moov_size(AVFormatContext *s) |
6127 | { |
6128 | int i, moov_size, moov_size2; |
6129 | MOVMuxContext *mov = s->priv_data; |
6130 | |
6131 | moov_size = get_moov_size(s); |
6132 | if (moov_size < 0) |
6133 | return moov_size; |
6134 | |
6135 | for (i = 0; i < mov->nb_streams; i++) |
6136 | mov->tracks[i].data_offset += moov_size; |
6137 | |
6138 | moov_size2 = get_moov_size(s); |
6139 | if (moov_size2 < 0) |
6140 | return moov_size2; |
6141 | |
6142 | /* if the size changed, we just switched from stco to co64 and need to |
6143 | * update the offsets */ |
6144 | if (moov_size2 != moov_size) |
6145 | for (i = 0; i < mov->nb_streams; i++) |
6146 | mov->tracks[i].data_offset += moov_size2 - moov_size; |
6147 | |
6148 | return moov_size2; |
6149 | } |
6150 | |
6151 | static int compute_sidx_size(AVFormatContext *s) |
6152 | { |
6153 | int i, sidx_size; |
6154 | MOVMuxContext *mov = s->priv_data; |
6155 | |
6156 | sidx_size = get_sidx_size(s); |
6157 | if (sidx_size < 0) |
6158 | return sidx_size; |
6159 | |
6160 | for (i = 0; i < mov->nb_streams; i++) |
6161 | mov->tracks[i].data_offset += sidx_size; |
6162 | |
6163 | return sidx_size; |
6164 | } |
6165 | |
6166 | static int shift_data(AVFormatContext *s) |
6167 | { |
6168 | int ret = 0, moov_size; |
6169 | MOVMuxContext *mov = s->priv_data; |
6170 | int64_t pos, pos_end = avio_tell(s->pb); |
6171 | uint8_t *buf, *read_buf[2]; |
6172 | int read_buf_id = 0; |
6173 | int read_size[2]; |
6174 | AVIOContext *read_pb; |
6175 | |
6176 | if (mov->flags & FF_MOV_FLAG_FRAGMENT) |
6177 | moov_size = compute_sidx_size(s); |
6178 | else |
6179 | moov_size = compute_moov_size(s); |
6180 | if (moov_size < 0) |
6181 | return moov_size; |
6182 | |
6183 | buf = av_malloc(moov_size * 2); |
6184 | if (!buf) |
6185 | return AVERROR(ENOMEM); |
6186 | read_buf[0] = buf; |
6187 | read_buf[1] = buf + moov_size; |
6188 | |
6189 | /* Shift the data: the AVIO context of the output can only be used for |
6190 | * writing, so we re-open the same output, but for reading. It also avoids |
6191 | * a read/seek/write/seek back and forth. */ |
6192 | avio_flush(s->pb); |
6193 | ret = s->io_open(s, &read_pb, s->filename, AVIO_FLAG_READ, NULL); |
6194 | if (ret < 0) { |
6195 | av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for " |
6196 | "the second pass (faststart)\n", s->filename); |
6197 | goto end; |
6198 | } |
6199 | |
6200 | /* mark the end of the shift to up to the last data we wrote, and get ready |
6201 | * for writing */ |
6202 | pos_end = avio_tell(s->pb); |
6203 | avio_seek(s->pb, mov->reserved_header_pos + moov_size, SEEK_SET); |
6204 | |
6205 | /* start reading at where the new moov will be placed */ |
6206 | avio_seek(read_pb, mov->reserved_header_pos, SEEK_SET); |
6207 | pos = avio_tell(read_pb); |
6208 | |
6209 | #define READ_BLOCK do { \ |
6210 | read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], moov_size); \ |
6211 | read_buf_id ^= 1; \ |
6212 | } while (0) |
6213 | |
6214 | /* shift data by chunk of at most moov_size */ |
6215 | READ_BLOCK; |
6216 | do { |
6217 | int n; |
6218 | READ_BLOCK; |
6219 | n = read_size[read_buf_id]; |
6220 | if (n <= 0) |
6221 | break; |
6222 | avio_write(s->pb, read_buf[read_buf_id], n); |
6223 | pos += n; |
6224 | } while (pos < pos_end); |
6225 | ff_format_io_close(s, &read_pb); |
6226 | |
6227 | end: |
6228 | av_free(buf); |
6229 | return ret; |
6230 | } |
6231 | |
6232 | static int mov_write_trailer(AVFormatContext *s) |
6233 | { |
6234 | MOVMuxContext *mov = s->priv_data; |
6235 | AVIOContext *pb = s->pb; |
6236 | int res = 0; |
6237 | int i; |
6238 | int64_t moov_pos; |
6239 | |
6240 | if (mov->need_rewrite_extradata) { |
6241 | for (i = 0; i < s->nb_streams; i++) { |
6242 | MOVTrack *track = &mov->tracks[i]; |
6243 | AVCodecParameters *par = track->par; |
6244 | |
6245 | track->vos_len = par->extradata_size; |
6246 | track->vos_data = av_malloc(track->vos_len); |
6247 | if (!track->vos_data) |
6248 | return AVERROR(ENOMEM); |
6249 | memcpy(track->vos_data, par->extradata, track->vos_len); |
6250 | } |
6251 | mov->need_rewrite_extradata = 0; |
6252 | } |
6253 | |
6254 | /* |
6255 | * Before actually writing the trailer, make sure that there are no |
6256 | * dangling subtitles, that need a terminating sample. |
6257 | */ |
6258 | for (i = 0; i < mov->nb_streams; i++) { |
6259 | MOVTrack *trk = &mov->tracks[i]; |
6260 | if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT && |
6261 | !trk->last_sample_is_subtitle_end) { |
6262 | mov_write_subtitle_end_packet(s, i, trk->track_duration); |
6263 | trk->last_sample_is_subtitle_end = 1; |
6264 | } |
6265 | } |
6266 | |
6267 | // If there were no chapters when the header was written, but there |
6268 | // are chapters now, write them in the trailer. This only works |
6269 | // when we are not doing fragments. |
6270 | if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) { |
6271 | if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) { |
6272 | mov->chapter_track = mov->nb_streams++; |
6273 | if ((res = mov_create_chapter_track(s, mov->chapter_track)) < 0) |
6274 | return res; |
6275 | } |
6276 | } |
6277 | |
6278 | if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) { |
6279 | moov_pos = avio_tell(pb); |
6280 | |
6281 | /* Write size of mdat tag */ |
6282 | if (mov->mdat_size + 8 <= UINT32_MAX) { |
6283 | avio_seek(pb, mov->mdat_pos, SEEK_SET); |
6284 | avio_wb32(pb, mov->mdat_size + 8); |
6285 | } else { |
6286 | /* overwrite 'wide' placeholder atom */ |
6287 | avio_seek(pb, mov->mdat_pos - 8, SEEK_SET); |
6288 | /* special value: real atom size will be 64 bit value after |
6289 | * tag field */ |
6290 | avio_wb32(pb, 1); |
6291 | ffio_wfourcc(pb, "mdat"); |
6292 | avio_wb64(pb, mov->mdat_size + 16); |
6293 | } |
6294 | avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_header_pos : moov_pos, SEEK_SET); |
6295 | |
6296 | if (mov->flags & FF_MOV_FLAG_FASTSTART) { |
6297 | av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n"); |
6298 | res = shift_data(s); |
6299 | if (res < 0) |
6300 | return res; |
6301 | avio_seek(pb, mov->reserved_header_pos, SEEK_SET); |
6302 | if ((res = mov_write_moov_tag(pb, mov, s)) < 0) |
6303 | return res; |
6304 | } else if (mov->reserved_moov_size > 0) { |
6305 | int64_t size; |
6306 | if ((res = mov_write_moov_tag(pb, mov, s)) < 0) |
6307 | return res; |
6308 | size = mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_header_pos); |
6309 | if (size < 8){ |
6310 | av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size); |
6311 | return AVERROR(EINVAL); |
6312 | } |
6313 | avio_wb32(pb, size); |
6314 | ffio_wfourcc(pb, "free"); |
6315 | ffio_fill(pb, 0, size - 8); |
6316 | avio_seek(pb, moov_pos, SEEK_SET); |
6317 | } else { |
6318 | if ((res = mov_write_moov_tag(pb, mov, s)) < 0) |
6319 | return res; |
6320 | } |
6321 | res = 0; |
6322 | } else { |
6323 | mov_auto_flush_fragment(s, 1); |
6324 | for (i = 0; i < mov->nb_streams; i++) |
6325 | mov->tracks[i].data_offset = 0; |
6326 | if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) { |
6327 | int64_t end; |
6328 | av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n"); |
6329 | res = shift_data(s); |
6330 | if (res < 0) |
6331 | return res; |
6332 | end = avio_tell(pb); |
6333 | avio_seek(pb, mov->reserved_header_pos, SEEK_SET); |
6334 | mov_write_sidx_tags(pb, mov, -1, 0); |
6335 | avio_seek(pb, end, SEEK_SET); |
6336 | avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); |
6337 | mov_write_mfra_tag(pb, mov); |
6338 | } else if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) { |
6339 | avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); |
6340 | mov_write_mfra_tag(pb, mov); |
6341 | } |
6342 | } |
6343 | |
6344 | return res; |
6345 | } |
6346 | |
6347 | static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) |
6348 | { |
6349 | int ret = 1; |
6350 | AVStream *st = s->streams[pkt->stream_index]; |
6351 | |
6352 | if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { |
6353 | if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) |
6354 | ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); |
6355 | } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) { |
6356 | ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL); |
6357 | } |
6358 | |
6359 | return ret; |
6360 | } |
6361 | |
6362 | #if CONFIG_MOV_MUXER |
6363 | MOV_CLASS(mov) |
6364 | AVOutputFormat ff_mov_muxer = { |
6365 | .name = "mov", |
6366 | .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"), |
6367 | .extensions = "mov", |
6368 | .priv_data_size = sizeof(MOVMuxContext), |
6369 | .audio_codec = AV_CODEC_ID_AAC, |
6370 | .video_codec = CONFIG_LIBX264_ENCODER ? |
6371 | AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, |
6372 | .init = mov_init, |
6373 | .write_header = mov_write_header, |
6374 | .write_packet = mov_write_packet, |
6375 | .write_trailer = mov_write_trailer, |
6376 | .deinit = mov_free, |
6377 | .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, |
6378 | .codec_tag = (const AVCodecTag* const []){ |
6379 | ff_codec_movvideo_tags, ff_codec_movaudio_tags, 0 |
6380 | }, |
6381 | .check_bitstream = mov_check_bitstream, |
6382 | .priv_class = &mov_muxer_class, |
6383 | }; |
6384 | #endif |
6385 | #if CONFIG_TGP_MUXER |
6386 | MOV_CLASS(tgp) |
6387 | AVOutputFormat ff_tgp_muxer = { |
6388 | .name = "3gp", |
6389 | .long_name = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"), |
6390 | .extensions = "3gp", |
6391 | .priv_data_size = sizeof(MOVMuxContext), |
6392 | .audio_codec = AV_CODEC_ID_AMR_NB, |
6393 | .video_codec = AV_CODEC_ID_H263, |
6394 | .init = mov_init, |
6395 | .write_header = mov_write_header, |
6396 | .write_packet = mov_write_packet, |
6397 | .write_trailer = mov_write_trailer, |
6398 | .deinit = mov_free, |
6399 | .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, |
6400 | .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 }, |
6401 | .check_bitstream = mov_check_bitstream, |
6402 | .priv_class = &tgp_muxer_class, |
6403 | }; |
6404 | #endif |
6405 | #if CONFIG_MP4_MUXER |
6406 | MOV_CLASS(mp4) |
6407 | AVOutputFormat ff_mp4_muxer = { |
6408 | .name = "mp4", |
6409 | .long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"), |
6410 | .mime_type = "video/mp4", |
6411 | .extensions = "mp4", |
6412 | .priv_data_size = sizeof(MOVMuxContext), |
6413 | .audio_codec = AV_CODEC_ID_AAC, |
6414 | .video_codec = CONFIG_LIBX264_ENCODER ? |
6415 | AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, |
6416 | .init = mov_init, |
6417 | .write_header = mov_write_header, |
6418 | .write_packet = mov_write_packet, |
6419 | .write_trailer = mov_write_trailer, |
6420 | .deinit = mov_free, |
6421 | .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, |
6422 | .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, |
6423 | .check_bitstream = mov_check_bitstream, |
6424 | .priv_class = &mp4_muxer_class, |
6425 | }; |
6426 | #endif |
6427 | #if CONFIG_PSP_MUXER |
6428 | MOV_CLASS(psp) |
6429 | AVOutputFormat ff_psp_muxer = { |
6430 | .name = "psp", |
6431 | .long_name = NULL_IF_CONFIG_SMALL("PSP MP4 (MPEG-4 Part 14)"), |
6432 | .extensions = "mp4,psp", |
6433 | .priv_data_size = sizeof(MOVMuxContext), |
6434 | .audio_codec = AV_CODEC_ID_AAC, |
6435 | .video_codec = CONFIG_LIBX264_ENCODER ? |
6436 | AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, |
6437 | .init = mov_init, |
6438 | .write_header = mov_write_header, |
6439 | .write_packet = mov_write_packet, |
6440 | .write_trailer = mov_write_trailer, |
6441 | .deinit = mov_free, |
6442 | .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, |
6443 | .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, |
6444 | .check_bitstream = mov_check_bitstream, |
6445 | .priv_class = &psp_muxer_class, |
6446 | }; |
6447 | #endif |
6448 | #if CONFIG_TG2_MUXER |
6449 | MOV_CLASS(tg2) |
6450 | AVOutputFormat ff_tg2_muxer = { |
6451 | .name = "3g2", |
6452 | .long_name = NULL_IF_CONFIG_SMALL("3GP2 (3GPP2 file format)"), |
6453 | .extensions = "3g2", |
6454 | .priv_data_size = sizeof(MOVMuxContext), |
6455 | .audio_codec = AV_CODEC_ID_AMR_NB, |
6456 | .video_codec = AV_CODEC_ID_H263, |
6457 | .init = mov_init, |
6458 | .write_header = mov_write_header, |
6459 | .write_packet = mov_write_packet, |
6460 | .write_trailer = mov_write_trailer, |
6461 | .deinit = mov_free, |
6462 | .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, |
6463 | .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 }, |
6464 | .check_bitstream = mov_check_bitstream, |
6465 | .priv_class = &tg2_muxer_class, |
6466 | }; |
6467 | #endif |
6468 | #if CONFIG_IPOD_MUXER |
6469 | MOV_CLASS(ipod) |
6470 | AVOutputFormat ff_ipod_muxer = { |
6471 | .name = "ipod", |
6472 | .long_name = NULL_IF_CONFIG_SMALL("iPod H.264 MP4 (MPEG-4 Part 14)"), |
6473 | .mime_type = "video/mp4", |
6474 | .extensions = "m4v,m4a", |
6475 | .priv_data_size = sizeof(MOVMuxContext), |
6476 | .audio_codec = AV_CODEC_ID_AAC, |
6477 | .video_codec = AV_CODEC_ID_H264, |
6478 | .init = mov_init, |
6479 | .write_header = mov_write_header, |
6480 | .write_packet = mov_write_packet, |
6481 | .write_trailer = mov_write_trailer, |
6482 | .deinit = mov_free, |
6483 | .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, |
6484 | .codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 }, |
6485 | .check_bitstream = mov_check_bitstream, |
6486 | .priv_class = &ipod_muxer_class, |
6487 | }; |
6488 | #endif |
6489 | #if CONFIG_ISMV_MUXER |
6490 | MOV_CLASS(ismv) |
6491 | AVOutputFormat ff_ismv_muxer = { |
6492 | .name = "ismv", |
6493 | .long_name = NULL_IF_CONFIG_SMALL("ISMV/ISMA (Smooth Streaming)"), |
6494 | .mime_type = "video/mp4", |
6495 | .extensions = "ismv,isma", |
6496 | .priv_data_size = sizeof(MOVMuxContext), |
6497 | .audio_codec = AV_CODEC_ID_AAC, |
6498 | .video_codec = AV_CODEC_ID_H264, |
6499 | .init = mov_init, |
6500 | .write_header = mov_write_header, |
6501 | .write_packet = mov_write_packet, |
6502 | .write_trailer = mov_write_trailer, |
6503 | .deinit = mov_free, |
6504 | .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, |
6505 | .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, |
6506 | .check_bitstream = mov_check_bitstream, |
6507 | .priv_class = &ismv_muxer_class, |
6508 | }; |
6509 | #endif |
6510 | #if CONFIG_F4V_MUXER |
6511 | MOV_CLASS(f4v) |
6512 | AVOutputFormat ff_f4v_muxer = { |
6513 | .name = "f4v", |
6514 | .long_name = NULL_IF_CONFIG_SMALL("F4V Adobe Flash Video"), |
6515 | .mime_type = "application/f4v", |
6516 | .extensions = "f4v", |
6517 | .priv_data_size = sizeof(MOVMuxContext), |
6518 | .audio_codec = AV_CODEC_ID_AAC, |
6519 | .video_codec = AV_CODEC_ID_H264, |
6520 | .init = mov_init, |
6521 | .write_header = mov_write_header, |
6522 | .write_packet = mov_write_packet, |
6523 | .write_trailer = mov_write_trailer, |
6524 | .deinit = mov_free, |
6525 | .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, |
6526 | .codec_tag = (const AVCodecTag* const []){ codec_f4v_tags, 0 }, |
6527 | .check_bitstream = mov_check_bitstream, |
6528 | .priv_class = &f4v_muxer_class, |
6529 | }; |
6530 | #endif |
6531 |