FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/matroskaenc.c
Date: 2024-04-24 18:52:15
Exec Total Coverage
Lines: 1607 1851 86.8%
Functions: 96 96 100.0%
Branches: 883 1175 75.1%

Line Branch Exec Source
1 /*
2 * Matroska muxer
3 * 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 <stdint.h>
23
24 #include "config_components.h"
25
26 #include "av1.h"
27 #include "avc.h"
28 #include "hevc.h"
29 #include "avformat.h"
30 #include "avio_internal.h"
31 #include "avlanguage.h"
32 #include "dovi_isom.h"
33 #include "flacenc.h"
34 #include "internal.h"
35 #include "isom.h"
36 #include "matroska.h"
37 #include "mux.h"
38 #include "riff.h"
39 #include "version.h"
40 #include "vorbiscomment.h"
41 #include "wv.h"
42
43 #include "libavutil/avstring.h"
44 #include "libavutil/channel_layout.h"
45 #include "libavutil/crc.h"
46 #include "libavutil/dict.h"
47 #include "libavutil/hdr_dynamic_metadata.h"
48 #include "libavutil/intfloat.h"
49 #include "libavutil/intreadwrite.h"
50 #include "libavutil/lfg.h"
51 #include "libavutil/mastering_display_metadata.h"
52 #include "libavutil/mathematics.h"
53 #include "libavutil/mem.h"
54 #include "libavutil/opt.h"
55 #include "libavutil/parseutils.h"
56 #include "libavutil/pixdesc.h"
57 #include "libavutil/random_seed.h"
58 #include "libavutil/rational.h"
59 #include "libavutil/samplefmt.h"
60 #include "libavutil/stereo3d.h"
61
62 #include "libavcodec/av1.h"
63 #include "libavcodec/bytestream.h"
64 #include "libavcodec/codec_desc.h"
65 #include "libavcodec/codec_par.h"
66 #include "libavcodec/defs.h"
67 #include "libavcodec/itut35.h"
68 #include "libavcodec/xiph.h"
69 #include "libavcodec/mpeg4audio.h"
70
71 /* Level 1 elements we create a SeekHead entry for:
72 * Info, Tracks, Chapters, Attachments, Tags (potentially twice) and Cues */
73 #define MAX_SEEKHEAD_ENTRIES 7
74
75 /* Largest known-length EBML length */
76 #define MAX_EBML_LENGTH ((1ULL << 56) - 2)
77 /* The dynamic buffer API we rely upon has a limit of INT_MAX;
78 * and so has avio_write(). */
79 #define MAX_SUPPORTED_EBML_LENGTH FFMIN(MAX_EBML_LENGTH, INT_MAX)
80
81 #define MODE_MATROSKAv2 0x01
82 #define MODE_WEBM 0x02
83
84 #define IS_WEBM(mkv) (CONFIG_WEBM_MUXER && CONFIG_MATROSKA_MUXER ? \
85 ((mkv)->mode == MODE_WEBM) : CONFIG_WEBM_MUXER)
86 #define IS_SEEKABLE(pb, mkv) (((pb)->seekable & AVIO_SEEKABLE_NORMAL) && \
87 !(mkv)->is_live)
88
89 enum {
90 DEFAULT_MODE_INFER,
91 DEFAULT_MODE_INFER_NO_SUBS,
92 DEFAULT_MODE_PASSTHROUGH,
93 };
94
95 typedef struct ebml_master {
96 int64_t pos; ///< absolute offset in the containing AVIOContext where the master's elements start
97 int sizebytes; ///< how many bytes were reserved for the size
98 } ebml_master;
99
100 typedef struct ebml_stored_master {
101 AVIOContext *bc;
102 int64_t pos;
103 } ebml_stored_master;
104
105 typedef enum EbmlType {
106 EBML_UINT,
107 EBML_SINT,
108 EBML_FLOAT,
109 EBML_UID,
110 EBML_STR,
111 EBML_UTF8 = EBML_STR,
112 EBML_BIN,
113 EBML_BLOCK, ///< pseudo-type for writing (Simple)Blocks
114 EBML_MASTER,
115 } EbmlType;
116
117 typedef struct BlockContext {
118 struct mkv_track *track;
119 const AVPacket *pkt;
120 int16_t rel_ts;
121 uint8_t flags;
122 NALUList h2645_nalu_list;
123 } BlockContext;
124
125 typedef struct EbmlMaster {
126 int nb_elements; ///< -1 if not finished
127 int containing_master; ///< -1 if no parent exists
128 } EbmlMaster;
129
130 typedef struct EbmlElement {
131 uint32_t id;
132 EbmlType type;
133 unsigned length_size;
134 uint64_t size; ///< excluding id and length field
135 union {
136 uint64_t uint;
137 int64_t sint;
138 double f;
139 const char *str;
140 const uint8_t *bin;
141 struct MatroskaMuxContext *mkv; ///< used by EBML_BLOCK
142 EbmlMaster master;
143 } priv;
144 } EbmlElement;
145
146 typedef struct EbmlWriter {
147 unsigned nb_elements;
148 int current_master_element;
149 EbmlElement *elements;
150 } EbmlWriter;
151
152 #define EBML_WRITER(max_nb_elems) \
153 EbmlElement elements[max_nb_elems]; \
154 EbmlWriter writer = (EbmlWriter){ .elements = elements, \
155 .current_master_element = -1 }
156
157 typedef struct mkv_seekhead_entry {
158 uint32_t elementid;
159 uint64_t segmentpos;
160 } mkv_seekhead_entry;
161
162 typedef struct mkv_seekhead {
163 int64_t filepos;
164 mkv_seekhead_entry entries[MAX_SEEKHEAD_ENTRIES];
165 int num_entries;
166 int reserved_size;
167 } mkv_seekhead;
168
169 typedef struct mkv_cuepoint {
170 uint64_t pts;
171 int stream_idx;
172 int64_t cluster_pos; ///< offset of the cluster containing the block relative to the segment
173 int64_t relative_pos; ///< relative offset from the position of the cluster containing the block
174 int64_t duration; ///< duration of the block according to time base
175 } mkv_cuepoint;
176
177 typedef struct mkv_cues {
178 mkv_cuepoint *entries;
179 int num_entries;
180 } mkv_cues;
181
182 struct MatroskaMuxContext;
183
184 typedef struct mkv_track {
185 int write_dts;
186 int has_cue;
187 uint64_t uid;
188 unsigned track_num;
189 int track_num_size;
190 int sample_rate;
191 unsigned offset;
192 int64_t sample_rate_offset;
193 int64_t last_timestamp;
194 int64_t duration;
195 int64_t duration_offset;
196 uint64_t max_blockaddid;
197 int64_t blockadditionmapping_offset;
198 int codecpriv_offset;
199 unsigned codecpriv_size; ///< size reserved for CodecPrivate excluding header+length field
200 int64_t ts_offset;
201 uint64_t default_duration_low;
202 uint64_t default_duration_high;
203 /* This callback will be called twice: First with a NULL AVIOContext
204 * to return the size of the (Simple)Block's data via size
205 * and a second time with the AVIOContext set when the data
206 * shall be written.
207 * The callback shall not return an error on the second call. */
208 int (*reformat)(struct MatroskaMuxContext *, AVIOContext *,
209 const AVPacket *, int *size);
210 } mkv_track;
211
212 typedef struct MatroskaMuxContext {
213 const AVClass *class;
214 AVFormatContext *ctx;
215
216 int mode;
217 ebml_stored_master info;
218 ebml_stored_master track;
219 ebml_stored_master tags;
220 int64_t segment_offset;
221 AVIOContext *cluster_bc;
222 int64_t cluster_pos; ///< file offset of the current Cluster
223 int64_t cluster_pts;
224 int64_t duration_offset;
225 int64_t duration;
226 mkv_track *tracks;
227 mkv_seekhead seekhead;
228 mkv_cues cues;
229 int64_t cues_pos;
230
231 BlockContext cur_block;
232
233 /* Used as temporary buffer to use the minimal amount of bytes
234 * to write the length field of EBML Masters.
235 * Every user has to reset the buffer after using it and
236 * different uses may not overlap. It is currently used in
237 * mkv_write_tag(), in mkv_assemble_cues() as well as in
238 * mkv_update_codecprivate() and mkv_write_track(). */
239 AVIOContext *tmp_bc;
240
241 AVPacket *cur_audio_pkt;
242
243 unsigned nb_attachments;
244 int have_video;
245
246 int wrote_chapters;
247 int wrote_tags;
248
249 int reserve_cues_space;
250 int cluster_size_limit;
251 int64_t cluster_time_limit;
252 int write_crc;
253 int is_live;
254
255 int is_dash;
256 int dash_track_number;
257 int allow_raw_vfw;
258 int flipped_raw_rgb;
259 int default_mode;
260 int move_cues_to_front;
261
262 uint32_t segment_uid[4];
263 } MatroskaMuxContext;
264
265 /** 2 bytes * 3 for EBML IDs, 3 1-byte EBML lengths, 8 bytes for 64 bit
266 * offset, 4 bytes for target EBML ID */
267 #define MAX_SEEKENTRY_SIZE 21
268
269 /** 4 * (1-byte EBML ID, 1-byte EBML size, 8-byte uint max) */
270 #define MAX_CUETRACKPOS_SIZE 40
271
272 /** DURATION_STRING_LENGTH must be <= 112 or the containing
273 * simpletag will need more than one byte for its length field. */
274 #define DURATION_STRING_LENGTH 19
275
276 /** 2 + 1 Simpletag header, 2 + 1 + 8 Name "DURATION", rest for TagString */
277 #define DURATION_SIMPLETAG_SIZE (2 + 1 + (2 + 1 + 8) + (2 + 1 + DURATION_STRING_LENGTH))
278
279 /** Seek preroll value for opus */
280 #define OPUS_SEEK_PREROLL 80000000
281
282 23887 static int ebml_id_size(uint32_t id)
283 {
284 23887 return (av_log2(id) + 7U) / 8;
285 }
286
287 21705 static void put_ebml_id(AVIOContext *pb, uint32_t id)
288 {
289 21705 int i = ebml_id_size(id);
290
2/2
✓ Branch 0 taken 27774 times.
✓ Branch 1 taken 21705 times.
49479 while (i--)
291 27774 avio_w8(pb, (uint8_t)(id >> (i * 8)));
292 21705 }
293
294 /**
295 * Write an EBML size meaning "unknown size".
296 *
297 * @param bytes The number of bytes the size should occupy (maximum: 8).
298 */
299 1894 static void put_ebml_size_unknown(AVIOContext *pb, int bytes)
300 {
301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1894 times.
1894 av_assert0(bytes <= 8);
302 1894 avio_w8(pb, 0x1ff >> bytes);
303 if (av_builtin_constant_p(bytes) && bytes == 1)
304 return;
305 1894 ffio_fill(pb, 0xff, bytes - 1);
306 }
307
308 /**
309 * Returns how many bytes are needed to represent a number
310 * as EBML variable length integer.
311 */
312 23494 static int ebml_num_size(uint64_t num)
313 {
314 23494 int bytes = 0;
315 do {
316 30774 bytes++;
317
2/2
✓ Branch 0 taken 7280 times.
✓ Branch 1 taken 23494 times.
30774 } while (num >>= 7);
318 23494 return bytes;
319 }
320
321 /**
322 * Calculate how many bytes are needed to represent the length field
323 * of an EBML element whose payload has a given length.
324 */
325 23421 static int ebml_length_size(uint64_t length)
326 {
327 23421 return ebml_num_size(length + 1);
328 }
329
330 /**
331 * Write a number as EBML variable length integer on `bytes` bytes.
332 * `bytes` is taken literally without checking.
333 */
334 28319 static void put_ebml_num(AVIOContext *pb, uint64_t num, int bytes)
335 {
336 28319 num |= 1ULL << bytes * 7;
337
2/2
✓ Branch 0 taken 37709 times.
✓ Branch 1 taken 28319 times.
66028 for (int i = bytes - 1; i >= 0; i--)
338 37709 avio_w8(pb, (uint8_t)(num >> i * 8));
339 28319 }
340
341 /**
342 * Write a length as EBML variable length integer.
343 *
344 * @param bytes The number of bytes that need to be used to write the number.
345 * If zero, the minimal number of bytes will be used.
346 */
347 12531 static void put_ebml_length(AVIOContext *pb, uint64_t length, int bytes)
348 {
349 12531 int needed_bytes = ebml_length_size(length);
350
351 // sizes larger than this are currently undefined in EBML
352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12531 times.
12531 av_assert0(length < (1ULL << 56) - 1);
353
354
2/2
✓ Branch 0 taken 10372 times.
✓ Branch 1 taken 2159 times.
12531 if (bytes == 0)
355 10372 bytes = needed_bytes;
356 // The bytes needed to write the given size must not exceed
357 // the bytes that we ought to use.
358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12531 times.
12531 av_assert0(bytes >= needed_bytes);
359 12531 put_ebml_num(pb, length, bytes);
360 12531 }
361
362 /**
363 * Write a (random) UID with fixed size to make the output more deterministic
364 */
365 147 static void put_ebml_uid(AVIOContext *pb, uint32_t elementid, uint64_t uid)
366 {
367 147 put_ebml_id(pb, elementid);
368 147 put_ebml_length(pb, 8, 0);
369 147 avio_wb64(pb, uid);
370 147 }
371
372 6588 static void put_ebml_uint(AVIOContext *pb, uint32_t elementid, uint64_t val)
373 {
374 6588 int i, bytes = 1;
375 6588 uint64_t tmp = val;
376
2/2
✓ Branch 0 taken 5208 times.
✓ Branch 1 taken 6588 times.
11796 while (tmp >>= 8)
377 5208 bytes++;
378
379 6588 put_ebml_id(pb, elementid);
380 6588 put_ebml_length(pb, bytes, 0);
381
2/2
✓ Branch 0 taken 11796 times.
✓ Branch 1 taken 6588 times.
18384 for (i = bytes - 1; i >= 0; i--)
382 11796 avio_w8(pb, (uint8_t)(val >> i * 8));
383 6588 }
384
385 77 static void put_ebml_float(AVIOContext *pb, uint32_t elementid, double val)
386 {
387 77 put_ebml_id(pb, elementid);
388 77 put_ebml_length(pb, 8, 0);
389 77 avio_wb64(pb, av_double2int(val));
390 77 }
391
392 2027 static void put_ebml_binary(AVIOContext *pb, uint32_t elementid,
393 const void *buf, int size)
394 {
395 2027 put_ebml_id(pb, elementid);
396 2027 put_ebml_length(pb, size, 0);
397 2027 avio_write(pb, buf, size);
398 2027 }
399
400 309 static void put_ebml_string(AVIOContext *pb, uint32_t elementid,
401 const char *str)
402 {
403 309 put_ebml_binary(pb, elementid, str, strlen(str));
404 309 }
405
406 /**
407 * Write a void element of a given size. Useful for reserving space in
408 * the file to be written to later.
409 *
410 * @param size The number of bytes to reserve, which must be at least 2.
411 */
412 706 static void put_ebml_void(AVIOContext *pb, int size)
413 {
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 av_assert0(size >= 2);
415
416 706 put_ebml_id(pb, EBML_ID_VOID);
417 // we need to subtract the length needed to store the size from the
418 // size we need to reserve so 2 cases, we use 8 bytes to store the
419 // size if possible, 1 byte otherwise
420
2/2
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 218 times.
706 if (size < 10) {
421 488 size -= 2;
422 488 put_ebml_length(pb, size, 0);
423 } else {
424 218 size -= 9;
425 218 put_ebml_length(pb, size, 8);
426 }
427 706 ffio_fill(pb, 0, size);
428 706 }
429
430 1851 static ebml_master start_ebml_master(AVIOContext *pb, uint32_t elementid,
431 uint64_t expectedsize)
432 {
433
2/2
✓ Branch 0 taken 1777 times.
✓ Branch 1 taken 74 times.
1851 int bytes = expectedsize ? ebml_length_size(expectedsize) : 8;
434
435 1851 put_ebml_id(pb, elementid);
436 1851 put_ebml_size_unknown(pb, bytes);
437 1851 return (ebml_master) { avio_tell(pb), bytes };
438 }
439
440 1851 static void end_ebml_master(AVIOContext *pb, ebml_master master)
441 {
442 1851 int64_t pos = avio_tell(pb);
443
444
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1851 times.
1851 if (avio_seek(pb, master.pos - master.sizebytes, SEEK_SET) < 0)
445 return;
446 1851 put_ebml_length(pb, pos - master.pos, master.sizebytes);
447 1851 avio_seek(pb, pos, SEEK_SET);
448 }
449
450 22183 static EbmlElement *ebml_writer_add(EbmlWriter *writer,
451 uint32_t id, EbmlType type)
452 {
453 22183 writer->elements[writer->nb_elements].id = id;
454 22183 writer->elements[writer->nb_elements].type = type;
455 22183 return &writer->elements[writer->nb_elements++];
456 }
457
458 13958 static void ebml_writer_open_master(EbmlWriter *writer, uint32_t id)
459 {
460 13958 EbmlElement *const elem = ebml_writer_add(writer, id, EBML_MASTER);
461 13958 EbmlMaster *const master = &elem->priv.master;
462
463 13958 master->containing_master = writer->current_master_element;
464 13958 master->nb_elements = -1;
465
466 13958 writer->current_master_element = writer->nb_elements - 1;
467 13958 }
468
469 276 static void ebml_writer_close_master(EbmlWriter *writer)
470 {
471 EbmlElement *elem;
472 av_assert2(writer->current_master_element >= 0);
473 av_assert2(writer->current_master_element < writer->nb_elements);
474 276 elem = &writer->elements[writer->current_master_element];
475 av_assert2(elem->type == EBML_MASTER);
476 av_assert2(elem->priv.master.nb_elements < 0); /* means unset */
477 276 elem->priv.master.nb_elements = writer->nb_elements - writer->current_master_element - 1;
478 av_assert2(elem->priv.master.containing_master < 0 ||
479 elem->priv.master.containing_master < writer->current_master_element);
480 276 writer->current_master_element = elem->priv.master.containing_master;
481 276 }
482
483 6848 static void ebml_writer_close_or_discard_master(EbmlWriter *writer)
484 {
485 av_assert2(writer->nb_elements > 0);
486 av_assert2(0 <= writer->current_master_element);
487 av_assert2(writer->current_master_element < writer->nb_elements);
488
2/2
✓ Branch 0 taken 6694 times.
✓ Branch 1 taken 154 times.
6848 if (writer->current_master_element == writer->nb_elements - 1) {
489 6694 const EbmlElement *const elem = &writer->elements[writer->nb_elements - 1];
490 /* The master element has no children. Discard it. */
491 av_assert2(elem->type == EBML_MASTER);
492 av_assert2(elem->priv.master.containing_master < 0 ||
493 elem->priv.master.containing_master < writer->current_master_element);
494 6694 writer->current_master_element = elem->priv.master.containing_master;
495 6694 writer->nb_elements--;
496 6694 return;
497 }
498 154 ebml_writer_close_master(writer);
499 }
500
501 300 static void ebml_writer_add_string(EbmlWriter *writer, uint32_t id,
502 const char *str)
503 {
504 300 EbmlElement *const elem = ebml_writer_add(writer, id, EBML_STR);
505
506 300 elem->priv.str = str;
507 300 }
508
509 127 static void ebml_writer_add_bin(EbmlWriter *writer, uint32_t id,
510 const uint8_t *data, size_t size)
511 {
512 127 EbmlElement *const elem = ebml_writer_add(writer, id, EBML_BIN);
513
514 #if SIZE_MAX > UINT64_MAX
515 size = FFMIN(size, UINT64_MAX);
516 #endif
517 127 elem->size = size;
518 127 elem->priv.bin = data;
519 127 }
520
521 27 static void ebml_writer_add_float(EbmlWriter *writer, uint32_t id,
522 double val)
523 {
524 27 EbmlElement *const elem = ebml_writer_add(writer, id, EBML_FLOAT);
525
526 27 elem->priv.f = val;
527 27 }
528
529 1 static void ebml_writer_add_uid(EbmlWriter *writer, uint32_t id,
530 uint64_t val)
531 {
532 1 EbmlElement *const elem = ebml_writer_add(writer, id, EBML_UID);
533 1 elem->priv.uint = val;
534 1 }
535
536 787 static void ebml_writer_add_uint(EbmlWriter *writer, uint32_t id,
537 uint64_t val)
538 {
539 787 EbmlElement *elem = ebml_writer_add(writer, id, EBML_UINT);
540 787 elem->priv.uint = val;
541 787 }
542
543 199 static void ebml_writer_add_sint(EbmlWriter *writer, uint32_t id,
544 int64_t val)
545 {
546 199 EbmlElement *elem = ebml_writer_add(writer, id, EBML_SINT);
547 199 elem->priv.sint = val;
548 199 }
549
550 6784 static void ebml_writer_add_block(EbmlWriter *writer, MatroskaMuxContext *mkv)
551 {
552 6784 EbmlElement *elem = ebml_writer_add(writer, MATROSKA_ID_BLOCK, EBML_BLOCK);
553 6784 elem->priv.mkv = mkv;
554 6784 }
555
556 300 static int ebml_writer_str_len(EbmlElement *elem)
557 {
558 300 size_t len = strlen(elem->priv.str);
559 #if SIZE_MAX > UINT64_MAX
560 len = FF_MIN(len, UINT64_MAX);
561 #endif
562 300 elem->size = len;
563 300 return 0;
564 }
565
566 986 static av_const int uint_size(uint64_t val)
567 {
568 986 int bytes = 0;
569 do {
570 1180 bytes++;
571
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 986 times.
1180 } while (val >>= 8);
572 986 return bytes;
573 }
574
575 787 static int ebml_writer_uint_len(EbmlElement *elem)
576 {
577 787 elem->size = uint_size(elem->priv.uint);
578 787 return 0;
579 }
580
581 199 static av_const int sint_size(int64_t val)
582 {
583
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 23 times.
199 uint64_t tmp = 2 * (uint64_t)(val < 0 ? val^-1 : val);
584 199 return uint_size(tmp);
585 }
586
587 199 static int ebml_writer_sint_len(EbmlElement *elem)
588 {
589 199 elem->size = sint_size(elem->priv.sint);
590 199 return 0;
591 }
592
593 static int ebml_writer_elem_len(EbmlWriter *writer, EbmlElement *elem,
594 int remaining_elems);
595
596 779 static int ebml_writer_master_len(EbmlWriter *writer, EbmlElement *elem,
597 int remaining_elems)
598 {
599
2/2
✓ Branch 0 taken 276 times.
✓ Branch 1 taken 503 times.
779 int nb_elems = elem->priv.master.nb_elements >= 0 ? elem->priv.master.nb_elements : remaining_elems - 1;
600 779 EbmlElement *const master = elem;
601 779 uint64_t total_size = 0;
602
603 779 master->priv.master.nb_elements = nb_elems;
604
2/2
✓ Branch 0 taken 2020 times.
✓ Branch 1 taken 779 times.
2799 for (; elem++, nb_elems > 0;) {
605 2020 int ret = ebml_writer_elem_len(writer, elem, nb_elems);
606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2020 times.
2020 if (ret < 0)
607 return ret;
608 av_assert2(ret < nb_elems);
609 /* No overflow is possible here, as both total_size and elem->size
610 * are bounded by MAX_SUPPORTED_EBML_LENGTH. */
611 2020 total_size += ebml_id_size(elem->id) + elem->length_size + elem->size;
612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2020 times.
2020 if (total_size > MAX_SUPPORTED_EBML_LENGTH)
613 return AVERROR(ERANGE);
614 2020 nb_elems--; /* consume elem */
615 2020 elem += ret, nb_elems -= ret; /* and elem's children */
616 }
617 779 master->size = total_size;
618
619 779 return master->priv.master.nb_elements;
620 }
621
622 6784 static int ebml_writer_block_len(EbmlElement *elem)
623 {
624 6784 MatroskaMuxContext *const mkv = elem->priv.mkv;
625 6784 BlockContext *const block = &mkv->cur_block;
626 6784 mkv_track *const track = block->track;
627 6784 const AVPacket *const pkt = block->pkt;
628 int err, size;
629
630
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 6579 times.
6784 if (track->reformat) {
631 205 err = track->reformat(mkv, NULL, pkt, &size);
632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 205 times.
205 if (err < 0) {
633 av_log(mkv->ctx, AV_LOG_ERROR, "Error when reformatting data of "
634 "a packet from stream %d.\n", pkt->stream_index);
635 return err;
636 }
637 } else {
638 6579 size = pkt->size;
639
1/2
✓ Branch 0 taken 6579 times.
✗ Branch 1 not taken.
6579 if (track->offset <= size)
640 6579 size -= track->offset;
641 }
642 6784 elem->size = track->track_num_size + 3U + size;
643
644 6784 return 0;
645 }
646
647 6784 static void ebml_writer_write_block(const EbmlElement *elem, AVIOContext *pb)
648 {
649 6784 MatroskaMuxContext *const mkv = elem->priv.mkv;
650 6784 BlockContext *const block = &mkv->cur_block;
651 6784 mkv_track *const track = block->track;
652 6784 const AVPacket *const pkt = block->pkt;
653
654 6784 put_ebml_num(pb, track->track_num, track->track_num_size);
655 6784 avio_wb16(pb, block->rel_ts);
656 6784 avio_w8(pb, block->flags);
657
658
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 6579 times.
6784 if (track->reformat) {
659 int size;
660 205 track->reformat(mkv, pb, pkt, &size);
661 } else {
662 6579 const uint8_t *data = pkt->data;
663
1/2
✓ Branch 0 taken 6579 times.
✗ Branch 1 not taken.
6579 unsigned offset = track->offset <= pkt->size ? track->offset : 0;
664 6579 avio_write(pb, data + offset, pkt->size - offset);
665 }
666 6784 }
667
668 9004 static int ebml_writer_elem_len(EbmlWriter *writer, EbmlElement *elem,
669 int remaining_elems)
670 {
671 9004 int ret = 0;
672
673
7/7
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 300 times.
✓ Branch 2 taken 787 times.
✓ Branch 3 taken 199 times.
✓ Branch 4 taken 6784 times.
✓ Branch 5 taken 779 times.
✓ Branch 6 taken 127 times.
9004 switch (elem->type) {
674 28 case EBML_FLOAT:
675 case EBML_UID:
676 28 elem->size = 8;
677 28 break;
678 300 case EBML_STR:
679 300 ret = ebml_writer_str_len(elem);
680 300 break;
681 787 case EBML_UINT:
682 787 ret = ebml_writer_uint_len(elem);
683 787 break;
684 199 case EBML_SINT:
685 199 ret = ebml_writer_sint_len(elem);
686 199 break;
687 6784 case EBML_BLOCK:
688 6784 ret = ebml_writer_block_len(elem);
689 6784 break;
690 779 case EBML_MASTER:
691 779 ret = ebml_writer_master_len(writer, elem, remaining_elems);
692 779 break;
693 }
694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9004 times.
9004 if (ret < 0)
695 return ret;
696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9004 times.
9004 if (elem->size > MAX_SUPPORTED_EBML_LENGTH)
697 return AVERROR(ERANGE);
698 9004 elem->length_size = ebml_length_size(elem->size);
699 9004 return ret; /* number of elements consumed excluding elem itself */
700 }
701
702 9004 static int ebml_writer_elem_write(const EbmlElement *elem, AVIOContext *pb)
703 {
704 9004 put_ebml_id(pb, elem->id);
705 9004 put_ebml_num(pb, elem->size, elem->length_size);
706
5/6
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 986 times.
✓ Branch 2 taken 427 times.
✓ Branch 3 taken 6784 times.
✓ Branch 4 taken 779 times.
✗ Branch 5 not taken.
9004 switch (elem->type) {
707 28 case EBML_UID:
708 case EBML_FLOAT: {
709 56 uint64_t val = elem->type == EBML_UID ? elem->priv.uint
710
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
28 : av_double2int(elem->priv.f);
711 28 avio_wb64(pb, val);
712 28 break;
713 }
714 986 case EBML_UINT:
715 case EBML_SINT: {
716 1972 uint64_t val = elem->type == EBML_UINT ? elem->priv.uint
717
2/2
✓ Branch 0 taken 787 times.
✓ Branch 1 taken 199 times.
986 : elem->priv.sint;
718
2/2
✓ Branch 0 taken 1180 times.
✓ Branch 1 taken 986 times.
2166 for (int i = elem->size; --i >= 0; )
719 1180 avio_w8(pb, (uint8_t)(val >> i * 8));
720 986 break;
721 }
722 427 case EBML_STR:
723 case EBML_BIN: {
724 854 const uint8_t *data = elem->type == EBML_BIN ? elem->priv.bin
725
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 300 times.
427 : (const uint8_t*)elem->priv.str;
726 427 avio_write(pb, data, elem->size);
727 427 break;
728 }
729 6784 case EBML_BLOCK:
730 6784 ebml_writer_write_block(elem, pb);
731 6784 break;
732 779 case EBML_MASTER: {
733 779 int nb_elems = elem->priv.master.nb_elements;
734
735 779 elem++;
736
2/2
✓ Branch 0 taken 2020 times.
✓ Branch 1 taken 779 times.
2799 for (int i = 0; i < nb_elems; i++)
737 2020 i += ebml_writer_elem_write(elem + i, pb);
738
739 779 return nb_elems;
740 }
741 }
742 8225 return 0;
743 }
744
745 6984 static int ebml_writer_write(EbmlWriter *writer, AVIOContext *pb)
746 {
747 6984 int ret = ebml_writer_elem_len(writer, writer->elements,
748 6984 writer->nb_elements);
749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6984 times.
6984 if (ret < 0)
750 return ret;
751 6984 ebml_writer_elem_write(writer->elements, pb);
752 6984 return 0;
753 }
754
755 162 static void mkv_add_seekhead_entry(MatroskaMuxContext *mkv, uint32_t elementid,
756 uint64_t filepos)
757 {
758 162 mkv_seekhead *seekhead = &mkv->seekhead;
759
760 av_assert1(seekhead->num_entries < MAX_SEEKHEAD_ENTRIES);
761
762 162 seekhead->entries[seekhead->num_entries].elementid = elementid;
763 162 seekhead->entries[seekhead->num_entries++].segmentpos = filepos - mkv->segment_offset;
764 162 }
765
766 785 static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv)
767 {
768 int ret;
769
770
3/4
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 537 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 248 times.
785 if (!*dyn_cp && (ret = avio_open_dyn_buf(dyn_cp)) < 0)
771 return ret;
772
773
2/2
✓ Branch 0 taken 487 times.
✓ Branch 1 taken 298 times.
785 if (mkv->write_crc)
774 487 put_ebml_void(*dyn_cp, 6); /* Reserve space for CRC32 so position/size calculations using avio_tell() take it into account */
775
776 785 return 0;
777 }
778
779 783 static int end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp,
780 MatroskaMuxContext *mkv, uint32_t id,
781 int length_size, int keep_buffer,
782 int add_seekentry)
783 {
784 uint8_t *buf, crc[4];
785 783 int ret, size, skip = 0;
786
787 783 size = avio_get_dyn_buf(*dyn_cp, &buf);
788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 783 times.
783 if ((ret = (*dyn_cp)->error) < 0)
789 goto fail;
790
791
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 726 times.
783 if (add_seekentry)
792 57 mkv_add_seekhead_entry(mkv, id, avio_tell(pb));
793
794 783 put_ebml_id(pb, id);
795 783 put_ebml_length(pb, size, length_size);
796
2/2
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 297 times.
783 if (mkv->write_crc) {
797 486 skip = 6; /* Skip reserved 6-byte long void element from the dynamic buffer. */
798 486 AV_WL32(crc, av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), UINT32_MAX, buf + skip, size - skip) ^ UINT32_MAX);
799 486 put_ebml_binary(pb, EBML_ID_CRC32, crc, sizeof(crc));
800 }
801 783 avio_write(pb, buf + skip, size - skip);
802
803 783 fail:
804
2/2
✓ Branch 0 taken 535 times.
✓ Branch 1 taken 248 times.
783 if (keep_buffer) {
805 535 ffio_reset_dyn_buf(*dyn_cp);
806 } else {
807 248 ffio_free_dyn_buf(dyn_cp);
808 }
809 783 return ret;
810 }
811
812 /**
813 * Output EBML master. Keep the buffer if seekable, allowing for later updates.
814 * Furthermore always add a SeekHead Entry for this element.
815 */
816 125 static int end_ebml_master_crc32_tentatively(AVIOContext *pb,
817 ebml_stored_master *elem,
818 MatroskaMuxContext *mkv, uint32_t id)
819 {
820
4/4
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 105 times.
✓ Branch 3 taken 9 times.
125 if (IS_SEEKABLE(pb, mkv)) {
821 uint8_t *buf;
822 105 int size = avio_get_dyn_buf(elem->bc, &buf);
823
824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105 times.
105 if (elem->bc->error < 0)
825 return elem->bc->error;
826
827 105 elem->pos = avio_tell(pb);
828 105 mkv_add_seekhead_entry(mkv, id, elem->pos);
829
830 105 put_ebml_id(pb, id);
831 105 put_ebml_length(pb, size, 0);
832 105 avio_write(pb, buf, size);
833
834 105 return 0;
835 } else
836 20 return end_ebml_master_crc32(pb, &elem->bc, mkv, id, 0, 0, 1);
837 }
838
839 16 static void put_xiph_size(AVIOContext *pb, int size)
840 {
841 16 ffio_fill(pb, 255, size / 255);
842 16 avio_w8(pb, size % 255);
843 16 }
844
845 /**
846 * Free the members allocated in the mux context.
847 */
848 43 static void mkv_deinit(AVFormatContext *s)
849 {
850 43 MatroskaMuxContext *mkv = s->priv_data;
851
852 43 ffio_free_dyn_buf(&mkv->cluster_bc);
853 43 ffio_free_dyn_buf(&mkv->info.bc);
854 43 ffio_free_dyn_buf(&mkv->track.bc);
855 43 ffio_free_dyn_buf(&mkv->tags.bc);
856 43 ffio_free_dyn_buf(&mkv->tmp_bc);
857
858 43 av_freep(&mkv->cur_block.h2645_nalu_list.nalus);
859 43 av_freep(&mkv->cues.entries);
860 43 av_freep(&mkv->tracks);
861 43 }
862
863 /**
864 * Initialize the SeekHead element to be ready to index level 1 Matroska
865 * elements. Enough space to write MAX_SEEKHEAD_ENTRIES SeekHead entries
866 * will be reserved at the current file location.
867 */
868 43 static void mkv_start_seekhead(MatroskaMuxContext *mkv, AVIOContext *pb)
869 {
870 43 mkv->seekhead.filepos = avio_tell(pb);
871 // 21 bytes max for a Seek entry, 6 bytes max for the SeekHead ID
872 // and size, 6 bytes for a CRC32 element, and 2 bytes to guarantee
873 // that an EBML void element will fit afterwards
874 43 mkv->seekhead.reserved_size = MAX_SEEKHEAD_ENTRIES * MAX_SEEKENTRY_SIZE + 14;
875 43 put_ebml_void(pb, mkv->seekhead.reserved_size);
876 43 }
877
878 /**
879 * Write the SeekHead to the file at the location reserved for it
880 * and seek to destpos afterwards. When error_on_seek_failure
881 * is not set, failure to seek to the position designated for the
882 * SeekHead is not considered an error and it is presumed that
883 * destpos is the current position; failure to seek to destpos
884 * afterwards is always an error.
885 *
886 * @return 0 on success, < 0 on error.
887 */
888 43 static int mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv,
889 int error_on_seek_failure, int64_t destpos)
890 {
891 43 AVIOContext *dyn_cp = NULL;
892 43 mkv_seekhead *seekhead = &mkv->seekhead;
893 int64_t remaining, ret64;
894 int i, ret;
895
896
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if ((ret64 = avio_seek(pb, seekhead->filepos, SEEK_SET)) < 0)
897 return error_on_seek_failure ? ret64 : 0;
898
899 43 ret = start_ebml_master_crc32(&dyn_cp, mkv);
900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
901 return ret;
902
903
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 43 times.
205 for (i = 0; i < seekhead->num_entries; i++) {
904 162 mkv_seekhead_entry *entry = &seekhead->entries[i];
905 162 ebml_master seekentry = start_ebml_master(dyn_cp, MATROSKA_ID_SEEKENTRY,
906 MAX_SEEKENTRY_SIZE);
907
908 162 put_ebml_id(dyn_cp, MATROSKA_ID_SEEKID);
909 162 put_ebml_length(dyn_cp, ebml_id_size(entry->elementid), 0);
910 162 put_ebml_id(dyn_cp, entry->elementid);
911
912 162 put_ebml_uint(dyn_cp, MATROSKA_ID_SEEKPOSITION, entry->segmentpos);
913 162 end_ebml_master(dyn_cp, seekentry);
914 }
915 43 ret = end_ebml_master_crc32(pb, &dyn_cp, mkv,
916 MATROSKA_ID_SEEKHEAD, 0, 0, 0);
917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
918 return ret;
919
920 43 remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb);
921 43 put_ebml_void(pb, remaining);
922
923
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 if ((ret64 = avio_seek(pb, destpos, SEEK_SET)) < 0)
924 return ret64;
925
926 43 return 0;
927 }
928
929 1161 static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int64_t ts,
930 int64_t cluster_pos, int64_t relative_pos, int64_t duration)
931 {
932 1161 mkv_cues *cues = &mkv->cues;
933 1161 mkv_cuepoint *entries = cues->entries;
934 1161 unsigned idx = cues->num_entries;
935
936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
1161 if (ts < 0)
937 return 0;
938
939 1161 entries = av_realloc_array(entries, cues->num_entries + 1, sizeof(mkv_cuepoint));
940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
1161 if (!entries)
941 return AVERROR(ENOMEM);
942 1161 cues->entries = entries;
943
944 /* Make sure the cues entries are sorted by pts. */
945
3/4
✓ Branch 0 taken 1126 times.
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1126 times.
1161 while (idx > 0 && entries[idx - 1].pts > ts)
946 idx--;
947 1161 memmove(&entries[idx + 1], &entries[idx],
948 1161 (cues->num_entries - idx) * sizeof(entries[0]));
949
950 1161 entries[idx].pts = ts;
951 1161 entries[idx].stream_idx = stream;
952 1161 entries[idx].cluster_pos = cluster_pos - mkv->segment_offset;
953 1161 entries[idx].relative_pos = relative_pos;
954 1161 entries[idx].duration = duration;
955
956 1161 cues->num_entries++;
957
958 1161 return 0;
959 }
960
961 37 static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, AVIOContext *cuepoint,
962 const mkv_cues *cues, mkv_track *tracks, int num_tracks,
963 uint64_t offset)
964 {
965 37 for (mkv_cuepoint *entry = cues->entries, *end = entry + cues->num_entries;
966
2/2
✓ Branch 0 taken 1081 times.
✓ Branch 1 taken 37 times.
1118 entry < end;) {
967 1081 uint64_t pts = entry->pts;
968 uint8_t *buf;
969 int size;
970
971 1081 put_ebml_uint(cuepoint, MATROSKA_ID_CUETIME, pts);
972
973 // put all the entries from different tracks that have the exact same
974 // timestamp into the same CuePoint
975
2/2
✓ Branch 0 taken 2176 times.
✓ Branch 1 taken 1081 times.
3257 for (int j = 0; j < num_tracks; j++)
976 2176 tracks[j].has_cue = 0;
977 do {
978 ebml_master track_positions;
979 1399 int idx = entry->stream_idx;
980
981
2/4
✓ Branch 0 taken 1399 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1399 times.
1399 av_assert0(idx >= 0 && idx < num_tracks);
982
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1397 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
1399 if (tracks[idx].has_cue && streams[idx]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
983 continue;
984 1399 tracks[idx].has_cue = 1;
985 1399 track_positions = start_ebml_master(cuepoint, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE);
986 1399 put_ebml_uint(cuepoint, MATROSKA_ID_CUETRACK , tracks[idx].track_num);
987 1399 put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos + offset);
988 1399 put_ebml_uint(cuepoint, MATROSKA_ID_CUERELATIVEPOSITION, entry->relative_pos);
989
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 1316 times.
1399 if (entry->duration > 0)
990 83 put_ebml_uint(cuepoint, MATROSKA_ID_CUEDURATION , entry->duration);
991 1399 end_ebml_master(cuepoint, track_positions);
992
4/4
✓ Branch 0 taken 1362 times.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 318 times.
✓ Branch 3 taken 1044 times.
1399 } while (++entry < end && entry->pts == pts);
993 1081 size = avio_get_dyn_buf(cuepoint, &buf);
994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1081 times.
1081 if (cuepoint->error < 0)
995 return cuepoint->error;
996 1081 put_ebml_binary(dyn_cp, MATROSKA_ID_POINTENTRY, buf, size);
997 1081 ffio_reset_dyn_buf(cuepoint);
998 }
999
1000 37 return 0;
1001 }
1002
1003 8 static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb,
1004 const AVCodecParameters *par,
1005 const uint8_t *extradata, int extradata_size)
1006 {
1007 const uint8_t *header_start[3];
1008 int header_len[3];
1009 int first_header_size;
1010 int err, j;
1011
1012
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (par->codec_id == AV_CODEC_ID_VORBIS)
1013 1 first_header_size = 30;
1014 else
1015 7 first_header_size = 42;
1016
1017 8 err = avpriv_split_xiph_headers(extradata, extradata_size,
1018 first_header_size, header_start, header_len);
1019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (err < 0) {
1020 av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
1021 return err;
1022 }
1023
1024 8 avio_w8(pb, 2); // number packets - 1
1025
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
24 for (j = 0; j < 2; j++) {
1026 16 put_xiph_size(pb, header_len[j]);
1027 }
1028
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 8 times.
32 for (j = 0; j < 3; j++)
1029 24 avio_write(pb, header_start[j], header_len[j]);
1030
1031 8 return 0;
1032 }
1033
1034 #if CONFIG_MATROSKA_MUXER
1035 2 static int put_wv_codecpriv(AVIOContext *pb, const uint8_t *extradata, int extradata_size)
1036 {
1037
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (extradata && extradata_size == 2)
1038 2 avio_write(pb, extradata, 2);
1039 else
1040 avio_wl16(pb, 0x410); // fallback to the most recent version
1041 2 return 0;
1042 }
1043
1044 6 static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb,
1045 const AVCodecParameters *par,
1046 const uint8_t *extradata, int extradata_size)
1047 {
1048 18 int write_comment = (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE &&
1049
4/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 2 times.
12 !(par->ch_layout.u.mask & ~0x3ffffULL) &&
1050 6 !ff_flac_is_native_layout(par->ch_layout.u.mask));
1051 6 int ret = ff_flac_write_header(pb, extradata, extradata_size,
1052 !write_comment);
1053
1054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
1055 return ret;
1056
1057
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (write_comment) {
1058 8 const char *vendor = (s->flags & AVFMT_FLAG_BITEXACT) ?
1059
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 "Lavf" : LIBAVFORMAT_IDENT;
1060 4 AVDictionary *dict = NULL;
1061 uint8_t buf[32];
1062 int64_t len;
1063
1064 4 snprintf(buf, sizeof(buf), "0x%"PRIx64, par->ch_layout.u.mask);
1065 4 av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0);
1066
1067 4 len = ff_vorbiscomment_length(dict, vendor, NULL, 0);
1068 av_assert1(len < (1 << 24) - 4);
1069
1070 4 avio_w8(pb, 0x84);
1071 4 avio_wb24(pb, len);
1072
1073 4 ff_vorbiscomment_write(pb, dict, vendor, NULL, 0);
1074
1075 4 av_dict_free(&dict);
1076 }
1077
1078 6 return 0;
1079 }
1080
1081 7 static int get_aac_sample_rates(AVFormatContext *s, MatroskaMuxContext *mkv,
1082 const uint8_t *extradata, int extradata_size,
1083 int *sample_rate, int *output_sample_rate)
1084 {
1085 MPEG4AudioConfig mp4ac;
1086 int ret;
1087
1088 7 ret = avpriv_mpeg4audio_get_config2(&mp4ac, extradata, extradata_size, 1, s);
1089 /* Don't abort if the failure is because of missing extradata. Assume in that
1090 * case a bitstream filter will provide the muxer with the extradata in the
1091 * first packet.
1092 * Abort however if s->pb is not seekable, as we would not be able to seek back
1093 * to write the sample rate elements once the extradata shows up, anyway. */
1094
5/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
7 if (ret < 0 && (extradata_size || !IS_SEEKABLE(s->pb, mkv))) {
1095 av_log(s, AV_LOG_ERROR,
1096 "Error parsing AAC extradata, unable to determine samplerate.\n");
1097 return AVERROR(EINVAL);
1098 }
1099
1100
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (ret < 0) {
1101 /* This will only happen when this function is called while writing the
1102 * header and no extradata is available. The space for this element has
1103 * to be reserved for when this function is called again after the
1104 * extradata shows up in the first packet, as there's no way to know if
1105 * output_sample_rate will be different than sample_rate or not. */
1106 1 *output_sample_rate = *sample_rate;
1107 } else {
1108 6 *sample_rate = mp4ac.sample_rate;
1109 6 *output_sample_rate = mp4ac.ext_sample_rate;
1110 }
1111 7 return 0;
1112 }
1113 #endif
1114
1115 68 static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp,
1116 const AVCodecParameters *par,
1117 const uint8_t *extradata,
1118 int extradata_size,
1119 unsigned *size_to_reserve)
1120 {
1121
9/10
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 33 times.
68 switch (par->codec_id) {
1122 8 case AV_CODEC_ID_VORBIS:
1123 case AV_CODEC_ID_THEORA:
1124 8 return put_xiph_codecpriv(s, dyn_cp, par, extradata, extradata_size);
1125 3 case AV_CODEC_ID_AV1:
1126
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (extradata_size)
1127 2 return ff_isom_write_av1c(dyn_cp, extradata,
1128 extradata_size, 1);
1129 else
1130 1 *size_to_reserve = (AV1_SANE_SEQUENCE_HEADER_MAX_BITS + 7) / 8 + 100;
1131 1 break;
1132 #if CONFIG_MATROSKA_MUXER
1133 6 case AV_CODEC_ID_FLAC:
1134 6 return put_flac_codecpriv(s, dyn_cp, par, extradata, extradata_size);
1135 2 case AV_CODEC_ID_WAVPACK:
1136 2 return put_wv_codecpriv(dyn_cp, extradata, extradata_size);
1137 5 case AV_CODEC_ID_H264:
1138 5 return ff_isom_write_avcc(dyn_cp, extradata,
1139 extradata_size);
1140 3 case AV_CODEC_ID_HEVC:
1141 3 return ff_isom_write_hvcc(dyn_cp, extradata,
1142 extradata_size, 0);
1143 1 case AV_CODEC_ID_ALAC:
1144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (extradata_size < 36) {
1145 av_log(s, AV_LOG_ERROR,
1146 "Invalid extradata found, ALAC expects a 36-byte "
1147 "QuickTime atom.");
1148 return AVERROR_INVALIDDATA;
1149 } else
1150 1 avio_write(dyn_cp, extradata + 12,
1151 extradata_size - 12);
1152 1 break;
1153 7 case AV_CODEC_ID_AAC:
1154
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (extradata_size)
1155 6 avio_write(dyn_cp, extradata, extradata_size);
1156 else
1157 1 *size_to_reserve = MAX_PCE_SIZE;
1158 7 break;
1159 case AV_CODEC_ID_ARIB_CAPTION: {
1160 unsigned stream_identifier, data_component_id;
1161 switch (par->profile) {
1162 case AV_PROFILE_ARIB_PROFILE_A:
1163 stream_identifier = 0x30;
1164 data_component_id = 0x0008;
1165 break;
1166 case AV_PROFILE_ARIB_PROFILE_C:
1167 stream_identifier = 0x87;
1168 data_component_id = 0x0012;
1169 break;
1170 default:
1171 av_log(s, AV_LOG_ERROR,
1172 "Unset/unknown ARIB caption profile %d utilized!\n",
1173 par->profile);
1174 return AVERROR_INVALIDDATA;
1175 }
1176 avio_w8(dyn_cp, stream_identifier);
1177 avio_wb16(dyn_cp, data_component_id);
1178 break;
1179 }
1180 #endif
1181 33 default:
1182
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
34 if (CONFIG_MATROSKA_MUXER && par->codec_id == AV_CODEC_ID_PRORES &&
1183 1 ff_codec_get_id(ff_codec_movvideo_tags, par->codec_tag) == AV_CODEC_ID_PRORES) {
1184 1 avio_wl32(dyn_cp, par->codec_tag);
1185
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
32 } else if (extradata_size && par->codec_id != AV_CODEC_ID_TTA)
1186 10 avio_write(dyn_cp, extradata, extradata_size);
1187 }
1188
1189 42 return 0;
1190 }
1191
1192 74 static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp,
1193 AVCodecParameters *par,
1194 const uint8_t *extradata, int extradata_size,
1195 int native_id, int qt_id,
1196 uint8_t **codecpriv, int *codecpriv_size,
1197 unsigned *max_payload_size)
1198 {
1199 74 MatroskaMuxContext av_unused *const mkv = s->priv_data;
1200 74 unsigned size_to_reserve = 0;
1201 int ret;
1202
1203
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 6 times.
74 if (native_id) {
1204 68 ret = mkv_assemble_native_codecprivate(s, dyn_cp, par,
1205 extradata, extradata_size,
1206 &size_to_reserve);
1207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
68 if (ret < 0)
1208 return ret;
1209 #if CONFIG_MATROSKA_MUXER
1210
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 } else if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
1211
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (qt_id) {
1212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!par->codec_tag)
1213 par->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags,
1214 par->codec_id);
1215
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if ( ff_codec_get_id(ff_codec_movvideo_tags, par->codec_tag) == par->codec_id
1216
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 && (!extradata_size || ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(extradata + 4)) != par->codec_id)
1217 ) {
1218 1 avio_wb32(dyn_cp, 0x5a + extradata_size);
1219 1 avio_wl32(dyn_cp, par->codec_tag);
1220 1 ffio_fill(dyn_cp, 0, 0x5a - 8);
1221 }
1222 1 avio_write(dyn_cp, extradata, extradata_size);
1223 } else {
1224
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (!ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id))
1225 2 av_log(s, AV_LOG_WARNING, "codec %s is not supported by this format\n",
1226 avcodec_get_name(par->codec_id));
1227
1228
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!par->codec_tag)
1229 2 par->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags,
1230 par->codec_id);
1231
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 if (!par->codec_tag && par->codec_id != AV_CODEC_ID_RAWVIDEO) {
1232 av_log(s, AV_LOG_ERROR, "No bmp codec tag found for codec %s\n",
1233 avcodec_get_name(par->codec_id));
1234 return AVERROR(EINVAL);
1235 }
1236
1237 /* If vfw extradata updates are supported, this will have
1238 * to be updated to pass extradata(_size) explicitly. */
1239 4 ff_put_bmp_header(dyn_cp, par, 0, 0, mkv->flipped_raw_rgb);
1240 }
1241
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
1242 unsigned int tag;
1243 1 tag = ff_codec_get_tag(ff_codec_wav_tags, par->codec_id);
1244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tag) {
1245 av_log(s, AV_LOG_ERROR, "No wav codec tag found for codec %s\n",
1246 avcodec_get_name(par->codec_id));
1247 return AVERROR(EINVAL);
1248 }
1249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!par->codec_tag)
1250 par->codec_tag = tag;
1251
1252 /* Same comment as for ff_put_bmp_header applies here. */
1253 1 ff_put_wav_header(s, dyn_cp, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
1254 #endif
1255 }
1256
1257 74 *codecpriv_size = avio_get_dyn_buf(dyn_cp, codecpriv);
1258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (dyn_cp->error < 0)
1259 return dyn_cp->error;
1260 74 *max_payload_size = *codecpriv_size + size_to_reserve;
1261
1262 74 return 0;
1263 }
1264
1265 74 static void mkv_put_codecprivate(AVIOContext *pb, unsigned max_payload_size,
1266 const uint8_t *codecpriv, unsigned codecpriv_size)
1267 {
1268 74 unsigned total_codecpriv_size = 0, total_size;
1269
1270 av_assert1(codecpriv_size <= max_payload_size);
1271
1272
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 52 times.
74 if (!max_payload_size)
1273 22 return;
1274
1275 52 total_size = 2 + ebml_length_size(max_payload_size) + max_payload_size;
1276
1277
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 2 times.
52 if (codecpriv_size) {
1278 50 unsigned length_size = ebml_length_size(codecpriv_size);
1279
1280 50 total_codecpriv_size = 2U + length_size + codecpriv_size;
1281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (total_codecpriv_size + 1 == total_size) {
1282 /* It is impossible to add one byte of padding via an EBML Void. */
1283 length_size++;
1284 total_codecpriv_size++;
1285 }
1286 50 put_ebml_id(pb, MATROSKA_ID_CODECPRIVATE);
1287 50 put_ebml_length(pb, codecpriv_size, length_size);
1288 50 avio_write(pb, codecpriv, codecpriv_size);
1289 }
1290
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 48 times.
52 if (total_codecpriv_size < total_size)
1291 4 put_ebml_void(pb, total_size - total_codecpriv_size);
1292 }
1293
1294 5 static int mkv_update_codecprivate(AVFormatContext *s, MatroskaMuxContext *mkv,
1295 uint8_t *side_data, int side_data_size,
1296 AVCodecParameters *par, AVIOContext *pb,
1297 mkv_track *track, unsigned alternative_size)
1298 {
1299 5 AVIOContext *const dyn_bc = mkv->tmp_bc;
1300 uint8_t *codecpriv;
1301 unsigned max_payload_size;
1302 int ret, codecpriv_size;
1303
1304 5 ret = mkv_assemble_codecprivate(s, dyn_bc, par,
1305 side_data, side_data_size, 1, 0,
1306 &codecpriv, &codecpriv_size, &max_payload_size);
1307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (ret < 0)
1308 goto fail;
1309
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 if (codecpriv_size > track->codecpriv_size && !alternative_size) {
1310 ret = AVERROR(ENOSPC);
1311 goto fail;
1312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 } else if (codecpriv_size > track->codecpriv_size) {
1313 av_assert1(alternative_size < track->codecpriv_size);
1314 codecpriv_size = alternative_size;
1315 }
1316 5 avio_seek(pb, track->codecpriv_offset, SEEK_SET);
1317 5 mkv_put_codecprivate(pb, track->codecpriv_size,
1318 codecpriv, codecpriv_size);
1319
1320
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (!par->extradata_size) {
1321 2 ret = ff_alloc_extradata(par, side_data_size);
1322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1323 goto fail;
1324 2 memcpy(par->extradata, side_data, side_data_size);
1325 }
1326 3 fail:
1327 5 ffio_reset_dyn_buf(dyn_bc);
1328 5 return ret;
1329 }
1330
1331 #define MAX_VIDEO_COLOR_ELEMS 20
1332 31 static void mkv_write_video_color(EbmlWriter *writer, const AVStream *st,
1333 const AVCodecParameters *par)
1334 {
1335 const AVPacketSideData *side_data;
1336
1337 31 ebml_writer_open_master(writer, MATROSKA_ID_VIDEOCOLOR);
1338
1339
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 20 times.
31 if (par->color_trc != AVCOL_TRC_UNSPECIFIED &&
1340
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 par->color_trc < AVCOL_TRC_NB) {
1341 11 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS,
1342 11 par->color_trc);
1343 }
1344
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 20 times.
31 if (par->color_space != AVCOL_SPC_UNSPECIFIED &&
1345
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 par->color_space < AVCOL_SPC_NB) {
1346 11 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORMATRIXCOEFF,
1347 11 par->color_space);
1348 }
1349
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 22 times.
31 if (par->color_primaries != AVCOL_PRI_UNSPECIFIED &&
1350
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 par->color_primaries < AVCOL_PRI_NB) {
1351 9 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORPRIMARIES,
1352 9 par->color_primaries);
1353 }
1354
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12 times.
31 if (par->color_range != AVCOL_RANGE_UNSPECIFIED &&
1355
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 par->color_range < AVCOL_RANGE_NB) {
1356 19 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORRANGE, par->color_range);
1357 }
1358
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 14 times.
31 if (par->chroma_location != AVCHROMA_LOC_UNSPECIFIED &&
1359
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 par->chroma_location <= AVCHROMA_LOC_TOP) {
1360 int xpos, ypos;
1361
1362 17 av_chroma_location_enum_to_pos(&xpos, &ypos, par->chroma_location);
1363 17 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ,
1364 17 (xpos >> 7) + 1);
1365 17 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT,
1366 17 (ypos >> 7) + 1);
1367 }
1368
1369 31 side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
1370 AV_PKT_DATA_CONTENT_LIGHT_LEVEL);
1371
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29 times.
31 if (side_data) {
1372 2 const AVContentLightMetadata *metadata = (AVContentLightMetadata *)side_data->data;
1373 2 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORMAXCLL,
1374 2 metadata->MaxCLL);
1375 2 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORMAXFALL,
1376 2 metadata->MaxFALL);
1377 }
1378
1379 31 side_data = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
1380 AV_PKT_DATA_MASTERING_DISPLAY_METADATA);
1381
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29 times.
31 if (side_data) {
1382 2 const AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)side_data->data;
1383 2 ebml_writer_open_master(writer, MATROSKA_ID_VIDEOCOLORMASTERINGMETA);
1384
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (metadata->has_primaries) {
1385 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_RX,
1386 av_q2d(metadata->display_primaries[0][0]));
1387 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_RY,
1388 av_q2d(metadata->display_primaries[0][1]));
1389 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_GX,
1390 av_q2d(metadata->display_primaries[1][0]));
1391 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_GY,
1392 av_q2d(metadata->display_primaries[1][1]));
1393 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_BX,
1394 av_q2d(metadata->display_primaries[2][0]));
1395 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_BY,
1396 av_q2d(metadata->display_primaries[2][1]));
1397 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_WHITEX,
1398 av_q2d(metadata->white_point[0]));
1399 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_WHITEY,
1400 av_q2d(metadata->white_point[1]));
1401 }
1402
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (metadata->has_luminance) {
1403 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX,
1404 av_q2d(metadata->max_luminance));
1405 2 ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN,
1406 av_q2d(metadata->min_luminance));
1407 }
1408 2 ebml_writer_close_or_discard_master(writer);
1409 }
1410
1411 31 ebml_writer_close_or_discard_master(writer);
1412 31 }
1413
1414 #define MAX_VIDEO_PROJECTION_ELEMS 6
1415 29 static void mkv_handle_rotation(void *logctx, const AVStream *st,
1416 double *yaw, double *roll)
1417 {
1418 const int32_t *matrix;
1419 const AVPacketSideData *side_data =
1420 29 av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
1421 AV_PKT_DATA_DISPLAYMATRIX);
1422
1423
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 2 times.
29 if (!side_data)
1424 27 return;
1425
1426 2 matrix = (int32_t *)side_data->data;
1427
1428 /* Check whether this is an affine transformation */
1429
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (matrix[2] || matrix[5])
1430 goto ignore;
1431
1432 /* This together with the checks below test whether
1433 * the upper-left 2x2 matrix is nonsingular. */
1434
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!matrix[0] && !matrix[1])
1435 goto ignore;
1436
1437 /* We ignore the translation part of the matrix (matrix[6] and matrix[7])
1438 * as well as any scaling, i.e. we only look at the upper left 2x2 matrix.
1439 * We only accept matrices that are an exact multiple of an orthogonal one.
1440 * Apart from the multiple, every such matrix can be obtained by
1441 * potentially flipping in the x-direction (corresponding to yaw = 180)
1442 * followed by a rotation of (say) an angle phi in the counterclockwise
1443 * direction. The upper-left 2x2 matrix then looks like this:
1444 * | (+/-)cos(phi) (-/+)sin(phi) |
1445 * scale * | |
1446 * | sin(phi) cos(phi) |
1447 * The first set of signs in the first row apply in case of no flipping,
1448 * the second set applies in case of flipping. */
1449
1450 /* The casts to int64_t are needed because -INT32_MIN doesn't fit
1451 * in an int32_t. */
1452
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 if (matrix[0] == matrix[4] && -(int64_t)matrix[1] == matrix[3]) {
1453 /* No flipping case */
1454 1 *yaw = 0;
1455
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 } else if (-(int64_t)matrix[0] == matrix[4] && matrix[1] == matrix[3]) {
1456 /* Horizontal flip */
1457 *yaw = 180;
1458 } else {
1459 1 ignore:
1460 1 av_log(logctx, AV_LOG_INFO, "Ignoring display matrix indicating "
1461 "non-orthogonal transformation.\n");
1462 1 return;
1463 }
1464 1 *roll = 180 / M_PI * atan2(matrix[3], matrix[4]);
1465
1466 /* We do not write a ProjectionType element indicating "rectangular",
1467 * because this is the default value. */
1468 }
1469
1470 31 static int mkv_handle_spherical(void *logctx, EbmlWriter *writer,
1471 const AVStream *st, uint8_t private[],
1472 double *yaw, double *pitch, double *roll)
1473 {
1474 31 const AVPacketSideData *sd = av_packet_side_data_get(st->codecpar->coded_side_data,
1475 31 st->codecpar->nb_coded_side_data,
1476 AV_PKT_DATA_SPHERICAL);
1477 const AVSphericalMapping *spherical;
1478
1479
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 2 times.
31 if (!sd)
1480 29 return 0;
1481
1482 2 spherical = (const AVSphericalMapping *)sd->data;
1483
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (spherical->projection != AV_SPHERICAL_EQUIRECTANGULAR &&
1484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 spherical->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE &&
1485 spherical->projection != AV_SPHERICAL_CUBEMAP) {
1486 av_log(logctx, AV_LOG_WARNING, "Unknown projection type\n");
1487 return 0;
1488 }
1489
1490
1/3
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
2 switch (spherical->projection) {
1491 2 case AV_SPHERICAL_EQUIRECTANGULAR:
1492 case AV_SPHERICAL_EQUIRECTANGULAR_TILE:
1493 2 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOPROJECTIONTYPE,
1494 MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR);
1495 2 AV_WB32(private, 0); // version + flags
1496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) {
1497 AV_WB32(private + 4, 0);
1498 AV_WB32(private + 8, 0);
1499 AV_WB32(private + 12, 0);
1500 AV_WB32(private + 16, 0);
1501 } else {
1502 2 AV_WB32(private + 4, spherical->bound_top);
1503 2 AV_WB32(private + 8, spherical->bound_bottom);
1504 2 AV_WB32(private + 12, spherical->bound_left);
1505 2 AV_WB32(private + 16, spherical->bound_right);
1506 }
1507 2 ebml_writer_add_bin(writer, MATROSKA_ID_VIDEOPROJECTIONPRIVATE,
1508 private, 20);
1509 2 break;
1510 case AV_SPHERICAL_CUBEMAP:
1511 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOPROJECTIONTYPE,
1512 MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP);
1513 AV_WB32(private, 0); // version + flags
1514 AV_WB32(private + 4, 0); // layout
1515 AV_WB32(private + 8, spherical->padding);
1516 ebml_writer_add_bin(writer, MATROSKA_ID_VIDEOPROJECTIONPRIVATE,
1517 private, 12);
1518 break;
1519 default:
1520 av_assert0(0);
1521 }
1522
1523 2 *yaw = (double) spherical->yaw / (1 << 16);
1524 2 *pitch = (double) spherical->pitch / (1 << 16);
1525 2 *roll = (double) spherical->roll / (1 << 16);
1526
1527 2 return 1; /* Projection included */
1528 }
1529
1530 31 static void mkv_write_video_projection(void *logctx, EbmlWriter *wr,
1531 const AVStream *st, uint8_t private[])
1532 {
1533 31 double yaw = 0, pitch = 0, roll = 0;
1534 int ret;
1535
1536 31 ebml_writer_open_master(wr, MATROSKA_ID_VIDEOPROJECTION);
1537
1538 31 ret = mkv_handle_spherical(logctx, wr, st, private, &yaw, &pitch, &roll);
1539
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 2 times.
31 if (!ret)
1540 29 mkv_handle_rotation(logctx, st, &yaw, &roll);
1541
1542
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29 times.
31 if (yaw)
1543 2 ebml_writer_add_float(wr, MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, yaw);
1544
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29 times.
31 if (pitch)
1545 2 ebml_writer_add_float(wr, MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, pitch);
1546
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 28 times.
31 if (roll)
1547 3 ebml_writer_add_float(wr, MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, roll);
1548
1549 31 ebml_writer_close_or_discard_master(wr);
1550 31 }
1551
1552 #define MAX_FIELD_ORDER_ELEMS 2
1553 31 static void mkv_write_field_order(EbmlWriter *writer, int is_webm,
1554 enum AVFieldOrder field_order)
1555 {
1556
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
31 switch (field_order) {
1557 17 case AV_FIELD_UNKNOWN:
1558 17 break;
1559 10 case AV_FIELD_PROGRESSIVE:
1560 10 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFLAGINTERLACED,
1561 MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE);
1562 10 break;
1563 4 case AV_FIELD_TT:
1564 case AV_FIELD_BB:
1565 case AV_FIELD_TB:
1566 case AV_FIELD_BT:
1567 4 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFLAGINTERLACED,
1568 MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED);
1569
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!is_webm) {
1570 switch (field_order) {
1571 3 case AV_FIELD_TT:
1572 3 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFIELDORDER,
1573 MATROSKA_VIDEO_FIELDORDER_TT);
1574 3 break;
1575 1 case AV_FIELD_BB:
1576 1 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFIELDORDER,
1577 MATROSKA_VIDEO_FIELDORDER_BB);
1578 1 break;
1579 case AV_FIELD_TB:
1580 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFIELDORDER,
1581 MATROSKA_VIDEO_FIELDORDER_TB);
1582 break;
1583 case AV_FIELD_BT:
1584 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFIELDORDER,
1585 MATROSKA_VIDEO_FIELDORDER_BT);
1586 break;
1587 }
1588 }
1589 }
1590 31 }
1591
1592 #define MAX_STEREO_MODE_ELEMS 1
1593 31 static int mkv_write_stereo_mode(AVFormatContext *s, EbmlWriter *writer,
1594 const AVStream *st, int is_webm,
1595 int *h_width, int *h_height)
1596 {
1597 31 const char *error_message_addendum = "";
1598 const AVDictionaryEntry *tag;
1599 31 MatroskaVideoStereoModeType format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB;
1600
1601 /* The following macros create bitfields where the ith bit
1602 * indicates whether the MatroskaVideoStereoModeType with that value
1603 * uses double width/height or is WebM compatible. */
1604 #define FLAG(STEREOMODETYPE, BOOL) | (BOOL) << (STEREOMODETYPE)
1605 #define WDIV1(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \
1606 FLAG(STEREOMODETYPE, WDIV)
1607 #define WDIV2(STEREOMODETYPE, WDIV, HDIV, WEBM) \
1608 FLAG(STEREOMODETYPE, WDIV)
1609 // The zero in the following line consumes the first '|'.
1610 31 const unsigned width_bitfield = 0 STEREOMODE_STEREO3D_MAPPING(WDIV1, WDIV2);
1611
1612 #define HDIV1(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \
1613 FLAG(STEREOMODETYPE, HDIV)
1614 #define HDIV2(STEREOMODETYPE, WDIV, HDIV, WEBM) \
1615 FLAG(STEREOMODETYPE, HDIV)
1616 31 const unsigned height_bitfield = 0 STEREOMODE_STEREO3D_MAPPING(HDIV1, HDIV2);
1617
1618 #define WEBM1(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \
1619 FLAG(STEREOMODETYPE, WEBM)
1620 #define WEBM2(STEREOMODETYPE, WDIV, HDIV, WEBM) \
1621 FLAG(STEREOMODETYPE, WEBM)
1622 31 const unsigned webm_bitfield = 0 STEREOMODE_STEREO3D_MAPPING(WEBM1, WEBM2);
1623
1624 31 *h_width = 1;
1625 31 *h_height = 1;
1626
1627
3/4
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
56 if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) ||
1628 25 (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) {
1629
1630
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 1 times.
48 for (int i = 0; i < MATROSKA_VIDEO_STEREOMODE_TYPE_NB; i++)
1631
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 42 times.
47 if (!strcmp(tag->value, ff_matroska_video_stereo_mode[i])){
1632 5 format = i;
1633 5 break;
1634 }
1635
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (format == MATROSKA_VIDEO_STEREOMODE_TYPE_NB) {
1636 1 long stereo_mode = strtol(tag->value, NULL, 0);
1637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ((unsigned long)stereo_mode >= MATROSKA_VIDEO_STEREOMODE_TYPE_NB)
1638 goto fail;
1639 1 format = stereo_mode;
1640 }
1641 } else {
1642 const AVPacketSideData *sd;
1643 const AVStereo3D *stereo;
1644 /* The following macro presumes all MATROSKA_VIDEO_STEREOMODE_TYPE_*
1645 * values to be in the range 0..254. */
1646 #define STEREOMODE(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \
1647 [(STEREO3DTYPE)][!!((FLAGS) & AV_STEREO3D_FLAG_INVERT)] = (STEREOMODETYPE) + 1,
1648 #define NOTHING(STEREOMODETYPE, WDIV, HDIV, WEBM)
1649 static const unsigned char conversion_table[][2] = {
1650 STEREOMODE_STEREO3D_MAPPING(STEREOMODE, NOTHING)
1651 };
1652 int fmt;
1653
1654 25 sd = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
1655 AV_PKT_DATA_STEREO3D);
1656
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 4 times.
25 if (!sd)
1657 21 return 0;
1658
1659 4 stereo = (const AVStereo3D*)sd->data;
1660
1661 /* A garbage AVStereo3D or something with no Matroska analogon. */
1662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if ((unsigned)stereo->type >= FF_ARRAY_ELEMS(conversion_table))
1663 return 0;
1664
1665 4 fmt = conversion_table[stereo->type][!!(stereo->flags & AV_STEREO3D_FLAG_INVERT)];
1666 /* Format with no Matroska analogon; ignore it */
1667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!fmt)
1668 return 0;
1669 4 format = fmt - 1;
1670 }
1671
1672 // if webm, do not write unsupported modes
1673
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
10 if (is_webm && !(webm_bitfield >> format)) {
1674 error_message_addendum = " for WebM";
1675 goto fail;
1676 }
1677
1678 10 *h_width = 1 << ((width_bitfield >> format) & 1);
1679 10 *h_height = 1 << ((height_bitfield >> format) & 1);
1680
1681 // write StereoMode if format is valid
1682 10 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOSTEREOMODE, format);
1683
1684 10 return 0;
1685 fail:
1686 av_log(s, AV_LOG_ERROR,
1687 "The specified stereo mode is not valid%s.\n",
1688 error_message_addendum);
1689 return AVERROR(EINVAL);
1690 }
1691
1692 66 static void mkv_write_blockadditionmapping(AVFormatContext *s, const MatroskaMuxContext *mkv,
1693 const AVCodecParameters *par, AVIOContext *pb,
1694 mkv_track *track, const AVStream *st)
1695 {
1696 #if CONFIG_MATROSKA_MUXER
1697 const AVDOVIDecoderConfigurationRecord *dovi;
1698 const AVPacketSideData *sd;
1699
1700
4/4
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 3 times.
66 if (IS_SEEKABLE(s->pb, mkv)) {
1701 58 track->blockadditionmapping_offset = avio_tell(pb);
1702 // We can't know at this point if there will be a block with BlockAdditions, so
1703 // we either write the default value here, or a void element. Either of them will
1704 // be overwritten when finishing the track.
1705 58 put_ebml_uint(pb, MATROSKA_ID_TRACKMAXBLKADDID, 0);
1706
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 30 times.
58 if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
1707 // Similarly, reserve space for an eventual
1708 // HDR10+ ITU T.35 metadata BlockAdditionMapping.
1709 28 put_ebml_void(pb, 3 /* BlockAdditionMapping */
1710 + 4 /* BlockAddIDValue */
1711 + 4 /* BlockAddIDType */);
1712 }
1713 }
1714
1715 66 sd = av_packet_side_data_get(st->codecpar->coded_side_data, st->codecpar->nb_coded_side_data,
1716 AV_PKT_DATA_DOVI_CONF);
1717
1718
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 2 times.
66 if (!sd)
1719 64 return;
1720
1721 2 dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
1722
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (dovi->dv_profile <= 10) {
1723 ebml_master mapping;
1724 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
1725 uint32_t type;
1726
1727 2 uint64_t expected_size = (2 + 1 + (sizeof(DVCC_DVVC_BLOCK_TYPE_NAME) - 1))
1728 + (2 + 1 + 4) + (2 + 1 + ISOM_DVCC_DVVC_SIZE);
1729
1730
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (dovi->dv_profile > 7) {
1731 1 type = MATROSKA_BLOCK_ADD_ID_TYPE_DVVC;
1732 } else {
1733 1 type = MATROSKA_BLOCK_ADD_ID_TYPE_DVCC;
1734 }
1735
1736 2 ff_isom_put_dvcc_dvvc(s, buf, dovi);
1737
1738 2 mapping = start_ebml_master(pb, MATROSKA_ID_TRACKBLKADDMAPPING, expected_size);
1739
1740 2 put_ebml_string(pb, MATROSKA_ID_BLKADDIDNAME, DVCC_DVVC_BLOCK_TYPE_NAME);
1741 2 put_ebml_uint(pb, MATROSKA_ID_BLKADDIDTYPE, type);
1742 2 put_ebml_binary(pb, MATROSKA_ID_BLKADDIDEXTRADATA, buf, sizeof(buf));
1743
1744 2 end_ebml_master(pb, mapping);
1745 }
1746 #endif
1747 }
1748
1749 31 static int mkv_write_track_video(AVFormatContext *s, MatroskaMuxContext *mkv,
1750 const AVStream *st, const AVCodecParameters *par,
1751 AVIOContext *pb)
1752 {
1753 const AVDictionaryEntry *tag;
1754 31 int display_width_div = 1, display_height_div = 1;
1755 uint8_t color_space[4], projection_private[20];
1756 31 EBML_WRITER(MAX_FIELD_ORDER_ELEMS + MAX_STEREO_MODE_ELEMS +
1757 MAX_VIDEO_COLOR_ELEMS + MAX_VIDEO_PROJECTION_ELEMS + 8);
1758 int ret;
1759
1760 31 ebml_writer_open_master(&writer, MATROSKA_ID_TRACKVIDEO);
1761
1762 31 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELWIDTH , par->width);
1763 31 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELHEIGHT, par->height);
1764
1765 31 mkv_write_field_order(&writer, IS_WEBM(mkv), par->field_order);
1766
1767 // check both side data and metadata for stereo information,
1768 // write the result to the bitstream if any is found
1769 31 ret = mkv_write_stereo_mode(s, &writer, st, IS_WEBM(mkv),
1770 &display_width_div,
1771 &display_height_div);
1772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (ret < 0)
1773 return ret;
1774
1775
3/4
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 1 times.
62 if (par->format == AV_PIX_FMT_YUVA420P ||
1776
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
61 ((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) ||
1777
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
31 (tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0))) && strtol(tag->value, NULL, 0))
1778 1 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOALPHAMODE, 1);
1779
1780 // write DisplayWidth and DisplayHeight, they contain the size of
1781 // a single source view and/or the display aspect ratio
1782
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 14 times.
31 if (st->sample_aspect_ratio.num) {
1783 17 int64_t d_width = av_rescale(par->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
1784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (d_width > INT_MAX) {
1785 av_log(s, AV_LOG_ERROR, "Overflow in display width\n");
1786 return AVERROR(EINVAL);
1787 }
1788
4/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
17 if (d_width != par->width || display_width_div != 1 || display_height_div != 1) {
1789
6/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6 times.
9 if (IS_WEBM(mkv) || display_width_div != 1 || display_height_div != 1) {
1790 3 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYWIDTH,
1791 3 d_width / display_width_div);
1792 3 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYHEIGHT,
1793 3 par->height / display_height_div);
1794 } else {
1795 AVRational display_aspect_ratio;
1796 6 av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
1797 6 par->width * (int64_t)st->sample_aspect_ratio.num,
1798 6 par->height * (int64_t)st->sample_aspect_ratio.den,
1799 1024 * 1024);
1800 6 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYWIDTH,
1801 6 display_aspect_ratio.num);
1802 6 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYHEIGHT,
1803 6 display_aspect_ratio.den);
1804 6 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYUNIT,
1805 MATROSKA_VIDEO_DISPLAYUNIT_DAR);
1806 }
1807 }
1808
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12 times.
14 } else if (display_width_div != 1 || display_height_div != 1) {
1809 2 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYWIDTH,
1810 2 par->width / display_width_div);
1811 2 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYHEIGHT,
1812 2 par->height / display_height_div);
1813
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 } else if (!IS_WEBM(mkv))
1814 12 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYUNIT,
1815 MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN);
1816
1817
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29 times.
31 if (par->codec_id == AV_CODEC_ID_RAWVIDEO) {
1818 2 AV_WL32(color_space, par->codec_tag);
1819 2 ebml_writer_add_bin(&writer, MATROSKA_ID_VIDEOCOLORSPACE,
1820 color_space, sizeof(color_space));
1821 }
1822 31 mkv_write_video_color(&writer, st, par);
1823 31 mkv_write_video_projection(s, &writer, st, projection_private);
1824
1825 31 return ebml_writer_write(&writer, pb);
1826 }
1827
1828 38 static void mkv_write_default_duration(mkv_track *track, AVIOContext *pb,
1829 AVRational duration)
1830 {
1831 38 put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION,
1832 38 1000000000LL * duration.num / duration.den);
1833 38 track->default_duration_low = 1000LL * duration.num / duration.den;
1834 38 track->default_duration_high = track->default_duration_low +
1835 38 !!(1000LL * duration.num % duration.den);
1836 38 }
1837
1838 74 static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
1839 AVStream *st, mkv_track *track, AVIOContext *pb,
1840 int is_default)
1841 {
1842 74 AVCodecParameters *par = st->codecpar;
1843 ebml_master subinfo, track_master;
1844 74 int native_id = 0;
1845 74 int qt_id = 0;
1846 int bit_depth;
1847 74 int sample_rate = par->sample_rate;
1848 74 int output_sample_rate = 0;
1849 int j, ret;
1850 const AVDictionaryEntry *tag;
1851
1852
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 73 times.
74 if (par->codec_type == AVMEDIA_TYPE_ATTACHMENT)
1853 1 return 0;
1854
1855 73 track_master = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0);
1856 73 put_ebml_uint(pb, MATROSKA_ID_TRACKNUMBER, track->track_num);
1857 73 put_ebml_uid (pb, MATROSKA_ID_TRACKUID, track->uid);
1858 73 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGLACING, 0); // no lacing (yet)
1859
1860
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 69 times.
73 if ((tag = av_dict_get(st->metadata, "title", NULL, 0)))
1861 4 put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value);
1862 73 tag = av_dict_get(st->metadata, "language", NULL, 0);
1863
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 40 times.
106 put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE,
1864
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 tag && tag->value[0] ? tag->value : "und");
1865
1866 // The default value for TRACKFLAGDEFAULT is 1, so add element
1867 // if we need to clear it.
1868
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 29 times.
73 if (!is_default)
1869 44 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, 0);
1870
1871
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 71 times.
73 if (st->disposition & AV_DISPOSITION_FORCED)
1872 2 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, 1);
1873
1874
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 66 times.
73 if (IS_WEBM(mkv)) {
1875 const char *codec_id;
1876
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (par->codec_id != AV_CODEC_ID_WEBVTT) {
1877
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 for (j = 0; ff_webm_codec_tags[j].id != AV_CODEC_ID_NONE; j++) {
1878
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
9 if (ff_webm_codec_tags[j].id == par->codec_id) {
1879 3 codec_id = ff_webm_codec_tags[j].str;
1880 3 native_id = 1;
1881 3 break;
1882 }
1883 }
1884 } else {
1885
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (st->disposition & AV_DISPOSITION_CAPTIONS) {
1886 1 codec_id = "D_WEBVTT/CAPTIONS";
1887 1 native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
1888
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 } else if (st->disposition & AV_DISPOSITION_DESCRIPTIONS) {
1889 1 codec_id = "D_WEBVTT/DESCRIPTIONS";
1890 1 native_id = MATROSKA_TRACK_TYPE_METADATA;
1891
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 } else if (st->disposition & AV_DISPOSITION_METADATA) {
1892 1 codec_id = "D_WEBVTT/METADATA";
1893 1 native_id = MATROSKA_TRACK_TYPE_METADATA;
1894 } else {
1895 1 codec_id = "D_WEBVTT/SUBTITLES";
1896 1 native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
1897 }
1898 }
1899
1900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!native_id) {
1901 av_log(s, AV_LOG_ERROR,
1902 "Only VP8 or VP9 or AV1 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM.\n");
1903 return AVERROR(EINVAL);
1904 }
1905
1906 7 put_ebml_string(pb, MATROSKA_ID_CODECID, codec_id);
1907 } else {
1908
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
66 if (st->disposition & AV_DISPOSITION_COMMENT)
1909 1 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGCOMMENTARY, 1);
1910
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 62 times.
66 if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
1911 4 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED, 1);
1912
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
66 if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
1913 1 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGVISUALIMPAIRED, 1);
1914
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 64 times.
66 if (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB) &&
1915
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB))
1916 != (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB))
1917 2 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGORIGINAL,
1918 2 !!(st->disposition & AV_DISPOSITION_ORIGINAL));
1919
1920 // look for a codec ID string specific to mkv to use,
1921 // if none are found, use AVI codes
1922
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 1 times.
66 if (par->codec_id == AV_CODEC_ID_FFV1) {
1923 /* FFV1 is actually supported natively in Matroska,
1924 * yet we use the VfW way to mux it for compatibility
1925 * with old demuxers. (FIXME: Are they really important?) */
1926
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
65 } else if (par->codec_id != AV_CODEC_ID_RAWVIDEO || par->codec_tag) {
1927
2/2
✓ Branch 0 taken 2403 times.
✓ Branch 1 taken 3 times.
2406 for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) {
1928
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 2343 times.
2403 if (ff_mkv_codec_tags[j].id == par->codec_id) {
1929 60 put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str);
1930 60 native_id = 1;
1931 60 break;
1932 }
1933 }
1934 } else {
1935
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mkv->allow_raw_vfw) {
1936 2 native_id = 0;
1937 } else {
1938 av_log(s, AV_LOG_ERROR, "Raw RGB is not supported Natively in Matroska, you can use AVI or NUT or\n"
1939 "If you would like to store it anyway using VFW mode, enable allow_raw_vfw (-allow_raw_vfw 1)\n");
1940 return AVERROR(EINVAL);
1941 }
1942 }
1943 }
1944
1945
3/4
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
73 switch (par->codec_type) {
1946 AVRational frame_rate;
1947 int audio_frame_samples;
1948
1949 31 case AVMEDIA_TYPE_VIDEO:
1950 31 mkv->have_video = 1;
1951 31 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
1952
1953 31 frame_rate = (AVRational){ 0, 1 };
1954
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
31 if (st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0)
1955 28 frame_rate = st->avg_frame_rate;
1956
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
3 else if (st->r_frame_rate.num > 0 && st->r_frame_rate.den > 0)
1957 2 frame_rate = st->r_frame_rate;
1958
1959
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 1 times.
31 if (frame_rate.num > 0)
1960 30 mkv_write_default_duration(track, pb, av_inv_q(frame_rate));
1961
1962
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
36 if (CONFIG_MATROSKA_MUXER && !native_id &&
1963
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
8 ff_codec_get_tag(ff_codec_movvideo_tags, par->codec_id) &&
1964
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
5 ((!ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id) && par->codec_id != AV_CODEC_ID_RAWVIDEO) ||
1965
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 par->codec_id == AV_CODEC_ID_SVQ1 ||
1966
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 par->codec_id == AV_CODEC_ID_SVQ3 ||
1967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 par->codec_id == AV_CODEC_ID_CINEPAK))
1968 1 qt_id = 1;
1969
1970
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
31 if (qt_id)
1971 1 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME");
1972
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 26 times.
30 else if (!native_id) {
1973 // if there is no mkv-specific codec ID, use VFW mode
1974 4 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC");
1975 4 track->write_dts = 1;
1976 4 ffformatcontext(s)->avoid_negative_ts_use_pts = 0;
1977 }
1978
1979 31 ret = mkv_write_track_video(s, mkv, st, par, pb);
1980
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (ret < 0)
1981 return ret;
1982
1983 31 break;
1984
1985 31 case AVMEDIA_TYPE_AUDIO:
1986
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 26 times.
31 if (par->initial_padding) {
1987 5 int64_t codecdelay = av_rescale_q(par->initial_padding,
1988 5 (AVRational){ 1, par->sample_rate },
1989 5 (AVRational){ 1, 1000000000 });
1990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (codecdelay < 0) {
1991 av_log(s, AV_LOG_ERROR, "Initial padding is invalid\n");
1992 return AVERROR(EINVAL);
1993 }
1994 5 put_ebml_uint(pb, MATROSKA_ID_CODECDELAY, codecdelay);
1995
1996 5 track->ts_offset = av_rescale_q(par->initial_padding,
1997 5 (AVRational){ 1, par->sample_rate },
1998 st->time_base);
1999 5 ffstream(st)->lowest_ts_allowed = -track->ts_offset;
2000 }
2001
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29 times.
31 if (par->codec_id == AV_CODEC_ID_OPUS)
2002 2 put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL);
2003 #if CONFIG_MATROSKA_MUXER
2004
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 23 times.
29 else if (par->codec_id == AV_CODEC_ID_AAC) {
2005 6 ret = get_aac_sample_rates(s, mkv, par->extradata, par->extradata_size,
2006 &sample_rate, &output_sample_rate);
2007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
2008 return ret;
2009 }
2010 #endif
2011
2012 31 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
2013
2014 31 audio_frame_samples = av_get_audio_frame_duration2(par, 0);
2015
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 23 times.
31 if (audio_frame_samples)
2016 8 mkv_write_default_duration(track, pb, (AVRational){ audio_frame_samples,
2017 8 par->sample_rate });
2018
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
31 if (!native_id)
2019 // no mkv-specific ID, use ACM mode
2020 1 put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM");
2021
2022 31 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 6 + 4 * 9);
2023 31 put_ebml_uint(pb, MATROSKA_ID_AUDIOCHANNELS, par->ch_layout.nb_channels);
2024
2025 31 track->sample_rate_offset = avio_tell(pb);
2026 31 put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate);
2027
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
31 if (output_sample_rate)
2028 1 put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
2029
2030 31 bit_depth = av_get_bits_per_sample(par->codec_id);
2031
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
31 if (!bit_depth && par->codec_id != AV_CODEC_ID_ADPCM_G726) {
2032
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14 times.
24 if (par->bits_per_raw_sample)
2033 10 bit_depth = par->bits_per_raw_sample;
2034 else
2035 14 bit_depth = av_get_bytes_per_sample(par->format) << 3;
2036 }
2037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!bit_depth)
2038 bit_depth = par->bits_per_coded_sample;
2039
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (bit_depth)
2040 31 put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth);
2041 31 end_ebml_master(pb, subinfo);
2042 31 break;
2043
2044 11 case AVMEDIA_TYPE_SUBTITLE:
2045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!native_id) {
2046 av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", par->codec_id);
2047 return AVERROR(ENOSYS);
2048 }
2049
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
11 if (!IS_WEBM(mkv) && st->disposition & AV_DISPOSITION_DESCRIPTIONS)
2050 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, 1);
2051
2052
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
11 if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT)
2053 7 native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
2054
2055 11 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id);
2056 11 break;
2057 default:
2058 av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n");
2059 return AVERROR(EINVAL);
2060 }
2061
2062
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 7 times.
73 if (!IS_WEBM(mkv))
2063 66 mkv_write_blockadditionmapping(s, mkv, par, pb, track, st);
2064
2065
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4 times.
73 if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) {
2066 uint8_t *codecpriv;
2067 int codecpriv_size, max_payload_size;
2068 69 track->codecpriv_offset = avio_tell(pb);
2069 69 ret = mkv_assemble_codecprivate(s, mkv->tmp_bc, par,
2070 69 par->extradata, par->extradata_size,
2071 native_id, qt_id,
2072 &codecpriv, &codecpriv_size, &max_payload_size);
2073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (ret < 0)
2074 goto fail;
2075 69 mkv_put_codecprivate(pb, max_payload_size, codecpriv, codecpriv_size);
2076 69 track->codecpriv_size = max_payload_size;
2077 }
2078
2079 73 end_ebml_master(pb, track_master);
2080 73 ret = 0;
2081 73 fail:
2082 73 ffio_reset_dyn_buf(mkv->tmp_bc);
2083
2084 73 return ret;
2085 }
2086
2087 43 static int mkv_write_tracks(AVFormatContext *s)
2088 {
2089 43 MatroskaMuxContext *mkv = s->priv_data;
2090 43 AVIOContext *pb = s->pb;
2091 43 int video_default_idx = -1, audio_default_idx = -1, subtitle_default_idx = -1;
2092 int i, ret;
2093
2094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (mkv->nb_attachments == s->nb_streams)
2095 return 0;
2096
2097 43 ret = start_ebml_master_crc32(&mkv->track.bc, mkv);
2098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2099 return ret;
2100
2101
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 40 times.
43 if (mkv->default_mode != DEFAULT_MODE_PASSTHROUGH) {
2102 3 int video_idx = -1, audio_idx = -1, subtitle_idx = -1;
2103
2104
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 3 times.
13 for (i = s->nb_streams - 1; i >= 0; i--) {
2105 10 AVStream *st = s->streams[i];
2106
2107
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
10 switch (st->codecpar->codec_type) {
2108 #define CASE(type, variable) \
2109 case AVMEDIA_TYPE_ ## type: \
2110 variable ## _idx = i; \
2111 if (st->disposition & AV_DISPOSITION_DEFAULT) \
2112 variable ## _default_idx = i; \
2113 break;
2114
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 CASE(VIDEO, video)
2115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 CASE(AUDIO, audio)
2116
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 CASE(SUBTITLE, subtitle)
2117 #undef CASE
2118 }
2119 }
2120
2121 3 video_default_idx = FFMAX(video_default_idx, video_idx);
2122 3 audio_default_idx = FFMAX(audio_default_idx, audio_idx);
2123
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (mkv->default_mode != DEFAULT_MODE_INFER_NO_SUBS)
2124 2 subtitle_default_idx = FFMAX(subtitle_default_idx, subtitle_idx);
2125 }
2126
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 43 times.
117 for (i = 0; i < s->nb_streams; i++) {
2127 74 AVStream *st = s->streams[i];
2128
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 int is_default = st->disposition & AV_DISPOSITION_DEFAULT ||
2129
5/6
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 45 times.
120 i == video_default_idx || i == audio_default_idx ||
2130 i == subtitle_default_idx;
2131 74 ret = mkv_write_track(s, mkv, st, &mkv->tracks[i],
2132 mkv->track.bc, is_default);
2133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (ret < 0)
2134 return ret;
2135 }
2136
2137 43 return end_ebml_master_crc32_tentatively(pb, &mkv->track, mkv,
2138 MATROSKA_ID_TRACKS);
2139 }
2140
2141 121 static int mkv_write_simpletag(AVIOContext *pb, const AVDictionaryEntry *t)
2142 {
2143 121 EBML_WRITER(4);
2144 121 uint8_t *key = av_strdup(t->key);
2145 121 uint8_t *p = key;
2146 121 const uint8_t *lang = NULL;
2147 int ret;
2148
2149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
121 if (!key)
2150 return AVERROR(ENOMEM);
2151
2152
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 114 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 2 times.
128 if ((p = strrchr(p, '-')) &&
2153 7 (lang = ff_convert_lang_to(p + 1, AV_LANG_ISO639_2_BIBL)))
2154 5 *p = 0;
2155
2156 121 p = key;
2157
2/2
✓ Branch 0 taken 1396 times.
✓ Branch 1 taken 121 times.
1517 while (*p) {
2158
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1395 times.
1396 if (*p == ' ')
2159 1 *p = '_';
2160
3/4
✓ Branch 0 taken 1225 times.
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 1225 times.
✗ Branch 3 not taken.
1395 else if (*p >= 'a' && *p <= 'z')
2161 1225 *p -= 'a' - 'A';
2162 1396 p++;
2163 }
2164
2165 121 ebml_writer_open_master(&writer, MATROSKA_ID_SIMPLETAG);
2166 121 ebml_writer_add_string(&writer, MATROSKA_ID_TAGNAME, key);
2167
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 116 times.
121 if (lang)
2168 5 ebml_writer_add_string(&writer, MATROSKA_ID_TAGLANG, lang);
2169 121 ebml_writer_add_string(&writer, MATROSKA_ID_TAGSTRING, t->value);
2170 121 ret = ebml_writer_write(&writer, pb);
2171
2172 121 av_freep(&key);
2173 121 return ret;
2174 }
2175
2176 117 static void mkv_write_tag_targets(MatroskaMuxContext *mkv, AVIOContext *pb,
2177 uint32_t elementid, uint64_t uid)
2178 {
2179 117 ebml_master targets = start_ebml_master(pb, MATROSKA_ID_TAGTARGETS,
2180 4 + 1 + 8);
2181
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 43 times.
117 if (elementid)
2182 74 put_ebml_uid(pb, elementid, uid);
2183 117 end_ebml_master(pb, targets);
2184 117 }
2185
2186 189 static int mkv_check_tag_name(const char *name, uint32_t elementid)
2187 {
2188
2/2
✓ Branch 1 taken 173 times.
✓ Branch 2 taken 6 times.
368 return av_strcasecmp(name, "title") &&
2189
2/2
✓ Branch 1 taken 161 times.
✓ Branch 2 taken 12 times.
352 av_strcasecmp(name, "stereo_mode") &&
2190
1/2
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
334 av_strcasecmp(name, "creation_time") &&
2191
2/2
✓ Branch 1 taken 156 times.
✓ Branch 2 taken 5 times.
322 av_strcasecmp(name, "encoding_tool") &&
2192
2/2
✓ Branch 1 taken 93 times.
✓ Branch 2 taken 63 times.
317 av_strcasecmp(name, "duration") &&
2193
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 33 times.
93 (elementid != MATROSKA_ID_TAGTARGETS_TRACKUID ||
2194
4/4
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 10 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 121 times.
463 av_strcasecmp(name, "language")) &&
2195
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 (elementid != MATROSKA_ID_TAGTARGETS_ATTACHUID ||
2196
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
3 (av_strcasecmp(name, "filename") &&
2197 1 av_strcasecmp(name, "mimetype")));
2198 }
2199
2200 117 static int mkv_write_tag(MatroskaMuxContext *mkv, const AVDictionary *m,
2201 AVIOContext **pb, unsigned reserved_size,
2202 uint32_t elementid, uint64_t uid)
2203 {
2204 117 const AVDictionaryEntry *t = NULL;
2205 117 AVIOContext *const tmp_bc = mkv->tmp_bc;
2206 uint8_t *buf;
2207 117 int ret = 0, size, tag_written = 0;
2208
2209 117 mkv_write_tag_targets(mkv, tmp_bc, elementid, uid);
2210
2211
2/2
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 117 times.
306 while ((t = av_dict_iterate(m, t))) {
2212
2/2
✓ Branch 1 taken 121 times.
✓ Branch 2 taken 68 times.
189 if (mkv_check_tag_name(t->key, elementid)) {
2213 121 ret = mkv_write_simpletag(tmp_bc, t);
2214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
121 if (ret < 0)
2215 goto end;
2216 121 tag_written = 1;
2217 }
2218 }
2219
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 52 times.
117 if (reserved_size)
2220 65 put_ebml_void(tmp_bc, reserved_size);
2221
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 14 times.
52 else if (!tag_written)
2222 38 goto end;
2223
2224 79 size = avio_get_dyn_buf(tmp_bc, &buf);
2225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (tmp_bc->error) {
2226 ret = tmp_bc->error;
2227 goto end;
2228 }
2229
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 40 times.
79 if (!*pb) {
2230 39 ret = start_ebml_master_crc32(pb, mkv);
2231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (ret < 0)
2232 goto end;
2233 }
2234 79 put_ebml_binary(*pb, MATROSKA_ID_TAG, buf, size);
2235
2236 117 end:
2237 117 ffio_reset_dyn_buf(tmp_bc);
2238 117 return ret;
2239 }
2240
2241 43 static int mkv_write_tags(AVFormatContext *s)
2242 {
2243 43 MatroskaMuxContext *mkv = s->priv_data;
2244
4/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 3 times.
43 int i, ret, seekable = IS_SEEKABLE(s->pb, mkv);
2245
2246 43 mkv->wrote_tags = 1;
2247
2248 43 ff_metadata_conv_ctx(s, ff_mkv_metadata_conv, NULL);
2249
2250 43 ret = mkv_write_tag(mkv, s->metadata, &mkv->tags.bc, 0, 0, 0);
2251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2252 return ret;
2253
2254
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 43 times.
117 for (i = 0; i < s->nb_streams; i++) {
2255 74 const AVStream *st = s->streams[i];
2256 74 mkv_track *track = &mkv->tracks[i];
2257
2258
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 73 times.
74 if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT)
2259 1 continue;
2260
2261
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 8 times.
73 ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc,
2262 seekable ? DURATION_SIMPLETAG_SIZE : 0,
2263 MATROSKA_ID_TAGTARGETS_TRACKUID, track->uid);
2264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (ret < 0)
2265 return ret;
2266
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 8 times.
73 if (seekable)
2267 65 track->duration_offset = avio_tell(mkv->tags.bc) - DURATION_SIMPLETAG_SIZE;
2268 }
2269
2270
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
43 if (mkv->nb_attachments && !IS_WEBM(mkv)) {
2271
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (i = 0; i < s->nb_streams; i++) {
2272 3 const mkv_track *track = &mkv->tracks[i];
2273 3 const AVStream *st = s->streams[i];
2274
2275
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT)
2276 2 continue;
2277
2278 1 ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc, 0,
2279 1 MATROSKA_ID_TAGTARGETS_ATTACHUID, track->uid);
2280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2281 return ret;
2282 }
2283 }
2284
2285
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 4 times.
43 if (mkv->tags.bc) {
2286 39 return end_ebml_master_crc32_tentatively(s->pb, &mkv->tags, mkv,
2287 MATROSKA_ID_TAGS);
2288 }
2289 4 return 0;
2290 }
2291
2292 1 static int mkv_new_chapter_ids_needed(const AVFormatContext *s)
2293 {
2294
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (unsigned i = 0; i < s->nb_chapters; i++) {
2295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!s->chapters[i]->id)
2296 return 1;
2297
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 for (unsigned j = 0; j < i; j++)
2298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (s->chapters[j]->id == s->chapters[i]->id)
2299 return 1;
2300 }
2301 1 return 0;
2302 }
2303
2304 86 static int mkv_write_chapters(AVFormatContext *s)
2305 {
2306 86 MatroskaMuxContext *mkv = s->priv_data;
2307 86 AVIOContext *dyn_cp = NULL, *dyn_tags = NULL, **tags, *pb = s->pb;
2308 ebml_master editionentry;
2309 86 AVRational scale = {1, 1E9};
2310 int ret, create_new_ids;
2311
2312
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
86 if (!s->nb_chapters || mkv->wrote_chapters)
2313 85 return 0;
2314
2315 1 ret = start_ebml_master_crc32(&dyn_cp, mkv);
2316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2317 return ret;
2318
2319 1 editionentry = start_ebml_master(dyn_cp, MATROSKA_ID_EDITIONENTRY, 0);
2320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!IS_WEBM(mkv)) {
2321 put_ebml_uint(dyn_cp, MATROSKA_ID_EDITIONFLAGDEFAULT, 1);
2322 /* If mkv_write_tags() has already been called, then any tags
2323 * corresponding to chapters will be put into a new Tags element. */
2324 tags = mkv->wrote_tags ? &dyn_tags : &mkv->tags.bc;
2325 } else
2326 1 tags = NULL;
2327
2328 1 create_new_ids = mkv_new_chapter_ids_needed(s);
2329
2330
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (unsigned i = 0; i < s->nb_chapters; i++) {
2331 4 AVChapter *const c = s->chapters[i];
2332 4 int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale);
2333 4 int64_t chapterend = av_rescale_q(c->end, c->time_base, scale);
2334 const AVDictionaryEntry *t;
2335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 uint64_t uid = create_new_ids ? i + 1ULL : c->id;
2336 4 EBML_WRITER(7);
2337
2338
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) {
2339 av_log(s, AV_LOG_ERROR,
2340 "Invalid chapter start (%"PRId64") or end (%"PRId64").\n",
2341 chapterstart, chapterend);
2342 ret = AVERROR_INVALIDDATA;
2343 goto fail;
2344 }
2345
2346 4 ebml_writer_open_master(&writer, MATROSKA_ID_CHAPTERATOM);
2347 4 ebml_writer_add_uint(&writer, MATROSKA_ID_CHAPTERUID, uid);
2348 4 ebml_writer_add_uint(&writer, MATROSKA_ID_CHAPTERTIMESTART, chapterstart);
2349 4 ebml_writer_add_uint(&writer, MATROSKA_ID_CHAPTERTIMEEND, chapterend);
2350
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
2351 4 ebml_writer_open_master(&writer, MATROSKA_ID_CHAPTERDISPLAY);
2352 4 ebml_writer_add_string(&writer, MATROSKA_ID_CHAPSTRING, t->value);
2353 4 ebml_writer_add_string(&writer, MATROSKA_ID_CHAPLANG , "und");
2354 }
2355 4 ret = ebml_writer_write(&writer, dyn_cp);
2356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
2357 goto fail;
2358
2359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (tags) {
2360 ff_metadata_conv(&c->metadata, ff_mkv_metadata_conv, NULL);
2361
2362 ret = mkv_write_tag(mkv, c->metadata, tags, 0,
2363 MATROSKA_ID_TAGTARGETS_CHAPTERUID, uid);
2364 if (ret < 0)
2365 goto fail;
2366 }
2367 }
2368 1 end_ebml_master(dyn_cp, editionentry);
2369 1 mkv->wrote_chapters = 1;
2370
2371 1 ret = end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS, 0, 0, 1);
2372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2373 goto fail;
2374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dyn_tags)
2375 return end_ebml_master_crc32(pb, &dyn_tags, mkv,
2376 MATROSKA_ID_TAGS, 0, 0, 1);
2377 1 return 0;
2378
2379 fail:
2380 if (tags) {
2381 /* tags == &mkv->tags.bc can only happen if mkv->tags.bc was
2382 * initially NULL, so we never free older tags. */
2383 ffio_free_dyn_buf(tags);
2384 }
2385 ffio_free_dyn_buf(&dyn_cp);
2386 return ret;
2387 }
2388
2389 2 static const char *get_mimetype(const AVStream *st)
2390 {
2391 const AVDictionaryEntry *t;
2392
2393
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (t = av_dict_get(st->metadata, "mimetype", NULL, 0))
2394 2 return t->value;
2395 if (st->codecpar->codec_id != AV_CODEC_ID_NONE) {
2396 const AVCodecDescriptor *desc = avcodec_descriptor_get(st->codecpar->codec_id);
2397 if (desc && desc->mime_types) {
2398 return desc->mime_types[0];
2399 } else if (st->codecpar->codec_id == AV_CODEC_ID_TEXT)
2400 return "text/plain";
2401 }
2402
2403 return NULL;
2404 }
2405
2406 39 static int mkv_write_attachments(AVFormatContext *s)
2407 {
2408 39 MatroskaMuxContext *mkv = s->priv_data;
2409 39 AVIOContext *dyn_cp = NULL, *pb = s->pb;
2410 int i, ret;
2411
2412
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 1 times.
39 if (!mkv->nb_attachments)
2413 38 return 0;
2414
2415 1 ret = start_ebml_master_crc32(&dyn_cp, mkv);
2416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2417 return ret;
2418
2419
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (i = 0; i < s->nb_streams; i++) {
2420 3 const AVStream *st = s->streams[i];
2421 3 mkv_track *track = &mkv->tracks[i];
2422 3 EBML_WRITER(6);
2423 const AVDictionaryEntry *t;
2424 const char *mimetype;
2425
2426
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT)
2427 2 continue;
2428
2429 1 ebml_writer_open_master(&writer, MATROSKA_ID_ATTACHEDFILE);
2430
2431
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (t = av_dict_get(st->metadata, "title", NULL, 0))
2432 ebml_writer_add_string(&writer, MATROSKA_ID_FILEDESC, t->value);
2433
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!(t = av_dict_get(st->metadata, "filename", NULL, 0))) {
2434 av_log(s, AV_LOG_ERROR, "Attachment stream %d has no filename tag.\n", i);
2435 ffio_free_dyn_buf(&dyn_cp);
2436 return AVERROR(EINVAL);
2437 }
2438 1 ebml_writer_add_string(&writer, MATROSKA_ID_FILENAME, t->value);
2439
2440 1 mimetype = get_mimetype(st);
2441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(mimetype);
2442 1 ebml_writer_add_string(&writer, MATROSKA_ID_FILEMIMETYPE, mimetype);
2443 1 ebml_writer_add_bin(&writer, MATROSKA_ID_FILEDATA,
2444 1 st->codecpar->extradata, st->codecpar->extradata_size);
2445 1 ebml_writer_add_uid(&writer, MATROSKA_ID_FILEUID, track->uid);
2446 1 ret = ebml_writer_write(&writer, dyn_cp);
2447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
2448 ffio_free_dyn_buf(&dyn_cp);
2449 return ret;
2450 }
2451 }
2452 1 return end_ebml_master_crc32(pb, &dyn_cp, mkv,
2453 MATROSKA_ID_ATTACHMENTS, 0, 0, 1);
2454 }
2455
2456 39 static int64_t get_metadata_duration(AVFormatContext *s)
2457 {
2458 39 const AVDictionaryEntry *duration = av_dict_get(s->metadata, "DURATION",
2459 NULL, 0);
2460 39 int64_t max = 0;
2461 int64_t us;
2462
2463
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
39 if (duration && (av_parse_time(&us, duration->value, 1) == 0) && us > 0) {
2464 av_log(s, AV_LOG_DEBUG, "get_metadata_duration found duration in context metadata: %" PRId64 "\n", us);
2465 return us;
2466 }
2467
2468
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 39 times.
109 for (unsigned i = 0; i < s->nb_streams; i++) {
2469 int64_t us;
2470 70 duration = av_dict_get(s->streams[i]->metadata, "DURATION", NULL, 0);
2471
2472
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 65 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
70 if (duration && (av_parse_time(&us, duration->value, 1) == 0))
2473 5 max = FFMAX(max, us);
2474 }
2475
2476 39 av_log(s, AV_LOG_DEBUG, "get_metadata_duration returned: %" PRId64 "\n", max);
2477 39 return max;
2478 }
2479
2480 43 static void ebml_write_header(AVIOContext *pb,
2481 const char *doctype, int version)
2482 {
2483 43 EBML_WRITER(8);
2484 43 ebml_writer_open_master(&writer, EBML_ID_HEADER);
2485 43 ebml_writer_add_uint (&writer, EBML_ID_EBMLVERSION, 1);
2486 43 ebml_writer_add_uint (&writer, EBML_ID_EBMLREADVERSION, 1);
2487 43 ebml_writer_add_uint (&writer, EBML_ID_EBMLMAXIDLENGTH, 4);
2488 43 ebml_writer_add_uint (&writer, EBML_ID_EBMLMAXSIZELENGTH, 8);
2489 43 ebml_writer_add_string(&writer, EBML_ID_DOCTYPE, doctype);
2490 43 ebml_writer_add_uint (&writer, EBML_ID_DOCTYPEVERSION, version);
2491 43 ebml_writer_add_uint (&writer, EBML_ID_DOCTYPEREADVERSION, 2);
2492 /* The size is bounded, so no need to check this. */
2493 43 ebml_writer_write(&writer, pb);
2494 43 }
2495
2496 43 static int mkv_write_info(AVFormatContext *s)
2497 {
2498 43 MatroskaMuxContext *mkv = s->priv_data;
2499 const AVDictionaryEntry *tag;
2500 int64_t creation_time;
2501 AVIOContext *pb;
2502 43 int ret = start_ebml_master_crc32(&mkv->info.bc, mkv);
2503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2504 return ret;
2505 43 pb = mkv->info.bc;
2506
2507 43 put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
2508
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 37 times.
43 if ((tag = av_dict_get(s->metadata, "title", NULL, 0)))
2509 6 put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value);
2510
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 39 times.
43 if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
2511 4 put_ebml_string(pb, MATROSKA_ID_MUXINGAPP, LIBAVFORMAT_IDENT);
2512
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((tag = av_dict_get(s->metadata, "encoding_tool", NULL, 0)))
2513 put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, tag->value);
2514 else
2515 4 put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);
2516
2517
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!IS_WEBM(mkv))
2518 4 put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, mkv->segment_uid, 16);
2519 } else {
2520 39 const char *ident = "Lavf";
2521 39 put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , ident);
2522 39 put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, ident);
2523 }
2524
2525
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 42 times.
43 if (ff_parse_creation_time_metadata(s, &creation_time, 0) > 0) {
2526 // Adjust time so it's relative to 2001-01-01 and convert to nanoseconds.
2527 1 int64_t date_utc = (creation_time - 978307200000000LL) * 1000;
2528 uint8_t date_utc_buf[8];
2529 1 AV_WB64(date_utc_buf, date_utc);
2530 1 put_ebml_binary(pb, MATROSKA_ID_DATEUTC, date_utc_buf, 8);
2531 }
2532
2533 // reserve space for the duration
2534 43 mkv->duration = 0;
2535 43 mkv->duration_offset = avio_tell(pb);
2536
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 4 times.
43 if (!mkv->is_live) {
2537 39 int64_t metadata_duration = get_metadata_duration(s);
2538
2539
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 35 times.
39 if (s->duration > 0) {
2540 4 int64_t scaledDuration = av_rescale(s->duration, 1000, AV_TIME_BASE);
2541 4 put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);
2542 4 av_log(s, AV_LOG_DEBUG, "Write early duration from recording time = %" PRIu64 "\n", scaledDuration);
2543
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 31 times.
35 } else if (metadata_duration > 0) {
2544 4 int64_t scaledDuration = av_rescale(metadata_duration, 1000, AV_TIME_BASE);
2545 4 put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);
2546 4 av_log(s, AV_LOG_DEBUG, "Write early duration from metadata = %" PRIu64 "\n", scaledDuration);
2547
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 4 times.
31 } else if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
2548 27 put_ebml_void(pb, 11); // assumes double-precision float to be written
2549 }
2550 }
2551 43 return end_ebml_master_crc32_tentatively(s->pb, &mkv->info,
2552 mkv, MATROSKA_ID_INFO);
2553 }
2554
2555 43 static int mkv_write_header(AVFormatContext *s)
2556 {
2557 43 MatroskaMuxContext *mkv = s->priv_data;
2558 43 AVIOContext *pb = s->pb;
2559 43 int ret, version = 2;
2560
2561 43 ret = avio_open_dyn_buf(&mkv->tmp_bc);
2562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2563 return ret;
2564
2565
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
47 if (!IS_WEBM(mkv) ||
2566
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
8 av_dict_get(s->metadata, "stereo_mode", NULL, 0) ||
2567 4 av_dict_get(s->metadata, "alpha_mode", NULL, 0))
2568 39 version = 4;
2569
2570
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 43 times.
117 for (unsigned i = 0; i < s->nb_streams; i++) {
2571
4/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 6 times.
146 if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_OPUS ||
2572
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 65 times.
138 av_dict_get(s->streams[i]->metadata, "stereo_mode", NULL, 0) ||
2573 66 av_dict_get(s->streams[i]->metadata, "alpha_mode", NULL, 0))
2574 9 version = 4;
2575 }
2576
2577 43 ebml_write_header(pb, s->oformat->name, version);
2578 43 put_ebml_id(pb, MATROSKA_ID_SEGMENT);
2579 43 put_ebml_size_unknown(pb, 8);
2580 43 mkv->segment_offset = avio_tell(pb);
2581
2582 // We write a SeekHead at the beginning to point to all other level
2583 // one elements (except Clusters).
2584 43 mkv_start_seekhead(mkv, pb);
2585
2586 43 ret = mkv_write_info(s);
2587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2588 return ret;
2589
2590 43 ret = mkv_write_tracks(s);
2591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2592 return ret;
2593
2594 43 ret = mkv_write_chapters(s);
2595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2596 return ret;
2597
2598
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 4 times.
43 if (!IS_WEBM(mkv)) {
2599 39 ret = mkv_write_attachments(s);
2600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (ret < 0)
2601 return ret;
2602 }
2603
2604 /* Must come after mkv_write_chapters() to write chapter tags
2605 * into the same Tags element as the other tags. */
2606 43 ret = mkv_write_tags(s);
2607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
2608 return ret;
2609
2610
4/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 35 times.
43 if (!IS_SEEKABLE(pb, mkv)) {
2611 8 ret = mkv_write_seekhead(pb, mkv, 0, avio_tell(pb));
2612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
2613 return ret;
2614 }
2615
2616
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 40 times.
43 if (s->metadata_header_padding > 0) {
2617
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->metadata_header_padding == 1)
2618 1 s->metadata_header_padding++;
2619 3 put_ebml_void(pb, s->metadata_header_padding);
2620 }
2621
2622
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 38 times.
43 if (mkv->reserve_cues_space || mkv->move_cues_to_front) {
2623
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 if (IS_SEEKABLE(pb, mkv)) {
2624 5 mkv->cues_pos = avio_tell(pb);
2625
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (mkv->reserve_cues_space >= 1) {
2626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (mkv->reserve_cues_space == 1)
2627 mkv->reserve_cues_space++;
2628 4 put_ebml_void(pb, mkv->reserve_cues_space);
2629 }
2630 } else
2631 mkv->reserve_cues_space = -1;
2632 }
2633
2634 43 mkv->cluster_pos = -1;
2635
2636 // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or
2637 // after 4k and on a keyframe
2638
4/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 3 times.
43 if (IS_SEEKABLE(pb, mkv)) {
2639
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2 times.
35 if (mkv->cluster_time_limit < 0)
2640 33 mkv->cluster_time_limit = 5000;
2641
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1 times.
35 if (mkv->cluster_size_limit < 0)
2642 34 mkv->cluster_size_limit = 5 * 1024 * 1024;
2643 } else {
2644
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (mkv->cluster_time_limit < 0)
2645 8 mkv->cluster_time_limit = 1000;
2646
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (mkv->cluster_size_limit < 0)
2647 8 mkv->cluster_size_limit = 32 * 1024;
2648 }
2649
2650 43 return 0;
2651 }
2652
2653 #if CONFIG_MATROSKA_MUXER
2654 158 static int mkv_reformat_h2645(MatroskaMuxContext *mkv, AVIOContext *pb,
2655 const AVPacket *pkt, int *size)
2656 {
2657 int ret;
2658
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 79 times.
158 if (pb) {
2659 79 ff_nal_units_write_list(&mkv->cur_block.h2645_nalu_list, pb, pkt->data);
2660 } else {
2661 79 ret = ff_nal_units_create_list(&mkv->cur_block.h2645_nalu_list, pkt->data, pkt->size);
2662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (ret < 0)
2663 return ret;
2664 79 *size = ret;
2665 }
2666 158 return 0;
2667 }
2668
2669 76 static int mkv_reformat_wavpack(MatroskaMuxContext *mkv, AVIOContext *pb,
2670 const AVPacket *pkt, int *size)
2671 {
2672 76 const uint8_t *src = pkt->data;
2673 76 int srclen = pkt->size;
2674 76 int offset = 0;
2675 int ret;
2676
2677
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 76 times.
264 while (srclen >= WV_HEADER_SIZE) {
2678 WvHeader header;
2679
2680 188 ret = ff_wv_parse_header(&header, src);
2681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
188 if (ret < 0)
2682 return ret;
2683 188 src += WV_HEADER_SIZE;
2684 188 srclen -= WV_HEADER_SIZE;
2685
2686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
188 if (srclen < header.blocksize)
2687 return AVERROR_INVALIDDATA;
2688
2689
6/6
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 112 times.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 112 times.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 48 times.
188 offset += 4 * !!header.initial + 8 + 4 * !(header.initial && header.final);
2690
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 94 times.
188 if (pb) {
2691
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 56 times.
94 if (header.initial)
2692 38 avio_wl32(pb, header.samples);
2693 94 avio_wl32(pb, header.flags);
2694 94 avio_wl32(pb, header.crc);
2695
2696
4/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 24 times.
94 if (!(header.initial && header.final))
2697 70 avio_wl32(pb, header.blocksize);
2698
2699 94 avio_write(pb, src, header.blocksize);
2700 }
2701 188 src += header.blocksize;
2702 188 srclen -= header.blocksize;
2703 188 offset += header.blocksize;
2704 }
2705 76 *size = offset;
2706
2707 76 return 0;
2708 }
2709 #endif
2710
2711 56 static int mkv_reformat_av1(MatroskaMuxContext *mkv, AVIOContext *pb,
2712 const AVPacket *pkt, int *size)
2713 {
2714 56 int ret = ff_av1_filter_obus(pb, pkt->data, pkt->size);
2715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (ret < 0)
2716 return ret;
2717 56 *size = ret;
2718 56 return 0;
2719 }
2720
2721 120 static int webm_reformat_vtt(MatroskaMuxContext *mkv, AVIOContext *pb,
2722 const AVPacket *pkt, int *size)
2723 {
2724 const uint8_t *id, *settings;
2725 size_t id_size, settings_size;
2726 120 unsigned total = pkt->size + 2U;
2727
2728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
120 if (total > INT_MAX)
2729 return AVERROR(ERANGE);
2730
2731 120 id = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_IDENTIFIER,
2732 &id_size);
2733 120 settings = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_SETTINGS,
2734 &settings_size);
2735
2/4
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 120 times.
120 if (id_size > INT_MAX - total || settings_size > INT_MAX - (total += id_size))
2736 return AVERROR(ERANGE);
2737 120 *size = total += settings_size;
2738
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 60 times.
120 if (pb) {
2739 60 avio_write(pb, id, id_size);
2740 60 avio_w8(pb, '\n');
2741 60 avio_write(pb, settings, settings_size);
2742 60 avio_w8(pb, '\n');
2743 60 avio_write(pb, pkt->data, pkt->size);
2744 }
2745 120 return 0;
2746 }
2747
2748 122 static void mkv_write_blockadditional(EbmlWriter *writer, const uint8_t *buf,
2749 size_t size, uint64_t additional_id)
2750 {
2751 122 ebml_writer_open_master(writer, MATROSKA_ID_BLOCKMORE);
2752 122 ebml_writer_add_uint(writer, MATROSKA_ID_BLOCKADDID, additional_id);
2753 122 ebml_writer_add_bin (writer, MATROSKA_ID_BLOCKADDITIONAL, buf, size);
2754 122 ebml_writer_close_master(writer);
2755 122 }
2756
2757 6784 static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv,
2758 AVIOContext *pb, const AVCodecParameters *par,
2759 mkv_track *track, const AVPacket *pkt,
2760 int keyframe, int64_t ts, uint64_t duration,
2761 int force_blockgroup, int64_t relative_packet_pos)
2762 {
2763 uint8_t t35_buf[6 + AV_HDR_PLUS_MAX_PAYLOAD_SIZE];
2764 uint8_t *side_data;
2765 size_t side_data_size;
2766 uint64_t additional_id;
2767 6784 unsigned track_number = track->track_num;
2768 6784 EBML_WRITER(12);
2769 int ret;
2770
2771 6784 mkv->cur_block.track = track;
2772 6784 mkv->cur_block.pkt = pkt;
2773 6784 mkv->cur_block.rel_ts = ts - mkv->cluster_pts;
2774 6784 mkv->cur_block.flags = 0;
2775
2776 /* Open a BlockGroup with a Block now; it will later be converted
2777 * to a SimpleBlock if possible. */
2778 6784 ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKGROUP);
2779 6784 ebml_writer_add_block(&writer, mkv);
2780
2781
4/4
✓ Branch 0 taken 6199 times.
✓ Branch 1 taken 585 times.
✓ Branch 2 taken 6108 times.
✓ Branch 3 taken 91 times.
6784 if (duration > 0 && (par->codec_type == AVMEDIA_TYPE_SUBTITLE ||
2782 /* If the packet's duration is inconsistent with the default duration,
2783 * add an explicit duration element. */
2784
2/2
✓ Branch 0 taken 3810 times.
✓ Branch 1 taken 2298 times.
6108 track->default_duration_high > 0 &&
2785
2/2
✓ Branch 0 taken 917 times.
✓ Branch 1 taken 2893 times.
3810 duration != track->default_duration_high &&
2786
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 834 times.
917 duration != track->default_duration_low))
2787 174 ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKDURATION, duration);
2788
2789 6784 av_log(logctx, AV_LOG_DEBUG,
2790 "Writing block of size %d with pts %" PRId64 ", dts %" PRId64 ", "
2791 "duration %" PRId64 " at relative offset %" PRId64 " in cluster "
2792 "at offset %" PRId64 ". TrackNumber %u, keyframe %d\n",
2793 6784 pkt->size, pkt->pts, pkt->dts, pkt->duration, relative_packet_pos,
2794 mkv->cluster_pos, track_number, keyframe != 0);
2795
2796 6784 side_data = av_packet_get_side_data(pkt,
2797 AV_PKT_DATA_SKIP_SAMPLES,
2798 &side_data_size);
2799
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6778 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6784 if (side_data && side_data_size >= 10) {
2800 6 int64_t discard_padding = AV_RL32(side_data + 4);
2801
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (discard_padding) {
2802 3 discard_padding = av_rescale_q(discard_padding,
2803 3 (AVRational){1, par->sample_rate},
2804 3 (AVRational){1, 1000000000});
2805 3 ebml_writer_add_sint(&writer, MATROSKA_ID_DISCARDPADDING, discard_padding);
2806 }
2807 }
2808
2809 6784 ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKADDITIONS);
2810 6784 side_data = av_packet_get_side_data(pkt,
2811 AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
2812 &side_data_size);
2813
3/4
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 6664 times.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
6784 if (side_data && side_data_size >= 8 &&
2814 // Only the Codec-specific BlockMore (id == 1) is currently supported.
2815
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 (additional_id = AV_RB64(side_data)) == MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE) {
2816 120 mkv_write_blockadditional(&writer, side_data + 8, side_data_size - 8,
2817 additional_id);
2818 120 track->max_blockaddid = FFMAX(track->max_blockaddid, additional_id);
2819 }
2820
2821
2/2
✓ Branch 0 taken 2216 times.
✓ Branch 1 taken 4568 times.
6784 if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
2822 2216 side_data = av_packet_get_side_data(pkt,
2823 AV_PKT_DATA_DYNAMIC_HDR10_PLUS,
2824 &side_data_size);
2825
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2214 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2216 if (side_data && side_data_size) {
2826 2 uint8_t *payload = t35_buf;
2827 2 size_t payload_size = sizeof(t35_buf) - 6;
2828
2829 2 bytestream_put_byte(&payload, ITU_T_T35_COUNTRY_CODE_US);
2830 2 bytestream_put_be16(&payload, ITU_T_T35_PROVIDER_CODE_SMTPE);
2831 2 bytestream_put_be16(&payload, 0x01); // provider_oriented_code
2832 2 bytestream_put_byte(&payload, 0x04); // application_identifier
2833
2834 2 ret = av_dynamic_hdr_plus_to_t35((AVDynamicHDRPlus *)side_data, &payload,
2835 &payload_size);
2836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2837 return ret;
2838
2839 2 mkv_write_blockadditional(&writer, t35_buf, payload_size + 6,
2840 MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
2841 2 track->max_blockaddid = FFMAX(track->max_blockaddid,
2842 MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
2843 }
2844 }
2845
2846 6784 ebml_writer_close_or_discard_master(&writer);
2847
2848
4/4
✓ Branch 0 taken 6724 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 6485 times.
✓ Branch 3 taken 239 times.
6784 if (!force_blockgroup && writer.nb_elements == 2) {
2849 /* Nothing except the BlockGroup + Block. Can use a SimpleBlock. */
2850 6485 writer.elements++; // Skip the BlockGroup.
2851 6485 writer.nb_elements--;
2852 av_assert2(writer.elements[0].id == MATROSKA_ID_BLOCK);
2853 6485 writer.elements[0].id = MATROSKA_ID_SIMPLEBLOCK;
2854
2/2
✓ Branch 0 taken 5208 times.
✓ Branch 1 taken 1277 times.
6485 if (keyframe)
2855 5208 mkv->cur_block.flags |= 1 << 7;
2856
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 103 times.
299 } else if (!keyframe)
2857 196 ebml_writer_add_sint(&writer, MATROSKA_ID_BLOCKREFERENCE,
2858 196 track->last_timestamp - ts);
2859
2860 6784 return ebml_writer_write(&writer, pb);
2861 }
2862
2863 535 static int mkv_end_cluster(AVFormatContext *s)
2864 {
2865 535 MatroskaMuxContext *mkv = s->priv_data;
2866 int ret;
2867
2868
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 233 times.
535 if (!mkv->have_video) {
2869
2/2
✓ Branch 0 taken 557 times.
✓ Branch 1 taken 302 times.
859 for (unsigned i = 0; i < s->nb_streams; i++)
2870 557 mkv->tracks[i].has_cue = 0;
2871 }
2872 535 mkv->cluster_pos = -1;
2873 535 ret = end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv,
2874 MATROSKA_ID_CLUSTER, 0, 1, 0);
2875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535 times.
535 if (ret < 0)
2876 return ret;
2877
2878 535 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
2879 535 return 0;
2880 }
2881
2882 6787 static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt)
2883 {
2884 6787 MatroskaMuxContext *mkv = s->priv_data;
2885 6787 mkv_track *track = &mkv->tracks[pkt->stream_index];
2886 6787 AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
2887 uint8_t *side_data;
2888 size_t side_data_size;
2889 int ret;
2890
2891 6787 side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
2892 &side_data_size);
2893
2894
4/4
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 6486 times.
6787 switch (par->codec_id) {
2895 #if CONFIG_MATROSKA_MUXER
2896 246 case AV_CODEC_ID_AAC:
2897
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 245 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
247 if (side_data_size && mkv->track.bc) {
2898 1 int output_sample_rate = 0;
2899 1 ret = get_aac_sample_rates(s, mkv, side_data, side_data_size,
2900 &track->sample_rate, &output_sample_rate);
2901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2902 return ret;
2903
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!output_sample_rate)
2904 1 output_sample_rate = track->sample_rate; // Space is already reserved, so it's this or a void element.
2905 1 ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size,
2906 par, mkv->track.bc, track, 0);
2907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2908 return ret;
2909 1 avio_seek(mkv->track.bc, track->sample_rate_offset, SEEK_SET);
2910 1 put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate);
2911 1 put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
2912
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
245 } else if (!par->extradata_size && !track->sample_rate) {
2913 // No extradata (codecpar or packet side data).
2914 av_log(s, AV_LOG_ERROR, "Error parsing AAC extradata, unable to determine samplerate.\n");
2915 return AVERROR(EINVAL);
2916 }
2917 246 break;
2918 27 case AV_CODEC_ID_FLAC:
2919
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
27 if (side_data_size && mkv->track.bc) {
2920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (side_data_size != par->extradata_size) {
2921 av_log(s, AV_LOG_ERROR, "Invalid FLAC STREAMINFO metadata for output stream %d\n",
2922 pkt->stream_index);
2923 return AVERROR(EINVAL);
2924 }
2925 3 ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size,
2926 par, mkv->track.bc, track, 0);
2927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
2928 return ret;
2929 }
2930 27 break;
2931 #endif
2932 // FIXME: Remove the following once libaom starts propagating proper extradata during init()
2933 // See https://bugs.chromium.org/p/aomedia/issues/detail?id=2208
2934 28 case AV_CODEC_ID_AV1:
2935
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
28 if (side_data_size && mkv->track.bc && !par->extradata_size) {
2936 // If the reserved space doesn't suffice, only write
2937 // the first four bytes of the av1C.
2938 1 ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size,
2939 par, mkv->track.bc, track, 4);
2940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2941 return ret;
2942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 } else if (!par->extradata_size)
2943 return AVERROR_INVALIDDATA;
2944 28 break;
2945 6486 default:
2946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6486 times.
6486 if (side_data_size)
2947 av_log(s, AV_LOG_DEBUG, "Ignoring new extradata in a packet for stream %d.\n", pkt->stream_index);
2948 6486 break;
2949 }
2950
2951 6787 return 0;
2952 }
2953
2954 6784 static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt)
2955 {
2956 6784 MatroskaMuxContext *mkv = s->priv_data;
2957 AVIOContext *pb;
2958 6784 AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
2959 6784 mkv_track *track = &mkv->tracks[pkt->stream_index];
2960 6784 int is_sub = par->codec_type == AVMEDIA_TYPE_SUBTITLE;
2961 /* All subtitle blocks are considered to be keyframes. */
2962
4/4
✓ Branch 0 taken 6622 times.
✓ Branch 1 taken 162 times.
✓ Branch 2 taken 5149 times.
✓ Branch 3 taken 1473 times.
6784 int keyframe = is_sub || !!(pkt->flags & AV_PKT_FLAG_KEY);
2963 6784 int64_t duration = FFMAX(pkt->duration, 0);
2964
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 6622 times.
6784 int64_t cue_duration = is_sub ? duration : 0;
2965 int ret;
2966
2/2
✓ Branch 0 taken 653 times.
✓ Branch 1 taken 6131 times.
6784 int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
2967 int64_t relative_packet_pos;
2968
2969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6784 times.
6784 if (ts == AV_NOPTS_VALUE) {
2970 av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n");
2971 return AVERROR(EINVAL);
2972 }
2973 6784 ts += track->ts_offset;
2974
2975
2/2
✓ Branch 0 taken 6206 times.
✓ Branch 1 taken 578 times.
6784 if (mkv->cluster_pos != -1) {
2976 6206 int64_t cluster_time = ts - mkv->cluster_pts;
2977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6206 times.
6206 if ((int16_t)cluster_time != cluster_time) {
2978 ret = mkv_end_cluster(s);
2979 if (ret < 0)
2980 return ret;
2981 av_log(s, AV_LOG_WARNING, "Starting new cluster due to timestamp\n");
2982 }
2983 }
2984
2985
2/2
✓ Branch 0 taken 578 times.
✓ Branch 1 taken 6206 times.
6784 if (mkv->cluster_pos == -1) {
2986 578 ret = start_ebml_master_crc32(&mkv->cluster_bc, mkv);
2987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (ret < 0)
2988 return ret;
2989 578 mkv->cluster_bc->direct = 1;
2990 578 mkv->cluster_pos = avio_tell(s->pb);
2991 578 put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts));
2992 578 mkv->cluster_pts = FFMAX(0, ts);
2993 578 av_log(s, AV_LOG_DEBUG,
2994 "Starting new cluster with timestamp "
2995 "%" PRId64 " at offset %" PRId64 " bytes\n",
2996 mkv->cluster_pts, mkv->cluster_pos);
2997 }
2998 6784 pb = mkv->cluster_bc;
2999
3000 6784 relative_packet_pos = avio_tell(pb);
3001
3002 /* The WebM spec requires WebVTT to be muxed in BlockGroups;
3003 * so we force it even for packets without duration. */
3004 6784 ret = mkv_write_block(s, mkv, pb, par, track, pkt,
3005 keyframe, ts, duration,
3006 6784 par->codec_id == AV_CODEC_ID_WEBVTT,
3007 relative_packet_pos);
3008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6784 times.
6784 if (ret < 0)
3009 return ret;
3010
6/6
✓ Branch 0 taken 5311 times.
✓ Branch 1 taken 1473 times.
✓ Branch 2 taken 5230 times.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 5196 times.
✓ Branch 5 taken 34 times.
6784 if (keyframe && IS_SEEKABLE(s->pb, mkv) &&
3011
2/2
✓ Branch 0 taken 4454 times.
✓ Branch 1 taken 742 times.
5196 (par->codec_type == AVMEDIA_TYPE_VIDEO ||
3012
2/2
✓ Branch 0 taken 4300 times.
✓ Branch 1 taken 154 times.
4454 par->codec_type == AVMEDIA_TYPE_SUBTITLE ||
3013
4/4
✓ Branch 0 taken 2300 times.
✓ Branch 1 taken 2000 times.
✓ Branch 2 taken 265 times.
✓ Branch 3 taken 2035 times.
4300 !mkv->have_video && !track->has_cue)) {
3014 1161 ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts,
3015 mkv->cluster_pos, relative_packet_pos,
3016 cue_duration);
3017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
1161 if (ret < 0)
3018 return ret;
3019 1161 track->has_cue = 1;
3020 }
3021
3022 6784 track->last_timestamp = ts;
3023 6784 mkv->duration = FFMAX(mkv->duration, ts + duration);
3024 6784 track->duration = FFMAX(track->duration, ts + duration);
3025
3026 6784 return 0;
3027 }
3028
3029 6787 static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt)
3030 {
3031 6787 MatroskaMuxContext *mkv = s->priv_data;
3032 6787 int codec_type = s->streams[pkt->stream_index]->codecpar->codec_type;
3033 6787 int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY);
3034 int cluster_size;
3035 int64_t cluster_time;
3036 int ret;
3037 int start_new_cluster;
3038
3039 6787 ret = mkv_check_new_extra_data(s, pkt);
3040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6787 times.
6787 if (ret < 0)
3041 return ret;
3042
3043
2/2
✓ Branch 0 taken 6723 times.
✓ Branch 1 taken 64 times.
6787 if (mkv->cluster_pos != -1) {
3044
2/2
✓ Branch 0 taken 650 times.
✓ Branch 1 taken 6073 times.
6723 if (mkv->tracks[pkt->stream_index].write_dts)
3045 650 cluster_time = pkt->dts - mkv->cluster_pts;
3046 else
3047 6073 cluster_time = pkt->pts - mkv->cluster_pts;
3048 6723 cluster_time += mkv->tracks[pkt->stream_index].ts_offset;
3049
3050 6723 cluster_size = avio_tell(mkv->cluster_bc);
3051
3052
3/4
✓ Branch 0 taken 730 times.
✓ Branch 1 taken 5993 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 730 times.
6723 if (mkv->is_dash && codec_type == AVMEDIA_TYPE_VIDEO) {
3053 // WebM DASH specification states that the first block of
3054 // every Cluster has to be a key frame. So for DASH video,
3055 // we only create a Cluster on seeing key frames.
3056 start_new_cluster = keyframe;
3057
4/4
✓ Branch 0 taken 730 times.
✓ Branch 1 taken 5993 times.
✓ Branch 2 taken 729 times.
✓ Branch 3 taken 1 times.
6723 } else if (mkv->is_dash && codec_type == AVMEDIA_TYPE_AUDIO &&
3058
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 716 times.
729 cluster_time > mkv->cluster_time_limit) {
3059 // For DASH audio, we create a Cluster based on cluster_time_limit.
3060 13 start_new_cluster = 1;
3061
2/2
✓ Branch 0 taken 5993 times.
✓ Branch 1 taken 717 times.
6710 } else if (!mkv->is_dash &&
3062
2/2
✓ Branch 0 taken 5961 times.
✓ Branch 1 taken 32 times.
5993 (cluster_size > mkv->cluster_size_limit ||
3063
4/4
✓ Branch 0 taken 5649 times.
✓ Branch 1 taken 312 times.
✓ Branch 2 taken 2138 times.
✓ Branch 3 taken 3511 times.
5961 cluster_time > mkv->cluster_time_limit ||
3064
4/4
✓ Branch 0 taken 669 times.
✓ Branch 1 taken 1469 times.
✓ Branch 2 taken 172 times.
✓ Branch 3 taken 497 times.
2138 (codec_type == AVMEDIA_TYPE_VIDEO && keyframe &&
3065 cluster_size > 4 * 1024))) {
3066 516 start_new_cluster = 1;
3067 } else
3068 6194 start_new_cluster = 0;
3069
3070
2/2
✓ Branch 0 taken 529 times.
✓ Branch 1 taken 6194 times.
6723 if (start_new_cluster) {
3071 529 ret = mkv_end_cluster(s);
3072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 529 times.
529 if (ret < 0)
3073 return ret;
3074 }
3075 }
3076
3077
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 6194 times.
6787 if (mkv->cluster_pos == -1)
3078
2/2
✓ Branch 0 taken 589 times.
✓ Branch 1 taken 4 times.
1182 avio_write_marker(s->pb,
3079 593 av_rescale_q(pkt->dts, s->streams[pkt->stream_index]->time_base, AV_TIME_BASE_Q),
3080
4/4
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 335 times.
✓ Branch 2 taken 246 times.
✓ Branch 3 taken 8 times.
589 keyframe && (mkv->have_video ? codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
3081
3082 // check if we have an audio packet cached
3083
2/2
✓ Branch 0 taken 4385 times.
✓ Branch 1 taken 2402 times.
6787 if (mkv->cur_audio_pkt->size > 0) {
3084 4385 ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt);
3085 4385 av_packet_unref(mkv->cur_audio_pkt);
3086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4385 times.
4385 if (ret < 0) {
3087 av_log(s, AV_LOG_ERROR,
3088 "Could not write cached audio packet ret:%d\n", ret);
3089 return ret;
3090 }
3091 }
3092
3093 // buffer an audio packet to ensure the packet containing the video
3094 // keyframe's timecode is contained in the same cluster for WebM
3095
2/2
✓ Branch 0 taken 4409 times.
✓ Branch 1 taken 2378 times.
6787 if (codec_type == AVMEDIA_TYPE_AUDIO) {
3096
2/2
✓ Branch 0 taken 4406 times.
✓ Branch 1 taken 3 times.
4409 if (pkt->size > 0)
3097 4406 ret = av_packet_ref(mkv->cur_audio_pkt, pkt);
3098 } else
3099 2378 ret = mkv_write_packet_internal(s, pkt);
3100 6787 return ret;
3101 }
3102
3103 6794 static int mkv_write_flush_packet(AVFormatContext *s, AVPacket *pkt)
3104 {
3105 6794 MatroskaMuxContext *mkv = s->priv_data;
3106
3107
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6787 times.
6794 if (!pkt) {
3108
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (mkv->cluster_pos != -1) {
3109 6 int ret = mkv_end_cluster(s);
3110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
3111 return ret;
3112 6 av_log(s, AV_LOG_DEBUG,
3113 "Flushing cluster at offset %" PRIu64 " bytes\n",
3114 avio_tell(s->pb));
3115 }
3116 7 return 1;
3117 }
3118 6787 return mkv_write_packet(s, pkt);
3119 }
3120
3121 43 static int mkv_write_trailer(AVFormatContext *s)
3122 {
3123 43 MatroskaMuxContext *mkv = s->priv_data;
3124 43 AVIOContext *pb = s->pb;
3125 int64_t endpos, ret64;
3126 43 int ret, ret2 = 0;
3127
3128 // check if we have an audio packet cached
3129
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 22 times.
43 if (mkv->cur_audio_pkt->size > 0) {
3130 21 ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt);
3131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (ret < 0) {
3132 av_log(s, AV_LOG_ERROR,
3133 "Could not write cached audio packet ret:%d\n", ret);
3134 return ret;
3135 }
3136 }
3137
3138
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (mkv->cluster_pos != -1) {
3139 43 ret = end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv,
3140 MATROSKA_ID_CLUSTER, 0, 0, 0);
3141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
3142 return ret;
3143 }
3144
3145 43 ret = mkv_write_chapters(s);
3146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
3147 return ret;
3148
3149
4/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 35 times.
43 if (!IS_SEEKABLE(pb, mkv))
3150 8 return 0;
3151
3152 35 endpos = avio_tell(pb);
3153
3154
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35 times.
35 if (mkv->cues.num_entries && mkv->reserve_cues_space >= 0) {
3155 35 AVIOContext *cues = NULL;
3156 35 uint64_t size, offset = 0;
3157 35 int length_size = 0;
3158
3159 37 redo_cues:
3160 37 ret = start_ebml_master_crc32(&cues, mkv);
3161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (ret < 0)
3162 return ret;
3163
3164 37 ret = mkv_assemble_cues(s->streams, cues, mkv->tmp_bc, &mkv->cues,
3165 37 mkv->tracks, s->nb_streams, offset);
3166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (ret < 0) {
3167 ffio_free_dyn_buf(&cues);
3168 return ret;
3169 }
3170
3171
4/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 30 times.
37 if (mkv->reserve_cues_space || mkv->move_cues_to_front) {
3172 7 size = avio_tell(cues);
3173 7 length_size = ebml_length_size(size);
3174 7 size += 4 + length_size;
3175
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 if (offset + mkv->reserve_cues_space < size) {
3176
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mkv->move_cues_to_front) {
3177 2 offset = size - mkv->reserve_cues_space;
3178 2 ffio_reset_dyn_buf(cues);
3179 2 goto redo_cues;
3180 }
3181 av_log(s, AV_LOG_WARNING,
3182 "Insufficient space reserved for Cues: "
3183 "%d < %"PRIu64". No Cues will be output.\n",
3184 mkv->reserve_cues_space, size);
3185 ret2 = AVERROR(EINVAL);
3186 goto after_cues;
3187 } else {
3188
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (offset) {
3189 2 ret = ff_format_shift_data(s, mkv->cues_pos + mkv->reserve_cues_space,
3190 offset);
3191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
3192 ffio_free_dyn_buf(&cues);
3193 return ret;
3194 }
3195 2 endpos += offset;
3196 }
3197
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if ((ret64 = avio_seek(pb, mkv->cues_pos, SEEK_SET)) < 0) {
3198 ffio_free_dyn_buf(&cues);
3199 return ret64;
3200 }
3201
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (mkv->reserve_cues_space == size + 1) {
3202 /* There is no way to reserve a single byte because
3203 * the minimal size of an EBML Void element is 2
3204 * (1 byte ID, 1 byte length field). This problem
3205 * is solved by writing the Cues' length field on
3206 * one byte more than necessary. */
3207 1 length_size++;
3208 1 size++;
3209 }
3210 }
3211 }
3212 35 ret = end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES,
3213 length_size, 0, 1);
3214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (ret < 0)
3215 return ret;
3216
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 31 times.
35 if (mkv->reserve_cues_space) {
3217
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (size < mkv->reserve_cues_space)
3218 2 put_ebml_void(pb, mkv->reserve_cues_space - size);
3219
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 1 times.
31 } else if (!mkv->move_cues_to_front)
3220 30 endpos = avio_tell(pb);
3221 }
3222
3223 after_cues:
3224 /* Lengths greater than (1ULL << 56) - 1 can't be represented
3225 * via an EBML number, so leave the unknown length field. */
3226
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (endpos - mkv->segment_offset < (1ULL << 56) - 1) {
3227
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
35 if ((ret64 = avio_seek(pb, mkv->segment_offset - 8, SEEK_SET)) < 0)
3228 return ret64;
3229 35 put_ebml_length(pb, endpos - mkv->segment_offset, 8);
3230 }
3231
3232 35 ret = mkv_write_seekhead(pb, mkv, 1, mkv->info.pos);
3233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (ret < 0)
3234 return ret;
3235
3236
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (mkv->info.bc) {
3237 // update the duration
3238 35 av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration);
3239 35 avio_seek(mkv->info.bc, mkv->duration_offset, SEEK_SET);
3240 35 put_ebml_float(mkv->info.bc, MATROSKA_ID_DURATION, mkv->duration);
3241 35 ret = end_ebml_master_crc32(pb, &mkv->info.bc, mkv,
3242 MATROSKA_ID_INFO, 0, 0, 0);
3243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (ret < 0)
3244 return ret;
3245 }
3246
3247
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (mkv->track.bc) {
3248 // write Tracks master
3249
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 4 times.
35 if (!IS_WEBM(mkv)) {
3250 31 AVIOContext *track_bc = mkv->track.bc;
3251
3252
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 31 times.
90 for (unsigned i = 0; i < s->nb_streams; i++) {
3253 59 const mkv_track *track = &mkv->tracks[i];
3254
3255
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 2 times.
59 if (!track->max_blockaddid)
3256 57 continue;
3257
3258 // We reserved a single byte to write this value.
3259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(track->max_blockaddid <= 0xFF);
3260
3261 2 avio_seek(track_bc, track->blockadditionmapping_offset, SEEK_SET);
3262
3263 2 put_ebml_uint(track_bc, MATROSKA_ID_TRACKMAXBLKADDID,
3264 2 track->max_blockaddid);
3265
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (track->max_blockaddid == MATROSKA_BLOCK_ADD_ID_ITU_T_T35) {
3266 1 ebml_master mapping_master = start_ebml_master(track_bc, MATROSKA_ID_TRACKBLKADDMAPPING, 8);
3267 1 put_ebml_uint(track_bc, MATROSKA_ID_BLKADDIDTYPE,
3268 MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35);
3269 1 put_ebml_uint(track_bc, MATROSKA_ID_BLKADDIDVALUE,
3270 MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
3271 1 end_ebml_master(track_bc, mapping_master);
3272 }
3273 }
3274 }
3275
3276 35 avio_seek(pb, mkv->track.pos, SEEK_SET);
3277 35 ret = end_ebml_master_crc32(pb, &mkv->track.bc, mkv,
3278 MATROSKA_ID_TRACKS, 0, 0, 0);
3279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (ret < 0)
3280 return ret;
3281 }
3282
3283 // update stream durations
3284
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (mkv->tags.bc) {
3285 35 AVIOContext *tags_bc = mkv->tags.bc;
3286 int i;
3287
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 35 times.
101 for (i = 0; i < s->nb_streams; ++i) {
3288 66 const AVStream *st = s->streams[i];
3289 66 const mkv_track *track = &mkv->tracks[i];
3290
3291
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 1 times.
66 if (track->duration_offset > 0) {
3292 65 double duration_sec = track->duration * av_q2d(st->time_base);
3293 65 char duration_string[DURATION_STRING_LENGTH + 1] = "";
3294 ebml_master simpletag;
3295
3296 65 av_log(s, AV_LOG_DEBUG, "stream %d end duration = %" PRIu64 "\n", i,
3297 65 track->duration);
3298
3299 65 avio_seek(tags_bc, track->duration_offset, SEEK_SET);
3300 65 simpletag = start_ebml_master(tags_bc, MATROSKA_ID_SIMPLETAG,
3301 2 + 1 + 8 + 23);
3302 65 put_ebml_string(tags_bc, MATROSKA_ID_TAGNAME, "DURATION");
3303
3304 65 snprintf(duration_string, sizeof(duration_string), "%02d:%02d:%012.9f",
3305 65 (int) duration_sec / 3600, ((int) duration_sec / 60) % 60,
3306 fmod(duration_sec, 60));
3307
3308 65 put_ebml_binary(tags_bc, MATROSKA_ID_TAGSTRING,
3309 duration_string, DURATION_STRING_LENGTH);
3310 65 end_ebml_master(tags_bc, simpletag);
3311 }
3312 }
3313
3314 35 avio_seek(pb, mkv->tags.pos, SEEK_SET);
3315 35 ret = end_ebml_master_crc32(pb, &mkv->tags.bc, mkv,
3316 MATROSKA_ID_TAGS, 0, 0, 0);
3317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (ret < 0)
3318 return ret;
3319 }
3320
3321 35 avio_seek(pb, endpos, SEEK_SET);
3322
3323 35 return ret2;
3324 }
3325
3326 4 static uint64_t mkv_get_uid(const mkv_track *tracks, int i, AVLFG *c)
3327 {
3328 while (1) {
3329 uint64_t uid;
3330 int k;
3331 4 uid = (uint64_t)av_lfg_get(c) << 32;
3332 4 uid |= av_lfg_get(c);
3333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!uid)
3334 continue;
3335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (k = 0; k < i; k++) {
3336 if (tracks[k].uid == uid)
3337 break;
3338 }
3339
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (k == i)
3340 4 return uid;
3341 }
3342 }
3343
3344 43 static int mkv_init(struct AVFormatContext *s)
3345 {
3346 43 FFFormatContext *const si = ffformatcontext(s);
3347 43 MatroskaMuxContext *mkv = s->priv_data;
3348 AVLFG c;
3349 43 unsigned nb_tracks = 0;
3350 int i;
3351
3352 43 mkv->ctx = s;
3353
3354
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 43 times.
117 for (i = 0; i < s->nb_streams; i++) {
3355
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 ||
3356
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_COOK ||
3357
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RA_288 ||
3358
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_SIPR ||
3359
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV10 ||
3360
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV20 ||
3361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV30) {
3362 av_log(s, AV_LOG_ERROR,
3363 "The Matroska muxer does not yet support muxing %s\n",
3364 avcodec_get_name(s->streams[i]->codecpar->codec_id));
3365 return AVERROR_PATCHWELCOME;
3366 }
3367 }
3368
3369
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 1 times.
43 if (s->avoid_negative_ts < 0) {
3370 42 s->avoid_negative_ts = 1;
3371 42 si->avoid_negative_ts_use_pts = 1;
3372 }
3373
3374 43 if (!CONFIG_MATROSKA_MUXER ||
3375
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 39 times.
43 (CONFIG_WEBM_MUXER && !strcmp(s->oformat->name, "webm"))) {
3376 4 mkv->mode = MODE_WEBM;
3377 4 mkv->write_crc = 0;
3378 } else
3379 39 mkv->mode = MODE_MATROSKAv2;
3380
3381 43 mkv->cur_audio_pkt = ffformatcontext(s)->pkt;
3382
3383 43 mkv->tracks = av_calloc(s->nb_streams, sizeof(*mkv->tracks));
3384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!mkv->tracks)
3385 return AVERROR(ENOMEM);
3386
3387
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 39 times.
43 if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
3388 4 av_lfg_init(&c, av_get_random_seed());
3389
3390 // Calculate the SegmentUID now in order not to waste our random seed.
3391
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (i = 0; i < 4; i++)
3392 16 mkv->segment_uid[i] = av_lfg_get(&c);
3393 }
3394
3395
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 43 times.
117 for (i = 0; i < s->nb_streams; i++) {
3396 74 AVStream *st = s->streams[i];
3397 74 const AVCodecParameters *const par = st->codecpar;
3398 74 mkv_track *track = &mkv->tracks[i];
3399
3400
6/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 57 times.
74 switch (par->codec_id) {
3401 #if CONFIG_MATROSKA_MUXER
3402 2 case AV_CODEC_ID_WAVPACK:
3403 2 track->reformat = mkv_reformat_wavpack;
3404 2 break;
3405 8 case AV_CODEC_ID_H264:
3406 case AV_CODEC_ID_HEVC:
3407
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
8 if ((par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 ||
3408
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6) &&
3409
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
8 (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1))
3410 2 track->reformat = mkv_reformat_h2645;
3411 8 break;
3412 1 case AV_CODEC_ID_PRORES:
3413 /* Matroska specification requires to remove
3414 * the first QuickTime atom. */
3415 1 track->offset = 8;
3416 1 break;
3417 #endif
3418 2 case AV_CODEC_ID_AV1:
3419 2 track->reformat = mkv_reformat_av1;
3420 2 break;
3421 4 case AV_CODEC_ID_WEBVTT:
3422 4 track->reformat = webm_reformat_vtt;
3423 4 break;
3424 }
3425
3426
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 4 times.
74 if (s->flags & AVFMT_FLAG_BITEXACT) {
3427 70 track->uid = i + 1;
3428 } else {
3429 4 track->uid = mkv_get_uid(mkv->tracks, i, &c);
3430 }
3431
3432 // ms precision is the de-facto standard timescale for mkv files
3433 74 avpriv_set_pts_info(st, 64, 1, 1000);
3434
3435
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 73 times.
74 if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
3436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (IS_WEBM(mkv)) {
3437 av_log(s, AV_LOG_WARNING, "Stream %d will be ignored "
3438 "as WebM doesn't support attachments.\n", i);
3439
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 } else if (!get_mimetype(st)) {
3440 av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype "
3441 "tag and it cannot be deduced from the codec id.\n", i);
3442 return AVERROR(EINVAL);
3443 }
3444 1 mkv->nb_attachments++;
3445 1 continue;
3446 }
3447
3448 73 nb_tracks++;
3449
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 71 times.
73 track->track_num = mkv->is_dash ? mkv->dash_track_number : nb_tracks;
3450 73 track->track_num_size = ebml_num_size(track->track_num);
3451 }
3452
3453
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
43 if (mkv->is_dash && nb_tracks != 1)
3454 return AVERROR(EINVAL);
3455
3456 43 return 0;
3457 }
3458
3459 71 static int mkv_check_bitstream(AVFormatContext *s, AVStream *st,
3460 const AVPacket *pkt)
3461 {
3462 71 int ret = 1;
3463
3464
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 67 times.
71 if (CONFIG_MATROSKA_MUXER && st->codecpar->codec_id == AV_CODEC_ID_AAC) {
3465
3/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
4 if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
3466 1 ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
3467
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 64 times.
67 } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
3468 3 ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
3469 64 } else if (CONFIG_MATROSKA_MUXER &&
3470
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 62 times.
64 st->codecpar->codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE) {
3471 2 ret = ff_stream_add_bitstream_filter(st, "pgs_frame_merge", NULL);
3472 }
3473
3474 71 return ret;
3475 }
3476
3477 static const AVCodecTag additional_audio_tags[] = {
3478 { AV_CODEC_ID_ALAC, 0XFFFFFFFF },
3479 { AV_CODEC_ID_ATRAC1, 0xFFFFFFFF },
3480 { AV_CODEC_ID_MLP, 0xFFFFFFFF },
3481 { AV_CODEC_ID_OPUS, 0xFFFFFFFF },
3482 { AV_CODEC_ID_PCM_S16BE, 0xFFFFFFFF },
3483 { AV_CODEC_ID_PCM_S24BE, 0xFFFFFFFF },
3484 { AV_CODEC_ID_PCM_S32BE, 0xFFFFFFFF },
3485 { AV_CODEC_ID_QDMC, 0xFFFFFFFF },
3486 { AV_CODEC_ID_QDM2, 0xFFFFFFFF },
3487 { AV_CODEC_ID_RA_144, 0xFFFFFFFF },
3488 { AV_CODEC_ID_TRUEHD, 0xFFFFFFFF },
3489 { AV_CODEC_ID_NONE, 0xFFFFFFFF }
3490 };
3491
3492 static const AVCodecTag additional_subtitle_tags[] = {
3493 { AV_CODEC_ID_DVB_SUBTITLE, 0xFFFFFFFF },
3494 { AV_CODEC_ID_DVD_SUBTITLE, 0xFFFFFFFF },
3495 { AV_CODEC_ID_HDMV_PGS_SUBTITLE, 0xFFFFFFFF },
3496 { AV_CODEC_ID_ARIB_CAPTION, 0xFFFFFFFF },
3497 { AV_CODEC_ID_NONE, 0xFFFFFFFF }
3498 };
3499
3500 #define OFFSET(x) offsetof(MatroskaMuxContext, x)
3501 #define FLAGS AV_OPT_FLAG_ENCODING_PARAM
3502 static const AVOption options[] = {
3503 { "reserve_index_space", "reserve a given amount of space (in bytes) at the beginning of the file for the index (cues)", OFFSET(reserve_cues_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
3504 { "cues_to_front", "move Cues (the index) to the front by shifting data if necessary", OFFSET(move_cues_to_front), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS },
3505 { "cluster_size_limit", "store at most the provided amount of bytes in a cluster", OFFSET(cluster_size_limit), AV_OPT_TYPE_INT , { .i64 = -1 }, -1, INT_MAX, FLAGS },
3506 { "cluster_time_limit", "store at most the provided number of milliseconds in a cluster", OFFSET(cluster_time_limit), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS },
3507 { "dash", "create a WebM file conforming to WebM DASH specification", OFFSET(is_dash), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
3508 { "dash_track_number", "track number for the DASH stream", OFFSET(dash_track_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, FLAGS },
3509 { "live", "write files assuming it is a live stream", OFFSET(is_live), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
3510 { "allow_raw_vfw", "allow raw VFW mode", OFFSET(allow_raw_vfw), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
3511 { "flipped_raw_rgb", "store raw RGB bitmaps in VFW mode in bottom-up mode", OFFSET(flipped_raw_rgb), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
3512 { "write_crc32", "write a CRC32 element inside every Level 1 element", OFFSET(write_crc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
3513 { "default_mode", "control how a track's FlagDefault is inferred", OFFSET(default_mode), AV_OPT_TYPE_INT, { .i64 = DEFAULT_MODE_PASSTHROUGH }, DEFAULT_MODE_INFER, DEFAULT_MODE_PASSTHROUGH, FLAGS, .unit = "default_mode" },
3514 { "infer", "for each track type, mark each track of disposition default as default; if none exists, mark the first track as default", 0, AV_OPT_TYPE_CONST, { .i64 = DEFAULT_MODE_INFER }, 0, 0, FLAGS, .unit = "default_mode" },
3515 { "infer_no_subs", "for each track type, mark each track of disposition default as default; for audio and video: if none exists, mark the first track as default", 0, AV_OPT_TYPE_CONST, { .i64 = DEFAULT_MODE_INFER_NO_SUBS }, 0, 0, FLAGS, .unit = "default_mode" },
3516 { "passthrough", "use the disposition flag as-is", 0, AV_OPT_TYPE_CONST, { .i64 = DEFAULT_MODE_PASSTHROUGH }, 0, 0, FLAGS, .unit = "default_mode" },
3517 { NULL },
3518 };
3519
3520 static const AVClass matroska_webm_class = {
3521 .class_name = "matroska/webm muxer",
3522 .item_name = av_default_item_name,
3523 .option = options,
3524 .version = LIBAVUTIL_VERSION_INT,
3525 };
3526
3527 #if CONFIG_MATROSKA_MUXER
3528 21 static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance)
3529 {
3530
1/2
✓ Branch 0 taken 1218 times.
✗ Branch 1 not taken.
1218 for (int i = 0; ff_mkv_codec_tags[i].id != AV_CODEC_ID_NONE; i++)
3531
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1197 times.
1218 if (ff_mkv_codec_tags[i].id == codec_id)
3532 21 return 1;
3533
3534 if (std_compliance < FF_COMPLIANCE_NORMAL) {
3535 enum AVMediaType type = avcodec_get_type(codec_id);
3536 // mkv theoretically supports any video/audio through VFW/ACM
3537 if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)
3538 return 1;
3539 }
3540
3541 return 0;
3542 }
3543
3544 const FFOutputFormat ff_matroska_muxer = {
3545 .p.name = "matroska",
3546 .p.long_name = NULL_IF_CONFIG_SMALL("Matroska"),
3547 .p.mime_type = "video/x-matroska",
3548 .p.extensions = "mkv",
3549 .priv_data_size = sizeof(MatroskaMuxContext),
3550 .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ?
3551 AV_CODEC_ID_VORBIS : AV_CODEC_ID_AC3,
3552 .p.video_codec = CONFIG_LIBX264_ENCODER ?
3553 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
3554 .init = mkv_init,
3555 .deinit = mkv_deinit,
3556 .write_header = mkv_write_header,
3557 .write_packet = mkv_write_flush_packet,
3558 .write_trailer = mkv_write_trailer,
3559 .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |
3560 #if FF_API_ALLOW_FLUSH
3561 AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH,
3562 #else
3563 AVFMT_TS_NONSTRICT,
3564 #endif
3565 .p.codec_tag = (const AVCodecTag* const []){
3566 ff_codec_bmp_tags, ff_codec_wav_tags,
3567 additional_audio_tags, additional_subtitle_tags, 0
3568 },
3569 .p.subtitle_codec = AV_CODEC_ID_ASS,
3570 .query_codec = mkv_query_codec,
3571 .check_bitstream = mkv_check_bitstream,
3572 .p.priv_class = &matroska_webm_class,
3573 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
3574 };
3575 #endif
3576
3577 #if CONFIG_WEBM_MUXER
3578 2 static int webm_query_codec(enum AVCodecID codec_id, int std_compliance)
3579 {
3580
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (int i = 0; ff_webm_codec_tags[i].id != AV_CODEC_ID_NONE; i++)
3581
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ff_webm_codec_tags[i].id == codec_id)
3582 2 return 1;
3583
3584 return 0;
3585 }
3586
3587 const FFOutputFormat ff_webm_muxer = {
3588 .p.name = "webm",
3589 .p.long_name = NULL_IF_CONFIG_SMALL("WebM"),
3590 .p.mime_type = "video/webm",
3591 .p.extensions = "webm",
3592 .priv_data_size = sizeof(MatroskaMuxContext),
3593 .p.audio_codec = CONFIG_LIBOPUS_ENCODER ? AV_CODEC_ID_OPUS : AV_CODEC_ID_VORBIS,
3594 .p.video_codec = CONFIG_LIBVPX_VP9_ENCODER? AV_CODEC_ID_VP9 : AV_CODEC_ID_VP8,
3595 .p.subtitle_codec = AV_CODEC_ID_WEBVTT,
3596 .init = mkv_init,
3597 .deinit = mkv_deinit,
3598 .write_header = mkv_write_header,
3599 .write_packet = mkv_write_flush_packet,
3600 .write_trailer = mkv_write_trailer,
3601 .query_codec = webm_query_codec,
3602 .check_bitstream = mkv_check_bitstream,
3603 .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |
3604 #if FF_API_ALLOW_FLUSH
3605 AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH,
3606 #else
3607 AVFMT_TS_NONSTRICT,
3608 #endif
3609 .p.priv_class = &matroska_webm_class,
3610 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
3611 };
3612 #endif
3613
3614 #if CONFIG_MATROSKA_AUDIO_MUXER
3615 const FFOutputFormat ff_matroska_audio_muxer = {
3616 .p.name = "matroska",
3617 .p.long_name = NULL_IF_CONFIG_SMALL("Matroska Audio"),
3618 .p.mime_type = "audio/x-matroska",
3619 .p.extensions = "mka",
3620 .priv_data_size = sizeof(MatroskaMuxContext),
3621 .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ?
3622 AV_CODEC_ID_VORBIS : AV_CODEC_ID_AC3,
3623 .p.video_codec = AV_CODEC_ID_NONE,
3624 .init = mkv_init,
3625 .deinit = mkv_deinit,
3626 .write_header = mkv_write_header,
3627 .write_packet = mkv_write_flush_packet,
3628 .write_trailer = mkv_write_trailer,
3629 .check_bitstream = mkv_check_bitstream,
3630 #if FF_API_ALLOW_FLUSH
3631 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT |
3632 AVFMT_ALLOW_FLUSH,
3633 #else
3634 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT,
3635 #endif
3636 .p.codec_tag = (const AVCodecTag* const []){
3637 ff_codec_wav_tags, additional_audio_tags, 0
3638 },
3639 .p.priv_class = &matroska_webm_class,
3640 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
3641 };
3642 #endif
3643