FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/matroskaenc.c
Date: 2026-09-28 11:37:26
Exec Total Coverage
Lines: 1683 1952 86.2%
Functions: 98 98 100.0%
Branches: 920 1231 74.7%

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