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() &&
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    251 uint64 EbmlElementSize(uint64 type, uint64 value) {
    252   return EbmlElementSize(type, value, 0);
    253 }
    254 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    441 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
    442   return WriteEbmlElement(writer, type, value, 0);
    443 }
    444 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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