ffmpeg / libavformat / matroskaenc.c @ e7ddafd5
History | View | Annotate | Download (36.8 KB)
1 | 67143c0f | David Conrad | /*
|
---|---|---|---|
2 | 8cf3bb26 | David Conrad | * Matroska muxer
|
3 | 67143c0f | David Conrad | * Copyright (c) 2007 David Conrad
|
4 | *
|
||
5 | * This file is part of FFmpeg.
|
||
6 | *
|
||
7 | * FFmpeg is free software; you can redistribute it and/or
|
||
8 | * modify it under the terms of the GNU Lesser General Public
|
||
9 | * License as published by the Free Software Foundation; either
|
||
10 | * version 2.1 of the License, or (at your option) any later version.
|
||
11 | *
|
||
12 | * FFmpeg is distributed in the hope that it will be useful,
|
||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
15 | * Lesser General Public License for more details.
|
||
16 | *
|
||
17 | * You should have received a copy of the GNU Lesser General Public
|
||
18 | * License along with FFmpeg; if not, write to the Free Software
|
||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
20 | */
|
||
21 | |||
22 | #include "avformat.h" |
||
23 | #include "riff.h" |
||
24 | f009e36f | Aurelien Jacobs | #include "isom.h" |
25 | 67143c0f | David Conrad | #include "matroska.h" |
26 | aacc5f22 | Aurelien Jacobs | #include "avc.h" |
27 | 2578326f | Justin Ruggles | #include "flacenc.h" |
28 | 6a5d31ac | Diego Biurrun | #include "libavutil/intreadwrite.h" |
29 | 1f4280e7 | David Conrad | #include "libavutil/random_seed.h" |
30 | #include "libavutil/lfg.h" |
||
31 | 245976da | Diego Biurrun | #include "libavcodec/xiph.h" |
32 | 7bfacd4e | Aurelien Jacobs | #include "libavcodec/mpeg4audio.h" |
33 | 67143c0f | David Conrad | |
34 | baf71dca | David Conrad | typedef struct ebml_master { |
35 | bc5c918e | Diego Biurrun | int64_t pos; ///< absolute offset in the file where the master's elements start
|
36 | baf71dca | David Conrad | int sizebytes; ///< how many bytes were reserved for the size |
37 | } ebml_master; |
||
38 | |||
39 | 967d815a | David Conrad | typedef struct mkv_seekhead_entry { |
40 | unsigned int elementid; |
||
41 | uint64_t segmentpos; |
||
42 | } mkv_seekhead_entry; |
||
43 | |||
44 | typedef struct mkv_seekhead { |
||
45 | bc5c918e | Diego Biurrun | int64_t filepos; |
46 | int64_t segment_offset; ///< the file offset to the beginning of the segment
|
||
47 | 1b66d314 | David Conrad | int reserved_size; ///< -1 if appending to file |
48 | 967d815a | David Conrad | int max_entries;
|
49 | mkv_seekhead_entry *entries; |
||
50 | int num_entries;
|
||
51 | } mkv_seekhead; |
||
52 | |||
53 | 6364d534 | David Conrad | typedef struct { |
54 | uint64_t pts; |
||
55 | int tracknum;
|
||
56 | bc5c918e | Diego Biurrun | int64_t cluster_pos; ///< file offset of the cluster containing the block
|
57 | 6364d534 | David Conrad | } mkv_cuepoint; |
58 | |||
59 | typedef struct { |
||
60 | bc5c918e | Diego Biurrun | int64_t segment_offset; |
61 | 6364d534 | David Conrad | mkv_cuepoint *entries; |
62 | int num_entries;
|
||
63 | } mkv_cues; |
||
64 | |||
65 | 84d4e599 | David Conrad | typedef struct { |
66 | int write_dts;
|
||
67 | } mkv_track; |
||
68 | |||
69 | 316d6c15 | James Zern | #define MODE_MATROSKAv2 0x01 |
70 | #define MODE_WEBM 0x02 |
||
71 | |||
72 | 67143c0f | David Conrad | typedef struct MatroskaMuxContext { |
73 | 316d6c15 | James Zern | int mode;
|
74 | 871b641b | David Conrad | ByteIOContext *dyn_bc; |
75 | baf71dca | David Conrad | ebml_master segment; |
76 | bc5c918e | Diego Biurrun | int64_t segment_offset; |
77 | baf71dca | David Conrad | ebml_master cluster; |
78 | bc5c918e | Diego Biurrun | int64_t cluster_pos; ///< file offset of the current cluster
|
79 | f9ff7179 | David Conrad | int64_t cluster_pts; |
80 | bc5c918e | Diego Biurrun | int64_t duration_offset; |
81 | f9ff7179 | David Conrad | int64_t duration; |
82 | 967d815a | David Conrad | mkv_seekhead *main_seekhead; |
83 | 6364d534 | David Conrad | mkv_cues *cues; |
84 | 84d4e599 | David Conrad | mkv_track *tracks; |
85 | 541d443c | David Conrad | |
86 | 1f4280e7 | David Conrad | AVLFG lfg; |
87 | ac9baa71 | James Zern | unsigned int audio_buffer_size; |
88 | AVPacket cur_audio_pkt; |
||
89 | 67143c0f | David Conrad | } MatroskaMuxContext; |
90 | |||
91 | baf71dca | David Conrad | |
92 | e3cd80cd | David Conrad | /** 2 bytes * 3 for EBML IDs, 3 1-byte EBML lengths, 8 bytes for 64 bit
|
93 | * offset, 4 bytes for target EBML ID */
|
||
94 | baf71dca | David Conrad | #define MAX_SEEKENTRY_SIZE 21 |
95 | |||
96 | e3cd80cd | David Conrad | /** per-cuepoint-track - 3 1-byte EBML IDs, 3 1-byte EBML sizes, 2
|
97 | * 8-byte uint max */
|
||
98 | baf71dca | David Conrad | #define MAX_CUETRACKPOS_SIZE 22 |
99 | |||
100 | e3cd80cd | David Conrad | /** per-cuepoint - 2 1-byte EBML IDs, 2 1-byte EBML sizes, 8-byte uint max */
|
101 | baf71dca | David Conrad | #define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE*num_tracks |
102 | |||
103 | |||
104 | 22ccb69a | David Conrad | static int ebml_id_size(unsigned int id) |
105 | { |
||
106 | return (av_log2(id+1)-1)/7+1; |
||
107 | } |
||
108 | |||
109 | 67143c0f | David Conrad | static void put_ebml_id(ByteIOContext *pb, unsigned int id) |
110 | { |
||
111 | 432adc13 | David Conrad | int i = ebml_id_size(id);
|
112 | while (i--)
|
||
113 | put_byte(pb, id >> (i*8));
|
||
114 | 67143c0f | David Conrad | } |
115 | |||
116 | ec8f4ad9 | David Conrad | /**
|
117 | bf898960 | Diego Biurrun | * Write an EBML size meaning "unknown size".
|
118 | ec8f4ad9 | David Conrad | *
|
119 | bf898960 | Diego Biurrun | * @param bytes The number of bytes the size should occupy (maximum: 8).
|
120 | ec8f4ad9 | David Conrad | */
|
121 | static void put_ebml_size_unknown(ByteIOContext *pb, int bytes) |
||
122 | { |
||
123 | 0580a122 | David Conrad | assert(bytes <= 8);
|
124 | 203cce9a | David Conrad | put_byte(pb, 0x1ff >> bytes);
|
125 | while (--bytes)
|
||
126 | put_byte(pb, 0xff);
|
||
127 | ec8f4ad9 | David Conrad | } |
128 | |||
129 | 1c73478c | David Conrad | /**
|
130 | 0f651e8c | David Conrad | * Calculate how many bytes are needed to represent a given number in EBML.
|
131 | 1c73478c | David Conrad | */
|
132 | 0f651e8c | David Conrad | static int ebml_num_size(uint64_t num) |
133 | 1c73478c | David Conrad | { |
134 | int bytes = 1; |
||
135 | 0f651e8c | David Conrad | while ((num+1) >> bytes*7) bytes++; |
136 | 1c73478c | David Conrad | return bytes;
|
137 | } |
||
138 | |||
139 | f0e9f442 | David Conrad | /**
|
140 | 0f651e8c | David Conrad | * Write a number in EBML variable length format.
|
141 | f0e9f442 | David Conrad | *
|
142 | 0f651e8c | David Conrad | * @param bytes The number of bytes that need to be used to write the number.
|
143 | f0e9f442 | David Conrad | * If zero, any number of bytes can be used.
|
144 | */
|
||
145 | 0f651e8c | David Conrad | static void put_ebml_num(ByteIOContext *pb, uint64_t num, int bytes) |
146 | 67143c0f | David Conrad | { |
147 | 0f651e8c | David Conrad | int i, needed_bytes = ebml_num_size(num);
|
148 | 67143c0f | David Conrad | |
149 | // sizes larger than this are currently undefined in EBML
|
||
150 | 0f651e8c | David Conrad | assert(num < (1ULL<<56)-1); |
151 | ffb880c2 | David Conrad | |
152 | f0e9f442 | David Conrad | if (bytes == 0) |
153 | // don't care how many bytes are used, so use the min
|
||
154 | bytes = needed_bytes; |
||
155 | 47e08c58 | David Conrad | // the bytes needed to write the given size would exceed the bytes
|
156 | // that we need to use, so write unknown size. This shouldn't happen.
|
||
157 | 0580a122 | David Conrad | assert(bytes >= needed_bytes); |
158 | f0e9f442 | David Conrad | |
159 | 0f651e8c | David Conrad | num |= 1ULL << bytes*7; |
160 | ddf16467 | David Conrad | for (i = bytes - 1; i >= 0; i--) |
161 | 0f651e8c | David Conrad | put_byte(pb, num >> i*8);
|
162 | 67143c0f | David Conrad | } |
163 | |||
164 | static void put_ebml_uint(ByteIOContext *pb, unsigned int elementid, uint64_t val) |
||
165 | { |
||
166 | 9f38fd7e | David Conrad | int i, bytes = 1; |
167 | 73260a11 | Aurelien Jacobs | uint64_t tmp = val; |
168 | while (tmp>>=8) bytes++; |
||
169 | 67143c0f | David Conrad | |
170 | put_ebml_id(pb, elementid); |
||
171 | 0f651e8c | David Conrad | put_ebml_num(pb, bytes, 0);
|
172 | 9f38fd7e | David Conrad | for (i = bytes - 1; i >= 0; i--) |
173 | put_byte(pb, val >> i*8);
|
||
174 | 67143c0f | David Conrad | } |
175 | |||
176 | 9b6b0c79 | David Conrad | static void put_ebml_float(ByteIOContext *pb, unsigned int elementid, double val) |
177 | { |
||
178 | put_ebml_id(pb, elementid); |
||
179 | 0f651e8c | David Conrad | put_ebml_num(pb, 8, 0); |
180 | 9b6b0c79 | David Conrad | put_be64(pb, av_dbl2int(val)); |
181 | } |
||
182 | |||
183 | 67143c0f | David Conrad | static void put_ebml_binary(ByteIOContext *pb, unsigned int elementid, |
184 | 4a6bef1f | David Conrad | const void *buf, int size) |
185 | 67143c0f | David Conrad | { |
186 | put_ebml_id(pb, elementid); |
||
187 | 0f651e8c | David Conrad | put_ebml_num(pb, size, 0);
|
188 | 67143c0f | David Conrad | put_buffer(pb, buf, size); |
189 | } |
||
190 | |||
191 | 1e18c4d0 | David Conrad | static void put_ebml_string(ByteIOContext *pb, unsigned int elementid, const char *str) |
192 | 67143c0f | David Conrad | { |
193 | put_ebml_binary(pb, elementid, str, strlen(str)); |
||
194 | } |
||
195 | |||
196 | 57848e9a | David Conrad | /**
|
197 | cfde5d18 | David Conrad | * Writes a void element of a given size. Useful for reserving space in
|
198 | * the file to be written to later.
|
||
199 | 57848e9a | David Conrad | *
|
200 | 5045da83 | David Conrad | * @param size The number of bytes to reserve, which must be at least 2.
|
201 | 57848e9a | David Conrad | */
|
202 | f57b85a5 | David Conrad | static void put_ebml_void(ByteIOContext *pb, uint64_t size) |
203 | { |
||
204 | bc5c918e | Diego Biurrun | int64_t currentpos = url_ftell(pb); |
205 | f57b85a5 | David Conrad | |
206 | 0580a122 | David Conrad | assert(size >= 2);
|
207 | f57b85a5 | David Conrad | |
208 | put_ebml_id(pb, EBML_ID_VOID); |
||
209 | cfde5d18 | David Conrad | // we need to subtract the length needed to store the size from the
|
210 | // size we need to reserve so 2 cases, we use 8 bytes to store the
|
||
211 | // size if possible, 1 byte otherwise
|
||
212 | f57b85a5 | David Conrad | if (size < 10) |
213 | 0f651e8c | David Conrad | put_ebml_num(pb, size-1, 0); |
214 | f57b85a5 | David Conrad | else
|
215 | 0f651e8c | David Conrad | put_ebml_num(pb, size-9, 8); |
216 | 2024c226 | Michael Niedermayer | while(url_ftell(pb) < currentpos + size)
|
217 | put_byte(pb, 0);
|
||
218 | f57b85a5 | David Conrad | } |
219 | |||
220 | baf71dca | David Conrad | static ebml_master start_ebml_master(ByteIOContext *pb, unsigned int elementid, uint64_t expectedsize) |
221 | 67143c0f | David Conrad | { |
222 | 0f651e8c | David Conrad | int bytes = expectedsize ? ebml_num_size(expectedsize) : 8; |
223 | 67143c0f | David Conrad | put_ebml_id(pb, elementid); |
224 | baf71dca | David Conrad | put_ebml_size_unknown(pb, bytes); |
225 | return (ebml_master){ url_ftell(pb), bytes };
|
||
226 | 67143c0f | David Conrad | } |
227 | |||
228 | baf71dca | David Conrad | static void end_ebml_master(ByteIOContext *pb, ebml_master master) |
229 | 67143c0f | David Conrad | { |
230 | bc5c918e | Diego Biurrun | int64_t pos = url_ftell(pb); |
231 | 67143c0f | David Conrad | |
232 | 2529bb30 | David Conrad | if (url_fseek(pb, master.pos - master.sizebytes, SEEK_SET) < 0) |
233 | ac9e1177 | David Conrad | return;
|
234 | 0f651e8c | David Conrad | put_ebml_num(pb, pos - master.pos, master.sizebytes); |
235 | 67143c0f | David Conrad | url_fseek(pb, pos, SEEK_SET); |
236 | } |
||
237 | |||
238 | 86be6637 | David Conrad | static void put_xiph_size(ByteIOContext *pb, int size) |
239 | { |
||
240 | int i;
|
||
241 | for (i = 0; i < size / 255; i++) |
||
242 | put_byte(pb, 255);
|
||
243 | put_byte(pb, size % 255);
|
||
244 | } |
||
245 | |||
246 | 57848e9a | David Conrad | /**
|
247 | cfde5d18 | David Conrad | * Initialize a mkv_seekhead element to be ready to index level 1 Matroska
|
248 | * elements. If a maximum number of elements is specified, enough space
|
||
249 | * will be reserved at the current file location to write a seek head of
|
||
250 | * that size.
|
||
251 | 57848e9a | David Conrad | *
|
252 | cfde5d18 | David Conrad | * @param segment_offset The absolute offset to the position in the file
|
253 | ab332d01 | David Conrad | * where the segment begins.
|
254 | * @param numelements The maximum number of elements that will be indexed
|
||
255 | cfde5d18 | David Conrad | * by this seek head, 0 if unlimited.
|
256 | 57848e9a | David Conrad | */
|
257 | bc5c918e | Diego Biurrun | static mkv_seekhead * mkv_start_seekhead(ByteIOContext *pb, int64_t segment_offset, int numelements) |
258 | 967d815a | David Conrad | { |
259 | mkv_seekhead *new_seekhead = av_mallocz(sizeof(mkv_seekhead));
|
||
260 | if (new_seekhead == NULL) |
||
261 | return NULL; |
||
262 | |||
263 | new_seekhead->segment_offset = segment_offset; |
||
264 | |||
265 | if (numelements > 0) { |
||
266 | new_seekhead->filepos = url_ftell(pb); |
||
267 | cfde5d18 | David Conrad | // 21 bytes max for a seek entry, 10 bytes max for the SeekHead ID
|
268 | // and size, and 3 bytes to guarantee that an EBML void element
|
||
269 | // will fit afterwards
|
||
270 | baf71dca | David Conrad | new_seekhead->reserved_size = numelements * MAX_SEEKENTRY_SIZE + 13;
|
271 | 967d815a | David Conrad | new_seekhead->max_entries = numelements; |
272 | put_ebml_void(pb, new_seekhead->reserved_size); |
||
273 | } |
||
274 | return new_seekhead;
|
||
275 | } |
||
276 | |||
277 | static int mkv_add_seekhead_entry(mkv_seekhead *seekhead, unsigned int elementid, uint64_t filepos) |
||
278 | { |
||
279 | mkv_seekhead_entry *entries = seekhead->entries; |
||
280 | |||
281 | // don't store more elements than we reserved space for
|
||
282 | if (seekhead->max_entries > 0 && seekhead->max_entries <= seekhead->num_entries) |
||
283 | return -1; |
||
284 | |||
285 | entries = av_realloc(entries, (seekhead->num_entries + 1) * sizeof(mkv_seekhead_entry)); |
||
286 | if (entries == NULL) |
||
287 | 0b38843a | David Conrad | return AVERROR(ENOMEM);
|
288 | 967d815a | David Conrad | |
289 | 91ca9690 | David Conrad | entries[seekhead->num_entries ].elementid = elementid; |
290 | entries[seekhead->num_entries++].segmentpos = filepos - seekhead->segment_offset; |
||
291 | 967d815a | David Conrad | |
292 | seekhead->entries = entries; |
||
293 | return 0; |
||
294 | } |
||
295 | |||
296 | 57848e9a | David Conrad | /**
|
297 | cfde5d18 | David Conrad | * Write the seek head to the file and free it. If a maximum number of
|
298 | * elements was specified to mkv_start_seekhead(), the seek head will
|
||
299 | * be written at the location reserved for it. Otherwise, it is written
|
||
300 | * at the current location in the file.
|
||
301 | 57848e9a | David Conrad | *
|
302 | 7a2a4840 | David Conrad | * @return The file offset where the seekhead was written,
|
303 | * -1 if an error occurred.
|
||
304 | 57848e9a | David Conrad | */
|
305 | bc5c918e | Diego Biurrun | static int64_t mkv_write_seekhead(ByteIOContext *pb, mkv_seekhead *seekhead)
|
306 | 967d815a | David Conrad | { |
307 | baf71dca | David Conrad | ebml_master metaseek, seekentry; |
308 | bc5c918e | Diego Biurrun | int64_t currentpos; |
309 | 967d815a | David Conrad | int i;
|
310 | |||
311 | currentpos = url_ftell(pb); |
||
312 | |||
313 | if (seekhead->reserved_size > 0) |
||
314 | 7a2a4840 | David Conrad | if (url_fseek(pb, seekhead->filepos, SEEK_SET) < 0) |
315 | return -1; |
||
316 | 967d815a | David Conrad | |
317 | baf71dca | David Conrad | metaseek = start_ebml_master(pb, MATROSKA_ID_SEEKHEAD, seekhead->reserved_size); |
318 | 967d815a | David Conrad | for (i = 0; i < seekhead->num_entries; i++) { |
319 | mkv_seekhead_entry *entry = &seekhead->entries[i]; |
||
320 | |||
321 | baf71dca | David Conrad | seekentry = start_ebml_master(pb, MATROSKA_ID_SEEKENTRY, MAX_SEEKENTRY_SIZE); |
322 | 967d815a | David Conrad | |
323 | put_ebml_id(pb, MATROSKA_ID_SEEKID); |
||
324 | 0f651e8c | David Conrad | put_ebml_num(pb, ebml_id_size(entry->elementid), 0);
|
325 | 967d815a | David Conrad | put_ebml_id(pb, entry->elementid); |
326 | |||
327 | put_ebml_uint(pb, MATROSKA_ID_SEEKPOSITION, entry->segmentpos); |
||
328 | end_ebml_master(pb, seekentry); |
||
329 | } |
||
330 | end_ebml_master(pb, metaseek); |
||
331 | |||
332 | if (seekhead->reserved_size > 0) { |
||
333 | uint64_t remaining = seekhead->filepos + seekhead->reserved_size - url_ftell(pb); |
||
334 | put_ebml_void(pb, remaining); |
||
335 | url_fseek(pb, currentpos, SEEK_SET); |
||
336 | |||
337 | currentpos = seekhead->filepos; |
||
338 | } |
||
339 | av_free(seekhead->entries); |
||
340 | av_free(seekhead); |
||
341 | |||
342 | return currentpos;
|
||
343 | } |
||
344 | |||
345 | bc5c918e | Diego Biurrun | static mkv_cues * mkv_start_cues(int64_t segment_offset)
|
346 | 6364d534 | David Conrad | { |
347 | mkv_cues *cues = av_mallocz(sizeof(mkv_cues));
|
||
348 | if (cues == NULL) |
||
349 | return NULL; |
||
350 | |||
351 | cues->segment_offset = segment_offset; |
||
352 | return cues;
|
||
353 | } |
||
354 | |||
355 | 84d4e599 | David Conrad | static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t cluster_pos) |
356 | 6364d534 | David Conrad | { |
357 | mkv_cuepoint *entries = cues->entries; |
||
358 | |||
359 | entries = av_realloc(entries, (cues->num_entries + 1) * sizeof(mkv_cuepoint)); |
||
360 | if (entries == NULL) |
||
361 | 0b38843a | David Conrad | return AVERROR(ENOMEM);
|
362 | 6364d534 | David Conrad | |
363 | f9ff7179 | David Conrad | if (ts < 0) |
364 | return 0; |
||
365 | |||
366 | 84d4e599 | David Conrad | entries[cues->num_entries ].pts = ts; |
367 | entries[cues->num_entries ].tracknum = stream + 1;
|
||
368 | 91ca9690 | David Conrad | entries[cues->num_entries++].cluster_pos = cluster_pos - cues->segment_offset; |
369 | 6364d534 | David Conrad | |
370 | cues->entries = entries; |
||
371 | return 0; |
||
372 | } |
||
373 | |||
374 | bc5c918e | Diego Biurrun | static int64_t mkv_write_cues(ByteIOContext *pb, mkv_cues *cues, int num_tracks) |
375 | 6364d534 | David Conrad | { |
376 | baf71dca | David Conrad | ebml_master cues_element; |
377 | bc5c918e | Diego Biurrun | int64_t currentpos; |
378 | 6364d534 | David Conrad | int i, j;
|
379 | |||
380 | currentpos = url_ftell(pb); |
||
381 | baf71dca | David Conrad | cues_element = start_ebml_master(pb, MATROSKA_ID_CUES, 0);
|
382 | 6364d534 | David Conrad | |
383 | for (i = 0; i < cues->num_entries; i++) { |
||
384 | baf71dca | David Conrad | ebml_master cuepoint, track_positions; |
385 | 6364d534 | David Conrad | mkv_cuepoint *entry = &cues->entries[i]; |
386 | uint64_t pts = entry->pts; |
||
387 | |||
388 | baf71dca | David Conrad | cuepoint = start_ebml_master(pb, MATROSKA_ID_POINTENTRY, MAX_CUEPOINT_SIZE(num_tracks)); |
389 | 6364d534 | David Conrad | put_ebml_uint(pb, MATROSKA_ID_CUETIME, pts); |
390 | |||
391 | // put all the entries from different tracks that have the exact same
|
||
392 | // timestamp into the same CuePoint
|
||
393 | for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) { |
||
394 | baf71dca | David Conrad | track_positions = start_ebml_master(pb, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); |
395 | 6364d534 | David Conrad | put_ebml_uint(pb, MATROSKA_ID_CUETRACK , entry[j].tracknum ); |
396 | put_ebml_uint(pb, MATROSKA_ID_CUECLUSTERPOSITION, entry[j].cluster_pos); |
||
397 | end_ebml_master(pb, track_positions); |
||
398 | } |
||
399 | i += j - 1;
|
||
400 | end_ebml_master(pb, cuepoint); |
||
401 | } |
||
402 | end_ebml_master(pb, cues_element); |
||
403 | |||
404 | av_free(cues->entries); |
||
405 | av_free(cues); |
||
406 | return currentpos;
|
||
407 | } |
||
408 | |||
409 | b62a33d0 | David Conrad | static int put_xiph_codecpriv(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec) |
410 | 56d55a3b | David Conrad | { |
411 | uint8_t *header_start[3];
|
||
412 | int header_len[3]; |
||
413 | int first_header_size;
|
||
414 | 86be6637 | David Conrad | int j;
|
415 | 56d55a3b | David Conrad | |
416 | if (codec->codec_id == CODEC_ID_VORBIS)
|
||
417 | first_header_size = 30;
|
||
418 | else
|
||
419 | first_header_size = 42;
|
||
420 | |||
421 | if (ff_split_xiph_headers(codec->extradata, codec->extradata_size,
|
||
422 | first_header_size, header_start, header_len) < 0) {
|
||
423 | b62a33d0 | David Conrad | av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
|
424 | 56d55a3b | David Conrad | return -1; |
425 | } |
||
426 | |||
427 | put_byte(pb, 2); // number packets - 1 |
||
428 | for (j = 0; j < 2; j++) { |
||
429 | 86be6637 | David Conrad | put_xiph_size(pb, header_len[j]); |
430 | 56d55a3b | David Conrad | } |
431 | for (j = 0; j < 3; j++) |
||
432 | put_buffer(pb, header_start[j], header_len[j]); |
||
433 | 801edb42 | David Conrad | |
434 | return 0; |
||
435 | 56d55a3b | David Conrad | } |
436 | 67143c0f | David Conrad | |
437 | b62a33d0 | David Conrad | static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, int *sample_rate, int *output_sample_rate) |
438 | 07918a22 | David Conrad | { |
439 | int sri;
|
||
440 | |||
441 | if (codec->extradata_size < 2) { |
||
442 | ab332d01 | David Conrad | av_log(s, AV_LOG_WARNING, "No AAC extradata, unable to determine samplerate.\n");
|
443 | 07918a22 | David Conrad | return;
|
444 | } |
||
445 | |||
446 | sri = ((codec->extradata[0] << 1) & 0xE) | (codec->extradata[1] >> 7); |
||
447 | if (sri > 12) { |
||
448 | b62a33d0 | David Conrad | av_log(s, AV_LOG_WARNING, "AAC samplerate index out of bounds\n");
|
449 | 07918a22 | David Conrad | return;
|
450 | } |
||
451 | 7bfacd4e | Aurelien Jacobs | *sample_rate = ff_mpeg4audio_sample_rates[sri]; |
452 | 07918a22 | David Conrad | |
453 | // if sbr, get output sample rate as well
|
||
454 | if (codec->extradata_size == 5) { |
||
455 | sri = (codec->extradata[4] >> 3) & 0xF; |
||
456 | if (sri > 12) { |
||
457 | b62a33d0 | David Conrad | av_log(s, AV_LOG_WARNING, "AAC output samplerate index out of bounds\n");
|
458 | 07918a22 | David Conrad | return;
|
459 | } |
||
460 | 7bfacd4e | Aurelien Jacobs | *output_sample_rate = ff_mpeg4audio_sample_rates[sri]; |
461 | 07918a22 | David Conrad | } |
462 | } |
||
463 | |||
464 | f009e36f | Aurelien Jacobs | static int mkv_write_codecprivate(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec, int native_id, int qt_id) |
465 | 5c559894 | David Conrad | { |
466 | 899681cd | Björn Axelsson | ByteIOContext *dyn_cp; |
467 | 46d18a88 | David Conrad | uint8_t *codecpriv; |
468 | 899681cd | Björn Axelsson | int ret, codecpriv_size;
|
469 | 46d18a88 | David Conrad | |
470 | 899681cd | Björn Axelsson | ret = url_open_dyn_buf(&dyn_cp); |
471 | if(ret < 0) |
||
472 | return ret;
|
||
473 | 5c559894 | David Conrad | |
474 | if (native_id) {
|
||
475 | c301d5ae | David Conrad | if (codec->codec_id == CODEC_ID_VORBIS || codec->codec_id == CODEC_ID_THEORA)
|
476 | 899681cd | Björn Axelsson | ret = put_xiph_codecpriv(s, dyn_cp, codec); |
477 | c301d5ae | David Conrad | else if (codec->codec_id == CODEC_ID_FLAC) |
478 | 66061a12 | James Darnley | ret = ff_flac_write_header(dyn_cp, codec, 1);
|
479 | aacc5f22 | Aurelien Jacobs | else if (codec->codec_id == CODEC_ID_H264) |
480 | 9ab3f71b | Aurelien Jacobs | ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_size); |
481 | c301d5ae | David Conrad | else if (codec->extradata_size) |
482 | 899681cd | Björn Axelsson | put_buffer(dyn_cp, codec->extradata, codec->extradata_size); |
483 | 72415b2a | Stefano Sabatini | } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { |
484 | f009e36f | Aurelien Jacobs | if (qt_id) {
|
485 | if (!codec->codec_tag)
|
||
486 | 1a40491e | Daniel Verkamp | codec->codec_tag = ff_codec_get_tag(codec_movvideo_tags, codec->codec_id); |
487 | f009e36f | Aurelien Jacobs | if (codec->extradata_size)
|
488 | put_buffer(dyn_cp, codec->extradata, codec->extradata_size); |
||
489 | } else {
|
||
490 | 434a70b8 | David Conrad | if (!codec->codec_tag)
|
491 | codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id); |
||
492 | if (!codec->codec_tag) {
|
||
493 | f75ab7a6 | Jai Menon | av_log(s, AV_LOG_ERROR, "No bmp codec ID found.\n");
|
494 | 434a70b8 | David Conrad | ret = -1;
|
495 | } |
||
496 | 5c559894 | David Conrad | |
497 | 434a70b8 | David Conrad | ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0);
|
498 | f009e36f | Aurelien Jacobs | } |
499 | 5c559894 | David Conrad | |
500 | 72415b2a | Stefano Sabatini | } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
501 | 4896dd57 | Jai Menon | unsigned int tag; |
502 | tag = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_id); |
||
503 | if (!tag) {
|
||
504 | f75ab7a6 | Jai Menon | av_log(s, AV_LOG_ERROR, "No wav codec ID found.\n");
|
505 | 46d18a88 | David Conrad | ret = -1;
|
506 | 5c559894 | David Conrad | } |
507 | 4896dd57 | Jai Menon | if (!codec->codec_tag)
|
508 | codec->codec_tag = tag; |
||
509 | 5c559894 | David Conrad | |
510 | 1a40491e | Daniel Verkamp | ff_put_wav_header(dyn_cp, codec); |
511 | 5c559894 | David Conrad | } |
512 | 46d18a88 | David Conrad | |
513 | 899681cd | Björn Axelsson | codecpriv_size = url_close_dyn_buf(dyn_cp, &codecpriv); |
514 | 46d18a88 | David Conrad | if (codecpriv_size)
|
515 | put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, codecpriv_size); |
||
516 | av_free(codecpriv); |
||
517 | return ret;
|
||
518 | 5c559894 | David Conrad | } |
519 | |||
520 | 5034ab90 | David Conrad | static int mkv_write_tracks(AVFormatContext *s) |
521 | 67143c0f | David Conrad | { |
522 | MatroskaMuxContext *mkv = s->priv_data; |
||
523 | 899681cd | Björn Axelsson | ByteIOContext *pb = s->pb; |
524 | baf71dca | David Conrad | ebml_master tracks; |
525 | 6d588ecd | David Conrad | int i, j, ret;
|
526 | 67143c0f | David Conrad | |
527 | 6d588ecd | David Conrad | ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TRACKS, url_ftell(pb)); |
528 | if (ret < 0) return ret; |
||
529 | 967d815a | David Conrad | |
530 | baf71dca | David Conrad | tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS, 0);
|
531 | 67143c0f | David Conrad | for (i = 0; i < s->nb_streams; i++) { |
532 | AVStream *st = s->streams[i]; |
||
533 | f622c4f4 | David Conrad | AVCodecContext *codec = st->codec; |
534 | baf71dca | David Conrad | ebml_master subinfo, track; |
535 | f622c4f4 | David Conrad | int native_id = 0; |
536 | f009e36f | Aurelien Jacobs | int qt_id = 0; |
537 | d22f88cb | David Conrad | int bit_depth = av_get_bits_per_sample(codec->codec_id);
|
538 | 07918a22 | David Conrad | int sample_rate = codec->sample_rate;
|
539 | int output_sample_rate = 0; |
||
540 | 5e565998 | Aurelien Jacobs | AVMetadataTag *tag; |
541 | 07918a22 | David Conrad | |
542 | a6da1aa0 | David Conrad | if (!bit_depth)
|
543 | bit_depth = av_get_bits_per_sample_format(codec->sample_fmt); |
||
544 | |||
545 | 07918a22 | David Conrad | if (codec->codec_id == CODEC_ID_AAC)
|
546 | b62a33d0 | David Conrad | get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate); |
547 | f622c4f4 | David Conrad | |
548 | baf71dca | David Conrad | track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0);
|
549 | 815eb6a2 | David Conrad | put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1);
|
550 | put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1);
|
||
551 | f622c4f4 | David Conrad | put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) |
552 | |||
553 | 690b4126 | Anton Khirnov | if ((tag = av_metadata_get(st->metadata, "title", NULL, 0))) |
554 | 5e565998 | Aurelien Jacobs | put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value); |
555 | tag = av_metadata_get(st->metadata, "language", NULL, 0); |
||
556 | put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag ? tag->value:"und");
|
||
557 | f622c4f4 | David Conrad | |
558 | 1c3db2aa | David Conrad | if (st->disposition)
|
559 | 3194b004 | David Conrad | put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition & AV_DISPOSITION_DEFAULT)); |
560 | 90c2295b | Evgeniy Stepanov | |
561 | ab332d01 | David Conrad | // look for a codec ID string specific to mkv to use,
|
562 | cfde5d18 | David Conrad | // if none are found, use AVI codes
|
563 | f622c4f4 | David Conrad | for (j = 0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++) { |
564 | if (ff_mkv_codec_tags[j].id == codec->codec_id) {
|
||
565 | put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str); |
||
566 | native_id = 1;
|
||
567 | break;
|
||
568 | } |
||
569 | } |
||
570 | |||
571 | 316d6c15 | James Zern | if (mkv->mode == MODE_WEBM && !(codec->codec_id == CODEC_ID_VP8 ||
|
572 | codec->codec_id == CODEC_ID_VORBIS)) { |
||
573 | av_log(s, AV_LOG_ERROR, |
||
574 | "Only VP8 video and Vorbis audio are supported for WebM.\n");
|
||
575 | return AVERROR(EINVAL);
|
||
576 | } |
||
577 | |||
578 | f622c4f4 | David Conrad | switch (codec->codec_type) {
|
579 | 72415b2a | Stefano Sabatini | case AVMEDIA_TYPE_VIDEO:
|
580 | f622c4f4 | David Conrad | put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO); |
581 | 7bb83d8d | David Conrad | put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, av_q2d(codec->time_base)*1E9);
|
582 | f622c4f4 | David Conrad | |
583 | f009e36f | Aurelien Jacobs | if (!native_id &&
|
584 | 1a40491e | Daniel Verkamp | ff_codec_get_tag(codec_movvideo_tags, codec->codec_id) && |
585 | (!ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id) |
||
586 | f009e36f | Aurelien Jacobs | || codec->codec_id == CODEC_ID_SVQ1 |
587 | || codec->codec_id == CODEC_ID_SVQ3 |
||
588 | || codec->codec_id == CODEC_ID_CINEPAK)) |
||
589 | qt_id = 1;
|
||
590 | |||
591 | if (qt_id)
|
||
592 | put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME");
|
||
593 | 84d4e599 | David Conrad | else if (!native_id) { |
594 | ab332d01 | David Conrad | // if there is no mkv-specific codec ID, use VFW mode
|
595 | cc8be506 | Aurelien Jacobs | put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC");
|
596 | 84d4e599 | David Conrad | mkv->tracks[i].write_dts = 1;
|
597 | } |
||
598 | c301d5ae | David Conrad | |
599 | baf71dca | David Conrad | subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0);
|
600 | f622c4f4 | David Conrad | // XXX: interlace flag?
|
601 | put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width); |
||
602 | put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); |
||
603 | 59729451 | Aurelien Jacobs | if (st->sample_aspect_ratio.num) {
|
604 | int d_width = codec->width*av_q2d(st->sample_aspect_ratio);
|
||
605 | put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width); |
||
606 | put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height); |
||
607 | 7332addd | David Conrad | } |
608 | f622c4f4 | David Conrad | end_ebml_master(pb, subinfo); |
609 | break;
|
||
610 | |||
611 | 72415b2a | Stefano Sabatini | case AVMEDIA_TYPE_AUDIO:
|
612 | f622c4f4 | David Conrad | put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); |
613 | |||
614 | c301d5ae | David Conrad | if (!native_id)
|
615 | 1a302a5c | David Conrad | // no mkv-specific ID, use ACM mode
|
616 | cc8be506 | Aurelien Jacobs | put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM");
|
617 | c301d5ae | David Conrad | |
618 | baf71dca | David Conrad | subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0);
|
619 | f622c4f4 | David Conrad | put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , codec->channels); |
620 | 07918a22 | David Conrad | put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate); |
621 | if (output_sample_rate)
|
||
622 | put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); |
||
623 | 44008871 | David Conrad | if (bit_depth)
|
624 | put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth); |
||
625 | f622c4f4 | David Conrad | end_ebml_master(pb, subinfo); |
626 | break;
|
||
627 | |||
628 | 72415b2a | Stefano Sabatini | case AVMEDIA_TYPE_SUBTITLE:
|
629 | 47e08c58 | David Conrad | put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_SUBTITLE); |
630 | break;
|
||
631 | f622c4f4 | David Conrad | default:
|
632 | 3967eb52 | David Conrad | av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.");
|
633 | f622c4f4 | David Conrad | break;
|
634 | } |
||
635 | f009e36f | Aurelien Jacobs | ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id); |
636 | 5c559894 | David Conrad | if (ret < 0) return ret; |
637 | |||
638 | 67143c0f | David Conrad | end_ebml_master(pb, track); |
639 | f622c4f4 | David Conrad | |
640 | // ms precision is the de-facto standard timescale for mkv files
|
||
641 | av_set_pts_info(st, 64, 1, 1000); |
||
642 | 67143c0f | David Conrad | } |
643 | end_ebml_master(pb, tracks); |
||
644 | 801edb42 | David Conrad | return 0; |
645 | 5034ab90 | David Conrad | } |
646 | |||
647 | 2bd0758e | Anton Khirnov | static int mkv_write_chapters(AVFormatContext *s) |
648 | { |
||
649 | MatroskaMuxContext *mkv = s->priv_data; |
||
650 | ByteIOContext *pb = s->pb; |
||
651 | ebml_master chapters, editionentry; |
||
652 | AVRational scale = {1, 1E9}; |
||
653 | int i, ret;
|
||
654 | |||
655 | if (!s->nb_chapters)
|
||
656 | return 0; |
||
657 | |||
658 | ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CHAPTERS, url_ftell(pb)); |
||
659 | if (ret < 0) return ret; |
||
660 | |||
661 | chapters = start_ebml_master(pb, MATROSKA_ID_CHAPTERS , 0);
|
||
662 | editionentry = start_ebml_master(pb, MATROSKA_ID_EDITIONENTRY, 0);
|
||
663 | put_ebml_uint(pb, MATROSKA_ID_EDITIONFLAGDEFAULT, 1);
|
||
664 | put_ebml_uint(pb, MATROSKA_ID_EDITIONFLAGHIDDEN , 0);
|
||
665 | for (i = 0; i < s->nb_chapters; i++) { |
||
666 | ebml_master chapteratom, chapterdisplay; |
||
667 | AVChapter *c = s->chapters[i]; |
||
668 | AVMetadataTag *t = NULL;
|
||
669 | |||
670 | chapteratom = start_ebml_master(pb, MATROSKA_ID_CHAPTERATOM, 0);
|
||
671 | put_ebml_uint(pb, MATROSKA_ID_CHAPTERUID, c->id); |
||
672 | put_ebml_uint(pb, MATROSKA_ID_CHAPTERTIMESTART, |
||
673 | av_rescale_q(c->start, c->time_base, scale)); |
||
674 | put_ebml_uint(pb, MATROSKA_ID_CHAPTERTIMEEND, |
||
675 | av_rescale_q(c->end, c->time_base, scale)); |
||
676 | put_ebml_uint(pb, MATROSKA_ID_CHAPTERFLAGHIDDEN , 0);
|
||
677 | put_ebml_uint(pb, MATROSKA_ID_CHAPTERFLAGENABLED, 1);
|
||
678 | if ((t = av_metadata_get(c->metadata, "title", NULL, 0))) { |
||
679 | chapterdisplay = start_ebml_master(pb, MATROSKA_ID_CHAPTERDISPLAY, 0);
|
||
680 | put_ebml_string(pb, MATROSKA_ID_CHAPSTRING, t->value); |
||
681 | put_ebml_string(pb, MATROSKA_ID_CHAPLANG , "und");
|
||
682 | end_ebml_master(pb, chapterdisplay); |
||
683 | } |
||
684 | end_ebml_master(pb, chapteratom); |
||
685 | } |
||
686 | end_ebml_master(pb, editionentry); |
||
687 | end_ebml_master(pb, chapters); |
||
688 | return 0; |
||
689 | } |
||
690 | |||
691 | 5034ab90 | David Conrad | static int mkv_write_header(AVFormatContext *s) |
692 | { |
||
693 | MatroskaMuxContext *mkv = s->priv_data; |
||
694 | 899681cd | Björn Axelsson | ByteIOContext *pb = s->pb; |
695 | baf71dca | David Conrad | ebml_master ebml_header, segment_info; |
696 | 5e565998 | Aurelien Jacobs | AVMetadataTag *tag; |
697 | 1f4280e7 | David Conrad | int ret, i;
|
698 | 5034ab90 | David Conrad | |
699 | 316d6c15 | James Zern | if (!strcmp(s->oformat->name, "webm")) mkv->mode = MODE_WEBM; |
700 | else mkv->mode = MODE_MATROSKAv2;
|
||
701 | |||
702 | 1f4280e7 | David Conrad | av_lfg_init(&mkv->lfg, av_get_random_seed()); |
703 | |||
704 | 84d4e599 | David Conrad | mkv->tracks = av_mallocz(s->nb_streams * sizeof(*mkv->tracks));
|
705 | d06735a3 | David Conrad | if (!mkv->tracks)
|
706 | return AVERROR(ENOMEM);
|
||
707 | 541d443c | David Conrad | |
708 | baf71dca | David Conrad | ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0);
|
709 | 5034ab90 | David Conrad | put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1);
|
710 | put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1);
|
||
711 | put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4);
|
||
712 | put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8);
|
||
713 | 316d6c15 | James Zern | put_ebml_string (pb, EBML_ID_DOCTYPE , s->oformat->name); |
714 | 5034ab90 | David Conrad | put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 2);
|
715 | put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 2);
|
||
716 | end_ebml_master(pb, ebml_header); |
||
717 | |||
718 | baf71dca | David Conrad | mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0);
|
719 | 967d815a | David Conrad | mkv->segment_offset = url_ftell(pb); |
720 | |||
721 | cfde5d18 | David Conrad | // we write 2 seek heads - one at the end of the file to point to each
|
722 | // cluster, and one at the beginning to point to all other level one
|
||
723 | // elements (including the seek head at the end of the file), which
|
||
724 | // isn't more than 10 elements if we only write one of each other
|
||
725 | // currently defined level 1 element
|
||
726 | 967d815a | David Conrad | mkv->main_seekhead = mkv_start_seekhead(pb, mkv->segment_offset, 10);
|
727 | e7ddafd5 | David Conrad | if (!mkv->main_seekhead)
|
728 | c35de1a1 | David Conrad | return AVERROR(ENOMEM);
|
729 | 967d815a | David Conrad | |
730 | 6d588ecd | David Conrad | ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, url_ftell(pb)); |
731 | if (ret < 0) return ret; |
||
732 | 5034ab90 | David Conrad | |
733 | baf71dca | David Conrad | segment_info = start_ebml_master(pb, MATROSKA_ID_INFO, 0);
|
734 | 5034ab90 | David Conrad | put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
|
735 | 5e565998 | Aurelien Jacobs | if ((tag = av_metadata_get(s->metadata, "title", NULL, 0))) |
736 | put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value); |
||
737 | 5034ab90 | David Conrad | if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { |
738 | 1f4280e7 | David Conrad | uint32_t segment_uid[4];
|
739 | for (i = 0; i < 4; i++) |
||
740 | segment_uid[i] = av_lfg_get(&mkv->lfg); |
||
741 | |||
742 | 5fd35c6e | David Conrad | put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , LIBAVFORMAT_IDENT); |
743 | 5034ab90 | David Conrad | put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT); |
744 | 1f4280e7 | David Conrad | put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16);
|
745 | 5034ab90 | David Conrad | } |
746 | 4b8f58ee | David Conrad | |
747 | 5034ab90 | David Conrad | // reserve space for the duration
|
748 | mkv->duration = 0;
|
||
749 | mkv->duration_offset = url_ftell(pb); |
||
750 | put_ebml_void(pb, 11); // assumes double-precision float to be written |
||
751 | end_ebml_master(pb, segment_info); |
||
752 | |||
753 | 6d588ecd | David Conrad | ret = mkv_write_tracks(s); |
754 | if (ret < 0) return ret; |
||
755 | 67143c0f | David Conrad | |
756 | 316d6c15 | James Zern | if (mkv->mode != MODE_WEBM) {
|
757 | ret = mkv_write_chapters(s); |
||
758 | if (ret < 0) return ret; |
||
759 | } |
||
760 | 2bd0758e | Anton Khirnov | |
761 | 7a2a4840 | David Conrad | if (url_is_streamed(s->pb))
|
762 | mkv_write_seekhead(pb, mkv->main_seekhead); |
||
763 | |||
764 | 6364d534 | David Conrad | mkv->cues = mkv_start_cues(mkv->segment_offset); |
765 | if (mkv->cues == NULL) |
||
766 | 0b38843a | David Conrad | return AVERROR(ENOMEM);
|
767 | 6364d534 | David Conrad | |
768 | ac9baa71 | James Zern | av_init_packet(&mkv->cur_audio_pkt); |
769 | mkv->cur_audio_pkt.size = 0;
|
||
770 | mkv->audio_buffer_size = 0;
|
||
771 | |||
772 | 8a86aaa3 | David Conrad | put_flush_packet(pb); |
773 | 67143c0f | David Conrad | return 0; |
774 | } |
||
775 | |||
776 | 1bfbe8ff | Aurelien Jacobs | static int mkv_blockgroup_size(int pkt_size) |
777 | baf71dca | David Conrad | { |
778 | 1bfbe8ff | Aurelien Jacobs | int size = pkt_size + 4; |
779 | 0f651e8c | David Conrad | size += ebml_num_size(size); |
780 | baf71dca | David Conrad | size += 2; // EBML ID for block and block duration |
781 | size += 8; // max size of block duration |
||
782 | 0f651e8c | David Conrad | size += ebml_num_size(size); |
783 | baf71dca | David Conrad | size += 1; // blockgroup EBML ID |
784 | return size;
|
||
785 | } |
||
786 | |||
787 | b7f4e76d | Aurelien Jacobs | static int ass_get_duration(const uint8_t *p) |
788 | { |
||
789 | int sh, sm, ss, sc, eh, em, es, ec;
|
||
790 | uint64_t start, end; |
||
791 | |||
792 | if (sscanf(p, "%*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d", |
||
793 | &sh, &sm, &ss, &sc, &eh, &em, &es, &ec) != 8)
|
||
794 | return 0; |
||
795 | start = 3600000*sh + 60000*sm + 1000*ss + 10*sc; |
||
796 | end = 3600000*eh + 60000*em + 1000*es + 10*ec; |
||
797 | return end - start;
|
||
798 | } |
||
799 | |||
800 | 871b641b | David Conrad | static int mkv_write_ass_blocks(AVFormatContext *s, ByteIOContext *pb, AVPacket *pkt) |
801 | b7f4e76d | Aurelien Jacobs | { |
802 | MatroskaMuxContext *mkv = s->priv_data; |
||
803 | int i, layer = 0, max_duration = 0, size, line_size, data_size = pkt->size; |
||
804 | uint8_t *start, *end, *data = pkt->data; |
||
805 | ebml_master blockgroup; |
||
806 | char buffer[2048]; |
||
807 | |||
808 | while (data_size) {
|
||
809 | int duration = ass_get_duration(data);
|
||
810 | max_duration = FFMAX(duration, max_duration); |
||
811 | end = memchr(data, '\n', data_size);
|
||
812 | size = line_size = end ? end-data+1 : data_size;
|
||
813 | size -= end ? (end[-1]=='\r')+1 : 0; |
||
814 | start = data; |
||
815 | for (i=0; i<3; i++, start++) |
||
816 | if (!(start = memchr(start, ',', size-(start-data)))) |
||
817 | return max_duration;
|
||
818 | size -= start - data; |
||
819 | sscanf(data, "Dialogue: %d,", &layer);
|
||
820 | i = snprintf(buffer, sizeof(buffer), "%"PRId64",%d,", |
||
821 | s->streams[pkt->stream_index]->nb_frames++, layer); |
||
822 | size = FFMIN(i+size, sizeof(buffer));
|
||
823 | memcpy(buffer+i, start, size-i); |
||
824 | |||
825 | av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " |
||
826 | "pts %" PRId64 ", duration %d\n", |
||
827 | url_ftell(pb), size, pkt->pts, duration); |
||
828 | blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(size)); |
||
829 | put_ebml_id(pb, MATROSKA_ID_BLOCK); |
||
830 | put_ebml_num(pb, size+4, 0); |
||
831 | put_byte(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 |
||
832 | put_be16(pb, pkt->pts - mkv->cluster_pts); |
||
833 | put_byte(pb, 0);
|
||
834 | put_buffer(pb, buffer, size); |
||
835 | put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); |
||
836 | end_ebml_master(pb, blockgroup); |
||
837 | |||
838 | data += line_size; |
||
839 | data_size -= line_size; |
||
840 | } |
||
841 | |||
842 | return max_duration;
|
||
843 | } |
||
844 | |||
845 | 871b641b | David Conrad | static void mkv_write_block(AVFormatContext *s, ByteIOContext *pb, |
846 | unsigned int blockid, AVPacket *pkt, int flags) |
||
847 | 95527e06 | David Conrad | { |
848 | MatroskaMuxContext *mkv = s->priv_data; |
||
849 | 0a63a676 | Luca Abeni | AVCodecContext *codec = s->streams[pkt->stream_index]->codec; |
850 | 5f8bae8d | Aurelien Jacobs | uint8_t *data = NULL;
|
851 | int size = pkt->size;
|
||
852 | 84d4e599 | David Conrad | int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; |
853 | 95527e06 | David Conrad | |
854 | 8ffc5f9e | David Conrad | av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " |
855 | "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n", |
||
856 | c1f5aa21 | David Conrad | url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags); |
857 | 5f8bae8d | Aurelien Jacobs | if (codec->codec_id == CODEC_ID_H264 && codec->extradata_size > 0 && |
858 | (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1)) |
||
859 | ff_avc_parse_nal_units_buf(pkt->data, &data, &size); |
||
860 | else
|
||
861 | data = pkt->data; |
||
862 | 95527e06 | David Conrad | put_ebml_id(pb, blockid); |
863 | 5f8bae8d | Aurelien Jacobs | put_ebml_num(pb, size+4, 0); |
864 | 95527e06 | David Conrad | put_byte(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 |
865 | 84d4e599 | David Conrad | put_be16(pb, ts - mkv->cluster_pts); |
866 | 95527e06 | David Conrad | put_byte(pb, flags); |
867 | 5f8bae8d | Aurelien Jacobs | put_buffer(pb, data, size); |
868 | if (data != pkt->data)
|
||
869 | av_free(data); |
||
870 | 95527e06 | David Conrad | } |
871 | |||
872 | 871b641b | David Conrad | static void mkv_flush_dynbuf(AVFormatContext *s) |
873 | { |
||
874 | MatroskaMuxContext *mkv = s->priv_data; |
||
875 | int bufsize;
|
||
876 | uint8_t *dyn_buf; |
||
877 | |||
878 | if (!mkv->dyn_bc)
|
||
879 | return;
|
||
880 | |||
881 | bufsize = url_close_dyn_buf(mkv->dyn_bc, &dyn_buf); |
||
882 | put_buffer(s->pb, dyn_buf, bufsize); |
||
883 | av_free(dyn_buf); |
||
884 | mkv->dyn_bc = NULL;
|
||
885 | } |
||
886 | |||
887 | ac9baa71 | James Zern | static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) |
888 | 67143c0f | David Conrad | { |
889 | 98186e41 | David Conrad | MatroskaMuxContext *mkv = s->priv_data; |
890 | 899681cd | Björn Axelsson | ByteIOContext *pb = s->pb; |
891 | 9245c5ca | David Conrad | AVCodecContext *codec = s->streams[pkt->stream_index]->codec; |
892 | cc947f04 | Jean-Daniel Dupas | int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY);
|
893 | 62c24705 | Aurelien Jacobs | int duration = pkt->duration;
|
894 | 6d588ecd | David Conrad | int ret;
|
895 | 84d4e599 | David Conrad | int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; |
896 | b1adb69c | David Conrad | |
897 | 654b65d0 | David Conrad | if (ts == AV_NOPTS_VALUE) {
|
898 | av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n");
|
||
899 | return AVERROR(EINVAL);
|
||
900 | } |
||
901 | |||
902 | 871b641b | David Conrad | if (url_is_streamed(s->pb)) {
|
903 | if (!mkv->dyn_bc)
|
||
904 | url_open_dyn_buf(&mkv->dyn_bc); |
||
905 | pb = mkv->dyn_bc; |
||
906 | } |
||
907 | |||
908 | 30f06a58 | David Conrad | if (!mkv->cluster_pos) {
|
909 | 871b641b | David Conrad | mkv->cluster_pos = url_ftell(s->pb); |
910 | baf71dca | David Conrad | mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0);
|
911 | f9ff7179 | David Conrad | put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts));
|
912 | mkv->cluster_pts = FFMAX(0, ts);
|
||
913 | 98186e41 | David Conrad | } |
914 | |||
915 | 72415b2a | Stefano Sabatini | if (codec->codec_type != AVMEDIA_TYPE_SUBTITLE) {
|
916 | 871b641b | David Conrad | mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7);
|
917 | b7f4e76d | Aurelien Jacobs | } else if (codec->codec_id == CODEC_ID_SSA) { |
918 | 871b641b | David Conrad | duration = mkv_write_ass_blocks(s, pb, pkt); |
919 | 663a5d9d | David Conrad | } else {
|
920 | 1bfbe8ff | Aurelien Jacobs | ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt->size)); |
921 | 62c24705 | Aurelien Jacobs | duration = pkt->convergence_duration; |
922 | 871b641b | David Conrad | mkv_write_block(s, pb, MATROSKA_ID_BLOCK, pkt, 0);
|
923 | 291902c2 | Aurelien Jacobs | put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); |
924 | 663a5d9d | David Conrad | end_ebml_master(pb, blockgroup); |
925 | } |
||
926 | 02f487fc | David Conrad | |
927 | 72415b2a | Stefano Sabatini | if (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe) {
|
928 | 84d4e599 | David Conrad | ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos); |
929 | 6d588ecd | David Conrad | if (ret < 0) return ret; |
930 | 6364d534 | David Conrad | } |
931 | |||
932 | ac9baa71 | James Zern | mkv->duration = FFMAX(mkv->duration, ts + duration); |
933 | return 0; |
||
934 | } |
||
935 | |||
936 | static int mkv_copy_packet(MatroskaMuxContext *mkv, const AVPacket *pkt) |
||
937 | { |
||
938 | uint8_t *data = mkv->cur_audio_pkt.data; |
||
939 | mkv->cur_audio_pkt = *pkt; |
||
940 | mkv->cur_audio_pkt.data = av_fast_realloc(data, &mkv->audio_buffer_size, pkt->size); |
||
941 | if (!mkv->cur_audio_pkt.data)
|
||
942 | return AVERROR(ENOMEM);
|
||
943 | |||
944 | memcpy(mkv->cur_audio_pkt.data, pkt->data, pkt->size); |
||
945 | mkv->cur_audio_pkt.size = pkt->size; |
||
946 | return 0; |
||
947 | } |
||
948 | |||
949 | static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) |
||
950 | { |
||
951 | MatroskaMuxContext *mkv = s->priv_data; |
||
952 | ByteIOContext *pb = url_is_streamed(s->pb) ? mkv->dyn_bc : s->pb; |
||
953 | AVCodecContext *codec = s->streams[pkt->stream_index]->codec; |
||
954 | int ret, keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY);
|
||
955 | int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; |
||
956 | int cluster_size = url_ftell(pb) - (url_is_streamed(s->pb) ? 0 : mkv->cluster_pos); |
||
957 | |||
958 | // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or
|
||
959 | // after 4k and on a keyframe
|
||
960 | if (mkv->cluster_pos &&
|
||
961 | ((url_is_streamed(s->pb) && (cluster_size > 32*1024 || ts > mkv->cluster_pts + 1000)) |
||
962 | || cluster_size > 5*1024*1024 || ts > mkv->cluster_pts + 5000 |
||
963 | || (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe && cluster_size > 4*1024))) { |
||
964 | 30f06a58 | David Conrad | av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
|
965 | 84d4e599 | David Conrad | " bytes, pts %" PRIu64 "\n", url_ftell(pb), ts); |
966 | 30f06a58 | David Conrad | end_ebml_master(pb, mkv->cluster); |
967 | mkv->cluster_pos = 0;
|
||
968 | 871b641b | David Conrad | if (mkv->dyn_bc)
|
969 | mkv_flush_dynbuf(s); |
||
970 | 30f06a58 | David Conrad | } |
971 | |||
972 | ac9baa71 | James Zern | // check if we have an audio packet cached
|
973 | if (mkv->cur_audio_pkt.size > 0) { |
||
974 | ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt); |
||
975 | mkv->cur_audio_pkt.size = 0;
|
||
976 | if (ret < 0) { |
||
977 | av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
|
||
978 | return ret;
|
||
979 | } |
||
980 | } |
||
981 | |||
982 | // buffer an audio packet to ensure the packet containing the video
|
||
983 | // keyframe's timecode is contained in the same cluster for WebM
|
||
984 | if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||
985 | ret = mkv_copy_packet(mkv, pkt); |
||
986 | else
|
||
987 | ret = mkv_write_packet_internal(s, pkt); |
||
988 | return ret;
|
||
989 | 67143c0f | David Conrad | } |
990 | |||
991 | static int mkv_write_trailer(AVFormatContext *s) |
||
992 | { |
||
993 | MatroskaMuxContext *mkv = s->priv_data; |
||
994 | 899681cd | Björn Axelsson | ByteIOContext *pb = s->pb; |
995 | e7ddafd5 | David Conrad | int64_t currentpos, cuespos; |
996 | 9e2a3e22 | David Conrad | int ret;
|
997 | 02f487fc | David Conrad | |
998 | ac9baa71 | James Zern | // check if we have an audio packet cached
|
999 | if (mkv->cur_audio_pkt.size > 0) { |
||
1000 | ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt); |
||
1001 | mkv->cur_audio_pkt.size = 0;
|
||
1002 | if (ret < 0) { |
||
1003 | av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret);
|
||
1004 | return ret;
|
||
1005 | } |
||
1006 | } |
||
1007 | |||
1008 | 871b641b | David Conrad | if (mkv->dyn_bc) {
|
1009 | end_ebml_master(mkv->dyn_bc, mkv->cluster); |
||
1010 | mkv_flush_dynbuf(s); |
||
1011 | } else if (mkv->cluster_pos) { |
||
1012 | end_ebml_master(pb, mkv->cluster); |
||
1013 | } |
||
1014 | 02f487fc | David Conrad | |
1015 | ac9e1177 | David Conrad | if (!url_is_streamed(pb)) {
|
1016 | e5c29287 | David Conrad | cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); |
1017 | 6364d534 | David Conrad | |
1018 | e5c29287 | David Conrad | ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES , cuespos); |
1019 | if (ret < 0) return ret; |
||
1020 | mkv_write_seekhead(pb, mkv->main_seekhead); |
||
1021 | |||
1022 | // update the duration
|
||
1023 | av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); |
||
1024 | currentpos = url_ftell(pb); |
||
1025 | url_fseek(pb, mkv->duration_offset, SEEK_SET); |
||
1026 | put_ebml_float(pb, MATROSKA_ID_DURATION, mkv->duration); |
||
1027 | |||
1028 | url_fseek(pb, currentpos, SEEK_SET); |
||
1029 | ac9e1177 | David Conrad | } |
1030 | 02f487fc | David Conrad | |
1031 | 67143c0f | David Conrad | end_ebml_master(pb, mkv->segment); |
1032 | 84d4e599 | David Conrad | av_free(mkv->tracks); |
1033 | ac9baa71 | James Zern | av_destruct_packet(&mkv->cur_audio_pkt); |
1034 | 8a86aaa3 | David Conrad | put_flush_packet(pb); |
1035 | 67143c0f | David Conrad | return 0; |
1036 | } |
||
1037 | |||
1038 | 316d6c15 | James Zern | #if CONFIG_MATROSKA_MUXER
|
1039 | 67143c0f | David Conrad | AVOutputFormat matroska_muxer = { |
1040 | "matroska",
|
||
1041 | bde15e74 | Stefano Sabatini | NULL_IF_CONFIG_SMALL("Matroska file format"),
|
1042 | 67143c0f | David Conrad | "video/x-matroska",
|
1043 | "mkv",
|
||
1044 | sizeof(MatroskaMuxContext),
|
||
1045 | CODEC_ID_MP2, |
||
1046 | CODEC_ID_MPEG4, |
||
1047 | mkv_write_header, |
||
1048 | mkv_write_packet, |
||
1049 | mkv_write_trailer, |
||
1050 | 25918212 | Michael Niedermayer | .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, |
1051 | 1a40491e | Daniel Verkamp | .codec_tag = (const AVCodecTag* const []){ff_codec_bmp_tags, ff_codec_wav_tags, 0}, |
1052 | c635497c | David Conrad | .subtitle_codec = CODEC_ID_TEXT, |
1053 | 67143c0f | David Conrad | }; |
1054 | 316d6c15 | James Zern | #endif
|
1055 | |||
1056 | #if CONFIG_WEBM_MUXER
|
||
1057 | AVOutputFormat webm_muxer = { |
||
1058 | "webm",
|
||
1059 | NULL_IF_CONFIG_SMALL("WebM file format"),
|
||
1060 | "video/webm",
|
||
1061 | "webm",
|
||
1062 | sizeof(MatroskaMuxContext),
|
||
1063 | CODEC_ID_VORBIS, |
||
1064 | CODEC_ID_VP8, |
||
1065 | mkv_write_header, |
||
1066 | mkv_write_packet, |
||
1067 | mkv_write_trailer, |
||
1068 | .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS, |
||
1069 | }; |
||
1070 | #endif
|
||
1071 | 55c151ef | David Conrad | |
1072 | 316d6c15 | James Zern | #if CONFIG_MATROSKA_AUDIO_MUXER
|
1073 | 55c151ef | David Conrad | AVOutputFormat matroska_audio_muxer = { |
1074 | "matroska",
|
||
1075 | bde15e74 | Stefano Sabatini | NULL_IF_CONFIG_SMALL("Matroska file format"),
|
1076 | 55c151ef | David Conrad | "audio/x-matroska",
|
1077 | "mka",
|
||
1078 | sizeof(MatroskaMuxContext),
|
||
1079 | CODEC_ID_MP2, |
||
1080 | CODEC_ID_NONE, |
||
1081 | mkv_write_header, |
||
1082 | mkv_write_packet, |
||
1083 | mkv_write_trailer, |
||
1084 | abce34d9 | Aurelien Jacobs | .flags = AVFMT_GLOBALHEADER, |
1085 | 1a40491e | Daniel Verkamp | .codec_tag = (const AVCodecTag* const []){ff_codec_wav_tags, 0}, |
1086 | 55c151ef | David Conrad | }; |
1087 | 316d6c15 | James Zern | #endif |