FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/matroskaenc.c
Date: 2026-05-02 17:52:23
Exec Total Coverage
Lines: 1658 1927 86.0%
Functions: 98 98 100.0%
Branches: 912 1227 74.3%

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 24215 static int ebml_id_size(uint32_t id)
315 {
316 24215 return (av_log2(id) + 7U) / 8;
317 }
318
319 21971 static void put_ebml_id(AVIOContext *pb, uint32_t id)
320 {
321 21971 int i = ebml_id_size(id);
322
2/2
✓ Branch 0 taken 28261 times.
✓ Branch 1 taken 21971 times.
50232 while (i--)
323 28261 avio_w8(pb, (uint8_t)(id >> (i * 8)));
324 21971 }
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 1922 static void put_ebml_size_unknown(AVIOContext *pb, int bytes)
332 {
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1922 times.
1922 av_assert0(bytes <= 8);
334 1922 avio_w8(pb, 0x1ff >> bytes);
335 if (av_builtin_constant_p(bytes) && bytes == 1)
336 return;
337 1922 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 23786 static int ebml_num_size(uint64_t num)
345 {
346 23786 int bytes = 0;
347 do {
348 31110 bytes++;
349
2/2
✓ Branch 0 taken 7324 times.
✓ Branch 1 taken 23786 times.
31110 } while (num >>= 7);
350 23786 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 23709 static int ebml_length_size(uint64_t length)
358 {
359 23709 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 28590 static void put_ebml_num(AVIOContext *pb, uint64_t num, int bytes)
367 {
368 28590 num |= 1ULL << bytes * 7;
369
2/2
✓ Branch 0 taken 38153 times.
✓ Branch 1 taken 28590 times.
66743 for (int i = bytes - 1; i >= 0; i--)
370 38153 avio_w8(pb, (uint8_t)(num >> i * 8));
371 28590 }
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 12719 static void put_ebml_length(AVIOContext *pb, uint64_t length, int bytes)
380 {
381 12719 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 12719 times.
12719 av_assert0(length < (1ULL << 56) - 1);
385
386
2/2
✓ Branch 0 taken 10514 times.
✓ Branch 1 taken 2205 times.
12719 if (bytes == 0)
387 10514 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 12719 times.
12719 av_assert0(bytes >= needed_bytes);
391 12719 put_ebml_num(pb, length, bytes);
392 12719 }
393
394 /**
395 * Write a (random) UID with fixed size to make the output more deterministic
396 */
397 155 static void put_ebml_uid(AVIOContext *pb, uint32_t elementid, uint64_t uid)
398 {
399 155 put_ebml_id(pb, elementid);
400 155 put_ebml_length(pb, 8, 0);
401 155 avio_wb64(pb, uid);
402 155 }
403
404 6637 static void put_ebml_uint(AVIOContext *pb, uint32_t elementid, uint64_t val)
405 {
406 6637 int i, bytes = 1;
407 6637 uint64_t tmp = val;
408
2/2
✓ Branch 0 taken 5235 times.
✓ Branch 1 taken 6637 times.
11872 while (tmp >>= 8)
409 5235 bytes++;
410
411 6637 put_ebml_id(pb, elementid);
412 6637 put_ebml_length(pb, bytes, 0);
413
2/2
✓ Branch 0 taken 11872 times.
✓ Branch 1 taken 6637 times.
18509 for (i = bytes - 1; i >= 0; i--)
414 11872 avio_w8(pb, (uint8_t)(val >> i * 8));
415 6637 }
416
417 79 static void put_ebml_float(AVIOContext *pb, uint32_t elementid, double val)
418 {
419 79 put_ebml_id(pb, elementid);
420 79 put_ebml_length(pb, 8, 0);
421 79 avio_wb64(pb, av_double2int(val));
422 79 }
423
424 2068 static void put_ebml_binary(AVIOContext *pb, uint32_t elementid,
425 const void *buf, int size)
426 {
427 2068 put_ebml_id(pb, elementid);
428 2068 put_ebml_length(pb, size, 0);
429 2068 avio_write(pb, buf, size);
430 2068 }
431
432 329 static void put_ebml_string(AVIOContext *pb, uint32_t elementid,
433 const char *str)
434 {
435 329 put_ebml_binary(pb, elementid, str, strlen(str));
436 329 }
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 734 static void put_ebml_void(AVIOContext *pb, int size)
445 {
446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 734 times.
734 av_assert0(size >= 2);
447
448 734 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 502 times.
✓ Branch 1 taken 232 times.
734 if (size < 10) {
453 502 size -= 2;
454 502 put_ebml_length(pb, size, 0);
455 } else {
456 232 size -= 9;
457 232 put_ebml_length(pb, size, 8);
458 }
459 734 ffio_fill(pb, 0, size);
460 734 }
461
462 1877 static ebml_master start_ebml_master(AVIOContext *pb, uint32_t elementid,
463 uint64_t expectedsize)
464 {
465
2/2
✓ Branch 0 taken 1799 times.
✓ Branch 1 taken 78 times.
1877 int bytes = expectedsize ? ebml_length_size(expectedsize) : 8;
466
467 1877 put_ebml_id(pb, elementid);
468 1877 put_ebml_size_unknown(pb, bytes);
469 1877 return (ebml_master) { avio_tell(pb), bytes };
470 }
471
472 1877 static void end_ebml_master(AVIOContext *pb, ebml_master master)
473 {
474 1877 int64_t pos = avio_tell(pb);
475
476
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1877 times.
1877 if (avio_seek(pb, master.pos - master.sizebytes, SEEK_SET) < 0)
477 return;
478 1877 put_ebml_length(pb, pos - master.pos, master.sizebytes);
479 1877 avio_seek(pb, pos, SEEK_SET);
480 }
481
482 22279 static EbmlElement *ebml_writer_add(EbmlWriter *writer,
483 uint32_t id, EbmlType type)
484 {
485 22279 writer->elements[writer->nb_elements].id = id;
486 22279 writer->elements[writer->nb_elements].type = type;
487 22279 return &writer->elements[writer->nb_elements++];
488 }
489
490 13995 static void ebml_writer_open_master(EbmlWriter *writer, uint32_t id)
491 {
492 13995 EbmlElement *const elem = ebml_writer_add(writer, id, EBML_MASTER);
493 13995 EbmlMaster *const master = &elem->priv.master;
494
495 13995 master->containing_master = writer->current_master_element;
496 13995 master->nb_elements = -1;
497
498 13995 writer->current_master_element = writer->nb_elements - 1;
499 13995 }
500
501 282 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 282 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 282 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 282 writer->current_master_element = elem->priv.master.containing_master;
513 282 }
514
515 6869 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 6709 times.
✓ Branch 1 taken 160 times.
6869 if (writer->current_master_element == writer->nb_elements - 1) {
521 6709 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 6709 writer->current_master_element = elem->priv.master.containing_master;
527 6709 writer->nb_elements--;
528 6709 return;
529 }
530 160 ebml_writer_close_master(writer);
531 }
532
533 296 static void ebml_writer_add_string(EbmlWriter *writer, uint32_t id,
534 const char *str)
535 {
536 296 EbmlElement *const elem = ebml_writer_add(writer, id, EBML_STR);
537
538 296 elem->priv.str = str;
539 296 }
540
541 127 static void ebml_writer_add_bin(EbmlWriter *writer, uint32_t id,
542 const uint8_t *data, size_t size)
543 {
544 127 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 127 elem->size = size;
550 127 elem->priv.bin = data;
551 127 }
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 832 static void ebml_writer_add_uint(EbmlWriter *writer, uint32_t id,
569 uint64_t val)
570 {
571 832 EbmlElement *elem = ebml_writer_add(writer, id, EBML_UINT);
572 832 elem->priv.uint = val;
573 832 }
574
575 200 static void ebml_writer_add_sint(EbmlWriter *writer, uint32_t id,
576 int64_t val)
577 {
578 200 EbmlElement *elem = ebml_writer_add(writer, id, EBML_SINT);
579 200 elem->priv.sint = val;
580 200 }
581
582 6797 static void ebml_writer_add_block(EbmlWriter *writer, MatroskaMuxContext *mkv)
583 {
584 6797 EbmlElement *elem = ebml_writer_add(writer, MATROSKA_ID_BLOCK, EBML_BLOCK);
585 6797 elem->priv.mkv = mkv;
586 6797 }
587
588 296 static int ebml_writer_str_len(EbmlElement *elem)
589 {
590 296 size_t len = strlen(elem->priv.str);
591 #if SIZE_MAX > UINT64_MAX
592 len = FF_MIN(len, UINT64_MAX);
593 #endif
594 296 elem->size = len;
595 296 return 0;
596 }
597
598 1032 static av_const int uint_size(uint64_t val)
599 {
600 1032 int bytes = 0;
601 do {
602 1236 bytes++;
603
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 1032 times.
1236 } while (val >>= 8);
604 1032 return bytes;
605 }
606
607 832 static int ebml_writer_uint_len(EbmlElement *elem)
608 {
609 832 elem->size = uint_size(elem->priv.uint);
610 832 return 0;
611 }
612
613 200 static av_const int sint_size(int64_t val)
614 {
615
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 24 times.
200 uint64_t tmp = 2 * (uint64_t)(val < 0 ? val^-1 : val);
616 200 return uint_size(tmp);
617 }
618
619 200 static int ebml_writer_sint_len(EbmlElement *elem)
620 {
621 200 elem->size = sint_size(elem->priv.sint);
622 200 return 0;
623 }
624
625 static int ebml_writer_elem_len(EbmlWriter *writer, EbmlElement *elem,
626 int remaining_elems);
627
628 790 static int ebml_writer_master_len(EbmlWriter *writer, EbmlElement *elem,
629 int remaining_elems)
630 {
631
2/2
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 508 times.
790 int nb_elems = elem->priv.master.nb_elements >= 0 ? elem->priv.master.nb_elements : remaining_elems - 1;
632 790 EbmlElement *const master = elem;
633 790 uint64_t total_size = 0;
634
635 790 master->priv.master.nb_elements = nb_elems;
636
2/2
✓ Branch 0 taken 2074 times.
✓ Branch 1 taken 790 times.
2864 for (; elem++, nb_elems > 0;) {
637 2074 int ret = ebml_writer_elem_len(writer, elem, nb_elems);
638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2074 times.
2074 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 2074 total_size += ebml_id_size(elem->id) + elem->length_size + elem->size;
644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2074 times.
2074 if (total_size > MAX_SUPPORTED_EBML_LENGTH)
645 return AVERROR(ERANGE);
646 2074 nb_elems--; /* consume elem */
647 2074 elem += ret, nb_elems -= ret; /* and elem's children */
648 }
649 790 master->size = total_size;
650
651 790 return master->priv.master.nb_elements;
652 }
653
654 6797 static int ebml_writer_block_len(EbmlElement *elem)
655 {
656 6797 MatroskaMuxContext *const mkv = elem->priv.mkv;
657 6797 BlockContext *const block = &mkv->cur_block;
658 6797 mkv_track *const track = block->track;
659 6797 const AVPacket *const pkt = block->pkt;
660 int err, size;
661
662
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 6582 times.
6797 if (track->reformat) {
663 215 err = track->reformat(mkv, NULL, pkt, &size);
664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 215 times.
215 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 6582 size = pkt->size;
671
1/2
✓ Branch 0 taken 6582 times.
✗ Branch 1 not taken.
6582 if (track->offset <= size)
672 6582 size -= track->offset;
673 }
674 6797 elem->size = track->track_num_size + 3U + size;
675
676 6797 return 0;
677 }
678
679 6797 static void ebml_writer_write_block(const EbmlElement *elem, AVIOContext *pb)
680 {
681 6797 MatroskaMuxContext *const mkv = elem->priv.mkv;
682 6797 BlockContext *const block = &mkv->cur_block;
683 6797 mkv_track *const track = block->track;
684 6797 const AVPacket *const pkt = block->pkt;
685
686 6797 put_ebml_num(pb, track->track_num, track->track_num_size);
687 6797 avio_wb16(pb, block->rel_ts);
688 6797 avio_w8(pb, block->flags);
689
690
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 6582 times.
6797 if (track->reformat) {
691 int size;
692 215 track->reformat(mkv, pb, pkt, &size);
693 } else {
694 6582 const uint8_t *data = pkt->data;
695
1/2
✓ Branch 0 taken 6582 times.
✗ Branch 1 not taken.
6582 unsigned offset = track->offset <= pkt->size ? track->offset : 0;
696 6582 avio_write(pb, data + offset, pkt->size - offset);
697 }
698 6797 }
699
700 9074 static int ebml_writer_elem_len(EbmlWriter *writer, EbmlElement *elem,
701 int remaining_elems)
702 {
703 9074 int ret = 0;
704
705
7/7
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 296 times.
✓ Branch 2 taken 832 times.
✓ Branch 3 taken 200 times.
✓ Branch 4 taken 6797 times.
✓ Branch 5 taken 790 times.
✓ Branch 6 taken 127 times.
9074 switch (elem->type) {
706 32 case EBML_FLOAT:
707 case EBML_UID:
708 32 elem->size = 8;
709 32 break;
710 296 case EBML_STR:
711 296 ret = ebml_writer_str_len(elem);
712 296 break;
713 832 case EBML_UINT:
714 832 ret = ebml_writer_uint_len(elem);
715 832 break;
716 200 case EBML_SINT:
717 200 ret = ebml_writer_sint_len(elem);
718 200 break;
719 6797 case EBML_BLOCK:
720 6797 ret = ebml_writer_block_len(elem);
721 6797 break;
722 790 case EBML_MASTER:
723 790 ret = ebml_writer_master_len(writer, elem, remaining_elems);
724 790 break;
725 }
726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9074 times.
9074 if (ret < 0)
727 return ret;
728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9074 times.
9074 if (elem->size > MAX_SUPPORTED_EBML_LENGTH)
729 return AVERROR(ERANGE);
730 9074 elem->length_size = ebml_length_size(elem->size);
731 9074 return ret; /* number of elements consumed excluding elem itself */
732 }
733
734 9074 static int ebml_writer_elem_write(const EbmlElement *elem, AVIOContext *pb)
735 {
736 9074 put_ebml_id(pb, elem->id);
737 9074 put_ebml_num(pb, elem->size, elem->length_size);
738
5/6
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1032 times.
✓ Branch 2 taken 423 times.
✓ Branch 3 taken 6797 times.
✓ Branch 4 taken 790 times.
✗ Branch 5 not taken.
9074 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 1032 case EBML_UINT:
747 case EBML_SINT: {
748 2064 uint64_t val = elem->type == EBML_UINT ? elem->priv.uint
749
2/2
✓ Branch 0 taken 832 times.
✓ Branch 1 taken 200 times.
1032 : elem->priv.sint;
750
2/2
✓ Branch 0 taken 1236 times.
✓ Branch 1 taken 1032 times.
2268 for (int i = elem->size; --i >= 0; )
751 1236 avio_w8(pb, (uint8_t)(val >> i * 8));
752 1032 break;
753 }
754 423 case EBML_STR:
755 case EBML_BIN: {
756 846 const uint8_t *data = elem->type == EBML_BIN ? elem->priv.bin
757
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 296 times.
423 : (const uint8_t*)elem->priv.str;
758 423 avio_write(pb, data, elem->size);
759 423 break;
760 }
761 6797 case EBML_BLOCK:
762 6797 ebml_writer_write_block(elem, pb);
763 6797 break;
764 790 case EBML_MASTER: {
765 790 int nb_elems = elem->priv.master.nb_elements;
766
767 790 elem++;
768
2/2
✓ Branch 0 taken 2074 times.
✓ Branch 1 taken 790 times.
2864 for (int i = 0; i < nb_elems; i++)
769 2074 i += ebml_writer_elem_write(elem + i, pb);
770
771 790 return nb_elems;
772 }
773 }
774 8284 return 0;
775 }
776
777 7000 static int ebml_writer_write(EbmlWriter *writer, AVIOContext *pb)
778 {
779 7000 int ret = ebml_writer_elem_len(writer, writer->elements,
780 7000 writer->nb_elements);
781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7000 times.
7000 if (ret < 0)
782 return ret;
783 7000 ebml_writer_elem_write(writer->elements, pb);
784 7000 return 0;
785 }
786
787 170 static void mkv_add_seekhead_entry(MatroskaMuxContext *mkv, uint32_t elementid,
788 uint64_t filepos)
789 {
790 170 mkv_seekhead *seekhead = &mkv->seekhead;
791
792 av_assert1(seekhead->num_entries < MAX_SEEKHEAD_ENTRIES);
793
794 170 seekhead->entries[seekhead->num_entries].elementid = elementid;
795 170 seekhead->entries[seekhead->num_entries++].segmentpos = filepos - mkv->segment_offset;
796 170 }
797
798 799 static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv)
799 {
800 int ret;
801
802
3/4
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 539 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 260 times.
799 if (!*dyn_cp && (ret = avio_open_dyn_buf(dyn_cp)) < 0)
803 return ret;
804
805
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 298 times.
799 if (mkv->write_crc)
806 501 put_ebml_void(*dyn_cp, 6); /* Reserve space for CRC32 so position/size calculations using avio_tell() take it into account */
807
808 799 return 0;
809 }
810
811 797 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 797 int ret, size, skip = 0;
818
819 797 size = avio_get_dyn_buf(*dyn_cp, &buf);
820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 797 times.
797 if ((ret = (*dyn_cp)->error) < 0)
821 goto fail;
822
823
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 738 times.
797 if (add_seekentry)
824 59 mkv_add_seekhead_entry(mkv, id, avio_tell(pb));
825
826 797 put_ebml_id(pb, id);
827 797 put_ebml_length(pb, size, length_size);
828
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 297 times.
797 if (mkv->write_crc) {
829 500 skip = 6; /* Skip reserved 6-byte long void element from the dynamic buffer. */
830 500 AV_WL32(crc, av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), UINT32_MAX, buf + skip, size - skip) ^ UINT32_MAX);
831 500 put_ebml_binary(pb, EBML_ID_CRC32, crc, sizeof(crc));
832 }
833 797 avio_write(pb, buf + skip, size - skip);
834
835 797 fail:
836
2/2
✓ Branch 0 taken 537 times.
✓ Branch 1 taken 260 times.
797 if (keep_buffer) {
837 537 ffio_reset_dyn_buf(*dyn_cp);
838 } else {
839 260 ffio_free_dyn_buf(dyn_cp);
840 }
841 797 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 131 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 120 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 111 times.
✓ Branch 3 taken 9 times.
131 if (IS_SEEKABLE(pb, mkv)) {
853 uint8_t *buf;
854 111 int size = avio_get_dyn_buf(elem->bc, &buf);
855
856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 if (elem->bc->error < 0)
857 return elem->bc->error;
858
859 111 elem->pos = avio_tell(pb);
860 111 mkv_add_seekhead_entry(mkv, id, elem->pos);
861
862 111 put_ebml_id(pb, id);
863 111 put_ebml_length(pb, size, 0);
864 111 avio_write(pb, buf, size);
865
866 111 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 45 static void mkv_deinit(AVFormatContext *s)
881 {
882 45 MatroskaMuxContext *mkv = s->priv_data;
883
884 45 ffio_free_dyn_buf(&mkv->cluster_bc);
885 45 ffio_free_dyn_buf(&mkv->info.bc);
886 45 ffio_free_dyn_buf(&mkv->track.bc);
887 45 ffio_free_dyn_buf(&mkv->tags.bc);
888 45 ffio_free_dyn_buf(&mkv->tmp_bc);
889
890 45 av_freep(&mkv->cur_block.h2645_nalu_list.nalus);
891 45 av_freep(&mkv->cues.entries);
892
893 45 av_freep(&mkv->tracks);
894 45 }
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 45 static void mkv_start_seekhead(MatroskaMuxContext *mkv, AVIOContext *pb)
902 {
903 45 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 45 mkv->seekhead.reserved_size = MAX_SEEKHEAD_ENTRIES * MAX_SEEKENTRY_SIZE + 14;
908 45 put_ebml_void(pb, mkv->seekhead.reserved_size);
909 45 }
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 45 static int mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv,
922 int error_on_seek_failure, int64_t destpos)
923 {
924 45 AVIOContext *dyn_cp = NULL;
925 45 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 45 times.
45 if ((ret64 = avio_seek(pb, seekhead->filepos, SEEK_SET)) < 0)
930 return error_on_seek_failure ? ret64 : 0;
931
932 45 ret = start_ebml_master_crc32(&dyn_cp, mkv);
933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
934 return ret;
935
936
2/2
✓ Branch 0 taken 170 times.
✓ Branch 1 taken 45 times.
215 for (i = 0; i < seekhead->num_entries; i++) {
937 170 mkv_seekhead_entry *entry = &seekhead->entries[i];
938 170 ebml_master seekentry = start_ebml_master(dyn_cp, MATROSKA_ID_SEEKENTRY,
939 MAX_SEEKENTRY_SIZE);
940
941 170 put_ebml_id(dyn_cp, MATROSKA_ID_SEEKID);
942 170 put_ebml_length(dyn_cp, ebml_id_size(entry->elementid), 0);
943 170 put_ebml_id(dyn_cp, entry->elementid);
944
945 170 put_ebml_uint(dyn_cp, MATROSKA_ID_SEEKPOSITION, entry->segmentpos);
946 170 end_ebml_master(dyn_cp, seekentry);
947 }
948 45 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 45 times.
45 if (ret < 0)
951 return ret;
952
953 45 remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb);
954 45 put_ebml_void(pb, remaining);
955
956
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
45 if ((ret64 = avio_seek(pb, destpos, SEEK_SET)) < 0)
957 return ret64;
958
959 45 return 0;
960 }
961
962 1165 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 1165 mkv_cues *cues = &mkv->cues;
966 1165 mkv_cuepoint *entries = cues->entries;
967 1165 unsigned idx = cues->num_entries;
968
969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1165 times.
1165 if (ts < 0)
970 return 0;
971
972 1165 entries = av_realloc_array(entries, cues->num_entries + 1, sizeof(mkv_cuepoint));
973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1165 times.
1165 if (!entries)
974 return AVERROR(ENOMEM);
975 1165 cues->entries = entries;
976
977 /* Make sure the cues entries are sorted by pts. */
978
3/4
✓ Branch 0 taken 1128 times.
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1128 times.
1165 while (idx > 0 && entries[idx - 1].pts > ts)
979 idx--;
980 1165 memmove(&entries[idx + 1], &entries[idx],
981 1165 (cues->num_entries - idx) * sizeof(entries[0]));
982
983 1165 entries[idx].pts = ts;
984 1165 entries[idx].stream_idx = stream;
985 1165 entries[idx].cluster_pos = cluster_pos - mkv->segment_offset;
986 1165 entries[idx].relative_pos = relative_pos;
987 1165 entries[idx].duration = duration;
988
989 1165 cues->num_entries++;
990
991 1165 return 0;
992 }
993
994 39 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 39 for (mkv_cuepoint *entry = cues->entries, *end = entry + cues->num_entries;
999
2/2
✓ Branch 0 taken 1083 times.
✓ Branch 1 taken 39 times.
1122 entry < end;) {
1000 1083 uint64_t pts = entry->pts;
1001 uint8_t *buf;
1002 int size;
1003
1004 1083 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 2180 times.
✓ Branch 1 taken 1083 times.
3263 for (int j = 0; j < num_tracks; j++)
1009 2180 tracks[j].has_cue = 0;
1010 do {
1011 ebml_master track_positions;
1012 1403 int idx = entry->stream_idx;
1013
1014
2/4
✓ Branch 0 taken 1403 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1403 times.
1403 av_assert0(idx >= 0 && idx < num_tracks);
1015
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1401 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
1403 if (tracks[idx].has_cue && streams[idx]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
1016 continue;
1017 1403 tracks[idx].has_cue = 1;
1018 1403 track_positions = start_ebml_master(cuepoint, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE);
1019 1403 put_ebml_uint(cuepoint, MATROSKA_ID_CUETRACK , tracks[idx].track_num);
1020 1403 put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos + offset);
1021 1403 put_ebml_uint(cuepoint, MATROSKA_ID_CUERELATIVEPOSITION, entry->relative_pos);
1022
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 1320 times.
1403 if (entry->duration > 0)
1023 83 put_ebml_uint(cuepoint, MATROSKA_ID_CUEDURATION , entry->duration);
1024 1403 end_ebml_master(cuepoint, track_positions);
1025
4/4
✓ Branch 0 taken 1364 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 320 times.
✓ Branch 3 taken 1044 times.
1403 } while (++entry < end && entry->pts == pts);
1026 1083 size = avio_get_dyn_buf(cuepoint, &buf);
1027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1083 times.
1083 if (cuepoint->error < 0)
1028 return cuepoint->error;
1029 1083 put_ebml_binary(dyn_cp, MATROSKA_ID_POINTENTRY, buf, size);
1030 1083 ffio_reset_dyn_buf(cuepoint);
1031 }
1032
1033 39 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 72 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 3 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 34 times.
72 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 3 case AV_CODEC_ID_AV1:
1161
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (extradata_size)
1162 2 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 5 case AV_CODEC_ID_HEVC:
1176 5 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 34 default:
1220
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
35 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 11 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
33 } else if (extradata_size && par->codec_id != AV_CODEC_ID_TTA)
1224 11 avio_write(dyn_cp, extradata, extradata_size);
1225 }
1226
1227 43 return 0;
1228 }
1229
1230 78 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 78 av_unused MatroskaMuxContext *const mkv = s->priv_data;
1238 78 unsigned size_to_reserve = 0;
1239 int ret;
1240
1241
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 6 times.
78 if (native_id) {
1242 72 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 72 times.
72 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 78 *codecpriv_size = avio_get_dyn_buf(dyn_cp, codecpriv);
1298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (dyn_cp->error < 0)
1299 return dyn_cp->error;
1300 78 *max_payload_size = *codecpriv_size + size_to_reserve;
1301
1302 78 return 0;
1303 }
1304
1305 78 static void mkv_put_codecprivate(AVIOContext *pb, unsigned max_payload_size,
1306 const uint8_t *codecpriv, unsigned codecpriv_size)
1307 {
1308 78 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 56 times.
78 if (!max_payload_size)
1313 22 return;
1314
1315 56 total_size = 2 + ebml_length_size(max_payload_size) + max_payload_size;
1316
1317
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 2 times.
56 if (codecpriv_size) {
1318 54 unsigned length_size = ebml_length_size(codecpriv_size);
1319
1320 54 total_codecpriv_size = 2U + length_size + codecpriv_size;
1321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 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 54 put_ebml_id(pb, MATROSKA_ID_CODECPRIVATE);
1327 54 put_ebml_length(pb, codecpriv_size, length_size);
1328 54 avio_write(pb, codecpriv, codecpriv_size);
1329 }
1330
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 52 times.
56 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 35 static void mkv_write_video_color(EbmlWriter *writer, const AVStream *st,
1373 const AVCodecParameters *par)
1374 {
1375 const AVPacketSideData *side_data;
1376
1377 35 ebml_writer_open_master(writer, MATROSKA_ID_VIDEOCOLOR);
1378
1379
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 24 times.
35 if (par->color_trc != AVCOL_TRC_UNSPECIFIED &&
1380
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 par->color_trc < AVCOL_TRC_NB) {
1381 11 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS,
1382 11 par->color_trc);
1383 }
1384
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 24 times.
35 if (par->color_space != AVCOL_SPC_UNSPECIFIED &&
1385
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 par->color_space < AVCOL_SPC_NB) {
1386 11 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORMATRIXCOEFF,
1387 11 par->color_space);
1388 }
1389
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 26 times.
35 if (par->color_primaries != AVCOL_PRI_UNSPECIFIED &&
1390
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 par->color_primaries < AVCOL_PRI_NB) {
1391 9 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORPRIMARIES,
1392 9 par->color_primaries);
1393 }
1394
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 12 times.
35 if (par->color_range != AVCOL_RANGE_UNSPECIFIED &&
1395
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 par->color_range < AVCOL_RANGE_NB) {
1396 23 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORRANGE, par->color_range);
1397 }
1398
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 15 times.
35 if (par->chroma_location != AVCHROMA_LOC_UNSPECIFIED &&
1399
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 par->chroma_location <= AVCHROMA_LOC_TOP) {
1400 int xpos, ypos;
1401
1402 20 av_chroma_location_enum_to_pos(&xpos, &ypos, par->chroma_location);
1403 20 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ,
1404 20 (xpos >> 7) + 1);
1405 20 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT,
1406 20 (ypos >> 7) + 1);
1407 }
1408
1409 35 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 33 times.
35 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 35 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 33 times.
35 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 35 ebml_writer_close_or_discard_master(writer);
1452 35 }
1453
1454 #define MAX_VIDEO_PROJECTION_ELEMS 6
1455 33 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 33 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 29 times.
✓ Branch 1 taken 4 times.
33 if (!side_data)
1464 29 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 35 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 35 const AVPacketSideData *sd = av_packet_side_data_get(par->coded_side_data,
1515 35 par->nb_coded_side_data,
1516 AV_PKT_DATA_SPHERICAL);
1517 const AVSphericalMapping *spherical;
1518
1519
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2 times.
35 if (!sd)
1520 33 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 35 static void mkv_write_video_projection(void *logctx, EbmlWriter *wr,
1571 const AVCodecParameters *par,
1572 uint8_t private[])
1573 {
1574 35 double yaw = 0, pitch = 0, roll = 0;
1575 int ret;
1576
1577 35 ebml_writer_open_master(wr, MATROSKA_ID_VIDEOPROJECTION);
1578
1579 35 ret = mkv_handle_spherical(logctx, wr, par, private, &yaw, &pitch, &roll);
1580
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2 times.
35 if (!ret)
1581 33 mkv_handle_rotation(logctx, par, &yaw, &roll);
1582
1583
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 31 times.
35 if (yaw)
1584 4 ebml_writer_add_float(wr, MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, yaw);
1585
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 33 times.
35 if (pitch)
1586 2 ebml_writer_add_float(wr, MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, pitch);
1587
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 30 times.
35 if (roll)
1588 5 ebml_writer_add_float(wr, MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, roll);
1589
1590 35 ebml_writer_close_or_discard_master(wr);
1591 35 }
1592
1593 #define MAX_FIELD_ORDER_ELEMS 2
1594 35 static void mkv_write_field_order(EbmlWriter *writer, int is_webm,
1595 enum AVFieldOrder field_order)
1596 {
1597
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
35 switch (field_order) {
1598 20 case AV_FIELD_UNKNOWN:
1599 20 break;
1600 11 case AV_FIELD_PROGRESSIVE:
1601 11 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFLAGINTERLACED,
1602 MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE);
1603 11 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 35 }
1632
1633 #define MAX_STEREO_MODE_ELEMS 1
1634 35 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 35 const char *error_message_addendum = "";
1640 const AVDictionaryEntry *tag;
1641 35 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 35 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 35 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 35 const unsigned webm_bitfield = 0 STEREOMODE_STEREO3D_MAPPING(WEBM1, WEBM2);
1665
1666 35 *h_width = 1;
1667 35 *h_height = 1;
1668
1669
3/4
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
64 if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) ||
1670 29 (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) {
1671
1672
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 1 times.
48 for (int i = 0; i < MATROSKA_VIDEO_STEREOMODE_TYPE_NB; i++)
1673
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 42 times.
47 if (!strcmp(tag->value, ff_matroska_video_stereo_mode[i])){
1674 5 format = i;
1675 5 break;
1676 }
1677
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 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 29 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 25 times.
✓ Branch 1 taken 4 times.
29 if (!sd)
1699 25 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 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
10 if (is_webm && !(webm_bitfield >> format)) {
1716 error_message_addendum = " for WebM";
1717 goto fail;
1718 }
1719
1720 10 *h_width = 1 << ((width_bitfield >> format) & 1);
1721 10 *h_height = 1 << ((height_bitfield >> format) & 1);
1722
1723 // write StereoMode if format is valid
1724 10 ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOSTEREOMODE, format);
1725
1726 10 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 70 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 #if CONFIG_MATROSKA_MUXER
1739 const AVDOVIDecoderConfigurationRecord *dovi;
1740 const AVPacketSideData *sd;
1741
1742
4/4
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 3 times.
70 if (IS_SEEKABLE(s->pb, mkv)) {
1743 62 track->blockadditionmapping_offset = avio_tell(pb);
1744 // We can't know at this point if there will be a block with BlockAdditions, so
1745 // we either write the default value here, or a void element. Either of them will
1746 // be overwritten when finishing the track.
1747 62 put_ebml_uint(pb, MATROSKA_ID_TRACKMAXBLKADDID, 0);
1748
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 30 times.
62 if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
1749 // Similarly, reserve space for an eventual
1750 // HDR10+ ITU T.35 metadata BlockAdditionMapping.
1751 32 put_ebml_void(pb, 3 /* BlockAdditionMapping */
1752 + 4 /* BlockAddIDValue */
1753 + 4 /* BlockAddIDType */);
1754 }
1755 }
1756
1757 70 sd = av_packet_side_data_get(par->coded_side_data, par->nb_coded_side_data,
1758 AV_PKT_DATA_DOVI_CONF);
1759
1760
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 2 times.
70 if (!sd)
1761 68 return;
1762
1763 2 dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data;
1764
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (dovi->dv_profile <= 10) {
1765 ebml_master mapping;
1766 uint8_t buf[ISOM_DVCC_DVVC_SIZE];
1767 uint32_t type;
1768
1769 2 uint64_t expected_size = (2 + 1 + (sizeof(DVCC_DVVC_BLOCK_TYPE_NAME) - 1))
1770 + (2 + 1 + 4) + (2 + 1 + ISOM_DVCC_DVVC_SIZE);
1771
1772
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (dovi->dv_profile > 7) {
1773 1 type = MATROSKA_BLOCK_ADD_ID_TYPE_DVVC;
1774 } else {
1775 1 type = MATROSKA_BLOCK_ADD_ID_TYPE_DVCC;
1776 }
1777
1778 2 ff_isom_put_dvcc_dvvc(s, buf, dovi);
1779
1780 2 mapping = start_ebml_master(pb, MATROSKA_ID_TRACKBLKADDMAPPING, expected_size);
1781
1782 2 put_ebml_string(pb, MATROSKA_ID_BLKADDIDNAME, DVCC_DVVC_BLOCK_TYPE_NAME);
1783 2 put_ebml_uint(pb, MATROSKA_ID_BLKADDIDTYPE, type);
1784 2 put_ebml_binary(pb, MATROSKA_ID_BLKADDIDEXTRADATA, buf, sizeof(buf));
1785
1786 2 end_ebml_master(pb, mapping);
1787 }
1788 #endif
1789 }
1790
1791 35 static bool codec_has_blockadditional_alpha(AVFormatContext *s, const AVStream *st,
1792 const AVCodecParameters *par)
1793 {
1794 const AVDictionaryEntry *tag;
1795
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1 times.
35 if (par->codec_id != AV_CODEC_ID_VP8 &&
1796
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 3 times.
34 par->codec_id != AV_CODEC_ID_VP9)
1797 31 return false;
1798 4 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format);
1799
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))
1800 return true;
1801
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
7 return ((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) ||
1802
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);
1803 }
1804
1805 35 static int mkv_write_track_video(AVFormatContext *s, MatroskaMuxContext *mkv,
1806 const AVStream *st, const AVCodecParameters *par,
1807 AVIOContext *pb)
1808 {
1809 35 int display_width_div = 1, display_height_div = 1;
1810 uint8_t color_space[4], projection_private[20];
1811 const AVPacketSideData *sd;
1812 35 EBML_WRITER(MAX_FIELD_ORDER_ELEMS + MAX_STEREO_MODE_ELEMS +
1813 MAX_VIDEO_COLOR_ELEMS + MAX_VIDEO_PROJECTION_ELEMS + 12);
1814 35 int cropped_width = par->width, cropped_height = par->height;
1815 int ret;
1816
1817 35 ebml_writer_open_master(&writer, MATROSKA_ID_TRACKVIDEO);
1818
1819 35 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELWIDTH , par->width);
1820 35 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELHEIGHT, par->height);
1821
1822 35 mkv_write_field_order(&writer, IS_WEBM(mkv), par->field_order);
1823
1824 // check both side data and metadata for stereo information,
1825 // write the result to the bitstream if any is found
1826 35 ret = mkv_write_stereo_mode(s, &writer, par, st, IS_WEBM(mkv),
1827 &display_width_div,
1828 &display_height_div);
1829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (ret < 0)
1830 return ret;
1831
1832
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 34 times.
35 if (codec_has_blockadditional_alpha(s, st, par))
1833 1 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOALPHAMODE, 1);
1834
1835 35 sd = av_packet_side_data_get(par->coded_side_data,
1836 35 par->nb_coded_side_data,
1837 AV_PKT_DATA_FRAME_CROPPING);
1838
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
35 if (sd && sd->size == sizeof(uint32_t) * 4) {
1839 uint64_t top, bottom, left, right;
1840
1841 2 top = AV_RL32(sd->data + 0);
1842 2 bottom = AV_RL32(sd->data + 4);
1843 2 left = AV_RL32(sd->data + 8);
1844 2 right = AV_RL32(sd->data + 12);
1845
1846
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if ((left + right) >= par->width ||
1847
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 (top + bottom) >= par->height) {
1848 av_log(s, AV_LOG_ERROR, "Invalid cropping dimensions in stream side data\n");
1849 return AVERROR(EINVAL);
1850 }
1851
1852
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (bottom)
1853 2 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELCROPB, bottom);
1854
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (top)
1855 2 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELCROPT, top);
1856
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (left)
1857 2 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELCROPL, left);
1858
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (right)
1859 2 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELCROPR, right);
1860
1861 2 cropped_width -= left + right;
1862 2 cropped_height -= top + bottom;
1863 }
1864
1865 // write DisplayWidth and DisplayHeight, they contain the size of
1866 // a single source view and/or the display aspect ratio
1867
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 17 times.
35 if (st->sample_aspect_ratio.num) {
1868 18 int64_t d_width = av_rescale(cropped_width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
1869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (d_width > INT_MAX) {
1870 av_log(s, AV_LOG_ERROR, "Overflow in display width\n");
1871 return AVERROR(EINVAL);
1872 }
1873
4/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
18 if (d_width != cropped_width || display_width_div != 1 || display_height_div != 1) {
1874
6/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6 times.
9 if (IS_WEBM(mkv) || display_width_div != 1 || display_height_div != 1) {
1875 3 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYWIDTH,
1876 3 d_width / display_width_div);
1877 3 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYHEIGHT,
1878 3 cropped_height / display_height_div);
1879 } else {
1880 AVRational display_aspect_ratio;
1881 6 av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
1882 6 cropped_width * (int64_t)st->sample_aspect_ratio.num,
1883 6 cropped_height * (int64_t)st->sample_aspect_ratio.den,
1884 1024 * 1024);
1885 6 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYWIDTH,
1886 6 display_aspect_ratio.num);
1887 6 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYHEIGHT,
1888 6 display_aspect_ratio.den);
1889 6 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYUNIT,
1890 MATROSKA_VIDEO_DISPLAYUNIT_DAR);
1891 }
1892 }
1893
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 15 times.
17 } else if (display_width_div != 1 || display_height_div != 1) {
1894 2 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYWIDTH,
1895 2 cropped_width / display_width_div);
1896 2 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYHEIGHT,
1897 2 cropped_height / display_height_div);
1898
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 } else if (!IS_WEBM(mkv))
1899 15 ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYUNIT,
1900 MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN);
1901
1902
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 33 times.
35 if (par->codec_id == AV_CODEC_ID_RAWVIDEO) {
1903 2 AV_WL32(color_space, par->codec_tag);
1904 2 ebml_writer_add_bin(&writer, MATROSKA_ID_VIDEOCOLORSPACE,
1905 color_space, sizeof(color_space));
1906 }
1907 35 mkv_write_video_color(&writer, st, par);
1908 35 mkv_write_video_projection(s, &writer, par, projection_private);
1909
1910 35 return ebml_writer_write(&writer, pb);
1911 }
1912
1913 42 static void mkv_write_default_duration(mkv_track *track, AVIOContext *pb,
1914 AVRational duration)
1915 {
1916 42 put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION,
1917 42 1000000000LL * duration.num / duration.den);
1918 42 track->default_duration_low = 1000LL * duration.num / duration.den;
1919 42 track->default_duration_high = track->default_duration_low +
1920 42 !!(1000LL * duration.num % duration.den);
1921 42 }
1922
1923 78 static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
1924 AVStream *st, mkv_track *track, AVIOContext *pb,
1925 int is_default)
1926 {
1927 78 AVCodecParameters *par = st->codecpar;
1928 ebml_master subinfo, track_master;
1929 78 int native_id = 0;
1930 78 int qt_id = 0;
1931 int bit_depth;
1932 78 int sample_rate = par->sample_rate;
1933 78 int output_sample_rate = 0;
1934 int j, ret;
1935 const AVDictionaryEntry *tag;
1936
1937
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 77 times.
78 if (par->codec_type == AVMEDIA_TYPE_ATTACHMENT)
1938 1 return 0;
1939
1940 77 track_master = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0);
1941 77 put_ebml_uint(pb, MATROSKA_ID_TRACKNUMBER, track->track_num);
1942 77 put_ebml_uid (pb, MATROSKA_ID_TRACKUID, track->uid);
1943 77 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGLACING, 0); // no lacing (yet)
1944
1945
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 70 times.
77 if ((tag = av_dict_get(st->metadata, "title", NULL, 0)))
1946 7 put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value);
1947 77 tag = av_dict_get(st->metadata, "language", NULL, 0);
1948
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 44 times.
110 put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE,
1949
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 tag && tag->value[0] ? tag->value : "und");
1950
1951 // The default value for TRACKFLAGDEFAULT is 1, so add element
1952 // if we need to clear it.
1953
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 32 times.
77 if (!is_default)
1954 45 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, 0);
1955
1956
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 75 times.
77 if (st->disposition & AV_DISPOSITION_FORCED)
1957 2 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, 1);
1958
1959
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 70 times.
77 if (IS_WEBM(mkv)) {
1960 const char *codec_id;
1961
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (par->codec_id != AV_CODEC_ID_WEBVTT) {
1962
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 for (j = 0; ff_webm_codec_tags[j].id != AV_CODEC_ID_NONE; j++) {
1963
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
9 if (ff_webm_codec_tags[j].id == par->codec_id) {
1964 3 codec_id = ff_webm_codec_tags[j].str;
1965 3 native_id = 1;
1966 3 break;
1967 }
1968 }
1969 } else {
1970
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (st->disposition & AV_DISPOSITION_CAPTIONS) {
1971 1 codec_id = "D_WEBVTT/CAPTIONS";
1972 1 native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
1973
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 } else if (st->disposition & AV_DISPOSITION_DESCRIPTIONS) {
1974 1 codec_id = "D_WEBVTT/DESCRIPTIONS";
1975 1 native_id = MATROSKA_TRACK_TYPE_METADATA;
1976
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 } else if (st->disposition & AV_DISPOSITION_METADATA) {
1977 1 codec_id = "D_WEBVTT/METADATA";
1978 1 native_id = MATROSKA_TRACK_TYPE_METADATA;
1979 } else {
1980 1 codec_id = "D_WEBVTT/SUBTITLES";
1981 1 native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
1982 }
1983 }
1984
1985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!native_id) {
1986 av_log(s, AV_LOG_ERROR,
1987 "Only VP8 or VP9 or AV1 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM.\n");
1988 return AVERROR(EINVAL);
1989 }
1990
1991 7 put_ebml_string(pb, MATROSKA_ID_CODECID, codec_id);
1992 } else {
1993
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 69 times.
70 if (st->disposition & AV_DISPOSITION_COMMENT)
1994 1 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGCOMMENTARY, 1);
1995
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 66 times.
70 if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
1996 4 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED, 1);
1997
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 69 times.
70 if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
1998 1 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGVISUALIMPAIRED, 1);
1999
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 68 times.
70 if (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB) &&
2000
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB))
2001 != (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB))
2002 2 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGORIGINAL,
2003 2 !!(st->disposition & AV_DISPOSITION_ORIGINAL));
2004
2005 // look for a codec ID string specific to mkv to use,
2006 // if none are found, use AVI codes
2007
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 if (par->codec_id == AV_CODEC_ID_JPEG2000) {
2008 /* JPEG2000 is actually supported natively in Matroska,
2009 * yet we use the VfW way to mux it for compatibility
2010 * with old demuxers. (FIXME: Are they really important?) */
2011
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
70 } else if (par->codec_id != AV_CODEC_ID_RAWVIDEO || par->codec_tag) {
2012
2/2
✓ Branch 0 taken 2762 times.
✓ Branch 1 taken 4 times.
2766 for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) {
2013
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 2698 times.
2762 if (ff_mkv_codec_tags[j].id == par->codec_id) {
2014 64 put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str);
2015 64 native_id = 1;
2016 64 break;
2017 }
2018 }
2019 } else {
2020
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mkv->allow_raw_vfw) {
2021 2 native_id = 0;
2022 } else {
2023 av_log(s, AV_LOG_ERROR, "Raw RGB is not supported Natively in Matroska, you can use AVI or NUT or\n"
2024 "If you would like to store it anyway using VFW mode, enable allow_raw_vfw (-allow_raw_vfw 1)\n");
2025 return AVERROR(EINVAL);
2026 }
2027 }
2028 }
2029
2030
3/4
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
77 switch (par->codec_type) {
2031 AVRational frame_rate;
2032 int audio_frame_samples;
2033
2034 35 case AVMEDIA_TYPE_VIDEO:
2035 35 mkv->have_video = 1;
2036 35 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
2037
2038 35 frame_rate = (AVRational){ 0, 1 };
2039
3/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
35 if (st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0)
2040 32 frame_rate = st->avg_frame_rate;
2041
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)
2042 2 frame_rate = st->r_frame_rate;
2043
2044
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1 times.
35 if (frame_rate.num > 0)
2045 34 mkv_write_default_duration(track, pb, av_inv_q(frame_rate));
2046
2047
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
40 if (CONFIG_MATROSKA_MUXER && !native_id &&
2048
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
8 ff_codec_get_tag(ff_codec_movvideo_tags, par->codec_id) &&
2049
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) ||
2050
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 par->codec_id == AV_CODEC_ID_SVQ1 ||
2051
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 par->codec_id == AV_CODEC_ID_SVQ3 ||
2052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 par->codec_id == AV_CODEC_ID_CINEPAK))
2053 1 qt_id = 1;
2054
2055
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34 times.
35 if (qt_id)
2056 1 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME");
2057
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 30 times.
34 else if (!native_id) {
2058 // if there is no mkv-specific codec ID, use VFW mode
2059 4 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC");
2060 4 track->write_dts = 1;
2061 4 ffformatcontext(s)->avoid_negative_ts_use_pts = 0;
2062 }
2063
2064 35 ret = mkv_write_track_video(s, mkv, st, par, pb);
2065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (ret < 0)
2066 return ret;
2067
2068 35 break;
2069
2070 31 case AVMEDIA_TYPE_AUDIO:
2071
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 26 times.
31 if (par->initial_padding) {
2072 5 int64_t codecdelay = av_rescale_q(par->initial_padding,
2073 5 (AVRational){ 1, par->sample_rate },
2074 5 (AVRational){ 1, 1000000000 });
2075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (codecdelay < 0) {
2076 av_log(s, AV_LOG_ERROR, "Initial padding is invalid\n");
2077 return AVERROR(EINVAL);
2078 }
2079 5 put_ebml_uint(pb, MATROSKA_ID_CODECDELAY, codecdelay);
2080
2081 5 track->ts_offset = av_rescale_q(par->initial_padding,
2082 5 (AVRational){ 1, par->sample_rate },
2083 st->time_base);
2084 5 ffstream(st)->lowest_ts_allowed = -track->ts_offset;
2085 }
2086
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29 times.
31 if (par->codec_id == AV_CODEC_ID_OPUS)
2087 2 put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL);
2088 #if CONFIG_MATROSKA_MUXER
2089
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 23 times.
29 else if (par->codec_id == AV_CODEC_ID_AAC) {
2090 6 ret = get_aac_sample_rates(s, mkv, par->extradata, par->extradata_size,
2091 &sample_rate, &output_sample_rate);
2092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
2093 return ret;
2094 }
2095 #endif
2096
2097 31 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
2098
2099 31 audio_frame_samples = av_get_audio_frame_duration2(par, 0);
2100
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 23 times.
31 if (audio_frame_samples)
2101 8 mkv_write_default_duration(track, pb, (AVRational){ audio_frame_samples,
2102 8 par->sample_rate });
2103
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
31 if (!native_id)
2104 // no mkv-specific ID, use ACM mode
2105 1 put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM");
2106
2107 31 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 6 + 4 * 9);
2108 31 put_ebml_uint(pb, MATROSKA_ID_AUDIOCHANNELS, par->ch_layout.nb_channels);
2109
2110 31 track->sample_rate_offset = avio_tell(pb);
2111 31 put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate);
2112
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
31 if (output_sample_rate)
2113 1 put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
2114
2115 31 bit_depth = av_get_bits_per_sample(par->codec_id);
2116
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) {
2117
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14 times.
24 if (par->bits_per_raw_sample)
2118 10 bit_depth = par->bits_per_raw_sample;
2119 else
2120 14 bit_depth = av_get_bytes_per_sample(par->format) << 3;
2121 }
2122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (!bit_depth)
2123 bit_depth = par->bits_per_coded_sample;
2124
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (bit_depth)
2125 31 put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth);
2126 31 end_ebml_master(pb, subinfo);
2127 31 break;
2128
2129 11 case AVMEDIA_TYPE_SUBTITLE:
2130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (!native_id) {
2131 av_log(s, AV_LOG_ERROR, "Subtitle codec %s (%d) is not supported.\n",
2132 avcodec_get_name(par->codec_id), par->codec_id);
2133 return AVERROR(ENOSYS);
2134 }
2135
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)
2136 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, 1);
2137
2138
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)
2139 7 native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
2140
2141 11 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id);
2142 11 break;
2143 default:
2144 av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n");
2145 return AVERROR(EINVAL);
2146 }
2147
2148
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 7 times.
77 if (!IS_WEBM(mkv))
2149 70 mkv_write_blockadditionmapping(s, mkv, par, pb, track, st);
2150
2151
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4 times.
77 if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) {
2152 uint8_t *codecpriv;
2153 int codecpriv_size, max_payload_size;
2154 73 track->codecpriv_offset = avio_tell(pb);
2155 73 ret = mkv_assemble_codecprivate(s, mkv->tmp_bc, par,
2156 73 par->extradata, par->extradata_size,
2157 native_id, qt_id,
2158 &codecpriv, &codecpriv_size, &max_payload_size);
2159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (ret < 0)
2160 goto fail;
2161 73 mkv_put_codecprivate(pb, max_payload_size, codecpriv, codecpriv_size);
2162 73 track->codecpriv_size = max_payload_size;
2163 }
2164
2165 77 end_ebml_master(pb, track_master);
2166 77 ret = 0;
2167 77 fail:
2168 77 ffio_reset_dyn_buf(mkv->tmp_bc);
2169
2170 77 return ret;
2171 }
2172
2173 45 static int mkv_write_tracks(AVFormatContext *s)
2174 {
2175 45 MatroskaMuxContext *mkv = s->priv_data;
2176 45 AVIOContext *pb = s->pb;
2177 45 int video_default_idx = -1, audio_default_idx = -1, subtitle_default_idx = -1;
2178 int i, ret;
2179
2180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (mkv->nb_attachments == s->nb_streams)
2181 return 0;
2182
2183 45 ret = start_ebml_master_crc32(&mkv->track.bc, mkv);
2184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
2185 return ret;
2186
2187
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 42 times.
45 if (mkv->default_mode != DEFAULT_MODE_PASSTHROUGH) {
2188 3 int video_idx = -1, audio_idx = -1, subtitle_idx = -1;
2189
2190
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 3 times.
13 for (i = s->nb_streams - 1; i >= 0; i--) {
2191 10 AVStream *st = s->streams[i];
2192
2193
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) {
2194 #define CASE(type, variable) \
2195 case AVMEDIA_TYPE_ ## type: \
2196 variable ## _idx = i; \
2197 if (st->disposition & AV_DISPOSITION_DEFAULT) \
2198 variable ## _default_idx = i; \
2199 break;
2200
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 CASE(VIDEO, video)
2201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 CASE(AUDIO, audio)
2202
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 CASE(SUBTITLE, subtitle)
2203 #undef CASE
2204 }
2205 }
2206
2207 3 video_default_idx = FFMAX(video_default_idx, video_idx);
2208 3 audio_default_idx = FFMAX(audio_default_idx, audio_idx);
2209
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (mkv->default_mode != DEFAULT_MODE_INFER_NO_SUBS)
2210 2 subtitle_default_idx = FFMAX(subtitle_default_idx, subtitle_idx);
2211 }
2212
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 45 times.
123 for (i = 0; i < s->nb_streams; i++) {
2213 78 AVStream *st = s->streams[i];
2214
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 int is_default = st->disposition & AV_DISPOSITION_DEFAULT ||
2215
5/6
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 46 times.
125 i == video_default_idx || i == audio_default_idx ||
2216 i == subtitle_default_idx;
2217 78 ret = mkv_write_track(s, mkv, st, &mkv->tracks[i],
2218 mkv->track.bc, is_default);
2219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (ret < 0)
2220 return ret;
2221 }
2222
2223 45 return end_ebml_master_crc32_tentatively(pb, &mkv->track, mkv,
2224 MATROSKA_ID_TRACKS);
2225 }
2226
2227 118 static int mkv_write_simpletag(AVIOContext *pb, const AVDictionaryEntry *t)
2228 {
2229 118 EBML_WRITER(4);
2230 118 uint8_t *key = av_strdup(t->key);
2231 118 uint8_t *p = key;
2232 118 const uint8_t *lang = NULL;
2233 int ret;
2234
2235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (!key)
2236 return AVERROR(ENOMEM);
2237
2238
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 111 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 2 times.
125 if ((p = strrchr(p, '-')) &&
2239 7 (lang = ff_convert_lang_to(p + 1, AV_LANG_ISO639_2_BIBL)))
2240 5 *p = 0;
2241
2242 118 p = key;
2243
2/2
✓ Branch 0 taken 1381 times.
✓ Branch 1 taken 118 times.
1499 while (*p) {
2244
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1380 times.
1381 if (*p == ' ')
2245 1 *p = '_';
2246
3/4
✓ Branch 0 taken 1214 times.
✓ Branch 1 taken 166 times.
✓ Branch 2 taken 1214 times.
✗ Branch 3 not taken.
1380 else if (*p >= 'a' && *p <= 'z')
2247 1214 *p -= 'a' - 'A';
2248 1381 p++;
2249 }
2250
2251 118 ebml_writer_open_master(&writer, MATROSKA_ID_SIMPLETAG);
2252 118 ebml_writer_add_string(&writer, MATROSKA_ID_TAGNAME, key);
2253
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 113 times.
118 if (lang)
2254 5 ebml_writer_add_string(&writer, MATROSKA_ID_TAGLANG, lang);
2255 118 ebml_writer_add_string(&writer, MATROSKA_ID_TAGSTRING, t->value);
2256 118 ret = ebml_writer_write(&writer, pb);
2257
2258 118 av_freep(&key);
2259 118 return ret;
2260 }
2261
2262 123 static void mkv_write_tag_targets(MatroskaMuxContext *mkv, AVIOContext *pb,
2263 uint32_t elementid, uint64_t uid)
2264 {
2265 123 ebml_master targets = start_ebml_master(pb, MATROSKA_ID_TAGTARGETS,
2266 4 + 1 + 8);
2267
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 45 times.
123 if (elementid)
2268 78 put_ebml_uid(pb, elementid, uid);
2269 123 end_ebml_master(pb, targets);
2270 123 }
2271
2272 190 static int mkv_check_tag_name(const char *name, uint32_t elementid)
2273 {
2274
2/2
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 6 times.
366 return av_strcasecmp(name, "title") &&
2275
2/2
✓ Branch 1 taken 158 times.
✓ Branch 2 taken 12 times.
346 av_strcasecmp(name, "stereo_mode") &&
2276
1/2
✓ Branch 1 taken 158 times.
✗ Branch 2 not taken.
328 av_strcasecmp(name, "creation_time") &&
2277
2/2
✓ Branch 1 taken 153 times.
✓ Branch 2 taken 5 times.
316 av_strcasecmp(name, "encoding_tool") &&
2278
2/2
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 66 times.
311 av_strcasecmp(name, "duration") &&
2279
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 33 times.
87 (elementid != MATROSKA_ID_TAGTARGETS_TRACKUID ||
2280
4/4
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 118 times.
455 av_strcasecmp(name, "language")) &&
2281
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 (elementid != MATROSKA_ID_TAGTARGETS_ATTACHUID ||
2282
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
3 (av_strcasecmp(name, "filename") &&
2283 1 av_strcasecmp(name, "mimetype")));
2284 }
2285
2286 123 static int mkv_write_tag(MatroskaMuxContext *mkv, const AVDictionary *m,
2287 AVIOContext **pb, unsigned reserved_size,
2288 uint32_t elementid, uint64_t uid)
2289 {
2290 123 const AVDictionaryEntry *t = NULL;
2291 123 AVIOContext *const tmp_bc = mkv->tmp_bc;
2292 uint8_t *buf;
2293 123 int ret = 0, size, tag_written = 0;
2294
2295 123 mkv_write_tag_targets(mkv, tmp_bc, elementid, uid);
2296
2297
2/2
✓ Branch 1 taken 190 times.
✓ Branch 2 taken 123 times.
313 while ((t = av_dict_iterate(m, t))) {
2298
2/2
✓ Branch 1 taken 118 times.
✓ Branch 2 taken 72 times.
190 if (mkv_check_tag_name(t->key, elementid)) {
2299 118 ret = mkv_write_simpletag(tmp_bc, t);
2300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (ret < 0)
2301 goto end;
2302 118 tag_written = 1;
2303 }
2304 }
2305
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 54 times.
123 if (reserved_size)
2306 69 put_ebml_void(tmp_bc, reserved_size);
2307
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 11 times.
54 else if (!tag_written)
2308 43 goto end;
2309
2310 80 size = avio_get_dyn_buf(tmp_bc, &buf);
2311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (tmp_bc->error) {
2312 ret = tmp_bc->error;
2313 goto end;
2314 }
2315
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 39 times.
80 if (!*pb) {
2316 41 ret = start_ebml_master_crc32(pb, mkv);
2317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
2318 goto end;
2319 }
2320 80 put_ebml_binary(*pb, MATROSKA_ID_TAG, buf, size);
2321
2322 123 end:
2323 123 ffio_reset_dyn_buf(tmp_bc);
2324 123 return ret;
2325 }
2326
2327 45 static int mkv_write_tags(AVFormatContext *s)
2328 {
2329 45 MatroskaMuxContext *mkv = s->priv_data;
2330
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 3 times.
45 int i, ret, seekable = IS_SEEKABLE(s->pb, mkv);
2331
2332 45 mkv->wrote_tags = 1;
2333
2334 45 ff_metadata_conv_ctx(s, ff_mkv_metadata_conv, NULL);
2335
2336 45 ret = mkv_write_tag(mkv, s->metadata, &mkv->tags.bc, 0, 0, 0);
2337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
2338 return ret;
2339
2340
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 45 times.
123 for (i = 0; i < s->nb_streams; i++) {
2341 78 const AVStream *st = s->streams[i];
2342 78 mkv_track *track = &mkv->tracks[i];
2343
2344
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 77 times.
78 if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT)
2345 1 continue;
2346
2347
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 8 times.
77 ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc,
2348 seekable ? DURATION_SIMPLETAG_SIZE : 0,
2349 MATROSKA_ID_TAGTARGETS_TRACKUID, track->uid);
2350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (ret < 0)
2351 return ret;
2352
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 8 times.
77 if (seekable)
2353 69 track->duration_offset = avio_tell(mkv->tags.bc) - DURATION_SIMPLETAG_SIZE;
2354 }
2355
2356
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
45 if (mkv->nb_attachments && !IS_WEBM(mkv)) {
2357
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (i = 0; i < s->nb_streams; i++) {
2358 3 const mkv_track *track = &mkv->tracks[i];
2359 3 const AVStream *st = s->streams[i];
2360
2361
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT)
2362 2 continue;
2363
2364 1 ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc, 0,
2365 1 MATROSKA_ID_TAGTARGETS_ATTACHUID, track->uid);
2366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2367 return ret;
2368 }
2369 }
2370
2371
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 4 times.
45 if (mkv->tags.bc) {
2372 41 return end_ebml_master_crc32_tentatively(s->pb, &mkv->tags, mkv,
2373 MATROSKA_ID_TAGS);
2374 }
2375 4 return 0;
2376 }
2377
2378 1 static int mkv_new_chapter_ids_needed(const AVFormatContext *s)
2379 {
2380
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (unsigned i = 0; i < s->nb_chapters; i++) {
2381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!s->chapters[i]->id)
2382 return 1;
2383
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 for (unsigned j = 0; j < i; j++)
2384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (s->chapters[j]->id == s->chapters[i]->id)
2385 return 1;
2386 }
2387 1 return 0;
2388 }
2389
2390 90 static int mkv_write_chapters(AVFormatContext *s)
2391 {
2392 90 MatroskaMuxContext *mkv = s->priv_data;
2393 90 AVIOContext *dyn_cp = NULL, *dyn_tags = NULL, **tags, *pb = s->pb;
2394 ebml_master editionentry;
2395 90 AVRational scale = {1, 1E9};
2396 int ret, create_new_ids;
2397
2398
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
90 if (!s->nb_chapters || mkv->wrote_chapters)
2399 89 return 0;
2400
2401 1 ret = start_ebml_master_crc32(&dyn_cp, mkv);
2402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2403 return ret;
2404
2405 1 editionentry = start_ebml_master(dyn_cp, MATROSKA_ID_EDITIONENTRY, 0);
2406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!IS_WEBM(mkv)) {
2407 put_ebml_uint(dyn_cp, MATROSKA_ID_EDITIONFLAGDEFAULT, 1);
2408 /* If mkv_write_tags() has already been called, then any tags
2409 * corresponding to chapters will be put into a new Tags element. */
2410 tags = mkv->wrote_tags ? &dyn_tags : &mkv->tags.bc;
2411 } else
2412 1 tags = NULL;
2413
2414 1 create_new_ids = mkv_new_chapter_ids_needed(s);
2415
2416
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (unsigned i = 0; i < s->nb_chapters; i++) {
2417 4 AVChapter *const c = s->chapters[i];
2418 4 int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale);
2419 4 int64_t chapterend = av_rescale_q(c->end, c->time_base, scale);
2420 const AVDictionaryEntry *t;
2421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 uint64_t uid = create_new_ids ? i + 1ULL : c->id;
2422 4 EBML_WRITER(7);
2423
2424
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) {
2425 av_log(s, AV_LOG_ERROR,
2426 "Invalid chapter start (%"PRId64") or end (%"PRId64").\n",
2427 chapterstart, chapterend);
2428 ret = AVERROR_INVALIDDATA;
2429 goto fail;
2430 }
2431
2432 4 ebml_writer_open_master(&writer, MATROSKA_ID_CHAPTERATOM);
2433 4 ebml_writer_add_uint(&writer, MATROSKA_ID_CHAPTERUID, uid);
2434 4 ebml_writer_add_uint(&writer, MATROSKA_ID_CHAPTERTIMESTART, chapterstart);
2435 4 ebml_writer_add_uint(&writer, MATROSKA_ID_CHAPTERTIMEEND, chapterend);
2436
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
2437 4 ebml_writer_open_master(&writer, MATROSKA_ID_CHAPTERDISPLAY);
2438 4 ebml_writer_add_string(&writer, MATROSKA_ID_CHAPSTRING, t->value);
2439 4 ebml_writer_add_string(&writer, MATROSKA_ID_CHAPLANG , "und");
2440 }
2441 4 ret = ebml_writer_write(&writer, dyn_cp);
2442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
2443 goto fail;
2444
2445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (tags) {
2446 ff_metadata_conv(&c->metadata, ff_mkv_metadata_conv, NULL);
2447
2448 ret = mkv_write_tag(mkv, c->metadata, tags, 0,
2449 MATROSKA_ID_TAGTARGETS_CHAPTERUID, uid);
2450 if (ret < 0)
2451 goto fail;
2452 }
2453 }
2454 1 end_ebml_master(dyn_cp, editionentry);
2455 1 mkv->wrote_chapters = 1;
2456
2457 1 ret = end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS, 0, 0, 1);
2458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2459 goto fail;
2460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dyn_tags)
2461 return end_ebml_master_crc32(pb, &dyn_tags, mkv,
2462 MATROSKA_ID_TAGS, 0, 0, 1);
2463 1 return 0;
2464
2465 fail:
2466 if (tags) {
2467 /* tags == &mkv->tags.bc can only happen if mkv->tags.bc was
2468 * initially NULL, so we never free older tags. */
2469 ffio_free_dyn_buf(tags);
2470 }
2471 ffio_free_dyn_buf(&dyn_cp);
2472 return ret;
2473 }
2474
2475 2 static const char *get_mimetype(const AVStream *st)
2476 {
2477 const AVDictionaryEntry *t;
2478
2479
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (t = av_dict_get(st->metadata, "mimetype", NULL, 0))
2480 2 return t->value;
2481 if (st->codecpar->codec_id != AV_CODEC_ID_NONE) {
2482 const AVCodecDescriptor *desc = avcodec_descriptor_get(st->codecpar->codec_id);
2483 if (desc && desc->mime_types) {
2484 return desc->mime_types[0];
2485 } else if (st->codecpar->codec_id == AV_CODEC_ID_TEXT)
2486 return "text/plain";
2487 }
2488
2489 return NULL;
2490 }
2491
2492 41 static int mkv_write_attachments(AVFormatContext *s)
2493 {
2494 41 MatroskaMuxContext *mkv = s->priv_data;
2495 41 AVIOContext *dyn_cp = NULL, *pb = s->pb;
2496 int i, ret;
2497
2498
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 1 times.
41 if (!mkv->nb_attachments)
2499 40 return 0;
2500
2501 1 ret = start_ebml_master_crc32(&dyn_cp, mkv);
2502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2503 return ret;
2504
2505
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (i = 0; i < s->nb_streams; i++) {
2506 3 const AVStream *st = s->streams[i];
2507 3 mkv_track *track = &mkv->tracks[i];
2508 3 EBML_WRITER(6);
2509 const AVDictionaryEntry *t;
2510 const char *mimetype;
2511
2512
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT)
2513 2 continue;
2514
2515 1 ebml_writer_open_master(&writer, MATROSKA_ID_ATTACHEDFILE);
2516
2517
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (t = av_dict_get(st->metadata, "title", NULL, 0))
2518 ebml_writer_add_string(&writer, MATROSKA_ID_FILEDESC, t->value);
2519
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!(t = av_dict_get(st->metadata, "filename", NULL, 0))) {
2520 av_log(s, AV_LOG_ERROR, "Attachment stream %d has no filename tag.\n", i);
2521 ffio_free_dyn_buf(&dyn_cp);
2522 return AVERROR(EINVAL);
2523 }
2524 1 ebml_writer_add_string(&writer, MATROSKA_ID_FILENAME, t->value);
2525
2526 1 mimetype = get_mimetype(st);
2527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(mimetype);
2528 1 ebml_writer_add_string(&writer, MATROSKA_ID_FILEMIMETYPE, mimetype);
2529 1 ebml_writer_add_bin(&writer, MATROSKA_ID_FILEDATA,
2530 1 st->codecpar->extradata, st->codecpar->extradata_size);
2531 1 ebml_writer_add_uid(&writer, MATROSKA_ID_FILEUID, track->uid);
2532 1 ret = ebml_writer_write(&writer, dyn_cp);
2533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
2534 ffio_free_dyn_buf(&dyn_cp);
2535 return ret;
2536 }
2537 }
2538 1 return end_ebml_master_crc32(pb, &dyn_cp, mkv,
2539 MATROSKA_ID_ATTACHMENTS, 0, 0, 1);
2540 }
2541
2542 41 static int64_t get_metadata_duration(AVFormatContext *s)
2543 {
2544 41 const AVDictionaryEntry *duration = av_dict_get(s->metadata, "DURATION",
2545 NULL, 0);
2546 41 int64_t max = 0;
2547 int64_t us;
2548
2549
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
41 if (duration && (av_parse_time(&us, duration->value, 1) == 0) && us > 0) {
2550 av_log(s, AV_LOG_DEBUG, "get_metadata_duration found duration in context metadata: %" PRId64 "\n", us);
2551 return us;
2552 }
2553
2554
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 41 times.
115 for (unsigned i = 0; i < s->nb_streams; i++) {
2555 int64_t stream_duration_us;
2556 74 duration = av_dict_get(s->streams[i]->metadata, "DURATION", NULL, 0);
2557
2558
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 69 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
74 if (duration && (av_parse_time(&stream_duration_us, duration->value, 1) == 0))
2559 5 max = FFMAX(max, stream_duration_us);
2560 }
2561
2562 41 av_log(s, AV_LOG_DEBUG, "get_metadata_duration returned: %" PRId64 "\n", max);
2563 41 return max;
2564 }
2565
2566 45 static void ebml_write_header(AVIOContext *pb,
2567 const char *doctype, int version)
2568 {
2569 45 EBML_WRITER(8);
2570 45 ebml_writer_open_master(&writer, EBML_ID_HEADER);
2571 45 ebml_writer_add_uint (&writer, EBML_ID_EBMLVERSION, 1);
2572 45 ebml_writer_add_uint (&writer, EBML_ID_EBMLREADVERSION, 1);
2573 45 ebml_writer_add_uint (&writer, EBML_ID_EBMLMAXIDLENGTH, 4);
2574 45 ebml_writer_add_uint (&writer, EBML_ID_EBMLMAXSIZELENGTH, 8);
2575 45 ebml_writer_add_string(&writer, EBML_ID_DOCTYPE, doctype);
2576 45 ebml_writer_add_uint (&writer, EBML_ID_DOCTYPEVERSION, version);
2577 45 ebml_writer_add_uint (&writer, EBML_ID_DOCTYPEREADVERSION, 2);
2578 /* The size is bounded, so no need to check this. */
2579 45 ebml_writer_write(&writer, pb);
2580 45 }
2581
2582 45 static int mkv_write_info(AVFormatContext *s)
2583 {
2584 45 MatroskaMuxContext *mkv = s->priv_data;
2585 const AVDictionaryEntry *tag;
2586 int64_t creation_time;
2587 AVIOContext *pb;
2588 45 int ret = start_ebml_master_crc32(&mkv->info.bc, mkv);
2589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
2590 return ret;
2591 45 pb = mkv->info.bc;
2592
2593 45 put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
2594
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 38 times.
45 if ((tag = av_dict_get(s->metadata, "title", NULL, 0)))
2595 7 put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value);
2596
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 41 times.
45 if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
2597 4 put_ebml_string(pb, MATROSKA_ID_MUXINGAPP, LIBAVFORMAT_IDENT);
2598
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((tag = av_dict_get(s->metadata, "encoding_tool", NULL, 0)))
2599 put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, tag->value);
2600 else
2601 4 put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);
2602
2603
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!IS_WEBM(mkv))
2604 4 put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, mkv->segment_uid, 16);
2605 } else {
2606 41 const char *ident = "Lavf";
2607 41 put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , ident);
2608 41 put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, ident);
2609 }
2610
2611
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 44 times.
45 if (ff_parse_creation_time_metadata(s, &creation_time, 0) > 0) {
2612 // Adjust time so it's relative to 2001-01-01 and convert to nanoseconds.
2613 1 int64_t date_utc = (creation_time - 978307200000000LL) * 1000;
2614 uint8_t date_utc_buf[8];
2615 1 AV_WB64(date_utc_buf, date_utc);
2616 1 put_ebml_binary(pb, MATROSKA_ID_DATEUTC, date_utc_buf, 8);
2617 }
2618
2619 // reserve space for the duration
2620 45 mkv->duration = 0;
2621 45 mkv->duration_offset = avio_tell(pb);
2622
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 4 times.
45 if (!mkv->is_live) {
2623 41 int64_t metadata_duration = get_metadata_duration(s);
2624
2625
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 37 times.
41 if (s->duration > 0) {
2626 4 int64_t scaledDuration = av_rescale(s->duration, 1000, AV_TIME_BASE);
2627 4 put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);
2628 4 av_log(s, AV_LOG_DEBUG, "Write early duration from recording time = %" PRIu64 "\n", scaledDuration);
2629
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 33 times.
37 } else if (metadata_duration > 0) {
2630 4 int64_t scaledDuration = av_rescale(metadata_duration, 1000, AV_TIME_BASE);
2631 4 put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);
2632 4 av_log(s, AV_LOG_DEBUG, "Write early duration from metadata = %" PRIu64 "\n", scaledDuration);
2633
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 4 times.
33 } else if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
2634 29 put_ebml_void(pb, 11); // assumes double-precision float to be written
2635 }
2636 }
2637 45 return end_ebml_master_crc32_tentatively(s->pb, &mkv->info,
2638 mkv, MATROSKA_ID_INFO);
2639 }
2640
2641 45 static int mkv_write_header(AVFormatContext *s)
2642 {
2643 45 MatroskaMuxContext *mkv = s->priv_data;
2644 45 AVIOContext *pb = s->pb;
2645 45 int ret, version = 2;
2646
2647 45 ret = avio_open_dyn_buf(&mkv->tmp_bc);
2648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
2649 return ret;
2650
2651
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
49 if (!IS_WEBM(mkv) ||
2652
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
8 av_dict_get(s->metadata, "stereo_mode", NULL, 0) ||
2653 4 av_dict_get(s->metadata, "alpha_mode", NULL, 0))
2654 41 version = 4;
2655
2656
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 45 times.
123 for (unsigned i = 0; i < s->nb_streams; i++) {
2657
4/4
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 6 times.
154 if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_OPUS ||
2658
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 69 times.
146 av_dict_get(s->streams[i]->metadata, "stereo_mode", NULL, 0) ||
2659 70 av_dict_get(s->streams[i]->metadata, "alpha_mode", NULL, 0))
2660 9 version = 4;
2661 }
2662
2663 45 ebml_write_header(pb, s->oformat->name, version);
2664 45 put_ebml_id(pb, MATROSKA_ID_SEGMENT);
2665 45 put_ebml_size_unknown(pb, 8);
2666 45 mkv->segment_offset = avio_tell(pb);
2667
2668 // We write a SeekHead at the beginning to point to all other level
2669 // one elements (except Clusters).
2670 45 mkv_start_seekhead(mkv, pb);
2671
2672 45 ret = mkv_write_info(s);
2673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
2674 return ret;
2675
2676 45 ret = mkv_write_tracks(s);
2677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
2678 return ret;
2679
2680 45 ret = mkv_write_chapters(s);
2681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
2682 return ret;
2683
2684
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 4 times.
45 if (!IS_WEBM(mkv)) {
2685 41 ret = mkv_write_attachments(s);
2686
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
2687 return ret;
2688 }
2689
2690 /* Must come after mkv_write_chapters() to write chapter tags
2691 * into the same Tags element as the other tags. */
2692 45 ret = mkv_write_tags(s);
2693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
2694 return ret;
2695
2696
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 37 times.
45 if (!IS_SEEKABLE(pb, mkv)) {
2697 8 ret = mkv_write_seekhead(pb, mkv, 0, avio_tell(pb));
2698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
2699 return ret;
2700 }
2701
2702
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 42 times.
45 if (s->metadata_header_padding > 0) {
2703
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->metadata_header_padding == 1)
2704 1 s->metadata_header_padding++;
2705 3 put_ebml_void(pb, s->metadata_header_padding);
2706 }
2707
2708
4/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 40 times.
45 if (mkv->reserve_cues_space || mkv->move_cues_to_front) {
2709
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)) {
2710 5 mkv->cues_pos = avio_tell(pb);
2711
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (mkv->reserve_cues_space >= 1) {
2712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (mkv->reserve_cues_space == 1)
2713 mkv->reserve_cues_space++;
2714 4 put_ebml_void(pb, mkv->reserve_cues_space);
2715 }
2716 } else
2717 mkv->reserve_cues_space = -1;
2718 }
2719
2720 45 mkv->cluster_pos = -1;
2721
2722 // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or
2723 // after 4k and on a keyframe
2724
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 3 times.
45 if (IS_SEEKABLE(pb, mkv)) {
2725
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 2 times.
37 if (mkv->cluster_time_limit < 0)
2726 35 mkv->cluster_time_limit = 5000;
2727
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 1 times.
37 if (mkv->cluster_size_limit < 0)
2728 36 mkv->cluster_size_limit = 5 * 1024 * 1024;
2729 } else {
2730
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (mkv->cluster_time_limit < 0)
2731 8 mkv->cluster_time_limit = 1000;
2732
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (mkv->cluster_size_limit < 0)
2733 8 mkv->cluster_size_limit = 32 * 1024;
2734 }
2735
2736 45 return 0;
2737 }
2738
2739 #if CONFIG_MATROSKA_MUXER
2740 178 static int mkv_reformat_h2645(MatroskaMuxContext *mkv, AVIOContext *pb,
2741 const AVPacket *pkt, int *size)
2742 {
2743 int ret;
2744
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 89 times.
178 if (pb) {
2745 89 ff_nal_units_write_list(&mkv->cur_block.h2645_nalu_list, pb, pkt->data);
2746 } else {
2747 89 ret = ff_nal_units_create_list(&mkv->cur_block.h2645_nalu_list, pkt->data, pkt->size);
2748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 if (ret < 0)
2749 return ret;
2750 89 *size = ret;
2751 }
2752 178 return 0;
2753 }
2754
2755 76 static int mkv_reformat_wavpack(MatroskaMuxContext *mkv, AVIOContext *pb,
2756 const AVPacket *pkt, int *size)
2757 {
2758 76 const uint8_t *src = pkt->data;
2759 76 int srclen = pkt->size;
2760 76 int offset = 0;
2761 int ret;
2762
2763
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 76 times.
264 while (srclen >= WV_HEADER_SIZE) {
2764 WvHeader header;
2765
2766 188 ret = ff_wv_parse_header(&header, src);
2767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
188 if (ret < 0)
2768 return ret;
2769 188 src += WV_HEADER_SIZE;
2770 188 srclen -= WV_HEADER_SIZE;
2771
2772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
188 if (srclen < header.blocksize)
2773 return AVERROR_INVALIDDATA;
2774
2775
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);
2776
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 94 times.
188 if (pb) {
2777
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 56 times.
94 if (header.initial)
2778 38 avio_wl32(pb, header.samples);
2779 94 avio_wl32(pb, header.flags);
2780 94 avio_wl32(pb, header.crc);
2781
2782
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))
2783 70 avio_wl32(pb, header.blocksize);
2784
2785 94 avio_write(pb, src, header.blocksize);
2786 }
2787 188 src += header.blocksize;
2788 188 srclen -= header.blocksize;
2789 188 offset += header.blocksize;
2790 }
2791 76 *size = offset;
2792
2793 76 return 0;
2794 }
2795 #endif
2796
2797 56 static int mkv_reformat_av1(MatroskaMuxContext *mkv, AVIOContext *pb,
2798 const AVPacket *pkt, int *size)
2799 {
2800 56 int ret = ff_av1_filter_obus(pb, pkt->data, pkt->size);
2801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (ret < 0)
2802 return ret;
2803 56 *size = ret;
2804 56 return 0;
2805 }
2806
2807 120 static int webm_reformat_vtt(MatroskaMuxContext *mkv, AVIOContext *pb,
2808 const AVPacket *pkt, int *size)
2809 {
2810 const uint8_t *id, *settings;
2811 size_t id_size, settings_size;
2812 120 unsigned total = pkt->size + 2U;
2813
2814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
120 if (total > INT_MAX)
2815 return AVERROR(ERANGE);
2816
2817 120 id = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_IDENTIFIER,
2818 &id_size);
2819 120 settings = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_SETTINGS,
2820 &settings_size);
2821
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))
2822 return AVERROR(ERANGE);
2823 120 *size = total += settings_size;
2824
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 60 times.
120 if (pb) {
2825 60 avio_write(pb, id, id_size);
2826 60 avio_w8(pb, '\n');
2827 60 avio_write(pb, settings, settings_size);
2828 60 avio_w8(pb, '\n');
2829 60 avio_write(pb, pkt->data, pkt->size);
2830 }
2831 120 return 0;
2832 }
2833
2834 122 static void mkv_write_blockadditional(EbmlWriter *writer, const uint8_t *buf,
2835 size_t size, uint64_t additional_id)
2836 {
2837 122 ebml_writer_open_master(writer, MATROSKA_ID_BLOCKMORE);
2838 122 ebml_writer_add_uint(writer, MATROSKA_ID_BLOCKADDID, additional_id);
2839 122 ebml_writer_add_bin (writer, MATROSKA_ID_BLOCKADDITIONAL, buf, size);
2840 122 ebml_writer_close_master(writer);
2841 122 }
2842
2843 6797 static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv,
2844 AVIOContext *pb, const AVStream *st,
2845 mkv_track *track, const AVPacket *pkt,
2846 int keyframe, int64_t ts, uint64_t duration,
2847 int force_blockgroup, int64_t relative_packet_pos)
2848 {
2849 6797 const AVCodecParameters *par = st->codecpar;
2850 uint8_t t35_buf[6 + AV_HDR_PLUS_MAX_PAYLOAD_SIZE];
2851 #define SMPTE_2094_APP5_MAX_SIZE 855
2852 uint8_t smpte_2094_app5_buf[5 + SMPTE_2094_APP5_MAX_SIZE];
2853 uint8_t *side_data;
2854 size_t side_data_size;
2855 uint64_t additional_id;
2856 6797 unsigned track_number = track->track_num;
2857 // BlockGroup, Block, BlockDuration, DiscardPadding, BlockReference
2858 // and BlockAdditions with three elements per BlockMore
2859 // Don't forget to increment the number of BlockMore when adding
2860 // support for writing a new blockadditional.
2861 6797 EBML_WRITER(5 + (1 + 3 * 3));
2862 int ret;
2863
2864 6797 mkv->cur_block.track = track;
2865 6797 mkv->cur_block.pkt = pkt;
2866 6797 mkv->cur_block.rel_ts = ts - mkv->cluster_pts;
2867 6797 mkv->cur_block.flags = 0;
2868
2869 /* Open a BlockGroup with a Block now; it will later be converted
2870 * to a SimpleBlock if possible. */
2871 6797 ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKGROUP);
2872 6797 ebml_writer_add_block(&writer, mkv);
2873
2874
4/4
✓ Branch 0 taken 6212 times.
✓ Branch 1 taken 585 times.
✓ Branch 2 taken 6121 times.
✓ Branch 3 taken 91 times.
6797 if (duration > 0 && (par->codec_type == AVMEDIA_TYPE_SUBTITLE ||
2875 /* If the packet's duration is inconsistent with the default duration,
2876 * add an explicit duration element. */
2877
2/2
✓ Branch 0 taken 3823 times.
✓ Branch 1 taken 2298 times.
6121 track->default_duration_high > 0 &&
2878
2/2
✓ Branch 0 taken 917 times.
✓ Branch 1 taken 2906 times.
3823 duration != track->default_duration_high &&
2879
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 832 times.
917 duration != track->default_duration_low))
2880 176 ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKDURATION, duration);
2881
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 6528 times.
6621 else if (par->codec_id == AV_CODEC_ID_OPUS) {
2882 93 ret = parse_opus_packet_duration(pkt->data, pkt->size);
2883
1/2
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
93 if (ret >= 0) {
2884 /* If the packet's duration is inconsistent with the coded duration,
2885 * add an explicit duration element. */
2886 93 uint64_t parsed_duration = av_rescale_q(ret, (AVRational){1, 48000},
2887 st->time_base);
2888
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 92 times.
93 if (parsed_duration != duration)
2889 1 ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKDURATION, duration);
2890 }
2891 }
2892
2893 6797 av_log(logctx, AV_LOG_DEBUG,
2894 "Writing block of size %d with pts %" PRId64 ", dts %" PRId64 ", "
2895 "duration %" PRId64 " at relative offset %" PRId64 " in cluster "
2896 "at offset %" PRId64 ". TrackNumber %u, keyframe %d\n",
2897 6797 pkt->size, pkt->pts, pkt->dts, pkt->duration, relative_packet_pos,
2898 mkv->cluster_pos, track_number, keyframe != 0);
2899
2900 6797 side_data = av_packet_get_side_data(pkt,
2901 AV_PKT_DATA_SKIP_SAMPLES,
2902 &side_data_size);
2903
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6790 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
6797 if (side_data && side_data_size >= 10) {
2904 7 int64_t discard_padding = AV_RL32(side_data + 4);
2905
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (discard_padding) {
2906 3 discard_padding = av_rescale_q(discard_padding,
2907 3 (AVRational){1, par->sample_rate},
2908 3 (AVRational){1, 1000000000});
2909 3 ebml_writer_add_sint(&writer, MATROSKA_ID_DISCARDPADDING, discard_padding);
2910 }
2911 }
2912
2913 6797 ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKADDITIONS);
2914 6797 side_data = av_packet_get_side_data(pkt,
2915 AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
2916 &side_data_size);
2917
3/4
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 6677 times.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
6797 if (side_data && side_data_size >= 8 &&
2918 // Only the Codec-specific BlockMore (id == 1) is currently supported.
2919
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 (additional_id = AV_RB64(side_data)) == MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE) {
2920 120 mkv_write_blockadditional(&writer, side_data + 8, side_data_size - 8,
2921 additional_id);
2922 120 track->max_blockaddid = FFMAX(track->max_blockaddid, additional_id);
2923 }
2924
2925
2/2
✓ Branch 0 taken 2229 times.
✓ Branch 1 taken 4568 times.
6797 if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
2926 2229 side_data = av_packet_get_side_data(pkt,
2927 AV_PKT_DATA_DYNAMIC_HDR10_PLUS,
2928 NULL);
2929
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2227 times.
2229 if (side_data) {
2930 2 uint8_t *payload = t35_buf;
2931 2 size_t payload_size = sizeof(t35_buf) - 6;
2932
2933 2 bytestream_put_byte(&payload, ITU_T_T35_COUNTRY_CODE_US);
2934 2 bytestream_put_be16(&payload, ITU_T_T35_PROVIDER_CODE_SAMSUNG);
2935 2 bytestream_put_be16(&payload, 0x01); // provider_oriented_code
2936 2 bytestream_put_byte(&payload, 0x04); // application_identifier
2937
2938 2 ret = av_dynamic_hdr_plus_to_t35((AVDynamicHDRPlus *)side_data, &payload,
2939 &payload_size);
2940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
2941 return ret;
2942
2943 2 mkv_write_blockadditional(&writer, t35_buf, payload_size + 6,
2944 MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
2945 2 track->max_blockaddid = FFMAX(track->max_blockaddid,
2946 MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
2947 }
2948 2229 side_data = av_packet_get_side_data(pkt,
2949 AV_PKT_DATA_DYNAMIC_HDR_SMPTE_2094_APP5,
2950 NULL);
2951
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2229 times.
2229 if (side_data) {
2952 uint8_t *payload = smpte_2094_app5_buf;
2953 size_t payload_size = sizeof(smpte_2094_app5_buf) - 5;
2954
2955 bytestream_put_byte(&payload, ITU_T_T35_COUNTRY_CODE_US);
2956 bytestream_put_be16(&payload, ITU_T_T35_PROVIDER_CODE_SMPTE);
2957 bytestream_put_be16(&payload, 0x01); // provider_oriented_code
2958
2959 ret = av_dynamic_hdr_smpte2094_app5_to_t35((AVDynamicHDRSmpte2094App5 *)side_data,
2960 &payload, &payload_size);
2961 if (ret < 0)
2962 return ret;
2963
2964 mkv_write_blockadditional(&writer, t35_buf, payload_size + 5,
2965 MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
2966 track->max_blockaddid = FFMAX(track->max_blockaddid,
2967 MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
2968 }
2969 }
2970
2971 6797 ebml_writer_close_or_discard_master(&writer);
2972
2973
4/4
✓ Branch 0 taken 6737 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 6496 times.
✓ Branch 3 taken 241 times.
6797 if (!force_blockgroup && writer.nb_elements == 2) {
2974 /* Nothing except the BlockGroup + Block. Can use a SimpleBlock. */
2975 6496 writer.elements++; // Skip the BlockGroup.
2976 6496 writer.nb_elements--;
2977 av_assert2(writer.elements[0].id == MATROSKA_ID_BLOCK);
2978 6496 writer.elements[0].id = MATROSKA_ID_SIMPLEBLOCK;
2979
2/2
✓ Branch 0 taken 5211 times.
✓ Branch 1 taken 1285 times.
6496 if (keyframe)
2980 5211 mkv->cur_block.flags |= 1 << 7;
2981
2/2
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 104 times.
301 } else if (!keyframe)
2982 197 ebml_writer_add_sint(&writer, MATROSKA_ID_BLOCKREFERENCE,
2983 197 track->last_timestamp - ts);
2984
2985 6797 return ebml_writer_write(&writer, pb);
2986 }
2987
2988 537 static int mkv_end_cluster(AVFormatContext *s)
2989 {
2990 537 MatroskaMuxContext *mkv = s->priv_data;
2991 int ret;
2992
2993
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 235 times.
537 if (!mkv->have_video) {
2994
2/2
✓ Branch 0 taken 557 times.
✓ Branch 1 taken 302 times.
859 for (unsigned i = 0; i < s->nb_streams; i++)
2995 557 mkv->tracks[i].has_cue = 0;
2996 }
2997 537 mkv->cluster_pos = -1;
2998 537 ret = end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv,
2999 MATROSKA_ID_CLUSTER, 0, 1, 0);
3000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 537 times.
537 if (ret < 0)
3001 return ret;
3002
3003 537 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
3004 537 return 0;
3005 }
3006
3007 6800 static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt)
3008 {
3009 6800 MatroskaMuxContext *mkv = s->priv_data;
3010 6800 mkv_track *track = &mkv->tracks[pkt->stream_index];
3011 6800 AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
3012 uint8_t *side_data;
3013 size_t side_data_size;
3014 int ret;
3015
3016 6800 side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
3017 &side_data_size);
3018
3019
4/4
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 6499 times.
6800 switch (par->codec_id) {
3020 #if CONFIG_MATROSKA_MUXER
3021 246 case AV_CODEC_ID_AAC:
3022
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) {
3023 1 int output_sample_rate = 0;
3024 1 ret = get_aac_sample_rates(s, mkv, side_data, side_data_size,
3025 &track->sample_rate, &output_sample_rate);
3026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
3027 return ret;
3028
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!output_sample_rate)
3029 1 output_sample_rate = track->sample_rate; // Space is already reserved, so it's this or a void element.
3030 1 ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size,
3031 par, mkv->track.bc, track, 0);
3032
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
3033 return ret;
3034 1 avio_seek(mkv->track.bc, track->sample_rate_offset, SEEK_SET);
3035 1 put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate);
3036 1 put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
3037
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) {
3038 // No extradata (codecpar or packet side data).
3039 av_log(s, AV_LOG_ERROR, "Error parsing AAC extradata, unable to determine samplerate.\n");
3040 return AVERROR(EINVAL);
3041 }
3042 246 break;
3043 27 case AV_CODEC_ID_FLAC:
3044
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) {
3045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (side_data_size != par->extradata_size) {
3046 av_log(s, AV_LOG_ERROR, "Invalid FLAC STREAMINFO metadata for output stream %d\n",
3047 pkt->stream_index);
3048 return AVERROR(EINVAL);
3049 }
3050 3 ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size,
3051 par, mkv->track.bc, track, 0);
3052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
3053 return ret;
3054 }
3055 27 break;
3056 #endif
3057 // FIXME: Remove the following once libaom starts propagating proper extradata during init()
3058 // See https://bugs.chromium.org/p/aomedia/issues/detail?id=2208
3059 28 case AV_CODEC_ID_AV1:
3060
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
28 if (side_data_size && mkv->track.bc && !par->extradata_size) {
3061 // If the reserved space doesn't suffice, only write
3062 // the first four bytes of the av1C.
3063 1 ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size,
3064 par, mkv->track.bc, track, 4);
3065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
3066 return ret;
3067
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 } else if (!par->extradata_size)
3068 return AVERROR_INVALIDDATA;
3069 28 break;
3070 6499 default:
3071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6499 times.
6499 if (side_data_size)
3072 av_log(s, AV_LOG_DEBUG, "Ignoring new extradata in a packet for stream %d.\n", pkt->stream_index);
3073 6499 break;
3074 }
3075
3076 6800 return 0;
3077 }
3078
3079 6797 static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt)
3080 {
3081 6797 MatroskaMuxContext *mkv = s->priv_data;
3082 AVIOContext *pb;
3083 6797 AVStream *st = s->streams[pkt->stream_index];
3084 6797 AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
3085 6797 mkv_track *track = &mkv->tracks[pkt->stream_index];
3086 6797 int is_sub = par->codec_type == AVMEDIA_TYPE_SUBTITLE;
3087 /* All subtitle blocks are considered to be keyframes. */
3088
4/4
✓ Branch 0 taken 6635 times.
✓ Branch 1 taken 162 times.
✓ Branch 2 taken 5153 times.
✓ Branch 3 taken 1482 times.
6797 int keyframe = is_sub || !!(pkt->flags & AV_PKT_FLAG_KEY);
3089 6797 int64_t duration = FFMAX(pkt->duration, 0);
3090
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 6635 times.
6797 int64_t cue_duration = is_sub ? duration : 0;
3091 int ret;
3092
2/2
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 6148 times.
6797 int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
3093 int64_t relative_packet_pos;
3094
3095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6797 times.
6797 if (ts == AV_NOPTS_VALUE) {
3096 av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n");
3097 return AVERROR(EINVAL);
3098 }
3099 6797 ts += track->ts_offset;
3100
3101
2/2
✓ Branch 0 taken 6215 times.
✓ Branch 1 taken 582 times.
6797 if (mkv->cluster_pos != -1) {
3102 6215 int64_t cluster_time = ts - mkv->cluster_pts;
3103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6215 times.
6215 if ((int16_t)cluster_time != cluster_time) {
3104 ret = mkv_end_cluster(s);
3105 if (ret < 0)
3106 return ret;
3107 av_log(s, AV_LOG_WARNING, "Starting new cluster due to timestamp\n");
3108 }
3109 }
3110
3111
2/2
✓ Branch 0 taken 582 times.
✓ Branch 1 taken 6215 times.
6797 if (mkv->cluster_pos == -1) {
3112 582 ret = start_ebml_master_crc32(&mkv->cluster_bc, mkv);
3113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 582 times.
582 if (ret < 0)
3114 return ret;
3115 582 mkv->cluster_bc->direct = 1;
3116 582 mkv->cluster_pos = avio_tell(s->pb);
3117 582 put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts));
3118 582 mkv->cluster_pts = FFMAX(0, ts);
3119 582 av_log(s, AV_LOG_DEBUG,
3120 "Starting new cluster with timestamp "
3121 "%" PRId64 " at offset %" PRId64 " bytes\n",
3122 mkv->cluster_pts, mkv->cluster_pos);
3123 }
3124 6797 pb = mkv->cluster_bc;
3125
3126 6797 relative_packet_pos = avio_tell(pb);
3127
3128 /* The WebM spec requires WebVTT to be muxed in BlockGroups;
3129 * so we force it even for packets without duration. */
3130 6797 ret = mkv_write_block(s, mkv, pb, st, track, pkt,
3131 keyframe, ts, duration,
3132 6797 par->codec_id == AV_CODEC_ID_WEBVTT,
3133 relative_packet_pos);
3134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6797 times.
6797 if (ret < 0)
3135 return ret;
3136
6/6
✓ Branch 0 taken 5315 times.
✓ Branch 1 taken 1482 times.
✓ Branch 2 taken 5234 times.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 5200 times.
✓ Branch 5 taken 34 times.
6797 if (keyframe && IS_SEEKABLE(s->pb, mkv) &&
3137
2/2
✓ Branch 0 taken 4454 times.
✓ Branch 1 taken 746 times.
5200 (par->codec_type == AVMEDIA_TYPE_VIDEO ||
3138
2/2
✓ Branch 0 taken 4300 times.
✓ Branch 1 taken 154 times.
4454 par->codec_type == AVMEDIA_TYPE_SUBTITLE ||
3139
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)) {
3140 1165 ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts,
3141 mkv->cluster_pos, relative_packet_pos,
3142 cue_duration);
3143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1165 times.
1165 if (ret < 0)
3144 return ret;
3145 1165 track->has_cue = 1;
3146 }
3147
3148 6797 track->last_timestamp = ts;
3149 6797 mkv->duration = FFMAX(mkv->duration, ts + duration);
3150 6797 track->duration = FFMAX(track->duration, ts + duration);
3151
3152 6797 return 0;
3153 }
3154
3155 6800 static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt)
3156 {
3157 6800 MatroskaMuxContext *mkv = s->priv_data;
3158 6800 int codec_type = s->streams[pkt->stream_index]->codecpar->codec_type;
3159 6800 int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY);
3160 int cluster_size;
3161 int64_t cluster_time;
3162 int ret;
3163 int start_new_cluster;
3164
3165 6800 ret = mkv_check_new_extra_data(s, pkt);
3166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6800 times.
6800 if (ret < 0)
3167 return ret;
3168
3169
2/2
✓ Branch 0 taken 6734 times.
✓ Branch 1 taken 66 times.
6800 if (mkv->cluster_pos != -1) {
3170
2/2
✓ Branch 0 taken 646 times.
✓ Branch 1 taken 6088 times.
6734 if (mkv->tracks[pkt->stream_index].write_dts)
3171 646 cluster_time = pkt->dts - mkv->cluster_pts;
3172 else
3173 6088 cluster_time = pkt->pts - mkv->cluster_pts;
3174 6734 cluster_time += mkv->tracks[pkt->stream_index].ts_offset;
3175
3176 6734 cluster_size = avio_tell(mkv->cluster_bc);
3177
3178
3/4
✓ Branch 0 taken 730 times.
✓ Branch 1 taken 6004 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 730 times.
6734 if (mkv->is_dash && codec_type == AVMEDIA_TYPE_VIDEO) {
3179 // WebM DASH specification states that the first block of
3180 // every Cluster has to be a key frame. So for DASH video,
3181 // we only create a Cluster on seeing key frames.
3182 start_new_cluster = keyframe;
3183
4/4
✓ Branch 0 taken 730 times.
✓ Branch 1 taken 6004 times.
✓ Branch 2 taken 729 times.
✓ Branch 3 taken 1 times.
6734 } else if (mkv->is_dash && codec_type == AVMEDIA_TYPE_AUDIO &&
3184
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 716 times.
729 cluster_time > mkv->cluster_time_limit) {
3185 // For DASH audio, we create a Cluster based on cluster_time_limit.
3186 13 start_new_cluster = 1;
3187
2/2
✓ Branch 0 taken 6004 times.
✓ Branch 1 taken 717 times.
6721 } else if (!mkv->is_dash &&
3188
2/2
✓ Branch 0 taken 5972 times.
✓ Branch 1 taken 32 times.
6004 (cluster_size > mkv->cluster_size_limit ||
3189
4/4
✓ Branch 0 taken 5660 times.
✓ Branch 1 taken 312 times.
✓ Branch 2 taken 2149 times.
✓ Branch 3 taken 3511 times.
5972 cluster_time > mkv->cluster_time_limit ||
3190
4/4
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 1478 times.
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 497 times.
2149 (codec_type == AVMEDIA_TYPE_VIDEO && keyframe &&
3191 cluster_size > 4 * 1024))) {
3192 518 start_new_cluster = 1;
3193 } else
3194 6203 start_new_cluster = 0;
3195
3196
2/2
✓ Branch 0 taken 531 times.
✓ Branch 1 taken 6203 times.
6734 if (start_new_cluster) {
3197 531 ret = mkv_end_cluster(s);
3198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 531 times.
531 if (ret < 0)
3199 return ret;
3200 }
3201 }
3202
3203
2/2
✓ Branch 0 taken 597 times.
✓ Branch 1 taken 6203 times.
6800 if (mkv->cluster_pos == -1)
3204
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 4 times.
1190 avio_write_marker(s->pb,
3205 597 av_rescale_q(pkt->dts, s->streams[pkt->stream_index]->time_base, AV_TIME_BASE_Q),
3206
4/4
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 335 times.
✓ Branch 2 taken 250 times.
✓ Branch 3 taken 8 times.
593 keyframe && (mkv->have_video ? codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
3207
3208 // check if we have an audio packet cached
3209
2/2
✓ Branch 0 taken 4385 times.
✓ Branch 1 taken 2415 times.
6800 if (mkv->cur_audio_pkt->size > 0) {
3210 4385 ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt);
3211 4385 av_packet_unref(mkv->cur_audio_pkt);
3212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4385 times.
4385 if (ret < 0) {
3213 av_log(s, AV_LOG_ERROR,
3214 "Could not write cached audio packet ret:%d\n", ret);
3215 return ret;
3216 }
3217 }
3218
3219 // buffer an audio packet to ensure the packet containing the video
3220 // keyframe's timecode is contained in the same cluster for WebM
3221
2/2
✓ Branch 0 taken 4409 times.
✓ Branch 1 taken 2391 times.
6800 if (codec_type == AVMEDIA_TYPE_AUDIO) {
3222
2/2
✓ Branch 0 taken 4406 times.
✓ Branch 1 taken 3 times.
4409 if (pkt->size > 0)
3223 4406 ret = av_packet_ref(mkv->cur_audio_pkt, pkt);
3224 } else
3225 2391 ret = mkv_write_packet_internal(s, pkt);
3226 6800 return ret;
3227 }
3228
3229 6807 static int mkv_write_flush_packet(AVFormatContext *s, AVPacket *pkt)
3230 {
3231 6807 MatroskaMuxContext *mkv = s->priv_data;
3232
3233
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6800 times.
6807 if (!pkt) {
3234
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (mkv->cluster_pos != -1) {
3235 6 int ret = mkv_end_cluster(s);
3236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
3237 return ret;
3238 6 av_log(s, AV_LOG_DEBUG,
3239 "Flushing cluster at offset %" PRIu64 " bytes\n",
3240 avio_tell(s->pb));
3241 }
3242 7 return 1;
3243 }
3244 6800 return mkv_write_packet(s, pkt);
3245 }
3246
3247 45 static int mkv_write_trailer(AVFormatContext *s)
3248 {
3249 45 MatroskaMuxContext *mkv = s->priv_data;
3250 45 AVIOContext *pb = s->pb;
3251 int64_t endpos, ret64;
3252 45 int ret, ret2 = 0;
3253
3254 // check if we have an audio packet cached
3255
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 24 times.
45 if (mkv->cur_audio_pkt->size > 0) {
3256 21 ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt);
3257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (ret < 0) {
3258 av_log(s, AV_LOG_ERROR,
3259 "Could not write cached audio packet ret:%d\n", ret);
3260 return ret;
3261 }
3262 }
3263
3264
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 if (mkv->cluster_pos != -1) {
3265 45 ret = end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv,
3266 MATROSKA_ID_CLUSTER, 0, 0, 0);
3267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
3268 return ret;
3269 }
3270
3271 45 ret = mkv_write_chapters(s);
3272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (ret < 0)
3273 return ret;
3274
3275
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 37 times.
45 if (!IS_SEEKABLE(pb, mkv))
3276 8 return 0;
3277
3278 37 endpos = avio_tell(pb);
3279
3280
2/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37 times.
37 if (mkv->cues.num_entries && mkv->reserve_cues_space >= 0) {
3281 37 AVIOContext *cues = NULL;
3282 37 uint64_t size, offset = 0;
3283 37 int length_size = 0;
3284
3285 39 redo_cues:
3286 39 ret = start_ebml_master_crc32(&cues, mkv);
3287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (ret < 0)
3288 return ret;
3289
3290 39 ret = mkv_assemble_cues(s->streams, cues, mkv->tmp_bc, &mkv->cues,
3291 39 mkv->tracks, s->nb_streams, offset);
3292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (ret < 0) {
3293 ffio_free_dyn_buf(&cues);
3294 return ret;
3295 }
3296
3297
4/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 32 times.
39 if (mkv->reserve_cues_space || mkv->move_cues_to_front) {
3298 7 size = avio_tell(cues);
3299 7 length_size = ebml_length_size(size);
3300 7 size += 4 + length_size;
3301
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 if (offset + mkv->reserve_cues_space < size) {
3302
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mkv->move_cues_to_front) {
3303 2 offset = size - mkv->reserve_cues_space;
3304 2 ffio_reset_dyn_buf(cues);
3305 2 goto redo_cues;
3306 }
3307 av_log(s, AV_LOG_WARNING,
3308 "Insufficient space reserved for Cues: "
3309 "%d < %"PRIu64". No Cues will be output.\n",
3310 mkv->reserve_cues_space, size);
3311 ret2 = AVERROR(EINVAL);
3312 goto after_cues;
3313 } else {
3314
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (offset) {
3315 2 ret = ff_format_shift_data(s, mkv->cues_pos + mkv->reserve_cues_space,
3316 offset);
3317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
3318 ffio_free_dyn_buf(&cues);
3319 return ret;
3320 }
3321 2 endpos += offset;
3322 }
3323
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if ((ret64 = avio_seek(pb, mkv->cues_pos, SEEK_SET)) < 0) {
3324 ffio_free_dyn_buf(&cues);
3325 return ret64;
3326 }
3327
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (mkv->reserve_cues_space == size + 1) {
3328 /* There is no way to reserve a single byte because
3329 * the minimal size of an EBML Void element is 2
3330 * (1 byte ID, 1 byte length field). This problem
3331 * is solved by writing the Cues' length field on
3332 * one byte more than necessary. */
3333 1 length_size++;
3334 1 size++;
3335 }
3336 }
3337 }
3338 37 ret = end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES,
3339 length_size, 0, 1);
3340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (ret < 0)
3341 return ret;
3342
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 33 times.
37 if (mkv->reserve_cues_space) {
3343
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (size < mkv->reserve_cues_space)
3344 2 put_ebml_void(pb, mkv->reserve_cues_space - size);
3345
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1 times.
33 } else if (!mkv->move_cues_to_front)
3346 32 endpos = avio_tell(pb);
3347 }
3348
3349 after_cues:
3350 /* Lengths greater than (1ULL << 56) - 1 can't be represented
3351 * via an EBML number, so leave the unknown length field. */
3352
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (endpos - mkv->segment_offset < (1ULL << 56) - 1) {
3353
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
37 if ((ret64 = avio_seek(pb, mkv->segment_offset - 8, SEEK_SET)) < 0)
3354 return ret64;
3355 37 put_ebml_length(pb, endpos - mkv->segment_offset, 8);
3356 }
3357
3358 37 ret = mkv_write_seekhead(pb, mkv, 1, mkv->info.pos);
3359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (ret < 0)
3360 return ret;
3361
3362
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (mkv->info.bc) {
3363 // update the duration
3364 37 av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration);
3365 37 avio_seek(mkv->info.bc, mkv->duration_offset, SEEK_SET);
3366 37 put_ebml_float(mkv->info.bc, MATROSKA_ID_DURATION, mkv->duration);
3367 37 ret = end_ebml_master_crc32(pb, &mkv->info.bc, mkv,
3368 MATROSKA_ID_INFO, 0, 0, 0);
3369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (ret < 0)
3370 return ret;
3371 }
3372
3373
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (mkv->track.bc) {
3374 // write Tracks master
3375
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 4 times.
37 if (!IS_WEBM(mkv)) {
3376 33 AVIOContext *track_bc = mkv->track.bc;
3377
3378
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 33 times.
96 for (unsigned i = 0; i < s->nb_streams; i++) {
3379 63 const mkv_track *track = &mkv->tracks[i];
3380
3381
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 2 times.
63 if (!track->max_blockaddid)
3382 61 continue;
3383
3384 // We reserved a single byte to write this value.
3385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 av_assert0(track->max_blockaddid <= 0xFF);
3386
3387 2 avio_seek(track_bc, track->blockadditionmapping_offset, SEEK_SET);
3388
3389 2 put_ebml_uint(track_bc, MATROSKA_ID_TRACKMAXBLKADDID,
3390 2 track->max_blockaddid);
3391
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (track->max_blockaddid == MATROSKA_BLOCK_ADD_ID_ITU_T_T35) {
3392 1 ebml_master mapping_master = start_ebml_master(track_bc, MATROSKA_ID_TRACKBLKADDMAPPING, 8);
3393 1 put_ebml_uint(track_bc, MATROSKA_ID_BLKADDIDTYPE,
3394 MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35);
3395 1 put_ebml_uint(track_bc, MATROSKA_ID_BLKADDIDVALUE,
3396 MATROSKA_BLOCK_ADD_ID_ITU_T_T35);
3397 1 end_ebml_master(track_bc, mapping_master);
3398 }
3399 }
3400 }
3401
3402 37 avio_seek(pb, mkv->track.pos, SEEK_SET);
3403 37 ret = end_ebml_master_crc32(pb, &mkv->track.bc, mkv,
3404 MATROSKA_ID_TRACKS, 0, 0, 0);
3405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (ret < 0)
3406 return ret;
3407 }
3408
3409 // update stream durations
3410
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (mkv->tags.bc) {
3411 37 AVIOContext *tags_bc = mkv->tags.bc;
3412 int i;
3413
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 37 times.
107 for (i = 0; i < s->nb_streams; ++i) {
3414 70 const AVStream *st = s->streams[i];
3415 70 const mkv_track *track = &mkv->tracks[i];
3416
3417
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 1 times.
70 if (track->duration_offset > 0) {
3418 69 double duration_sec = track->duration * av_q2d(st->time_base);
3419 69 char duration_string[DURATION_STRING_LENGTH + 1] = "";
3420 ebml_master simpletag;
3421
3422 69 av_log(s, AV_LOG_DEBUG, "stream %d end duration = %" PRIu64 "\n", i,
3423 69 track->duration);
3424
3425 69 avio_seek(tags_bc, track->duration_offset, SEEK_SET);
3426 69 simpletag = start_ebml_master(tags_bc, MATROSKA_ID_SIMPLETAG,
3427 2 + 1 + 8 + 23);
3428 69 put_ebml_string(tags_bc, MATROSKA_ID_TAGNAME, "DURATION");
3429
3430 69 snprintf(duration_string, sizeof(duration_string), "%02d:%02d:%012.9f",
3431 69 (int) duration_sec / 3600, ((int) duration_sec / 60) % 60,
3432 fmod(duration_sec, 60));
3433
3434 69 put_ebml_binary(tags_bc, MATROSKA_ID_TAGSTRING,
3435 duration_string, DURATION_STRING_LENGTH);
3436 69 end_ebml_master(tags_bc, simpletag);
3437 }
3438 }
3439
3440 37 avio_seek(pb, mkv->tags.pos, SEEK_SET);
3441 37 ret = end_ebml_master_crc32(pb, &mkv->tags.bc, mkv,
3442 MATROSKA_ID_TAGS, 0, 0, 0);
3443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (ret < 0)
3444 return ret;
3445 }
3446
3447 37 avio_seek(pb, endpos, SEEK_SET);
3448
3449 37 return ret2;
3450 }
3451
3452 4 static uint64_t mkv_get_uid(const mkv_track *tracks, int i, AVLFG *c)
3453 {
3454 while (1) {
3455 uint64_t uid;
3456 int k;
3457 4 uid = (uint64_t)av_lfg_get(c) << 32;
3458 4 uid |= av_lfg_get(c);
3459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!uid)
3460 continue;
3461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (k = 0; k < i; k++) {
3462 if (tracks[k].uid == uid)
3463 break;
3464 }
3465
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (k == i)
3466 4 return uid;
3467 }
3468 }
3469
3470 45 static int mkv_init(struct AVFormatContext *s)
3471 {
3472 45 FFFormatContext *const si = ffformatcontext(s);
3473 45 MatroskaMuxContext *mkv = s->priv_data;
3474 AVLFG c;
3475 45 unsigned nb_tracks = 0;
3476 int i;
3477
3478 45 mkv->ctx = s;
3479
3480
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 45 times.
123 for (i = 0; i < s->nb_streams; i++) {
3481
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 ||
3482
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_COOK ||
3483
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RA_288 ||
3484
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_SIPR ||
3485
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV10 ||
3486
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV20 ||
3487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV30) {
3488 av_log(s, AV_LOG_ERROR,
3489 "The Matroska muxer does not yet support muxing %s\n",
3490 avcodec_get_name(s->streams[i]->codecpar->codec_id));
3491 return AVERROR_PATCHWELCOME;
3492 }
3493 }
3494
3495
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 1 times.
45 if (s->avoid_negative_ts < 0) {
3496 44 s->avoid_negative_ts = 1;
3497 44 si->avoid_negative_ts_use_pts = 1;
3498 }
3499
3500 45 if (!CONFIG_MATROSKA_MUXER ||
3501
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 41 times.
45 (CONFIG_WEBM_MUXER && !strcmp(s->oformat->name, "webm"))) {
3502 4 mkv->mode = MODE_WEBM;
3503 4 mkv->write_crc = 0;
3504 } else
3505 41 mkv->mode = MODE_MATROSKAv2;
3506
3507 45 mkv->cur_audio_pkt = ffformatcontext(s)->pkt;
3508
3509 45 mkv->tracks = av_calloc(s->nb_streams, sizeof(*mkv->tracks));
3510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (!mkv->tracks)
3511 return AVERROR(ENOMEM);
3512
3513
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 41 times.
45 if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
3514 4 av_lfg_init(&c, av_get_random_seed());
3515
3516 // Calculate the SegmentUID now in order not to waste our random seed.
3517
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for (i = 0; i < 4; i++)
3518 16 mkv->segment_uid[i] = av_lfg_get(&c);
3519 }
3520
3521
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 45 times.
123 for (i = 0; i < s->nb_streams; i++) {
3522 78 AVStream *st = s->streams[i];
3523 78 const AVCodecParameters *const par = st->codecpar;
3524 78 mkv_track *track = &mkv->tracks[i];
3525
3526
6/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 58 times.
78 switch (par->codec_id) {
3527 #if CONFIG_MATROSKA_MUXER
3528 2 case AV_CODEC_ID_WAVPACK:
3529 2 track->reformat = mkv_reformat_wavpack;
3530 2 break;
3531 11 case AV_CODEC_ID_H264:
3532 case AV_CODEC_ID_HEVC:
3533 case AV_CODEC_ID_VVC:
3534
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
11 if (((par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0) ||
3535
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
6 (par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6) ||
3536
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)) &&
3537
3/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 8 times.
11 (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1))
3538 3 track->reformat = mkv_reformat_h2645;
3539 11 break;
3540 1 case AV_CODEC_ID_PRORES:
3541 /* Matroska specification requires to remove
3542 * the first QuickTime atom. */
3543 1 track->offset = 8;
3544 1 break;
3545 #endif
3546 2 case AV_CODEC_ID_AV1:
3547 2 track->reformat = mkv_reformat_av1;
3548 2 break;
3549 4 case AV_CODEC_ID_WEBVTT:
3550 4 track->reformat = webm_reformat_vtt;
3551 4 break;
3552 }
3553
3554
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 4 times.
78 if (s->flags & AVFMT_FLAG_BITEXACT) {
3555 74 track->uid = i + 1;
3556 } else {
3557 4 track->uid = mkv_get_uid(mkv->tracks, i, &c);
3558 }
3559
3560 // ms precision is the de-facto standard timescale for mkv files
3561 78 avpriv_set_pts_info(st, 64, 1, 1000);
3562
3563
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 77 times.
78 if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
3564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (IS_WEBM(mkv)) {
3565 av_log(s, AV_LOG_WARNING, "Stream %d will be ignored "
3566 "as WebM doesn't support attachments.\n", i);
3567
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 } else if (!get_mimetype(st)) {
3568 av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype "
3569 "tag and it cannot be deduced from the codec id.\n", i);
3570 return AVERROR(EINVAL);
3571 }
3572 1 mkv->nb_attachments++;
3573 1 continue;
3574 }
3575
3576 77 nb_tracks++;
3577
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 75 times.
77 track->track_num = mkv->is_dash ? mkv->dash_track_number : nb_tracks;
3578 77 track->track_num_size = ebml_num_size(track->track_num);
3579 }
3580
3581
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
45 if (mkv->is_dash && nb_tracks != 1)
3582 return AVERROR(EINVAL);
3583
3584 45 return 0;
3585 }
3586
3587 75 static int mkv_check_bitstream(AVFormatContext *s, AVStream *st,
3588 const AVPacket *pkt)
3589 {
3590 75 int ret = 1;
3591
3592
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 71 times.
75 if (CONFIG_MATROSKA_MUXER && st->codecpar->codec_id == AV_CODEC_ID_AAC) {
3593
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)
3594 1 ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
3595
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 68 times.
71 } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
3596 3 ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
3597 68 } else if (CONFIG_MATROSKA_MUXER &&
3598
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
68 st->codecpar->codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE) {
3599 2 ret = ff_stream_add_bitstream_filter(st, "pgs_frame_merge", NULL);
3600 }
3601
3602 75 return ret;
3603 }
3604
3605 static const AVCodecTag additional_audio_tags[] = {
3606 { AV_CODEC_ID_ALAC, 0XFFFFFFFF },
3607 { AV_CODEC_ID_ATRAC1, 0xFFFFFFFF },
3608 { AV_CODEC_ID_MLP, 0xFFFFFFFF },
3609 { AV_CODEC_ID_OPUS, 0xFFFFFFFF },
3610 { AV_CODEC_ID_PCM_S16BE, 0xFFFFFFFF },
3611 { AV_CODEC_ID_PCM_S24BE, 0xFFFFFFFF },
3612 { AV_CODEC_ID_PCM_S32BE, 0xFFFFFFFF },
3613 { AV_CODEC_ID_QDMC, 0xFFFFFFFF },
3614 { AV_CODEC_ID_QDM2, 0xFFFFFFFF },
3615 { AV_CODEC_ID_RA_144, 0xFFFFFFFF },
3616 { AV_CODEC_ID_TRUEHD, 0xFFFFFFFF },
3617 { AV_CODEC_ID_NONE, 0xFFFFFFFF }
3618 };
3619
3620 static const AVCodecTag additional_subtitle_tags[] = {
3621 { AV_CODEC_ID_DVB_SUBTITLE, 0xFFFFFFFF },
3622 { AV_CODEC_ID_DVD_SUBTITLE, 0xFFFFFFFF },
3623 { AV_CODEC_ID_HDMV_PGS_SUBTITLE, 0xFFFFFFFF },
3624 { AV_CODEC_ID_ARIB_CAPTION, 0xFFFFFFFF },
3625 { AV_CODEC_ID_NONE, 0xFFFFFFFF }
3626 };
3627
3628 #define OFFSET(x) offsetof(MatroskaMuxContext, x)
3629 #define FLAGS AV_OPT_FLAG_ENCODING_PARAM
3630 static const AVOption options[] = {
3631 { "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 },
3632 { "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 },
3633 { "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 },
3634 { "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 },
3635 { "dash", "create a WebM file conforming to WebM DASH specification", OFFSET(is_dash), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
3636 { "dash_track_number", "track number for the DASH stream", OFFSET(dash_track_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, FLAGS },
3637 { "live", "write files assuming it is a live stream", OFFSET(is_live), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
3638 { "allow_raw_vfw", "allow raw VFW mode", OFFSET(allow_raw_vfw), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
3639 { "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 },
3640 { "write_crc32", "write a CRC32 element inside every Level 1 element", OFFSET(write_crc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
3641 { "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" },
3642 { "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" },
3643 { "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" },
3644 { "passthrough", "use the disposition flag as-is", 0, AV_OPT_TYPE_CONST, { .i64 = DEFAULT_MODE_PASSTHROUGH }, 0, 0, FLAGS, .unit = "default_mode" },
3645 { NULL },
3646 };
3647
3648 static const AVClass matroska_webm_class = {
3649 .class_name = "matroska/webm muxer",
3650 .item_name = av_default_item_name,
3651 .option = options,
3652 .version = LIBAVUTIL_VERSION_INT,
3653 };
3654
3655 #if CONFIG_MATROSKA_MUXER
3656 22 static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance)
3657 {
3658
1/2
✓ Branch 0 taken 1298 times.
✗ Branch 1 not taken.
1298 for (int i = 0; ff_mkv_codec_tags[i].id != AV_CODEC_ID_NONE; i++)
3659
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 1276 times.
1298 if (ff_mkv_codec_tags[i].id == codec_id)
3660 22 return 1;
3661
3662 if (std_compliance < FF_COMPLIANCE_NORMAL) {
3663 enum AVMediaType type = avcodec_get_type(codec_id);
3664 // mkv theoretically supports any video/audio through VFW/ACM
3665 if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)
3666 return 1;
3667 }
3668
3669 return 0;
3670 }
3671
3672 const FFOutputFormat ff_matroska_muxer = {
3673 .p.name = "matroska",
3674 .p.long_name = NULL_IF_CONFIG_SMALL("Matroska"),
3675 .p.mime_type = "video/x-matroska",
3676 .p.extensions = "mkv",
3677 .priv_data_size = sizeof(MatroskaMuxContext),
3678 .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ?
3679 AV_CODEC_ID_VORBIS : AV_CODEC_ID_AC3,
3680 .p.video_codec = CONFIG_LIBX264_ENCODER ?
3681 AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
3682 .init = mkv_init,
3683 .deinit = mkv_deinit,
3684 .write_header = mkv_write_header,
3685 .write_packet = mkv_write_flush_packet,
3686 .write_trailer = mkv_write_trailer,
3687 .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |
3688 AVFMT_TS_NONSTRICT,
3689 .p.codec_tag = (const AVCodecTag* const []){
3690 ff_codec_bmp_tags, ff_codec_wav_tags,
3691 additional_audio_tags, additional_subtitle_tags, 0
3692 },
3693 .p.subtitle_codec = AV_CODEC_ID_ASS,
3694 .query_codec = mkv_query_codec,
3695 .check_bitstream = mkv_check_bitstream,
3696 .p.priv_class = &matroska_webm_class,
3697 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
3698 };
3699 #endif
3700
3701 #if CONFIG_WEBM_MUXER
3702 2 static int webm_query_codec(enum AVCodecID codec_id, int std_compliance)
3703 {
3704
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 for (int i = 0; ff_webm_codec_tags[i].id != AV_CODEC_ID_NONE; i++)
3705
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ff_webm_codec_tags[i].id == codec_id)
3706 2 return 1;
3707
3708 return 0;
3709 }
3710
3711 const FFOutputFormat ff_webm_muxer = {
3712 .p.name = "webm",
3713 .p.long_name = NULL_IF_CONFIG_SMALL("WebM"),
3714 .p.mime_type = "video/webm",
3715 .p.extensions = "webm",
3716 .priv_data_size = sizeof(MatroskaMuxContext),
3717 .p.audio_codec = CONFIG_LIBOPUS_ENCODER ? AV_CODEC_ID_OPUS : AV_CODEC_ID_VORBIS,
3718 .p.video_codec = CONFIG_LIBVPX_VP9_ENCODER? AV_CODEC_ID_VP9 : AV_CODEC_ID_VP8,
3719 .p.subtitle_codec = AV_CODEC_ID_WEBVTT,
3720 .init = mkv_init,
3721 .deinit = mkv_deinit,
3722 .write_header = mkv_write_header,
3723 .write_packet = mkv_write_flush_packet,
3724 .write_trailer = mkv_write_trailer,
3725 .query_codec = webm_query_codec,
3726 .check_bitstream = mkv_check_bitstream,
3727 .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |
3728 AVFMT_TS_NONSTRICT,
3729 .p.priv_class = &matroska_webm_class,
3730 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
3731 };
3732 #endif
3733
3734 #if CONFIG_MATROSKA_AUDIO_MUXER
3735 const FFOutputFormat ff_matroska_audio_muxer = {
3736 .p.name = "matroska",
3737 .p.long_name = NULL_IF_CONFIG_SMALL("Matroska Audio"),
3738 .p.mime_type = "audio/x-matroska",
3739 .p.extensions = "mka",
3740 .priv_data_size = sizeof(MatroskaMuxContext),
3741 .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ?
3742 AV_CODEC_ID_VORBIS : AV_CODEC_ID_AC3,
3743 .p.video_codec = AV_CODEC_ID_NONE,
3744 .init = mkv_init,
3745 .deinit = mkv_deinit,
3746 .write_header = mkv_write_header,
3747 .write_packet = mkv_write_flush_packet,
3748 .write_trailer = mkv_write_trailer,
3749 .check_bitstream = mkv_check_bitstream,
3750 .p.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT,
3751 .p.codec_tag = (const AVCodecTag* const []){
3752 ff_codec_wav_tags, additional_audio_tags, 0
3753 },
3754 .p.priv_class = &matroska_webm_class,
3755 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
3756 };
3757 #endif
3758