Home | History | Annotate | Download | only in mkvmuxer
      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 
     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() && !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 
    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 
    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 
    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 
    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 
    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 
    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 
    250 uint64 EbmlElementSize(uint64 type, uint64 value) {
    251   return EbmlElementSize(type, value, 0);
    252 }
    253 
    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 
    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 
    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 += GetCodedUIntSize(strlen(value));
    292 
    293   return ebml_size;
    294 }
    295 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    440 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
    441   return WriteEbmlElement(writer, type, value, 0);
    442 }
    443 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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