1233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Copyright (c) 2012 The WebM project authors. All Rights Reserved. 2233d2500723e5594f3e7c70896ffeeef32b9c950ywan// 3233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Use of this source code is governed by a BSD-style license 4233d2500723e5594f3e7c70896ffeeef32b9c950ywan// that can be found in the LICENSE file in the root of the source 5233d2500723e5594f3e7c70896ffeeef32b9c950ywan// tree. An additional intellectual property rights grant can be found 6233d2500723e5594f3e7c70896ffeeef32b9c950ywan// in the file PATENTS. All contributing project authors may 7233d2500723e5594f3e7c70896ffeeef32b9c950ywan// be found in the AUTHORS file in the root of the source tree. 8233d2500723e5594f3e7c70896ffeeef32b9c950ywan 9233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "mkvmuxerutil.hpp" 10233d2500723e5594f3e7c70896ffeeef32b9c950ywan 11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef __ANDROID__ 12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <fcntl.h> 13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 14233d2500723e5594f3e7c70896ffeeef32b9c950ywan 15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cassert> 16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cmath> 17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cstdio> 18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER 19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define _CRT_RAND_S 20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 21233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cstdlib> 22233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <cstring> 23233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <ctime> 24233d2500723e5594f3e7c70896ffeeef32b9c950ywan 25233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <new> 26233d2500723e5594f3e7c70896ffeeef32b9c950ywan 27233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "mkvwriter.hpp" 28233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "webmids.hpp" 29233d2500723e5594f3e7c70896ffeeef32b9c950ywan 30233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace mkvmuxer { 31233d2500723e5594f3e7c70896ffeeef32b9c950ywan 32233d2500723e5594f3e7c70896ffeeef32b9c950ywanint32 GetCodedUIntSize(uint64 value) { 33233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (value < 0x000000000000007FULL) 34233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1; 35233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x0000000000003FFFULL) 36233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 2; 37233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x00000000001FFFFFULL) 38233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3; 39233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x000000000FFFFFFFULL) 40233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 4; 41233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x00000007FFFFFFFFULL) 42233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 5; 43233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x000003FFFFFFFFFFULL) 44233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 6; 45233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x0001FFFFFFFFFFFFULL) 46233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 7; 47233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 8; 48233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 49233d2500723e5594f3e7c70896ffeeef32b9c950ywan 50233d2500723e5594f3e7c70896ffeeef32b9c950ywanint32 GetUIntSize(uint64 value) { 51233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (value < 0x0000000000000100ULL) 52233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1; 53233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x0000000000010000ULL) 54233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 2; 55233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x0000000001000000ULL) 56233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3; 57233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x0000000100000000ULL) 58233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 4; 59233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x0000010000000000ULL) 60233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 5; 61233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x0001000000000000ULL) 62233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 6; 63233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (value < 0x0100000000000000ULL) 64233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 7; 65233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 8; 66233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 67233d2500723e5594f3e7c70896ffeeef32b9c950ywan 68233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 EbmlMasterElementSize(uint64 type, uint64 value) { 69233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Size of EBML ID 70233d2500723e5594f3e7c70896ffeeef32b9c950ywan int32 ebml_size = GetUIntSize(type); 71233d2500723e5594f3e7c70896ffeeef32b9c950ywan 72233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Datasize 73233d2500723e5594f3e7c70896ffeeef32b9c950ywan ebml_size += GetCodedUIntSize(value); 74233d2500723e5594f3e7c70896ffeeef32b9c950ywan 75233d2500723e5594f3e7c70896ffeeef32b9c950ywan return ebml_size; 76233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 77233d2500723e5594f3e7c70896ffeeef32b9c950ywan 78233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 EbmlElementSize(uint64 type, int64 value) { 79233d2500723e5594f3e7c70896ffeeef32b9c950ywan return EbmlElementSize(type, static_cast<uint64>(value)); 80233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 81233d2500723e5594f3e7c70896ffeeef32b9c950ywan 82233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 EbmlElementSize(uint64 type, uint64 value) { 83233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Size of EBML ID 84233d2500723e5594f3e7c70896ffeeef32b9c950ywan int32 ebml_size = GetUIntSize(type); 85233d2500723e5594f3e7c70896ffeeef32b9c950ywan 86233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Datasize 87233d2500723e5594f3e7c70896ffeeef32b9c950ywan ebml_size += GetUIntSize(value); 88233d2500723e5594f3e7c70896ffeeef32b9c950ywan 89233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Size of Datasize 90233d2500723e5594f3e7c70896ffeeef32b9c950ywan ebml_size++; 91233d2500723e5594f3e7c70896ffeeef32b9c950ywan 92233d2500723e5594f3e7c70896ffeeef32b9c950ywan return ebml_size; 93233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 94233d2500723e5594f3e7c70896ffeeef32b9c950ywan 95233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 EbmlElementSize(uint64 type, float /* value */ ) { 96233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Size of EBML ID 97233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 ebml_size = GetUIntSize(type); 98233d2500723e5594f3e7c70896ffeeef32b9c950ywan 99233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Datasize 100233d2500723e5594f3e7c70896ffeeef32b9c950ywan ebml_size += sizeof(float); 101233d2500723e5594f3e7c70896ffeeef32b9c950ywan 102233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Size of Datasize 103233d2500723e5594f3e7c70896ffeeef32b9c950ywan ebml_size++; 104233d2500723e5594f3e7c70896ffeeef32b9c950ywan 105233d2500723e5594f3e7c70896ffeeef32b9c950ywan return ebml_size; 106233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 107233d2500723e5594f3e7c70896ffeeef32b9c950ywan 108233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 EbmlElementSize(uint64 type, const char* value) { 109233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!value) 110233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 111233d2500723e5594f3e7c70896ffeeef32b9c950ywan 112233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Size of EBML ID 113233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 ebml_size = GetUIntSize(type); 114233d2500723e5594f3e7c70896ffeeef32b9c950ywan 115233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Datasize 116233d2500723e5594f3e7c70896ffeeef32b9c950ywan ebml_size += strlen(value); 117233d2500723e5594f3e7c70896ffeeef32b9c950ywan 118233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Size of Datasize 119233d2500723e5594f3e7c70896ffeeef32b9c950ywan ebml_size++; 120233d2500723e5594f3e7c70896ffeeef32b9c950ywan 121233d2500723e5594f3e7c70896ffeeef32b9c950ywan return ebml_size; 122233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 123233d2500723e5594f3e7c70896ffeeef32b9c950ywan 124233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) { 125233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!value) 126233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 127233d2500723e5594f3e7c70896ffeeef32b9c950ywan 128233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Size of EBML ID 129233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 ebml_size = GetUIntSize(type); 130233d2500723e5594f3e7c70896ffeeef32b9c950ywan 131233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Datasize 132233d2500723e5594f3e7c70896ffeeef32b9c950ywan ebml_size += size; 133233d2500723e5594f3e7c70896ffeeef32b9c950ywan 134233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Size of Datasize 135233d2500723e5594f3e7c70896ffeeef32b9c950ywan ebml_size += GetCodedUIntSize(size); 136233d2500723e5594f3e7c70896ffeeef32b9c950ywan 137233d2500723e5594f3e7c70896ffeeef32b9c950ywan return ebml_size; 138233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 139233d2500723e5594f3e7c70896ffeeef32b9c950ywan 140233d2500723e5594f3e7c70896ffeeef32b9c950ywanint32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) { 141233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer || size < 1 || size > 8) 142233d2500723e5594f3e7c70896ffeeef32b9c950ywan return -1; 143233d2500723e5594f3e7c70896ffeeef32b9c950ywan 144233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (int32 i = 1; i <= size; ++i) { 145233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 byte_count = size - i; 146233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 bit_count = byte_count * 8; 147233d2500723e5594f3e7c70896ffeeef32b9c950ywan 148233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int64 bb = value >> bit_count; 149233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint8 b = static_cast<uint8>(bb); 150233d2500723e5594f3e7c70896ffeeef32b9c950ywan 151233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 status = writer->Write(&b, 1); 152233d2500723e5594f3e7c70896ffeeef32b9c950ywan 153233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (status < 0) 154233d2500723e5594f3e7c70896ffeeef32b9c950ywan return status; 155233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 156233d2500723e5594f3e7c70896ffeeef32b9c950ywan 157233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 158233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 159233d2500723e5594f3e7c70896ffeeef32b9c950ywan 160233d2500723e5594f3e7c70896ffeeef32b9c950ywanint32 SerializeFloat(IMkvWriter* writer, float f) { 161233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer) 162233d2500723e5594f3e7c70896ffeeef32b9c950ywan return -1; 163233d2500723e5594f3e7c70896ffeeef32b9c950ywan 164233d2500723e5594f3e7c70896ffeeef32b9c950ywan assert(sizeof(uint32) == sizeof(float)); 165233d2500723e5594f3e7c70896ffeeef32b9c950ywan // This union is merely used to avoid a reinterpret_cast from float& to 166233d2500723e5594f3e7c70896ffeeef32b9c950ywan // uint32& which will result in violation of strict aliasing. 167233d2500723e5594f3e7c70896ffeeef32b9c950ywan union U32 { 168233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint32 u32; 169233d2500723e5594f3e7c70896ffeeef32b9c950ywan float f; 170233d2500723e5594f3e7c70896ffeeef32b9c950ywan } value; 171233d2500723e5594f3e7c70896ffeeef32b9c950ywan value.f = f; 172233d2500723e5594f3e7c70896ffeeef32b9c950ywan 173233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (int32 i = 1; i <= 4; ++i) { 174233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 byte_count = 4 - i; 175233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 bit_count = byte_count * 8; 176233d2500723e5594f3e7c70896ffeeef32b9c950ywan 177233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint8 byte = static_cast<uint8>(value.u32 >> bit_count); 178233d2500723e5594f3e7c70896ffeeef32b9c950ywan 179233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 status = writer->Write(&byte, 1); 180233d2500723e5594f3e7c70896ffeeef32b9c950ywan 181233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (status < 0) 182233d2500723e5594f3e7c70896ffeeef32b9c950ywan return status; 183233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 184233d2500723e5594f3e7c70896ffeeef32b9c950ywan 185233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 186233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 187233d2500723e5594f3e7c70896ffeeef32b9c950ywan 188233d2500723e5594f3e7c70896ffeeef32b9c950ywanint32 WriteUInt(IMkvWriter* writer, uint64 value) { 189233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer) 190233d2500723e5594f3e7c70896ffeeef32b9c950ywan return -1; 191233d2500723e5594f3e7c70896ffeeef32b9c950ywan 192233d2500723e5594f3e7c70896ffeeef32b9c950ywan int32 size = GetCodedUIntSize(value); 193233d2500723e5594f3e7c70896ffeeef32b9c950ywan 194233d2500723e5594f3e7c70896ffeeef32b9c950ywan return WriteUIntSize(writer, value, size); 195233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 196233d2500723e5594f3e7c70896ffeeef32b9c950ywan 197233d2500723e5594f3e7c70896ffeeef32b9c950ywanint32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) { 198233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer || size < 0 || size > 8) 199233d2500723e5594f3e7c70896ffeeef32b9c950ywan return -1; 200233d2500723e5594f3e7c70896ffeeef32b9c950ywan 201233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (size > 0) { 202233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 bit = 1LL << (size * 7); 203233d2500723e5594f3e7c70896ffeeef32b9c950ywan 204233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (value > (bit - 2)) 205233d2500723e5594f3e7c70896ffeeef32b9c950ywan return -1; 206233d2500723e5594f3e7c70896ffeeef32b9c950ywan 207233d2500723e5594f3e7c70896ffeeef32b9c950ywan value |= bit; 208233d2500723e5594f3e7c70896ffeeef32b9c950ywan } else { 209233d2500723e5594f3e7c70896ffeeef32b9c950ywan size = 1; 210233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64 bit; 211233d2500723e5594f3e7c70896ffeeef32b9c950ywan 212233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (;;) { 213233d2500723e5594f3e7c70896ffeeef32b9c950ywan bit = 1LL << (size * 7); 214233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 max = bit - 2; 215233d2500723e5594f3e7c70896ffeeef32b9c950ywan 216233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (value <= max) 217233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 218233d2500723e5594f3e7c70896ffeeef32b9c950ywan 219233d2500723e5594f3e7c70896ffeeef32b9c950ywan ++size; 220233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 221233d2500723e5594f3e7c70896ffeeef32b9c950ywan 222233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (size > 8) 223233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 224233d2500723e5594f3e7c70896ffeeef32b9c950ywan 225233d2500723e5594f3e7c70896ffeeef32b9c950ywan value |= bit; 226233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 227233d2500723e5594f3e7c70896ffeeef32b9c950ywan 228233d2500723e5594f3e7c70896ffeeef32b9c950ywan return SerializeInt(writer, value, size); 229233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 230233d2500723e5594f3e7c70896ffeeef32b9c950ywan 231233d2500723e5594f3e7c70896ffeeef32b9c950ywanint32 WriteID(IMkvWriter* writer, uint64 type) { 232233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer) 233233d2500723e5594f3e7c70896ffeeef32b9c950ywan return -1; 234233d2500723e5594f3e7c70896ffeeef32b9c950ywan 235233d2500723e5594f3e7c70896ffeeef32b9c950ywan writer->ElementStartNotify(type, writer->Position()); 236233d2500723e5594f3e7c70896ffeeef32b9c950ywan 237233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 size = GetUIntSize(type); 238233d2500723e5594f3e7c70896ffeeef32b9c950ywan 239233d2500723e5594f3e7c70896ffeeef32b9c950ywan return SerializeInt(writer, type, size); 240233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 241233d2500723e5594f3e7c70896ffeeef32b9c950ywan 242233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) { 243233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer) 244233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 245233d2500723e5594f3e7c70896ffeeef32b9c950ywan 246233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, type)) 247233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 248233d2500723e5594f3e7c70896ffeeef32b9c950ywan 249233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, size)) 250233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 251233d2500723e5594f3e7c70896ffeeef32b9c950ywan 252233d2500723e5594f3e7c70896ffeeef32b9c950ywan return true; 253233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 254233d2500723e5594f3e7c70896ffeeef32b9c950ywan 255233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) { 256233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer) 257233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 258233d2500723e5594f3e7c70896ffeeef32b9c950ywan 259233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, type)) 260233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 261233d2500723e5594f3e7c70896ffeeef32b9c950ywan 262233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 size = GetUIntSize(value); 263233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, size)) 264233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 265233d2500723e5594f3e7c70896ffeeef32b9c950ywan 266233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, value, static_cast<int32>(size))) 267233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 268233d2500723e5594f3e7c70896ffeeef32b9c950ywan 269233d2500723e5594f3e7c70896ffeeef32b9c950ywan return true; 270233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 271233d2500723e5594f3e7c70896ffeeef32b9c950ywan 272233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) { 273233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer) 274233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 275233d2500723e5594f3e7c70896ffeeef32b9c950ywan 276233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, type)) 277233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 278233d2500723e5594f3e7c70896ffeeef32b9c950ywan 279233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, 4)) 280233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 281233d2500723e5594f3e7c70896ffeeef32b9c950ywan 282233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeFloat(writer, value)) 283233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 284233d2500723e5594f3e7c70896ffeeef32b9c950ywan 285233d2500723e5594f3e7c70896ffeeef32b9c950ywan return true; 286233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 287233d2500723e5594f3e7c70896ffeeef32b9c950ywan 288233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) { 289233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer || !value) 290233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 291233d2500723e5594f3e7c70896ffeeef32b9c950ywan 292233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, type)) 293233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 294233d2500723e5594f3e7c70896ffeeef32b9c950ywan 295233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 length = strlen(value); 296233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, length)) 297233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 298233d2500723e5594f3e7c70896ffeeef32b9c950ywan 299233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (writer->Write(value, length)) 300233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 301233d2500723e5594f3e7c70896ffeeef32b9c950ywan 302233d2500723e5594f3e7c70896ffeeef32b9c950ywan return true; 303233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 304233d2500723e5594f3e7c70896ffeeef32b9c950ywan 305233d2500723e5594f3e7c70896ffeeef32b9c950ywanbool WriteEbmlElement(IMkvWriter* writer, 306233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 type, 307233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint8* value, 308233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 size) { 309233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer || !value || size < 1) 310233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 311233d2500723e5594f3e7c70896ffeeef32b9c950ywan 312233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, type)) 313233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 314233d2500723e5594f3e7c70896ffeeef32b9c950ywan 315233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, size)) 316233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 317233d2500723e5594f3e7c70896ffeeef32b9c950ywan 318233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (writer->Write(value, static_cast<uint32>(size))) 319233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 320233d2500723e5594f3e7c70896ffeeef32b9c950ywan 321233d2500723e5594f3e7c70896ffeeef32b9c950ywan return true; 322233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 323233d2500723e5594f3e7c70896ffeeef32b9c950ywan 324233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 WriteSimpleBlock(IMkvWriter* writer, 325233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint8* data, 326233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 length, 327233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 track_number, 328233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64 timecode, 329233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 is_key) { 330233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer) 331233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 332233d2500723e5594f3e7c70896ffeeef32b9c950ywan 333233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!data || length < 1) 334233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 335233d2500723e5594f3e7c70896ffeeef32b9c950ywan 336233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Here we only permit track number values to be no greater than 337233d2500723e5594f3e7c70896ffeeef32b9c950ywan // 126, which the largest value we can store having a Matroska 338233d2500723e5594f3e7c70896ffeeef32b9c950ywan // integer representation of only 1 byte. 339233d2500723e5594f3e7c70896ffeeef32b9c950ywan 340233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (track_number < 1 || track_number > 126) 341233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 342233d2500723e5594f3e7c70896ffeeef32b9c950ywan 343233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Technically the timestamp for a block can be less than the 344233d2500723e5594f3e7c70896ffeeef32b9c950ywan // timestamp for the cluster itself (remember that block timestamp 345233d2500723e5594f3e7c70896ffeeef32b9c950ywan // is a signed, 16-bit integer). However, as a simplification we 346233d2500723e5594f3e7c70896ffeeef32b9c950ywan // only permit non-negative cluster-relative timestamps for blocks. 347233d2500723e5594f3e7c70896ffeeef32b9c950ywan 348233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (timecode < 0 || timecode > kMaxBlockTimecode) 349233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 350233d2500723e5594f3e7c70896ffeeef32b9c950ywan 351233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, kMkvSimpleBlock)) 352233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 353233d2500723e5594f3e7c70896ffeeef32b9c950ywan 354233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 size = static_cast<int32>(length) + 4; 355233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, size)) 356233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 357233d2500723e5594f3e7c70896ffeeef32b9c950ywan 358233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, static_cast<uint64>(track_number))) 359233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 360233d2500723e5594f3e7c70896ffeeef32b9c950ywan 361233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, timecode, 2)) 362233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 363233d2500723e5594f3e7c70896ffeeef32b9c950ywan 364233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 flags = 0; 365233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (is_key) 366233d2500723e5594f3e7c70896ffeeef32b9c950ywan flags |= 0x80; 367233d2500723e5594f3e7c70896ffeeef32b9c950ywan 368233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, flags, 1)) 369233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 370233d2500723e5594f3e7c70896ffeeef32b9c950ywan 371233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (writer->Write(data, static_cast<uint32>(length))) 372233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 373233d2500723e5594f3e7c70896ffeeef32b9c950ywan 374233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 element_size = 375233d2500723e5594f3e7c70896ffeeef32b9c950ywan GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 + length; 376233d2500723e5594f3e7c70896ffeeef32b9c950ywan 377233d2500723e5594f3e7c70896ffeeef32b9c950ywan return element_size; 378233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 379233d2500723e5594f3e7c70896ffeeef32b9c950ywan 380233d2500723e5594f3e7c70896ffeeef32b9c950ywan// We must write the metadata (key)frame as a BlockGroup element, 381233d2500723e5594f3e7c70896ffeeef32b9c950ywan// because we need to specify a duration for the frame. The 382233d2500723e5594f3e7c70896ffeeef32b9c950ywan// BlockGroup element comprises the frame itself and its duration, 383233d2500723e5594f3e7c70896ffeeef32b9c950ywan// and is laid out as follows: 384233d2500723e5594f3e7c70896ffeeef32b9c950ywan// 385233d2500723e5594f3e7c70896ffeeef32b9c950ywan// BlockGroup tag 386233d2500723e5594f3e7c70896ffeeef32b9c950ywan// BlockGroup size 387233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Block tag 388233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Block size 389233d2500723e5594f3e7c70896ffeeef32b9c950ywan// (the frame is the block payload) 390233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Duration tag 391233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Duration size 392233d2500723e5594f3e7c70896ffeeef32b9c950ywan// (duration payload) 393233d2500723e5594f3e7c70896ffeeef32b9c950ywan// 394233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 WriteMetadataBlock(IMkvWriter* writer, 395233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint8* data, 396233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 length, 397233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 track_number, 398233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64 timecode, 399233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 duration) { 400233d2500723e5594f3e7c70896ffeeef32b9c950ywan // We don't backtrack when writing to the stream, so we must 401233d2500723e5594f3e7c70896ffeeef32b9c950ywan // pre-compute the BlockGroup size, by summing the sizes of each 402233d2500723e5594f3e7c70896ffeeef32b9c950ywan // sub-element (the block and the duration). 403233d2500723e5594f3e7c70896ffeeef32b9c950ywan 404233d2500723e5594f3e7c70896ffeeef32b9c950ywan // We use a single byte for the track number of the block, which 405233d2500723e5594f3e7c70896ffeeef32b9c950ywan // means the block header is exactly 4 bytes. 406233d2500723e5594f3e7c70896ffeeef32b9c950ywan 407233d2500723e5594f3e7c70896ffeeef32b9c950ywan // TODO(matthewjheaney): use EbmlMasterElementSize and WriteEbmlMasterElement 408233d2500723e5594f3e7c70896ffeeef32b9c950ywan 409233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_payload_size = 4 + length; 410233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 block_size = GetCodedUIntSize(block_payload_size); 411233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_elem_size = 1 + block_size + block_payload_size; 412233d2500723e5594f3e7c70896ffeeef32b9c950ywan 413233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 duration_payload_size = GetUIntSize(duration); 414233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 duration_size = GetCodedUIntSize(duration_payload_size); 415233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 duration_elem_size = 1 + duration_size + duration_payload_size; 416233d2500723e5594f3e7c70896ffeeef32b9c950ywan 417233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 blockg_payload_size = block_elem_size + duration_elem_size; 418233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 blockg_size = GetCodedUIntSize(blockg_payload_size); 419233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 blockg_elem_size = 1 + blockg_size + blockg_payload_size; 420233d2500723e5594f3e7c70896ffeeef32b9c950ywan 421233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, kMkvBlockGroup)) // 1-byte ID size 422233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 423233d2500723e5594f3e7c70896ffeeef32b9c950ywan 424233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, blockg_payload_size)) 425233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 426233d2500723e5594f3e7c70896ffeeef32b9c950ywan 427233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Write Block element 428233d2500723e5594f3e7c70896ffeeef32b9c950ywan 429233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, kMkvBlock)) // 1-byte ID size 430233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 431233d2500723e5594f3e7c70896ffeeef32b9c950ywan 432233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, block_payload_size)) 433233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 434233d2500723e5594f3e7c70896ffeeef32b9c950ywan 435233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Byte 1 of 4 436233d2500723e5594f3e7c70896ffeeef32b9c950ywan 437233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, track_number)) 438233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 439233d2500723e5594f3e7c70896ffeeef32b9c950ywan 440233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Bytes 2 & 3 of 4 441233d2500723e5594f3e7c70896ffeeef32b9c950ywan 442233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, timecode, 2)) 443233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 444233d2500723e5594f3e7c70896ffeeef32b9c950ywan 445233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Byte 4 of 4 446233d2500723e5594f3e7c70896ffeeef32b9c950ywan 447233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 flags = 0; 448233d2500723e5594f3e7c70896ffeeef32b9c950ywan 449233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, flags, 1)) 450233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 451233d2500723e5594f3e7c70896ffeeef32b9c950ywan 452233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Now write the actual frame (of metadata) 453233d2500723e5594f3e7c70896ffeeef32b9c950ywan 454233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (writer->Write(data, static_cast<uint32>(length))) 455233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 456233d2500723e5594f3e7c70896ffeeef32b9c950ywan 457233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Write Duration element 458233d2500723e5594f3e7c70896ffeeef32b9c950ywan 459233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, kMkvBlockDuration)) // 1-byte ID size 460233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 461233d2500723e5594f3e7c70896ffeeef32b9c950ywan 462233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, duration_payload_size)) 463233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 464233d2500723e5594f3e7c70896ffeeef32b9c950ywan 465233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, duration, duration_payload_size)) 466233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 467233d2500723e5594f3e7c70896ffeeef32b9c950ywan 468233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Note that we don't write a reference time as part of the block 469233d2500723e5594f3e7c70896ffeeef32b9c950ywan // group; no reference time(s) indicates that this block is a 470233d2500723e5594f3e7c70896ffeeef32b9c950ywan // keyframe. (Unlike the case for a SimpleBlock element, the header 471233d2500723e5594f3e7c70896ffeeef32b9c950ywan // bits of the Block sub-element of a BlockGroup element do not 472233d2500723e5594f3e7c70896ffeeef32b9c950ywan // indicate keyframe status. The keyframe status is inferred from 473233d2500723e5594f3e7c70896ffeeef32b9c950ywan // the absence of reference time sub-elements.) 474233d2500723e5594f3e7c70896ffeeef32b9c950ywan 475233d2500723e5594f3e7c70896ffeeef32b9c950ywan return blockg_elem_size; 476233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 477233d2500723e5594f3e7c70896ffeeef32b9c950ywan 478233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Writes a WebM BlockGroup with BlockAdditional data. The structure is as 479233d2500723e5594f3e7c70896ffeeef32b9c950ywan// follows: 480233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Indentation shows sub-levels 481233d2500723e5594f3e7c70896ffeeef32b9c950ywan// BlockGroup 482233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Block 483233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Data 484233d2500723e5594f3e7c70896ffeeef32b9c950ywan// BlockAdditions 485233d2500723e5594f3e7c70896ffeeef32b9c950ywan// BlockMore 486233d2500723e5594f3e7c70896ffeeef32b9c950ywan// BlockAddID 487233d2500723e5594f3e7c70896ffeeef32b9c950ywan// 1 (Denotes Alpha) 488233d2500723e5594f3e7c70896ffeeef32b9c950ywan// BlockAdditional 489233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Data 490233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 WriteBlockWithAdditional(IMkvWriter* writer, 491233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint8* data, 492233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 length, 493233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint8* additional, 494233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 additional_length, 495233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 add_id, 496233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 track_number, 497233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64 timecode, 498233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 is_key) { 499233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!data || !additional || length < 1 || additional_length < 1) 500233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 501233d2500723e5594f3e7c70896ffeeef32b9c950ywan 502233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_payload_size = 4 + length; 503233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock, 504233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_payload_size) + 505233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_payload_size; 506233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_additional_elem_size = EbmlElementSize(kMkvBlockAdditional, 507233d2500723e5594f3e7c70896ffeeef32b9c950ywan additional, 508233d2500723e5594f3e7c70896ffeeef32b9c950ywan additional_length); 509233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, add_id); 510233d2500723e5594f3e7c70896ffeeef32b9c950ywan 511233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_more_payload_size = block_addid_elem_size + 512233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_additional_elem_size; 513233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_more_elem_size = EbmlMasterElementSize( 514233d2500723e5594f3e7c70896ffeeef32b9c950ywan kMkvBlockMore, 515233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_more_payload_size) + 516233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_more_payload_size; 517233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_additions_payload_size = block_more_elem_size; 518233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_additions_elem_size = EbmlMasterElementSize( 519233d2500723e5594f3e7c70896ffeeef32b9c950ywan kMkvBlockAdditions, 520233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_additions_payload_size) + 521233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_additions_payload_size; 522233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_group_payload_size = block_elem_size + 523233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_additions_elem_size; 524233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_group_elem_size = EbmlMasterElementSize( 525233d2500723e5594f3e7c70896ffeeef32b9c950ywan kMkvBlockGroup, 526233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_group_payload_size) + 527233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_group_payload_size; 528233d2500723e5594f3e7c70896ffeeef32b9c950ywan 529233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!WriteEbmlMasterElement(writer, kMkvBlockGroup, 530233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_group_payload_size)) 531233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 532233d2500723e5594f3e7c70896ffeeef32b9c950ywan 533233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size)) 534233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 535233d2500723e5594f3e7c70896ffeeef32b9c950ywan 536233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, track_number)) 537233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 538233d2500723e5594f3e7c70896ffeeef32b9c950ywan 539233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, timecode, 2)) 540233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 541233d2500723e5594f3e7c70896ffeeef32b9c950ywan 542233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 flags = 0; 543233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (is_key) 544233d2500723e5594f3e7c70896ffeeef32b9c950ywan flags |= 0x80; 545233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, flags, 1)) 546233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 547233d2500723e5594f3e7c70896ffeeef32b9c950ywan 548233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (writer->Write(data, static_cast<uint32>(length))) 549233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 550233d2500723e5594f3e7c70896ffeeef32b9c950ywan 551233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions, 552233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_additions_payload_size)) 553233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 554233d2500723e5594f3e7c70896ffeeef32b9c950ywan 555233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size)) 556233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 557233d2500723e5594f3e7c70896ffeeef32b9c950ywan 558233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!WriteEbmlElement(writer, kMkvBlockAddID, add_id)) 559233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 560233d2500723e5594f3e7c70896ffeeef32b9c950ywan 561233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!WriteEbmlElement(writer, kMkvBlockAdditional, 562233d2500723e5594f3e7c70896ffeeef32b9c950ywan additional, additional_length)) 563233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 564233d2500723e5594f3e7c70896ffeeef32b9c950ywan 565233d2500723e5594f3e7c70896ffeeef32b9c950ywan return block_group_elem_size; 566233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 567233d2500723e5594f3e7c70896ffeeef32b9c950ywan 568233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Writes a WebM BlockGroup with DiscardPadding. The structure is as follows: 569233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Indentation shows sub-levels 570233d2500723e5594f3e7c70896ffeeef32b9c950ywan// BlockGroup 571233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Block 572233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Data 573233d2500723e5594f3e7c70896ffeeef32b9c950ywan// DiscardPadding 574233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 WriteBlockWithDiscardPadding(IMkvWriter* writer, 575233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint8* data, 576233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 length, 577233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64 discard_padding, 578233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 track_number, 579233d2500723e5594f3e7c70896ffeeef32b9c950ywan int64 timecode, 580233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 is_key) { 581233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!data || length < 1 || discard_padding <= 0) 582233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 583233d2500723e5594f3e7c70896ffeeef32b9c950ywan 584233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_payload_size = 4 + length; 585233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock, 586233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_payload_size) + 587233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_payload_size; 588233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 discard_padding_elem_size = EbmlElementSize(kMkvDiscardPadding, 589233d2500723e5594f3e7c70896ffeeef32b9c950ywan discard_padding); 590233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_group_payload_size = block_elem_size + 591233d2500723e5594f3e7c70896ffeeef32b9c950ywan discard_padding_elem_size; 592233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 block_group_elem_size = EbmlMasterElementSize( 593233d2500723e5594f3e7c70896ffeeef32b9c950ywan kMkvBlockGroup, 594233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_group_payload_size) + 595233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_group_payload_size; 596233d2500723e5594f3e7c70896ffeeef32b9c950ywan 597233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!WriteEbmlMasterElement(writer, kMkvBlockGroup, 598233d2500723e5594f3e7c70896ffeeef32b9c950ywan block_group_payload_size)) 599233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 600233d2500723e5594f3e7c70896ffeeef32b9c950ywan 601233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size)) 602233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 603233d2500723e5594f3e7c70896ffeeef32b9c950ywan 604233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, track_number)) 605233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 606233d2500723e5594f3e7c70896ffeeef32b9c950ywan 607233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, timecode, 2)) 608233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 609233d2500723e5594f3e7c70896ffeeef32b9c950ywan 610233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 flags = 0; 611233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (is_key) 612233d2500723e5594f3e7c70896ffeeef32b9c950ywan flags |= 0x80; 613233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, flags, 1)) 614233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 615233d2500723e5594f3e7c70896ffeeef32b9c950ywan 616233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (writer->Write(data, static_cast<uint32>(length))) 617233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 618233d2500723e5594f3e7c70896ffeeef32b9c950ywan 619233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, kMkvDiscardPadding)) 620233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 621233d2500723e5594f3e7c70896ffeeef32b9c950ywan 622233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint64 size = GetUIntSize(discard_padding); 623233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, size)) 624233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 625233d2500723e5594f3e7c70896ffeeef32b9c950ywan 626233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (SerializeInt(writer, discard_padding, static_cast<int32>(size))) 627233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 628233d2500723e5594f3e7c70896ffeeef32b9c950ywan 629233d2500723e5594f3e7c70896ffeeef32b9c950ywan return block_group_elem_size; 630233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 631233d2500723e5594f3e7c70896ffeeef32b9c950ywan 632233d2500723e5594f3e7c70896ffeeef32b9c950ywanuint64 WriteVoidElement(IMkvWriter* writer, uint64 size) { 633233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!writer) 634233d2500723e5594f3e7c70896ffeeef32b9c950ywan return false; 635233d2500723e5594f3e7c70896ffeeef32b9c950ywan 636233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Subtract one for the void ID and the coded size. 637233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 void_entry_size = size - 1 - GetCodedUIntSize(size-1); 638233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 void_size = EbmlMasterElementSize(kMkvVoid, void_entry_size) + 639233d2500723e5594f3e7c70896ffeeef32b9c950ywan void_entry_size; 640233d2500723e5594f3e7c70896ffeeef32b9c950ywan 641233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (void_size != size) 642233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 643233d2500723e5594f3e7c70896ffeeef32b9c950ywan 644233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int64 payload_position = writer->Position(); 645233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (payload_position < 0) 646233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 647233d2500723e5594f3e7c70896ffeeef32b9c950ywan 648233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteID(writer, kMkvVoid)) 649233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 650233d2500723e5594f3e7c70896ffeeef32b9c950ywan 651233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (WriteUInt(writer, void_entry_size)) 652233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 653233d2500723e5594f3e7c70896ffeeef32b9c950ywan 654233d2500723e5594f3e7c70896ffeeef32b9c950ywan const uint8 value = 0; 655233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) { 656233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (writer->Write(&value, 1)) 657233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 658233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 659233d2500723e5594f3e7c70896ffeeef32b9c950ywan 660233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int64 stop_position = writer->Position(); 661233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (stop_position < 0 || 662233d2500723e5594f3e7c70896ffeeef32b9c950ywan stop_position - payload_position != static_cast<int64>(void_size)) 663233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 0; 664233d2500723e5594f3e7c70896ffeeef32b9c950ywan 665233d2500723e5594f3e7c70896ffeeef32b9c950ywan return void_size; 666233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 667233d2500723e5594f3e7c70896ffeeef32b9c950ywan 668233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid GetVersion(int32* major, int32* minor, int32* build, int32* revision) { 669233d2500723e5594f3e7c70896ffeeef32b9c950ywan *major = 0; 670233d2500723e5594f3e7c70896ffeeef32b9c950ywan *minor = 2; 671233d2500723e5594f3e7c70896ffeeef32b9c950ywan *build = 1; 672233d2500723e5594f3e7c70896ffeeef32b9c950ywan *revision = 0; 673233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 674233d2500723e5594f3e7c70896ffeeef32b9c950ywan 675233d2500723e5594f3e7c70896ffeeef32b9c950ywan} // namespace mkvmuxer 676233d2500723e5594f3e7c70896ffeeef32b9c950ywan 677233d2500723e5594f3e7c70896ffeeef32b9c950ywanmkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) { 678233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint64 uid = 0; 679233d2500723e5594f3e7c70896ffeeef32b9c950ywan 680233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef __MINGW32__ 681233d2500723e5594f3e7c70896ffeeef32b9c950ywan srand(*seed); 682233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 683233d2500723e5594f3e7c70896ffeeef32b9c950ywan 684233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values 685233d2500723e5594f3e7c70896ffeeef32b9c950ywan uid <<= 8; 686233d2500723e5594f3e7c70896ffeeef32b9c950ywan 687233d2500723e5594f3e7c70896ffeeef32b9c950ywan // TODO(fgalligan): Move random number generation to platform specific code. 688233d2500723e5594f3e7c70896ffeeef32b9c950ywan#ifdef _MSC_VER 689233d2500723e5594f3e7c70896ffeeef32b9c950ywan (void)seed; 690233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int random_value; 691233d2500723e5594f3e7c70896ffeeef32b9c950ywan const errno_t e = rand_s(&random_value); 692233d2500723e5594f3e7c70896ffeeef32b9c950ywan (void)e; 693233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 nn = random_value; 694233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif __ANDROID__ 695233d2500723e5594f3e7c70896ffeeef32b9c950ywan int32 temp_num = 1; 696233d2500723e5594f3e7c70896ffeeef32b9c950ywan int fd = open("/dev/urandom", O_RDONLY); 697233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (fd != -1) { 698233d2500723e5594f3e7c70896ffeeef32b9c950ywan read(fd, &temp_num, sizeof(int32)); 699233d2500723e5594f3e7c70896ffeeef32b9c950ywan close(fd); 700233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 701233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 nn = temp_num; 702233d2500723e5594f3e7c70896ffeeef32b9c950ywan#elif defined __MINGW32__ 703233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 nn = rand(); 704233d2500723e5594f3e7c70896ffeeef32b9c950ywan#else 705233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 nn = rand_r(seed); 706233d2500723e5594f3e7c70896ffeeef32b9c950ywan#endif 707233d2500723e5594f3e7c70896ffeeef32b9c950ywan const int32 n = 0xFF & (nn >> 4); // throw away low-order bits 708233d2500723e5594f3e7c70896ffeeef32b9c950ywan 709233d2500723e5594f3e7c70896ffeeef32b9c950ywan uid |= n; 710233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 711233d2500723e5594f3e7c70896ffeeef32b9c950ywan 712233d2500723e5594f3e7c70896ffeeef32b9c950ywan return uid; 713233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 714