]> granicus.if.org Git - libvpx/blob - third_party/libwebm/mkvmuxer/mkvmuxerutil.cc
vp9-noise estimate: Adhust threshold for Low level detection.
[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 GetUIntSize(libwebm::kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 +
177          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 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 ebml_size;
246 }
247
248 uint64_t EbmlElementSize(uint64_t type, uint64_t value) {
249   // Size of EBML ID
250   int32_t ebml_size = GetUIntSize(type);
251
252   // Datasize
253   ebml_size += GetUIntSize(value);
254
255   // Size of Datasize
256   ebml_size++;
257
258   return ebml_size;
259 }
260
261 uint64_t EbmlElementSize(uint64_t type, float /* value */) {
262   // Size of EBML ID
263   uint64_t ebml_size = GetUIntSize(type);
264
265   // Datasize
266   ebml_size += sizeof(float);
267
268   // Size of Datasize
269   ebml_size++;
270
271   return ebml_size;
272 }
273
274 uint64_t EbmlElementSize(uint64_t type, const char* value) {
275   if (!value)
276     return 0;
277
278   // Size of EBML ID
279   uint64_t ebml_size = GetUIntSize(type);
280
281   // Datasize
282   ebml_size += strlen(value);
283
284   // Size of Datasize
285   ebml_size++;
286
287   return ebml_size;
288 }
289
290 uint64_t EbmlElementSize(uint64_t type, const uint8_t* value, uint64_t size) {
291   if (!value)
292     return 0;
293
294   // Size of EBML ID
295   uint64_t ebml_size = GetUIntSize(type);
296
297   // Datasize
298   ebml_size += size;
299
300   // Size of Datasize
301   ebml_size += GetCodedUIntSize(size);
302
303   return ebml_size;
304 }
305
306 uint64_t EbmlDateElementSize(uint64_t type) {
307   // Size of EBML ID
308   uint64_t ebml_size = GetUIntSize(type);
309
310   // Datasize
311   ebml_size += kDateElementSize;
312
313   // Size of Datasize
314   ebml_size++;
315
316   return ebml_size;
317 }
318
319 int32_t SerializeInt(IMkvWriter* writer, int64_t value, int32_t size) {
320   if (!writer || size < 1 || size > 8)
321     return -1;
322
323   for (int32_t i = 1; i <= size; ++i) {
324     const int32_t byte_count = size - i;
325     const int32_t bit_count = byte_count * 8;
326
327     const int64_t bb = value >> bit_count;
328     const uint8_t b = static_cast<uint8_t>(bb);
329
330     const int32_t status = writer->Write(&b, 1);
331
332     if (status < 0)
333       return status;
334   }
335
336   return 0;
337 }
338
339 int32_t SerializeFloat(IMkvWriter* writer, float f) {
340   if (!writer)
341     return -1;
342
343   assert(sizeof(uint32_t) == sizeof(float));
344   // This union is merely used to avoid a reinterpret_cast from float& to
345   // uint32& which will result in violation of strict aliasing.
346   union U32 {
347     uint32_t u32;
348     float f;
349   } value;
350   value.f = f;
351
352   for (int32_t i = 1; i <= 4; ++i) {
353     const int32_t byte_count = 4 - i;
354     const int32_t bit_count = byte_count * 8;
355
356     const uint8_t byte = static_cast<uint8_t>(value.u32 >> bit_count);
357
358     const int32_t status = writer->Write(&byte, 1);
359
360     if (status < 0)
361       return status;
362   }
363
364   return 0;
365 }
366
367 int32_t WriteUInt(IMkvWriter* writer, uint64_t value) {
368   if (!writer)
369     return -1;
370
371   int32_t size = GetCodedUIntSize(value);
372
373   return WriteUIntSize(writer, value, size);
374 }
375
376 int32_t WriteUIntSize(IMkvWriter* writer, uint64_t value, int32_t size) {
377   if (!writer || size < 0 || size > 8)
378     return -1;
379
380   if (size > 0) {
381     const uint64_t bit = 1LL << (size * 7);
382
383     if (value > (bit - 2))
384       return -1;
385
386     value |= bit;
387   } else {
388     size = 1;
389     int64_t bit;
390
391     for (;;) {
392       bit = 1LL << (size * 7);
393       const uint64_t max = bit - 2;
394
395       if (value <= max)
396         break;
397
398       ++size;
399     }
400
401     if (size > 8)
402       return false;
403
404     value |= bit;
405   }
406
407   return SerializeInt(writer, value, size);
408 }
409
410 int32_t WriteID(IMkvWriter* writer, uint64_t type) {
411   if (!writer)
412     return -1;
413
414   writer->ElementStartNotify(type, writer->Position());
415
416   const int32_t size = GetUIntSize(type);
417
418   return SerializeInt(writer, type, size);
419 }
420
421 bool WriteEbmlMasterElement(IMkvWriter* writer, uint64_t type, uint64_t size) {
422   if (!writer)
423     return false;
424
425   if (WriteID(writer, type))
426     return false;
427
428   if (WriteUInt(writer, size))
429     return false;
430
431   return true;
432 }
433
434 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value) {
435   if (!writer)
436     return false;
437
438   if (WriteID(writer, type))
439     return false;
440
441   const uint64_t size = GetUIntSize(value);
442   if (WriteUInt(writer, size))
443     return false;
444
445   if (SerializeInt(writer, value, static_cast<int32_t>(size)))
446     return false;
447
448   return true;
449 }
450
451 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, int64_t value) {
452   if (!writer)
453     return false;
454
455   if (WriteID(writer, type))
456     return 0;
457
458   const uint64_t size = GetIntSize(value);
459   if (WriteUInt(writer, size))
460     return false;
461
462   if (SerializeInt(writer, value, static_cast<int32_t>(size)))
463     return false;
464
465   return true;
466 }
467
468 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, float value) {
469   if (!writer)
470     return false;
471
472   if (WriteID(writer, type))
473     return false;
474
475   if (WriteUInt(writer, 4))
476     return false;
477
478   if (SerializeFloat(writer, value))
479     return false;
480
481   return true;
482 }
483
484 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const char* value) {
485   if (!writer || !value)
486     return false;
487
488   if (WriteID(writer, type))
489     return false;
490
491   const uint64_t length = strlen(value);
492   if (WriteUInt(writer, length))
493     return false;
494
495   if (writer->Write(value, static_cast<const uint32_t>(length)))
496     return false;
497
498   return true;
499 }
500
501 bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const uint8_t* value,
502                       uint64_t size) {
503   if (!writer || !value || size < 1)
504     return false;
505
506   if (WriteID(writer, type))
507     return false;
508
509   if (WriteUInt(writer, size))
510     return false;
511
512   if (writer->Write(value, static_cast<uint32_t>(size)))
513     return false;
514
515   return true;
516 }
517
518 bool WriteEbmlDateElement(IMkvWriter* writer, uint64_t type, int64_t value) {
519   if (!writer)
520     return false;
521
522   if (WriteID(writer, type))
523     return false;
524
525   if (WriteUInt(writer, kDateElementSize))
526     return false;
527
528   if (SerializeInt(writer, value, kDateElementSize))
529     return false;
530
531   return true;
532 }
533
534 uint64_t WriteFrame(IMkvWriter* writer, const Frame* const frame,
535                     Cluster* cluster) {
536   if (!writer || !frame || !frame->IsValid() || !cluster ||
537       !cluster->timecode_scale())
538     return 0;
539
540   //  Technically the timecode for a block can be less than the
541   //  timecode for the cluster itself (remember that block timecode
542   //  is a signed, 16-bit integer).  However, as a simplification we
543   //  only permit non-negative cluster-relative timecodes for blocks.
544   const int64_t relative_timecode = cluster->GetRelativeTimecode(
545       frame->timestamp() / cluster->timecode_scale());
546   if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
547     return 0;
548
549   return frame->CanBeSimpleBlock() ?
550              WriteSimpleBlock(writer, frame, relative_timecode) :
551              WriteBlock(writer, frame, relative_timecode,
552                         cluster->timecode_scale());
553 }
554
555 uint64_t WriteVoidElement(IMkvWriter* writer, uint64_t size) {
556   if (!writer)
557     return false;
558
559   // Subtract one for the void ID and the coded size.
560   uint64_t void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
561   uint64_t void_size =
562       EbmlMasterElementSize(libwebm::kMkvVoid, void_entry_size) +
563       void_entry_size;
564
565   if (void_size != size)
566     return 0;
567
568   const int64_t payload_position = writer->Position();
569   if (payload_position < 0)
570     return 0;
571
572   if (WriteID(writer, libwebm::kMkvVoid))
573     return 0;
574
575   if (WriteUInt(writer, void_entry_size))
576     return 0;
577
578   const uint8_t value = 0;
579   for (int32_t i = 0; i < static_cast<int32_t>(void_entry_size); ++i) {
580     if (writer->Write(&value, 1))
581       return 0;
582   }
583
584   const int64_t stop_position = writer->Position();
585   if (stop_position < 0 ||
586       stop_position - payload_position != static_cast<int64_t>(void_size))
587     return 0;
588
589   return void_size;
590 }
591
592 void GetVersion(int32_t* major, int32_t* minor, int32_t* build,
593                 int32_t* revision) {
594   *major = 0;
595   *minor = 2;
596   *build = 1;
597   *revision = 0;
598 }
599
600 uint64_t MakeUID(unsigned int* seed) {
601   uint64_t uid = 0;
602
603 #ifdef __MINGW32__
604   srand(*seed);
605 #endif
606
607   for (int i = 0; i < 7; ++i) {  // avoid problems with 8-byte values
608     uid <<= 8;
609
610 // TODO(fgalligan): Move random number generation to platform specific code.
611 #ifdef _MSC_VER
612     (void)seed;
613     const int32_t nn = rand();
614 #elif __ANDROID__
615     int32_t temp_num = 1;
616     int fd = open("/dev/urandom", O_RDONLY);
617     if (fd != -1) {
618       read(fd, &temp_num, sizeof(temp_num));
619       close(fd);
620     }
621     const int32_t nn = temp_num;
622 #elif defined __MINGW32__
623     const int32_t nn = rand();
624 #else
625     const int32_t nn = rand_r(seed);
626 #endif
627     const int32_t n = 0xFF & (nn >> 4);  // throw away low-order bits
628
629     uid |= n;
630   }
631
632   return uid;
633 }
634
635 }  // namespace mkvmuxer