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