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