]> granicus.if.org Git - libvpx/blob - third_party/libwebm/mkvmuxer/mkvmuxerutil.cc
Revert "third_party: Roll libwebm snapshot."
[libvpx] / third_party / libwebm / mkvmuxer / mkvmuxerutil.cc
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 #endif
14
15 #include <cassert>
16 #include <cmath>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20 #include <ctime>
21 #include <new>
22
23 #include "common/webmids.h"
24 #include "mkvmuxer/mkvmuxer.h"
25 #include "mkvmuxer/mkvwriter.h"
26
27 namespace mkvmuxer {
28
29 namespace {
30
31 // Date elements are always 8 octets in size.
32 const int kDateElementSize = 8;
33
34 uint64_t WriteBlock(IMkvWriter* writer, const Frame* const frame,
35                     int64_t timecode, uint64_t timecode_scale) {
36   uint64_t block_additional_elem_size = 0;
37   uint64_t block_addid_elem_size = 0;
38   uint64_t block_more_payload_size = 0;
39   uint64_t block_more_elem_size = 0;
40   uint64_t block_additions_payload_size = 0;
41   uint64_t block_additions_elem_size = 0;
42   if (frame->additional()) {
43     block_additional_elem_size =
44         EbmlElementSize(libwebm::kMkvBlockAdditional, frame->additional(),
45                         frame->additional_length());
46     block_addid_elem_size =
47         EbmlElementSize(libwebm::kMkvBlockAddID, frame->add_id());
48
49     block_more_payload_size =
50         block_addid_elem_size + block_additional_elem_size;
51     block_more_elem_size =
52         EbmlMasterElementSize(libwebm::kMkvBlockMore, block_more_payload_size) +
53         block_more_payload_size;
54     block_additions_payload_size = block_more_elem_size;
55     block_additions_elem_size =
56         EbmlMasterElementSize(libwebm::kMkvBlockAdditions,
57                               block_additions_payload_size) +
58         block_additions_payload_size;
59   }
60
61   uint64_t discard_padding_elem_size = 0;
62   if (frame->discard_padding() != 0) {
63     discard_padding_elem_size =
64         EbmlElementSize(libwebm::kMkvDiscardPadding, frame->discard_padding());
65   }
66
67   const uint64_t reference_block_timestamp =
68       frame->reference_block_timestamp() / timecode_scale;
69   uint64_t reference_block_elem_size = 0;
70   if (!frame->is_key()) {
71     reference_block_elem_size =
72         EbmlElementSize(libwebm::kMkvReferenceBlock, reference_block_timestamp);
73   }
74
75   const uint64_t duration = frame->duration() / timecode_scale;
76   uint64_t block_duration_elem_size = 0;
77   if (duration > 0)
78     block_duration_elem_size =
79         EbmlElementSize(libwebm::kMkvBlockDuration, duration);
80
81   const uint64_t block_payload_size = 4 + frame->length();
82   const uint64_t block_elem_size =
83       EbmlMasterElementSize(libwebm::kMkvBlock, block_payload_size) +
84       block_payload_size;
85
86   const uint64_t block_group_payload_size =
87       block_elem_size + block_additions_elem_size + block_duration_elem_size +
88       discard_padding_elem_size + reference_block_elem_size;
89
90   if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockGroup,
91                               block_group_payload_size)) {
92     return 0;
93   }
94
95   if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlock, block_payload_size))
96     return 0;
97
98   if (WriteUInt(writer, frame->track_number()))
99     return 0;
100
101   if (SerializeInt(writer, timecode, 2))
102     return 0;
103
104   // For a Block, flags is always 0.
105   if (SerializeInt(writer, 0, 1))
106     return 0;
107
108   if (writer->Write(frame->frame(), static_cast<uint32_t>(frame->length())))
109     return 0;
110
111   if (frame->additional()) {
112     if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockAdditions,
113                                 block_additions_payload_size)) {
114       return 0;
115     }
116
117     if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockMore,
118                                 block_more_payload_size))
119       return 0;
120
121     if (!WriteEbmlElement(writer, libwebm::kMkvBlockAddID, frame->add_id()))
122       return 0;
123
124     if (!WriteEbmlElement(writer, libwebm::kMkvBlockAdditional,
125                           frame->additional(), frame->additional_length())) {
126       return 0;
127     }
128   }
129
130   if (frame->discard_padding() != 0 &&
131       !WriteEbmlElement(writer, libwebm::kMkvDiscardPadding,
132                         frame->discard_padding())) {
133     return false;
134   }
135
136   if (!frame->is_key() &&
137       !WriteEbmlElement(writer, libwebm::kMkvReferenceBlock,
138                         reference_block_timestamp)) {
139     return false;
140   }
141
142   if (duration > 0 &&
143       !WriteEbmlElement(writer, libwebm::kMkvBlockDuration, duration)) {
144     return false;
145   }
146   return EbmlMasterElementSize(libwebm::kMkvBlockGroup,
147                                block_group_payload_size) +
148          block_group_payload_size;
149 }
150
151 uint64_t WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame,
152                           int64_t timecode) {
153   if (WriteID(writer, libwebm::kMkvSimpleBlock))
154     return 0;
155
156   const int32_t size = static_cast<int32_t>(frame->length()) + 4;
157   if (WriteUInt(writer, size))
158     return 0;
159
160   if (WriteUInt(writer, static_cast<uint64_t>(frame->track_number())))
161     return 0;
162
163   if (SerializeInt(writer, timecode, 2))
164     return 0;
165
166   uint64_t flags = 0;
167   if (frame->is_key())
168     flags |= 0x80;
169
170   if (SerializeInt(writer, flags, 1))
171     return 0;
172
173   if (writer->Write(frame->frame(), static_cast<uint32_t>(frame->length())))
174     return 0;
175
176   return static_cast<uint64_t>(GetUIntSize(libwebm::kMkvSimpleBlock) +
177                                GetCodedUIntSize(size) + 4 + frame->length());
178 }
179
180 }  // namespace
181
182 int32_t GetCodedUIntSize(uint64_t value) {
183   if (value < 0x000000000000007FULL)
184     return 1;
185   else if (value < 0x0000000000003FFFULL)
186     return 2;
187   else if (value < 0x00000000001FFFFFULL)
188     return 3;
189   else if (value < 0x000000000FFFFFFFULL)
190     return 4;
191   else if (value < 0x00000007FFFFFFFFULL)
192     return 5;
193   else if (value < 0x000003FFFFFFFFFFULL)
194     return 6;
195   else if (value < 0x0001FFFFFFFFFFFFULL)
196     return 7;
197   return 8;
198 }
199
200 int32_t GetUIntSize(uint64_t value) {
201   if (value < 0x0000000000000100ULL)
202     return 1;
203   else if (value < 0x0000000000010000ULL)
204     return 2;
205   else if (value < 0x0000000001000000ULL)
206     return 3;
207   else if (value < 0x0000000100000000ULL)
208     return 4;
209   else if (value < 0x0000010000000000ULL)
210     return 5;
211   else if (value < 0x0001000000000000ULL)
212     return 6;
213   else if (value < 0x0100000000000000ULL)
214     return 7;
215   return 8;
216 }
217
218 int32_t GetIntSize(int64_t value) {
219   // Doubling the requested value ensures positive values with their high bit
220   // set are written with 0-padding to avoid flipping the signedness.
221   const uint64_t v = (value < 0) ? value ^ -1LL : value;
222   return GetUIntSize(2 * v);
223 }
224
225 uint64_t EbmlMasterElementSize(uint64_t type, uint64_t value) {
226   // Size of EBML ID
227   int32_t ebml_size = GetUIntSize(type);
228
229   // Datasize
230   ebml_size += GetCodedUIntSize(value);
231
232   return static_cast<uint64_t>(ebml_size);
233 }
234
235 uint64_t EbmlElementSize(uint64_t type, int64_t value) {
236   // Size of EBML ID
237   int32_t ebml_size = GetUIntSize(type);
238
239   // Datasize
240   ebml_size += GetIntSize(value);
241
242   // Size of Datasize
243   ebml_size++;
244
245   return static_cast<uint64_t>(ebml_size);
246 }
247
248 uint64_t EbmlElementSize(uint64_t type, uint64_t value) {
249   return EbmlElementSize(type, value, 0);
250 }
251
252 uint64_t EbmlElementSize(uint64_t type, uint64_t value, uint64_t fixed_size) {
253   // Size of EBML ID
254   uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
255
256   // Datasize
257   ebml_size +=
258       (fixed_size > 0) ? fixed_size : static_cast<uint64_t>(GetUIntSize(value));
259
260   // Size of Datasize
261   ebml_size++;
262
263   return ebml_size;
264 }
265
266 uint64_t EbmlElementSize(uint64_t type, float /* value */) {
267   // Size of EBML ID
268   uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
269
270   // Datasize
271   ebml_size += sizeof(float);
272
273   // Size of Datasize
274   ebml_size++;
275
276   return ebml_size;
277 }
278
279 uint64_t EbmlElementSize(uint64_t type, const char* value) {
280   if (!value)
281     return 0;
282
283   // Size of EBML ID
284   uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
285
286   // Datasize
287   ebml_size += strlen(value);
288
289   // Size of Datasize
290   ebml_size++;
291
292   return ebml_size;
293 }
294
295 uint64_t EbmlElementSize(uint64_t type, const uint8_t* value, uint64_t size) {
296   if (!value)
297     return 0;
298
299   // Size of EBML ID
300   uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
301
302   // Datasize
303   ebml_size += size;
304
305   // Size of Datasize
306   ebml_size += GetCodedUIntSize(size);
307
308   return ebml_size;
309 }
310
311 uint64_t EbmlDateElementSize(uint64_t type) {
312   // Size of EBML ID
313   uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
314
315   // Datasize
316   ebml_size += kDateElementSize;
317
318   // Size of Datasize
319   ebml_size++;
320
321   return ebml_size;
322 }
323
324 int32_t SerializeInt(IMkvWriter* writer, int64_t value, int32_t size) {
325   if (!writer || size < 1 || size > 8)
326     return -1;
327
328   for (int32_t i = 1; i <= size; ++i) {
329     const int32_t byte_count = size - i;
330     const int32_t bit_count = byte_count * 8;
331
332     const int64_t bb = value >> bit_count;
333     const uint8_t b = static_cast<uint8_t>(bb);
334
335     const int32_t status = writer->Write(&b, 1);
336
337     if (status < 0)
338       return status;
339   }
340
341   return 0;
342 }
343
344 int32_t SerializeFloat(IMkvWriter* writer, float f) {
345   if (!writer)
346     return -1;
347
348   assert(sizeof(uint32_t) == sizeof(float));
349   // This union is merely used to avoid a reinterpret_cast from float& to
350   // uint32& which will result in violation of strict aliasing.
351   union U32 {
352     uint32_t u32;
353     float f;
354   } value;
355   value.f = f;
356
357   for (int32_t i = 1; i <= 4; ++i) {
358     const int32_t byte_count = 4 - i;
359     const int32_t bit_count = byte_count * 8;
360
361     const uint8_t byte = static_cast<uint8_t>(value.u32 >> bit_count);
362
363     const int32_t status = writer->Write(&byte, 1);
364
365     if (status < 0)
366       return status;
367   }
368
369   return 0;
370 }
371
372 int32_t WriteUInt(IMkvWriter* writer, uint64_t value) {
373   if (!writer)
374     return -1;
375
376   int32_t size = GetCodedUIntSize(value);
377
378   return WriteUIntSize(writer, value, size);
379 }
380
381 int32_t WriteUIntSize(IMkvWriter* writer, uint64_t value, int32_t size) {
382   if (!writer || size < 0 || size > 8)
383     return -1;
384
385   if (size > 0) {
386     const uint64_t bit = 1LL << (size * 7);
387
388     if (value > (bit - 2))
389       return -1;
390
391     value |= bit;
392   } else {
393     size = 1;
394     int64_t bit;
395
396     for (;;) {
397       bit = 1LL << (size * 7);
398       const uint64_t max = bit - 2;
399
400       if (value <= max)
401         break;
402
403       ++size;
404     }
405
406     if (size > 8)
407       return false;
408
409     value |= bit;
410   }
411
412   return SerializeInt(writer, value, size);
413 }
414
415 int32_t WriteID(IMkvWriter* writer, uint64_t type) {
416   if (!writer)
417     return -1;
418
419   writer->ElementStartNotify(type, writer->Position());
420
421   const int32_t size = GetUIntSize(type);
422
423   return SerializeInt(writer, type, size);
424 }
425
426 bool WriteEbmlMasterElement(IMkvWriter* writer, uint64_t type, uint64_t size) {
427   if (!writer)
428     return false;
429
430   if (WriteID(writer, type))
431     return false;
432
433   if (WriteUInt(writer, size))
434     return false;
435
436   return true;
437 }
438
439 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value) {
440   return WriteEbmlElement(writer, type, value, 0);
441 }
442
443 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value,
444                       uint64_t fixed_size) {
445   if (!writer)
446     return false;
447
448   if (WriteID(writer, type))
449     return false;
450
451   uint64_t size = static_cast<uint64_t>(GetUIntSize(value));
452   if (fixed_size > 0) {
453     if (size > fixed_size)
454       return false;
455     size = fixed_size;
456   }
457   if (WriteUInt(writer, size))
458     return false;
459
460   if (SerializeInt(writer, value, static_cast<int32_t>(size)))
461     return false;
462
463   return true;
464 }
465
466 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, int64_t value) {
467   if (!writer)
468     return false;
469
470   if (WriteID(writer, type))
471     return 0;
472
473   const uint64_t size = GetIntSize(value);
474   if (WriteUInt(writer, size))
475     return false;
476
477   if (SerializeInt(writer, value, static_cast<int32_t>(size)))
478     return false;
479
480   return true;
481 }
482
483 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, float value) {
484   if (!writer)
485     return false;
486
487   if (WriteID(writer, type))
488     return false;
489
490   if (WriteUInt(writer, 4))
491     return false;
492
493   if (SerializeFloat(writer, value))
494     return false;
495
496   return true;
497 }
498
499 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const char* value) {
500   if (!writer || !value)
501     return false;
502
503   if (WriteID(writer, type))
504     return false;
505
506   const uint64_t length = strlen(value);
507   if (WriteUInt(writer, length))
508     return false;
509
510   if (writer->Write(value, static_cast<const uint32_t>(length)))
511     return false;
512
513   return true;
514 }
515
516 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const uint8_t* value,
517                       uint64_t size) {
518   if (!writer || !value || size < 1)
519     return false;
520
521   if (WriteID(writer, type))
522     return false;
523
524   if (WriteUInt(writer, size))
525     return false;
526
527   if (writer->Write(value, static_cast<uint32_t>(size)))
528     return false;
529
530   return true;
531 }
532
533 bool WriteEbmlDateElement(IMkvWriter* writer, uint64_t type, int64_t value) {
534   if (!writer)
535     return false;
536
537   if (WriteID(writer, type))
538     return false;
539
540   if (WriteUInt(writer, kDateElementSize))
541     return false;
542
543   if (SerializeInt(writer, value, kDateElementSize))
544     return false;
545
546   return true;
547 }
548
549 uint64_t WriteFrame(IMkvWriter* writer, const Frame* const frame,
550                     Cluster* cluster) {
551   if (!writer || !frame || !frame->IsValid() || !cluster ||
552       !cluster->timecode_scale())
553     return 0;
554
555   //  Technically the timecode for a block can be less than the
556   //  timecode for the cluster itself (remember that block timecode
557   //  is a signed, 16-bit integer).  However, as a simplification we
558   //  only permit non-negative cluster-relative timecodes for blocks.
559   const int64_t relative_timecode = cluster->GetRelativeTimecode(
560       frame->timestamp() / cluster->timecode_scale());
561   if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
562     return 0;
563
564   return frame->CanBeSimpleBlock() ?
565              WriteSimpleBlock(writer, frame, relative_timecode) :
566              WriteBlock(writer, frame, relative_timecode,
567                         cluster->timecode_scale());
568 }
569
570 uint64_t WriteVoidElement(IMkvWriter* writer, uint64_t size) {
571   if (!writer)
572     return false;
573
574   // Subtract one for the void ID and the coded size.
575   uint64_t void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
576   uint64_t void_size =
577       EbmlMasterElementSize(libwebm::kMkvVoid, void_entry_size) +
578       void_entry_size;
579
580   if (void_size != size)
581     return 0;
582
583   const int64_t 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_t value = 0;
594   for (int32_t i = 0; i < static_cast<int32_t>(void_entry_size); ++i) {
595     if (writer->Write(&value, 1))
596       return 0;
597   }
598
599   const int64_t stop_position = writer->Position();
600   if (stop_position < 0 ||
601       stop_position - payload_position != static_cast<int64_t>(void_size))
602     return 0;
603
604   return void_size;
605 }
606
607 void GetVersion(int32_t* major, int32_t* minor, int32_t* build,
608                 int32_t* revision) {
609   *major = 0;
610   *minor = 2;
611   *build = 1;
612   *revision = 0;
613 }
614
615 uint64_t MakeUID(unsigned int* seed) {
616   uint64_t 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_t nn = rand();
629 #elif __ANDROID__
630     int32_t 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_t nn = temp_num;
637 #elif defined __MINGW32__
638     const int32_t nn = rand();
639 #else
640     const int32_t nn = rand_r(seed);
641 #endif
642     const int32_t n = 0xFF & (nn >> 4);  // throw away low-order bits
643
644     uid |= n;
645   }
646
647   return uid;
648 }
649
650 }  // namespace mkvmuxer