Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / libwebm / source / mkvmuxerutil.cpp
index e46cd7b..2424da5 100644 (file)
 #include <fcntl.h>
 #endif
 
+#include <cassert>
 #include <cmath>
 #include <cstdio>
-#ifdef _WIN32
+#ifdef _MSC_VER
 #define _CRT_RAND_S
 #endif
 #include <cstdlib>
 
 namespace mkvmuxer {
 
+namespace {
+
+// Date elements are always 8 octets in size.
+const int kDateElementSize = 8;
+
+}  // namespace
+
 int32 GetCodedUIntSize(uint64 value) {
   if (value < 0x000000000000007FULL)
     return 1;
@@ -74,6 +82,10 @@ uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
   return ebml_size;
 }
 
+uint64 EbmlElementSize(uint64 type, int64 value) {
+  return EbmlElementSize(type, static_cast<uint64>(value));
+}
+
 uint64 EbmlElementSize(uint64 type, uint64 value) {
   // Size of EBML ID
   int32 ebml_size = GetUIntSize(type);
@@ -132,6 +144,19 @@ uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
   return ebml_size;
 }
 
+uint64 EbmlDateElementSize(uint64 type, int64 value) {
+  // Size of EBML ID
+  uint64 ebml_size = GetUIntSize(type);
+
+  // Datasize
+  ebml_size += kDateElementSize;
+
+  // Size of Datasize
+  ebml_size++;
+
+  return ebml_size;
+}
+
 int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
   if (!writer || size < 1 || size > 8)
     return -1;
@@ -156,16 +181,22 @@ int32 SerializeFloat(IMkvWriter* writer, float f) {
   if (!writer)
     return -1;
 
-  const uint32& val = reinterpret_cast<const uint32&>(f);
+  assert(sizeof(uint32) == sizeof(float));
+  // This union is merely used to avoid a reinterpret_cast from float& to
+  // uint32& which will result in violation of strict aliasing.
+  union U32 {
+    uint32 u32;
+    float f;
+  } value;
+  value.f = f;
 
   for (int32 i = 1; i <= 4; ++i) {
     const int32 byte_count = 4 - i;
     const int32 bit_count = byte_count * 8;
 
-    const uint32 bb = val >> bit_count;
-    const uint8 b = static_cast<uint8>(bb);
+    const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
 
-    const int32 status = writer->Write(&b, 1);
+    const int32 status = writer->Write(&byte, 1);
 
     if (status < 0)
       return status;
@@ -281,11 +312,11 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
   if (WriteID(writer, type))
     return false;
 
-  const int32 length = strlen(value);
+  const uint64 length = strlen(value);
   if (WriteUInt(writer, length))
     return false;
 
-  if (writer->Write(value, length))
+  if (writer->Write(value, static_cast<const uint32>(length)))
     return false;
 
   return true;
@@ -310,6 +341,22 @@ bool WriteEbmlElement(IMkvWriter* writer,
   return true;
 }
 
+bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
+  if (!writer)
+    return false;
+
+  if (WriteID(writer, type))
+    return false;
+
+  if (WriteUInt(writer, kDateElementSize))
+    return false;
+
+  if (SerializeInt(writer, value, kDateElementSize))
+    return false;
+
+  return true;
+}
+
 uint64 WriteSimpleBlock(IMkvWriter* writer,
                         const uint8* data,
                         uint64 length,
@@ -464,7 +511,8 @@ uint64 WriteMetadataBlock(IMkvWriter* writer,
   return blockg_elem_size;
 }
 
-// Writes a WebM Block with Additional. The structure is as follows
+// Writes a WebM BlockGroup with BlockAdditional data. The structure is as
+// follows:
 // Indentation shows sub-levels
 // BlockGroup
 //  Block
@@ -553,6 +601,70 @@ uint64 WriteBlockWithAdditional(IMkvWriter* writer,
   return block_group_elem_size;
 }
 
+// Writes a WebM BlockGroup with DiscardPadding. The structure is as follows:
+// Indentation shows sub-levels
+// BlockGroup
+//  Block
+//    Data
+//  DiscardPadding
+uint64 WriteBlockWithDiscardPadding(IMkvWriter* writer,
+                                    const uint8* data,
+                                    uint64 length,
+                                    int64 discard_padding,
+                                    uint64 track_number,
+                                    int64 timecode,
+                                    uint64 is_key) {
+  if (!data || length < 1 || discard_padding <= 0)
+    return 0;
+
+  const uint64 block_payload_size = 4 + length;
+  const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock,
+                                                       block_payload_size) +
+                                 block_payload_size;
+  const uint64 discard_padding_elem_size = EbmlElementSize(kMkvDiscardPadding,
+                                                           discard_padding);
+  const uint64 block_group_payload_size = block_elem_size +
+                                          discard_padding_elem_size;
+  const uint64 block_group_elem_size = EbmlMasterElementSize(
+                                           kMkvBlockGroup,
+                                           block_group_payload_size) +
+                                       block_group_payload_size;
+
+  if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
+                              block_group_payload_size))
+    return 0;
+
+  if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
+    return 0;
+
+  if (WriteUInt(writer, track_number))
+    return 0;
+
+  if (SerializeInt(writer, timecode, 2))
+    return 0;
+
+  uint64 flags = 0;
+  if (is_key)
+    flags |= 0x80;
+  if (SerializeInt(writer, flags, 1))
+    return 0;
+
+  if (writer->Write(data, static_cast<uint32>(length)))
+    return 0;
+
+  if (WriteID(writer, kMkvDiscardPadding))
+    return 0;
+
+  const uint64 size = GetUIntSize(discard_padding);
+  if (WriteUInt(writer, size))
+    return false;
+
+  if (SerializeInt(writer, discard_padding, static_cast<int32>(size)))
+    return false;
+
+  return block_group_elem_size;
+}
+
 uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
   if (!writer)
     return false;
@@ -600,11 +712,16 @@ void GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
 
 mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
   uint64 uid = 0;
+
+#ifdef __MINGW32__
+  srand(*seed);
+#endif
+
   for (int i = 0; i < 7; ++i) {  // avoid problems with 8-byte values
     uid <<= 8;
 
     // TODO(fgalligan): Move random number generation to platform specific code.
-#ifdef _WIN32
+#ifdef _MSC_VER
     (void)seed;
     unsigned int random_value;
     const errno_t e = rand_s(&random_value);
@@ -618,6 +735,8 @@ mkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
       close(fd);
     }
     const int32 nn = temp_num;
+#elif defined __MINGW32__
+    const int32 nn = rand();
 #else
     const int32 nn = rand_r(seed);
 #endif