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