Home | History | Annotate | Download | only in libwebm
      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 "mkvmuxerutil.hpp"
     10 
     11 #ifdef __ANDROID__
     12 #include <fcntl.h>
     13 #endif
     14 
     15 #include <cassert>
     16 #include <cmath>
     17 #include <cstdio>
     18 #ifdef _MSC_VER
     19 #define _CRT_RAND_S
     20 #endif
     21 #include <cstdlib>
     22 #include <cstring>
     23 #include <ctime>
     24 
     25 #include <new>
     26 
     27 #include "mkvwriter.hpp"
     28 #include "webmids.hpp"
     29 
     30 namespace mkvmuxer {
     31 
     32 int32 GetCodedUIntSize(uint64 value) {
     33   if (value < 0x000000000000007FULL)
     34     return 1;
     35   else if (value < 0x0000000000003FFFULL)
     36     return 2;
     37   else if (value < 0x00000000001FFFFFULL)
     38     return 3;
     39   else if (value < 0x000000000FFFFFFFULL)
     40     return 4;
     41   else if (value < 0x00000007FFFFFFFFULL)
     42     return 5;
     43   else if (value < 0x000003FFFFFFFFFFULL)
     44     return 6;
     45   else if (value < 0x0001FFFFFFFFFFFFULL)
     46     return 7;
     47   return 8;
     48 }
     49 
     50 int32 GetUIntSize(uint64 value) {
     51   if (value < 0x0000000000000100ULL)
     52     return 1;
     53   else if (value < 0x0000000000010000ULL)
     54     return 2;
     55   else if (value < 0x0000000001000000ULL)
     56     return 3;
     57   else if (value < 0x0000000100000000ULL)
     58     return 4;
     59   else if (value < 0x0000010000000000ULL)
     60     return 5;
     61   else if (value < 0x0001000000000000ULL)
     62     return 6;
     63   else if (value < 0x0100000000000000ULL)
     64     return 7;
     65   return 8;
     66 }
     67 
     68 uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
     69   // Size of EBML ID
     70   int32 ebml_size = GetUIntSize(type);
     71 
     72   // Datasize
     73   ebml_size += GetCodedUIntSize(value);
     74 
     75   return ebml_size;
     76 }
     77 
     78 uint64 EbmlElementSize(uint64 type, int64 value) {
     79   return EbmlElementSize(type, static_cast<uint64>(value));
     80 }
     81 
     82 uint64 EbmlElementSize(uint64 type, uint64 value) {
     83   // Size of EBML ID
     84   int32 ebml_size = GetUIntSize(type);
     85 
     86   // Datasize
     87   ebml_size += GetUIntSize(value);
     88 
     89   // Size of Datasize
     90   ebml_size++;
     91 
     92   return ebml_size;
     93 }
     94 
     95 uint64 EbmlElementSize(uint64 type, float /* value */ ) {
     96   // Size of EBML ID
     97   uint64 ebml_size = GetUIntSize(type);
     98 
     99   // Datasize
    100   ebml_size += sizeof(float);
    101 
    102   // Size of Datasize
    103   ebml_size++;
    104 
    105   return ebml_size;
    106 }
    107 
    108 uint64 EbmlElementSize(uint64 type, const char* value) {
    109   if (!value)
    110     return 0;
    111 
    112   // Size of EBML ID
    113   uint64 ebml_size = GetUIntSize(type);
    114 
    115   // Datasize
    116   ebml_size += strlen(value);
    117 
    118   // Size of Datasize
    119   ebml_size++;
    120 
    121   return ebml_size;
    122 }
    123 
    124 uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
    125   if (!value)
    126     return 0;
    127 
    128   // Size of EBML ID
    129   uint64 ebml_size = GetUIntSize(type);
    130 
    131   // Datasize
    132   ebml_size += size;
    133 
    134   // Size of Datasize
    135   ebml_size += GetCodedUIntSize(size);
    136 
    137   return ebml_size;
    138 }
    139 
    140 int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
    141   if (!writer || size < 1 || size > 8)
    142     return -1;
    143 
    144   for (int32 i = 1; i <= size; ++i) {
    145     const int32 byte_count = size - i;
    146     const int32 bit_count = byte_count * 8;
    147 
    148     const int64 bb = value >> bit_count;
    149     const uint8 b = static_cast<uint8>(bb);
    150 
    151     const int32 status = writer->Write(&b, 1);
    152 
    153     if (status < 0)
    154       return status;
    155   }
    156 
    157   return 0;
    158 }
    159 
    160 int32 SerializeFloat(IMkvWriter* writer, float f) {
    161   if (!writer)
    162     return -1;
    163 
    164   assert(sizeof(uint32) == sizeof(float));
    165   // This union is merely used to avoid a reinterpret_cast from float& to
    166   // uint32& which will result in violation of strict aliasing.
    167   union U32 {
    168     uint32 u32;
    169     float f;
    170   } value;
    171   value.f = f;
    172 
    173   for (int32 i = 1; i <= 4; ++i) {
    174     const int32 byte_count = 4 - i;
    175     const int32 bit_count = byte_count * 8;
    176 
    177     const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
    178 
    179     const int32 status = writer->Write(&byte, 1);
    180 
    181     if (status < 0)
    182       return status;
    183   }
    184 
    185   return 0;
    186 }
    187 
    188 int32 WriteUInt(IMkvWriter* writer, uint64 value) {
    189   if (!writer)
    190     return -1;
    191 
    192   int32 size = GetCodedUIntSize(value);
    193 
    194   return WriteUIntSize(writer, value, size);
    195 }
    196 
    197 int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) {
    198   if (!writer || size < 0 || size > 8)
    199     return -1;
    200 
    201   if (size > 0) {
    202     const uint64 bit = 1LL << (size * 7);
    203 
    204     if (value > (bit - 2))
    205       return -1;
    206 
    207     value |= bit;
    208   } else {
    209     size = 1;
    210     int64 bit;
    211 
    212     for (;;) {
    213       bit = 1LL << (size * 7);
    214       const uint64 max = bit - 2;
    215 
    216       if (value <= max)
    217         break;
    218 
    219       ++size;
    220     }
    221 
    222     if (size > 8)
    223       return false;
    224 
    225     value |= bit;
    226   }
    227 
    228   return SerializeInt(writer, value, size);
    229 }
    230 
    231 int32 WriteID(IMkvWriter* writer, uint64 type) {
    232   if (!writer)
    233     return -1;
    234 
    235   writer->ElementStartNotify(type, writer->Position());
    236 
    237   const int32 size = GetUIntSize(type);
    238 
    239   return SerializeInt(writer, type, size);
    240 }
    241 
    242 bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) {
    243   if (!writer)
    244     return false;
    245 
    246   if (WriteID(writer, type))
    247     return false;
    248 
    249   if (WriteUInt(writer, size))
    250     return false;
    251 
    252   return true;
    253 }
    254 
    255 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
    256   if (!writer)
    257     return false;
    258 
    259   if (WriteID(writer, type))
    260     return false;
    261 
    262   const uint64 size = GetUIntSize(value);
    263   if (WriteUInt(writer, size))
    264     return false;
    265 
    266   if (SerializeInt(writer, value, static_cast<int32>(size)))
    267     return false;
    268 
    269   return true;
    270 }
    271 
    272 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
    273   if (!writer)
    274     return false;
    275 
    276   if (WriteID(writer, type))
    277     return false;
    278 
    279   if (WriteUInt(writer, 4))
    280     return false;
    281 
    282   if (SerializeFloat(writer, value))
    283     return false;
    284 
    285   return true;
    286 }
    287 
    288 bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
    289   if (!writer || !value)
    290     return false;
    291 
    292   if (WriteID(writer, type))
    293     return false;
    294 
    295   const int32 length = strlen(value);
    296   if (WriteUInt(writer, length))
    297     return false;
    298 
    299   if (writer->Write(value, length))
    300     return false;
    301 
    302   return true;
    303 }
    304 
    305 bool WriteEbmlElement(IMkvWriter* writer,
    306                       uint64 type,
    307                       const uint8* value,
    308                       uint64 size) {
    309   if (!writer || !value || size < 1)
    310     return false;
    311 
    312   if (WriteID(writer, type))
    313     return false;
    314 
    315   if (WriteUInt(writer, size))
    316     return false;
    317 
    318   if (writer->Write(value, static_cast<uint32>(size)))
    319     return false;
    320 
    321   return true;
    322 }
    323 
    324 uint64 WriteSimpleBlock(IMkvWriter* writer,
    325                         const uint8* data,
    326                         uint64 length,
    327                         uint64 track_number,
    328                         int64 timecode,
    329                         uint64 is_key) {
    330   if (!writer)
    331     return false;
    332 
    333   if (!data || length < 1)
    334     return false;
    335 
    336   //  Here we only permit track number values to be no greater than
    337   //  126, which the largest value we can store having a Matroska
    338   //  integer representation of only 1 byte.
    339 
    340   if (track_number < 1 || track_number > 126)
    341     return false;
    342 
    343   //  Technically the timestamp for a block can be less than the
    344   //  timestamp for the cluster itself (remember that block timestamp
    345   //  is a signed, 16-bit integer).  However, as a simplification we
    346   //  only permit non-negative cluster-relative timestamps for blocks.
    347 
    348   if (timecode < 0 || timecode > kMaxBlockTimecode)
    349     return false;
    350 
    351   if (WriteID(writer, kMkvSimpleBlock))
    352     return 0;
    353 
    354   const int32 size = static_cast<int32>(length) + 4;
    355   if (WriteUInt(writer, size))
    356     return 0;
    357 
    358   if (WriteUInt(writer, static_cast<uint64>(track_number)))
    359     return 0;
    360 
    361   if (SerializeInt(writer, timecode, 2))
    362     return 0;
    363 
    364   uint64 flags = 0;
    365   if (is_key)
    366     flags |= 0x80;
    367 
    368   if (SerializeInt(writer, flags, 1))
    369     return 0;
    370 
    371   if (writer->Write(data, static_cast<uint32>(length)))
    372     return 0;
    373 
    374   const uint64 element_size =
    375     GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 + length;
    376 
    377   return element_size;
    378 }
    379 
    380 // We must write the metadata (key)frame as a BlockGroup element,
    381 // because we need to specify a duration for the frame.  The
    382 // BlockGroup element comprises the frame itself and its duration,
    383 // and is laid out as follows:
    384 //
    385 //   BlockGroup tag
    386 //   BlockGroup size
    387 //     Block tag
    388 //     Block size
    389 //     (the frame is the block payload)
    390 //     Duration tag
    391 //     Duration size
    392 //     (duration payload)
    393 //
    394 uint64 WriteMetadataBlock(IMkvWriter* writer,
    395                           const uint8* data,
    396                           uint64 length,
    397                           uint64 track_number,
    398                           int64 timecode,
    399                           uint64 duration) {
    400   // We don't backtrack when writing to the stream, so we must
    401   // pre-compute the BlockGroup size, by summing the sizes of each
    402   // sub-element (the block and the duration).
    403 
    404   // We use a single byte for the track number of the block, which
    405   // means the block header is exactly 4 bytes.
    406 
    407   // TODO(matthewjheaney): use EbmlMasterElementSize and WriteEbmlMasterElement
    408 
    409   const uint64 block_payload_size = 4 + length;
    410   const int32 block_size = GetCodedUIntSize(block_payload_size);
    411   const uint64 block_elem_size = 1 + block_size + block_payload_size;
    412 
    413   const int32 duration_payload_size = GetUIntSize(duration);
    414   const int32 duration_size = GetCodedUIntSize(duration_payload_size);
    415   const uint64 duration_elem_size = 1 + duration_size + duration_payload_size;
    416 
    417   const uint64 blockg_payload_size = block_elem_size + duration_elem_size;
    418   const int32 blockg_size = GetCodedUIntSize(blockg_payload_size);
    419   const uint64 blockg_elem_size = 1 + blockg_size + blockg_payload_size;
    420 
    421   if (WriteID(writer, kMkvBlockGroup))  // 1-byte ID size
    422     return 0;
    423 
    424   if (WriteUInt(writer, blockg_payload_size))
    425     return 0;
    426 
    427   //  Write Block element
    428 
    429   if (WriteID(writer, kMkvBlock))  // 1-byte ID size
    430     return 0;
    431 
    432   if (WriteUInt(writer, block_payload_size))
    433     return 0;
    434 
    435   // Byte 1 of 4
    436 
    437   if (WriteUInt(writer, track_number))
    438     return 0;
    439 
    440   // Bytes 2 & 3 of 4
    441 
    442   if (SerializeInt(writer, timecode, 2))
    443     return 0;
    444 
    445   // Byte 4 of 4
    446 
    447   const uint64 flags = 0;
    448 
    449   if (SerializeInt(writer, flags, 1))
    450     return 0;
    451 
    452   // Now write the actual frame (of metadata)
    453 
    454   if (writer->Write(data, static_cast<uint32>(length)))
    455     return 0;
    456 
    457   // Write Duration element
    458 
    459   if (WriteID(writer, kMkvBlockDuration))  // 1-byte ID size
    460     return 0;
    461 
    462   if (WriteUInt(writer, duration_payload_size))
    463     return 0;
    464 
    465   if (SerializeInt(writer, duration, duration_payload_size))
    466     return 0;
    467 
    468   // Note that we don't write a reference time as part of the block
    469   // group; no reference time(s) indicates that this block is a
    470   // keyframe.  (Unlike the case for a SimpleBlock element, the header
    471   // bits of the Block sub-element of a BlockGroup element do not
    472   // indicate keyframe status.  The keyframe status is inferred from
    473   // the absence of reference time sub-elements.)
    474 
    475   return blockg_elem_size;
    476 }
    477 
    478 // Writes a WebM BlockGroup with BlockAdditional data. The structure is as
    479 // follows:
    480 // Indentation shows sub-levels
    481 // BlockGroup
    482 //  Block
    483 //    Data
    484 //  BlockAdditions
    485 //    BlockMore
    486 //      BlockAddID
    487 //        1 (Denotes Alpha)
    488 //      BlockAdditional
    489 //        Data
    490 uint64 WriteBlockWithAdditional(IMkvWriter* writer,
    491                                 const uint8* data,
    492                                 uint64 length,
    493                                 const uint8* additional,
    494                                 uint64 additional_length,
    495                                 uint64 add_id,
    496                                 uint64 track_number,
    497                                 int64 timecode,
    498                                 uint64 is_key) {
    499   if (!data || !additional || length < 1 || additional_length < 1)
    500     return 0;
    501 
    502   const uint64 block_payload_size = 4 + length;
    503   const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock,
    504                                                        block_payload_size) +
    505                                  block_payload_size;
    506   const uint64 block_additional_elem_size = EbmlElementSize(kMkvBlockAdditional,
    507                                                             additional,
    508                                                             additional_length);
    509   const uint64 block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, add_id);
    510 
    511   const uint64 block_more_payload_size = block_addid_elem_size +
    512                                          block_additional_elem_size;
    513   const uint64 block_more_elem_size = EbmlMasterElementSize(
    514                                           kMkvBlockMore,
    515                                           block_more_payload_size) +
    516                                       block_more_payload_size;
    517   const uint64 block_additions_payload_size = block_more_elem_size;
    518   const uint64 block_additions_elem_size = EbmlMasterElementSize(
    519                                                kMkvBlockAdditions,
    520                                                block_additions_payload_size) +
    521                                            block_additions_payload_size;
    522   const uint64 block_group_payload_size = block_elem_size +
    523                                           block_additions_elem_size;
    524   const uint64 block_group_elem_size = EbmlMasterElementSize(
    525                                            kMkvBlockGroup,
    526                                            block_group_payload_size) +
    527                                        block_group_payload_size;
    528 
    529   if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
    530                               block_group_payload_size))
    531     return 0;
    532 
    533   if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
    534     return 0;
    535 
    536   if (WriteUInt(writer, track_number))
    537     return 0;
    538 
    539   if (SerializeInt(writer, timecode, 2))
    540     return 0;
    541 
    542   uint64 flags = 0;
    543   if (is_key)
    544     flags |= 0x80;
    545   if (SerializeInt(writer, flags, 1))
    546     return 0;
    547 
    548   if (writer->Write(data, static_cast<uint32>(length)))
    549     return 0;
    550 
    551   if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions,
    552                               block_additions_payload_size))
    553     return 0;
    554 
    555   if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size))
    556     return 0;
    557 
    558   if (!WriteEbmlElement(writer, kMkvBlockAddID, add_id))
    559     return 0;
    560 
    561   if (!WriteEbmlElement(writer, kMkvBlockAdditional,
    562                         additional, additional_length))
    563     return 0;
    564 
    565   return block_group_elem_size;
    566 }
    567 
    568 // Writes a WebM BlockGroup with DiscardPadding. The structure is as follows:
    569 // Indentation shows sub-levels
    570 // BlockGroup
    571 //  Block
    572 //    Data
    573 //  DiscardPadding
    574 uint64 WriteBlockWithDiscardPadding(IMkvWriter* writer,
    575                                     const uint8* data,
    576                                     uint64 length,
    577                                     int64 discard_padding,
    578                                     uint64 track_number,
    579                                     int64 timecode,
    580                                     uint64 is_key) {
    581   if (!data || length < 1 || discard_padding <= 0)
    582     return 0;
    583 
    584   const uint64 block_payload_size = 4 + length;
    585   const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock,
    586                                                        block_payload_size) +
    587                                  block_payload_size;
    588   const uint64 discard_padding_elem_size = EbmlElementSize(kMkvDiscardPadding,
    589                                                            discard_padding);
    590   const uint64 block_group_payload_size = block_elem_size +
    591                                           discard_padding_elem_size;
    592   const uint64 block_group_elem_size = EbmlMasterElementSize(
    593                                            kMkvBlockGroup,
    594                                            block_group_payload_size) +
    595                                        block_group_payload_size;
    596 
    597   if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
    598                               block_group_payload_size))
    599     return 0;
    600 
    601   if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
    602     return 0;
    603 
    604   if (WriteUInt(writer, track_number))
    605     return 0;
    606 
    607   if (SerializeInt(writer, timecode, 2))
    608     return 0;
    609 
    610   uint64 flags = 0;
    611   if (is_key)
    612     flags |= 0x80;
    613   if (SerializeInt(writer, flags, 1))
    614     return 0;
    615 
    616   if (writer->Write(data, static_cast<uint32>(length)))
    617     return 0;
    618 
    619   if (WriteID(writer, kMkvDiscardPadding))
    620     return 0;
    621 
    622   const uint64 size = GetUIntSize(discard_padding);
    623   if (WriteUInt(writer, size))
    624     return false;
    625 
    626   if (SerializeInt(writer, discard_padding, static_cast<int32>(size)))
    627     return false;
    628 
    629   return block_group_elem_size;
    630 }
    631 
    632 uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
    633   if (!writer)
    634     return false;
    635 
    636   // Subtract one for the void ID and the coded size.
    637   uint64 void_entry_size = size - 1 - GetCodedUIntSize(size-1);
    638   uint64 void_size = EbmlMasterElementSize(kMkvVoid, void_entry_size) +
    639                      void_entry_size;
    640 
    641   if (void_size != size)
    642     return 0;
    643 
    644   const int64 payload_position = writer->Position();
    645   if (payload_position < 0)
    646     return 0;
    647 
    648   if (WriteID(writer, kMkvVoid))
    649     return 0;
    650 
    651   if (WriteUInt(writer, void_entry_size))
    652     return 0;
    653 
    654   const uint8 value = 0;
    655   for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) {
    656     if (writer->Write(&value, 1))
    657       return 0;
    658   }
    659 
    660   const int64 stop_position = writer->Position();
    661   if (stop_position < 0 ||
    662       stop_position - payload_position != static_cast<int64>(void_size))
    663     return 0;
    664 
    665   return void_size;
    666 }
    667 
    668 void GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
    669   *major = 0;
    670   *minor = 2;
    671   *build = 1;
    672   *revision = 0;
    673 }
    674 
    675 }  // namespace mkvmuxer
    676 
    677 mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
    678   uint64 uid = 0;
    679 
    680 #ifdef __MINGW32__
    681   srand(*seed);
    682 #endif
    683 
    684   for (int i = 0; i < 7; ++i) {  // avoid problems with 8-byte values
    685     uid <<= 8;
    686 
    687     // TODO(fgalligan): Move random number generation to platform specific code.
    688 #ifdef _MSC_VER
    689     (void)seed;
    690     unsigned int random_value;
    691     const errno_t e = rand_s(&random_value);
    692     (void)e;
    693     const int32 nn  = random_value;
    694 #elif __ANDROID__
    695     int32 temp_num = 1;
    696     int fd = open("/dev/urandom", O_RDONLY);
    697     if (fd != -1) {
    698       read(fd, &temp_num, sizeof(int32));
    699       close(fd);
    700     }
    701     const int32 nn = temp_num;
    702 #elif defined __MINGW32__
    703     const int32 nn = rand();
    704 #else
    705     const int32 nn = rand_r(seed);
    706 #endif
    707     const int32 n = 0xFF & (nn >> 4);  // throw away low-order bits
    708 
    709     uid |= n;
    710   }
    711 
    712   return uid;
    713 }
    714