1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8
9 #include "mkvmuxer/mkvmuxerutil.h"
10
11 #ifdef __ANDROID__
12 #include <fcntl.h>
13 #endif
14
15 #include <cassert>
16 #include <cmath>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20 #include <ctime>
21 #include <new>
22
23 #include "common/webmids.h"
24 #include "mkvmuxer/mkvmuxer.h"
25 #include "mkvmuxer/mkvwriter.h"
26
27 namespace mkvmuxer {
28
29 namespace {
30
31 // Date elements are always 8 octets in size.
32 const int kDateElementSize = 8;
33
WriteBlock(IMkvWriter * writer,const Frame * const frame,int64 timecode,uint64 timecode_scale)34 uint64 WriteBlock(IMkvWriter* writer, const Frame* const frame, int64 timecode,
35 uint64 timecode_scale) {
36 uint64 block_additional_elem_size = 0;
37 uint64 block_addid_elem_size = 0;
38 uint64 block_more_payload_size = 0;
39 uint64 block_more_elem_size = 0;
40 uint64 block_additions_payload_size = 0;
41 uint64 block_additions_elem_size = 0;
42 if (frame->additional()) {
43 block_additional_elem_size =
44 EbmlElementSize(libwebm::kMkvBlockAdditional, frame->additional(),
45 frame->additional_length());
46 block_addid_elem_size = EbmlElementSize(
47 libwebm::kMkvBlockAddID, static_cast<uint64>(frame->add_id()));
48
49 block_more_payload_size =
50 block_addid_elem_size + block_additional_elem_size;
51 block_more_elem_size =
52 EbmlMasterElementSize(libwebm::kMkvBlockMore, block_more_payload_size) +
53 block_more_payload_size;
54 block_additions_payload_size = block_more_elem_size;
55 block_additions_elem_size =
56 EbmlMasterElementSize(libwebm::kMkvBlockAdditions,
57 block_additions_payload_size) +
58 block_additions_payload_size;
59 }
60
61 uint64 discard_padding_elem_size = 0;
62 if (frame->discard_padding() != 0) {
63 discard_padding_elem_size =
64 EbmlElementSize(libwebm::kMkvDiscardPadding,
65 static_cast<int64>(frame->discard_padding()));
66 }
67
68 const uint64 reference_block_timestamp =
69 frame->reference_block_timestamp() / timecode_scale;
70 uint64 reference_block_elem_size = 0;
71 if (!frame->is_key()) {
72 reference_block_elem_size =
73 EbmlElementSize(libwebm::kMkvReferenceBlock, reference_block_timestamp);
74 }
75
76 const uint64 duration = frame->duration() / timecode_scale;
77 uint64 block_duration_elem_size = 0;
78 if (duration > 0)
79 block_duration_elem_size =
80 EbmlElementSize(libwebm::kMkvBlockDuration, duration);
81
82 const uint64 block_payload_size = 4 + frame->length();
83 const uint64 block_elem_size =
84 EbmlMasterElementSize(libwebm::kMkvBlock, block_payload_size) +
85 block_payload_size;
86
87 const uint64 block_group_payload_size =
88 block_elem_size + block_additions_elem_size + block_duration_elem_size +
89 discard_padding_elem_size + reference_block_elem_size;
90
91 if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockGroup,
92 block_group_payload_size)) {
93 return 0;
94 }
95
96 if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlock, block_payload_size))
97 return 0;
98
99 if (WriteUInt(writer, frame->track_number()))
100 return 0;
101
102 if (SerializeInt(writer, timecode, 2))
103 return 0;
104
105 // For a Block, flags is always 0.
106 if (SerializeInt(writer, 0, 1))
107 return 0;
108
109 if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
110 return 0;
111
112 if (frame->additional()) {
113 if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockAdditions,
114 block_additions_payload_size)) {
115 return 0;
116 }
117
118 if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockMore,
119 block_more_payload_size))
120 return 0;
121
122 if (!WriteEbmlElement(writer, libwebm::kMkvBlockAddID,
123 static_cast<uint64>(frame->add_id())))
124 return 0;
125
126 if (!WriteEbmlElement(writer, libwebm::kMkvBlockAdditional,
127 frame->additional(), frame->additional_length())) {
128 return 0;
129 }
130 }
131
132 if (frame->discard_padding() != 0 &&
133 !WriteEbmlElement(writer, libwebm::kMkvDiscardPadding,
134 static_cast<int64>(frame->discard_padding()))) {
135 return false;
136 }
137
138 if (!frame->is_key() &&
139 !WriteEbmlElement(writer, libwebm::kMkvReferenceBlock,
140 reference_block_timestamp)) {
141 return false;
142 }
143
144 if (duration > 0 &&
145 !WriteEbmlElement(writer, libwebm::kMkvBlockDuration, duration)) {
146 return false;
147 }
148 return EbmlMasterElementSize(libwebm::kMkvBlockGroup,
149 block_group_payload_size) +
150 block_group_payload_size;
151 }
152
WriteSimpleBlock(IMkvWriter * writer,const Frame * const frame,int64 timecode)153 uint64 WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame,
154 int64 timecode) {
155 if (WriteID(writer, libwebm::kMkvSimpleBlock))
156 return 0;
157
158 const int32 size = static_cast<int32>(frame->length()) + 4;
159 if (WriteUInt(writer, size))
160 return 0;
161
162 if (WriteUInt(writer, static_cast<uint64>(frame->track_number())))
163 return 0;
164
165 if (SerializeInt(writer, timecode, 2))
166 return 0;
167
168 uint64 flags = 0;
169 if (frame->is_key())
170 flags |= 0x80;
171
172 if (SerializeInt(writer, flags, 1))
173 return 0;
174
175 if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
176 return 0;
177
178 return GetUIntSize(libwebm::kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 +
179 frame->length();
180 }
181
182 } // namespace
183
GetCodedUIntSize(uint64 value)184 int32 GetCodedUIntSize(uint64 value) {
185 if (value < 0x000000000000007FULL)
186 return 1;
187 else if (value < 0x0000000000003FFFULL)
188 return 2;
189 else if (value < 0x00000000001FFFFFULL)
190 return 3;
191 else if (value < 0x000000000FFFFFFFULL)
192 return 4;
193 else if (value < 0x00000007FFFFFFFFULL)
194 return 5;
195 else if (value < 0x000003FFFFFFFFFFULL)
196 return 6;
197 else if (value < 0x0001FFFFFFFFFFFFULL)
198 return 7;
199 return 8;
200 }
201
GetUIntSize(uint64 value)202 int32 GetUIntSize(uint64 value) {
203 if (value < 0x0000000000000100ULL)
204 return 1;
205 else if (value < 0x0000000000010000ULL)
206 return 2;
207 else if (value < 0x0000000001000000ULL)
208 return 3;
209 else if (value < 0x0000000100000000ULL)
210 return 4;
211 else if (value < 0x0000010000000000ULL)
212 return 5;
213 else if (value < 0x0001000000000000ULL)
214 return 6;
215 else if (value < 0x0100000000000000ULL)
216 return 7;
217 return 8;
218 }
219
GetIntSize(int64 value)220 int32 GetIntSize(int64 value) {
221 // Doubling the requested value ensures positive values with their high bit
222 // set are written with 0-padding to avoid flipping the signedness.
223 const uint64 v = (value < 0) ? value ^ -1LL : value;
224 return GetUIntSize(2 * v);
225 }
226
EbmlMasterElementSize(uint64 type,uint64 value)227 uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
228 // Size of EBML ID
229 int32 ebml_size = GetUIntSize(type);
230
231 // Datasize
232 ebml_size += GetCodedUIntSize(value);
233
234 return ebml_size;
235 }
236
EbmlElementSize(uint64 type,int64 value)237 uint64 EbmlElementSize(uint64 type, int64 value) {
238 // Size of EBML ID
239 int32 ebml_size = GetUIntSize(type);
240
241 // Datasize
242 ebml_size += GetIntSize(value);
243
244 // Size of Datasize
245 ebml_size++;
246
247 return ebml_size;
248 }
249
EbmlElementSize(uint64 type,uint64 value)250 uint64 EbmlElementSize(uint64 type, uint64 value) {
251 return EbmlElementSize(type, value, 0);
252 }
253
EbmlElementSize(uint64 type,uint64 value,uint64 fixed_size)254 uint64 EbmlElementSize(uint64 type, uint64 value, uint64 fixed_size) {
255 // Size of EBML ID
256 uint64 ebml_size = GetUIntSize(type);
257
258 // Datasize
259 ebml_size += (fixed_size > 0) ? fixed_size : GetUIntSize(value);
260
261 // Size of Datasize
262 ebml_size++;
263
264 return ebml_size;
265 }
266
EbmlElementSize(uint64 type,float)267 uint64 EbmlElementSize(uint64 type, float /* value */) {
268 // Size of EBML ID
269 uint64 ebml_size = GetUIntSize(type);
270
271 // Datasize
272 ebml_size += sizeof(float);
273
274 // Size of Datasize
275 ebml_size++;
276
277 return ebml_size;
278 }
279
EbmlElementSize(uint64 type,const char * value)280 uint64 EbmlElementSize(uint64 type, const char* value) {
281 if (!value)
282 return 0;
283
284 // Size of EBML ID
285 uint64 ebml_size = GetUIntSize(type);
286
287 // Datasize
288 ebml_size += strlen(value);
289
290 // Size of Datasize
291 ebml_size++;
292
293 return ebml_size;
294 }
295
EbmlElementSize(uint64 type,const uint8 * value,uint64 size)296 uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
297 if (!value)
298 return 0;
299
300 // Size of EBML ID
301 uint64 ebml_size = GetUIntSize(type);
302
303 // Datasize
304 ebml_size += size;
305
306 // Size of Datasize
307 ebml_size += GetCodedUIntSize(size);
308
309 return ebml_size;
310 }
311
EbmlDateElementSize(uint64 type)312 uint64 EbmlDateElementSize(uint64 type) {
313 // Size of EBML ID
314 uint64 ebml_size = GetUIntSize(type);
315
316 // Datasize
317 ebml_size += kDateElementSize;
318
319 // Size of Datasize
320 ebml_size++;
321
322 return ebml_size;
323 }
324
SerializeInt(IMkvWriter * writer,int64 value,int32 size)325 int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
326 if (!writer || size < 1 || size > 8)
327 return -1;
328
329 for (int32 i = 1; i <= size; ++i) {
330 const int32 byte_count = size - i;
331 const int32 bit_count = byte_count * 8;
332
333 const int64 bb = value >> bit_count;
334 const uint8 b = static_cast<uint8>(bb);
335
336 const int32 status = writer->Write(&b, 1);
337
338 if (status < 0)
339 return status;
340 }
341
342 return 0;
343 }
344
SerializeFloat(IMkvWriter * writer,float f)345 int32 SerializeFloat(IMkvWriter* writer, float f) {
346 if (!writer)
347 return -1;
348
349 assert(sizeof(uint32) == sizeof(float));
350 // This union is merely used to avoid a reinterpret_cast from float& to
351 // uint32& which will result in violation of strict aliasing.
352 union U32 {
353 uint32 u32;
354 float f;
355 } value;
356 value.f = f;
357
358 for (int32 i = 1; i <= 4; ++i) {
359 const int32 byte_count = 4 - i;
360 const int32 bit_count = byte_count * 8;
361
362 const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
363
364 const int32 status = writer->Write(&byte, 1);
365
366 if (status < 0)
367 return status;
368 }
369
370 return 0;
371 }
372
WriteUInt(IMkvWriter * writer,uint64 value)373 int32 WriteUInt(IMkvWriter* writer, uint64 value) {
374 if (!writer)
375 return -1;
376
377 int32 size = GetCodedUIntSize(value);
378
379 return WriteUIntSize(writer, value, size);
380 }
381
WriteUIntSize(IMkvWriter * writer,uint64 value,int32 size)382 int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) {
383 if (!writer || size < 0 || size > 8)
384 return -1;
385
386 if (size > 0) {
387 const uint64 bit = 1LL << (size * 7);
388
389 if (value > (bit - 2))
390 return -1;
391
392 value |= bit;
393 } else {
394 size = 1;
395 int64 bit;
396
397 for (;;) {
398 bit = 1LL << (size * 7);
399 const uint64 max = bit - 2;
400
401 if (value <= max)
402 break;
403
404 ++size;
405 }
406
407 if (size > 8)
408 return false;
409
410 value |= bit;
411 }
412
413 return SerializeInt(writer, value, size);
414 }
415
WriteID(IMkvWriter * writer,uint64 type)416 int32 WriteID(IMkvWriter* writer, uint64 type) {
417 if (!writer)
418 return -1;
419
420 writer->ElementStartNotify(type, writer->Position());
421
422 const int32 size = GetUIntSize(type);
423
424 return SerializeInt(writer, type, size);
425 }
426
WriteEbmlMasterElement(IMkvWriter * writer,uint64 type,uint64 size)427 bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) {
428 if (!writer)
429 return false;
430
431 if (WriteID(writer, type))
432 return false;
433
434 if (WriteUInt(writer, size))
435 return false;
436
437 return true;
438 }
439
WriteEbmlElement(IMkvWriter * writer,uint64 type,uint64 value)440 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
441 return WriteEbmlElement(writer, type, value, 0);
442 }
443
WriteEbmlElement(IMkvWriter * writer,uint64 type,uint64 value,uint64 fixed_size)444 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value,
445 uint64 fixed_size) {
446 if (!writer)
447 return false;
448
449 if (WriteID(writer, type))
450 return false;
451
452 uint64 size = GetUIntSize(value);
453 if (fixed_size > 0) {
454 if (size > fixed_size)
455 return false;
456 size = fixed_size;
457 }
458 if (WriteUInt(writer, size))
459 return false;
460
461 if (SerializeInt(writer, value, static_cast<int32>(size)))
462 return false;
463
464 return true;
465 }
466
WriteEbmlElement(IMkvWriter * writer,uint64 type,int64 value)467 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value) {
468 if (!writer)
469 return false;
470
471 if (WriteID(writer, type))
472 return 0;
473
474 const uint64 size = GetIntSize(value);
475 if (WriteUInt(writer, size))
476 return false;
477
478 if (SerializeInt(writer, value, static_cast<int32>(size)))
479 return false;
480
481 return true;
482 }
483
WriteEbmlElement(IMkvWriter * writer,uint64 type,float value)484 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
485 if (!writer)
486 return false;
487
488 if (WriteID(writer, type))
489 return false;
490
491 if (WriteUInt(writer, 4))
492 return false;
493
494 if (SerializeFloat(writer, value))
495 return false;
496
497 return true;
498 }
499
WriteEbmlElement(IMkvWriter * writer,uint64 type,const char * value)500 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
501 if (!writer || !value)
502 return false;
503
504 if (WriteID(writer, type))
505 return false;
506
507 const uint64 length = strlen(value);
508 if (WriteUInt(writer, length))
509 return false;
510
511 if (writer->Write(value, static_cast<const uint32>(length)))
512 return false;
513
514 return true;
515 }
516
WriteEbmlElement(IMkvWriter * writer,uint64 type,const uint8 * value,uint64 size)517 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
518 uint64 size) {
519 if (!writer || !value || size < 1)
520 return false;
521
522 if (WriteID(writer, type))
523 return false;
524
525 if (WriteUInt(writer, size))
526 return false;
527
528 if (writer->Write(value, static_cast<uint32>(size)))
529 return false;
530
531 return true;
532 }
533
WriteEbmlDateElement(IMkvWriter * writer,uint64 type,int64 value)534 bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
535 if (!writer)
536 return false;
537
538 if (WriteID(writer, type))
539 return false;
540
541 if (WriteUInt(writer, kDateElementSize))
542 return false;
543
544 if (SerializeInt(writer, value, kDateElementSize))
545 return false;
546
547 return true;
548 }
549
WriteFrame(IMkvWriter * writer,const Frame * const frame,Cluster * cluster)550 uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
551 Cluster* cluster) {
552 if (!writer || !frame || !frame->IsValid() || !cluster ||
553 !cluster->timecode_scale())
554 return 0;
555
556 // Technically the timecode for a block can be less than the
557 // timecode for the cluster itself (remember that block timecode
558 // is a signed, 16-bit integer). However, as a simplification we
559 // only permit non-negative cluster-relative timecodes for blocks.
560 const int64 relative_timecode = cluster->GetRelativeTimecode(
561 frame->timestamp() / cluster->timecode_scale());
562 if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
563 return 0;
564
565 return frame->CanBeSimpleBlock() ?
566 WriteSimpleBlock(writer, frame, relative_timecode) :
567 WriteBlock(writer, frame, relative_timecode,
568 cluster->timecode_scale());
569 }
570
WriteVoidElement(IMkvWriter * writer,uint64 size)571 uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
572 if (!writer)
573 return false;
574
575 // Subtract one for the void ID and the coded size.
576 uint64 void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
577 uint64 void_size = EbmlMasterElementSize(libwebm::kMkvVoid, void_entry_size) +
578 void_entry_size;
579
580 if (void_size != size)
581 return 0;
582
583 const int64 payload_position = writer->Position();
584 if (payload_position < 0)
585 return 0;
586
587 if (WriteID(writer, libwebm::kMkvVoid))
588 return 0;
589
590 if (WriteUInt(writer, void_entry_size))
591 return 0;
592
593 const uint8 value = 0;
594 for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) {
595 if (writer->Write(&value, 1))
596 return 0;
597 }
598
599 const int64 stop_position = writer->Position();
600 if (stop_position < 0 ||
601 stop_position - payload_position != static_cast<int64>(void_size))
602 return 0;
603
604 return void_size;
605 }
606
GetVersion(int32 * major,int32 * minor,int32 * build,int32 * revision)607 void GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
608 *major = 0;
609 *minor = 2;
610 *build = 1;
611 *revision = 0;
612 }
613
MakeUID(unsigned int * seed)614 uint64 MakeUID(unsigned int* seed) {
615 uint64 uid = 0;
616
617 #ifdef __MINGW32__
618 srand(*seed);
619 #endif
620
621 for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values
622 uid <<= 8;
623
624 // TODO(fgalligan): Move random number generation to platform specific code.
625 #ifdef _MSC_VER
626 (void)seed;
627 const int32 nn = rand();
628 #elif __ANDROID__
629 (void)seed;
630 int32 temp_num = 1;
631 int fd = open("/dev/urandom", O_RDONLY);
632 if (fd != -1) {
633 read(fd, &temp_num, sizeof(temp_num));
634 close(fd);
635 }
636 const int32 nn = temp_num;
637 #elif defined __MINGW32__
638 const int32 nn = rand();
639 #else
640 const int32 nn = rand_r(seed);
641 #endif
642 const int32 n = 0xFF & (nn >> 4); // throw away low-order bits
643
644 uid |= n;
645 }
646
647 return uid;
648 }
649
IsMatrixCoefficientsValueValid(uint64_t value)650 bool IsMatrixCoefficientsValueValid(uint64_t value) {
651 switch (value) {
652 case mkvmuxer::Colour::kGbr:
653 case mkvmuxer::Colour::kBt709:
654 case mkvmuxer::Colour::kUnspecifiedMc:
655 case mkvmuxer::Colour::kReserved:
656 case mkvmuxer::Colour::kFcc:
657 case mkvmuxer::Colour::kBt470bg:
658 case mkvmuxer::Colour::kSmpte170MMc:
659 case mkvmuxer::Colour::kSmpte240MMc:
660 case mkvmuxer::Colour::kYcocg:
661 case mkvmuxer::Colour::kBt2020NonConstantLuminance:
662 case mkvmuxer::Colour::kBt2020ConstantLuminance:
663 return true;
664 }
665 return false;
666 }
667
IsChromaSitingHorzValueValid(uint64_t value)668 bool IsChromaSitingHorzValueValid(uint64_t value) {
669 switch (value) {
670 case mkvmuxer::Colour::kUnspecifiedCsh:
671 case mkvmuxer::Colour::kLeftCollocated:
672 case mkvmuxer::Colour::kHalfCsh:
673 return true;
674 }
675 return false;
676 }
677
IsChromaSitingVertValueValid(uint64_t value)678 bool IsChromaSitingVertValueValid(uint64_t value) {
679 switch (value) {
680 case mkvmuxer::Colour::kUnspecifiedCsv:
681 case mkvmuxer::Colour::kTopCollocated:
682 case mkvmuxer::Colour::kHalfCsv:
683 return true;
684 }
685 return false;
686 }
687
IsColourRangeValueValid(uint64_t value)688 bool IsColourRangeValueValid(uint64_t value) {
689 switch (value) {
690 case mkvmuxer::Colour::kUnspecifiedCr:
691 case mkvmuxer::Colour::kBroadcastRange:
692 case mkvmuxer::Colour::kFullRange:
693 case mkvmuxer::Colour::kMcTcDefined:
694 return true;
695 }
696 return false;
697 }
698
IsTransferCharacteristicsValueValid(uint64_t value)699 bool IsTransferCharacteristicsValueValid(uint64_t value) {
700 switch (value) {
701 case mkvmuxer::Colour::kIturBt709Tc:
702 case mkvmuxer::Colour::kUnspecifiedTc:
703 case mkvmuxer::Colour::kReservedTc:
704 case mkvmuxer::Colour::kGamma22Curve:
705 case mkvmuxer::Colour::kGamma28Curve:
706 case mkvmuxer::Colour::kSmpte170MTc:
707 case mkvmuxer::Colour::kSmpte240MTc:
708 case mkvmuxer::Colour::kLinear:
709 case mkvmuxer::Colour::kLog:
710 case mkvmuxer::Colour::kLogSqrt:
711 case mkvmuxer::Colour::kIec6196624:
712 case mkvmuxer::Colour::kIturBt1361ExtendedColourGamut:
713 case mkvmuxer::Colour::kIec6196621:
714 case mkvmuxer::Colour::kIturBt202010bit:
715 case mkvmuxer::Colour::kIturBt202012bit:
716 case mkvmuxer::Colour::kSmpteSt2084:
717 case mkvmuxer::Colour::kSmpteSt4281Tc:
718 case mkvmuxer::Colour::kAribStdB67Hlg:
719 return true;
720 }
721 return false;
722 }
723
IsPrimariesValueValid(uint64_t value)724 bool IsPrimariesValueValid(uint64_t value) {
725 switch (value) {
726 case mkvmuxer::Colour::kReservedP0:
727 case mkvmuxer::Colour::kIturBt709P:
728 case mkvmuxer::Colour::kUnspecifiedP:
729 case mkvmuxer::Colour::kReservedP3:
730 case mkvmuxer::Colour::kIturBt470M:
731 case mkvmuxer::Colour::kIturBt470Bg:
732 case mkvmuxer::Colour::kSmpte170MP:
733 case mkvmuxer::Colour::kSmpte240MP:
734 case mkvmuxer::Colour::kFilm:
735 case mkvmuxer::Colour::kIturBt2020:
736 case mkvmuxer::Colour::kSmpteSt4281P:
737 case mkvmuxer::Colour::kJedecP22Phosphors:
738 return true;
739 }
740 return false;
741 }
742
743 } // namespace mkvmuxer
744