Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / libvpx / source / libvpx / third_party / libwebm / mkvmuxerutil.cpp
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 namespace {
33
34 // Date elements are always 8 octets in size.
35 const int kDateElementSize = 8;
36
37 }  // namespace
38
39 int32 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
57 int32 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
75 uint64 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
85 uint64 EbmlElementSize(uint64 type, int64 value) {
86   return EbmlElementSize(type, static_cast<uint64>(value));
87 }
88
89 uint64 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
102 uint64 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
115 uint64 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
131 uint64 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
147 uint64 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
160 int32 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
180 int32 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
208 int32 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
217 int32 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
251 int32 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
262 bool 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
275 bool 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
292 bool 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
308 bool 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
325 bool 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
342 bool 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
358 uint64 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 //
424 uint64 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
517 uint64 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
591 uint64 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
643 uint64 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
679 void 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
688 mkvmuxer::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 }