#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;
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);
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;
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;
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;
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,
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
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;
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);
close(fd);
}
const int32 nn = temp_num;
+#elif defined __MINGW32__
+ const int32 nn = rand();
#else
const int32 nn = rand_r(seed);
#endif