1a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//
3a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// Use of this source code is governed by a BSD-style license
4a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// that can be found in the LICENSE file in the root of the source
5a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// tree. An additional intellectual property rights grant can be found
6a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// in the file PATENTS.  All contributing project authors may
7a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// be found in the AUTHORS file in the root of the source tree.
8a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
9a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include "mkvmuxerutil.hpp"
10a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
11a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#ifdef __ANDROID__
12a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include <fcntl.h>
13a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#endif
14a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
15a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include <cassert>
16a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include <cmath>
17a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include <cstdio>
18a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#ifdef _MSC_VER
19a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#define _CRT_RAND_S
20a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#endif
21a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include <cstdlib>
22a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include <cstring>
23a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include <ctime>
24a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
25a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include <new>
26a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
27a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include "mkvwriter.hpp"
28a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#include "webmids.hpp"
29a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
30a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramaniannamespace mkvmuxer {
31a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
32a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianint32 GetCodedUIntSize(uint64 value) {
33a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (value < 0x000000000000007FULL)
34a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 1;
35a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x0000000000003FFFULL)
36a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 2;
37a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x00000000001FFFFFULL)
38a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 3;
39a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x000000000FFFFFFFULL)
40a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 4;
41a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x00000007FFFFFFFFULL)
42a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 5;
43a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x000003FFFFFFFFFFULL)
44a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 6;
45a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x0001FFFFFFFFFFFFULL)
46a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 7;
47a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return 8;
48a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
49a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
50a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianint32 GetUIntSize(uint64 value) {
51a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (value < 0x0000000000000100ULL)
52a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 1;
53a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x0000000000010000ULL)
54a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 2;
55a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x0000000001000000ULL)
56a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 3;
57a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x0000000100000000ULL)
58a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 4;
59a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x0000010000000000ULL)
60a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 5;
61a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x0001000000000000ULL)
62a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 6;
63a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  else if (value < 0x0100000000000000ULL)
64a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 7;
65a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return 8;
66a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
67a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
68a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 EbmlMasterElementSize(uint64 type, uint64 value) {
69a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Size of EBML ID
70a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  int32 ebml_size = GetUIntSize(type);
71a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
72a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Datasize
73a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ebml_size += GetCodedUIntSize(value);
74a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
75a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return ebml_size;
76a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
77a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
78a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 EbmlElementSize(uint64 type, int64 value) {
79a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return EbmlElementSize(type, static_cast<uint64>(value));
80a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
81a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
82a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 EbmlElementSize(uint64 type, uint64 value) {
83a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Size of EBML ID
84a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  int32 ebml_size = GetUIntSize(type);
85a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
86a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Datasize
87a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ebml_size += GetUIntSize(value);
88a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
89a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Size of Datasize
90a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ebml_size++;
91a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
92a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return ebml_size;
93a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
94a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
95a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 EbmlElementSize(uint64 type, float /* value */ ) {
96a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Size of EBML ID
97a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  uint64 ebml_size = GetUIntSize(type);
98a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
99a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Datasize
100a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ebml_size += sizeof(float);
101a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
102a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Size of Datasize
103a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ebml_size++;
104a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
105a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return ebml_size;
106a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
107a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
108a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 EbmlElementSize(uint64 type, const char* value) {
109a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!value)
110a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
111a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
112a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Size of EBML ID
113a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  uint64 ebml_size = GetUIntSize(type);
114a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
115a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Datasize
116a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ebml_size += strlen(value);
117a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
118a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Size of Datasize
119a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ebml_size++;
120a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
121a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return ebml_size;
122a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
123a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
124a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
125a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!value)
126a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
127a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
128a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Size of EBML ID
129a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  uint64 ebml_size = GetUIntSize(type);
130a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
131a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Datasize
132a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ebml_size += size;
133a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
134a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Size of Datasize
135a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ebml_size += GetCodedUIntSize(size);
136a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
137a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return ebml_size;
138a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
139a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
140a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianint32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
141a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer || size < 1 || size > 8)
142a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return -1;
143a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
144a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  for (int32 i = 1; i <= size; ++i) {
145a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 byte_count = size - i;
146a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 bit_count = byte_count * 8;
147a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
148a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int64 bb = value >> bit_count;
149a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const uint8 b = static_cast<uint8>(bb);
150a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
151a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 status = writer->Write(&b, 1);
152a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
153a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    if (status < 0)
154a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      return status;
155a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  }
156a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
157a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return 0;
158a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
159a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
160a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianint32 SerializeFloat(IMkvWriter* writer, float f) {
161a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer)
162a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return -1;
163a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
164a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  assert(sizeof(uint32) == sizeof(float));
165a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // This union is merely used to avoid a reinterpret_cast from float& to
166a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // uint32& which will result in violation of strict aliasing.
167a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  union U32 {
168a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    uint32 u32;
169a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    float f;
170a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  } value;
171a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  value.f = f;
172a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
173a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  for (int32 i = 1; i <= 4; ++i) {
174a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 byte_count = 4 - i;
175a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 bit_count = byte_count * 8;
176a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
177a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
178a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
179a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 status = writer->Write(&byte, 1);
180a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
181a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    if (status < 0)
182a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      return status;
183a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  }
184a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
185a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return 0;
186a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
187a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
188a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianint32 WriteUInt(IMkvWriter* writer, uint64 value) {
189a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer)
190a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return -1;
191a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
192a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  int32 size = GetCodedUIntSize(value);
193a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
194a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return WriteUIntSize(writer, value, size);
195a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
196a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
197a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianint32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) {
198a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer || size < 0 || size > 8)
199a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return -1;
200a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
201a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (size > 0) {
202a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const uint64 bit = 1LL << (size * 7);
203a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
204a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    if (value > (bit - 2))
205a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      return -1;
206a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
207a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    value |= bit;
208a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  } else {
209a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    size = 1;
210a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    int64 bit;
211a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
212a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    for (;;) {
213a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      bit = 1LL << (size * 7);
214a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      const uint64 max = bit - 2;
215a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
216a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      if (value <= max)
217a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian        break;
218a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
219a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      ++size;
220a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    }
221a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
222a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    if (size > 8)
223a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      return false;
224a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
225a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    value |= bit;
226a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  }
227a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
228a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return SerializeInt(writer, value, size);
229a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
230a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
231a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianint32 WriteID(IMkvWriter* writer, uint64 type) {
232a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer)
233a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return -1;
234a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
235a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  writer->ElementStartNotify(type, writer->Position());
236a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
237a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const int32 size = GetUIntSize(type);
238a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
239a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return SerializeInt(writer, type, size);
240a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
241a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
242a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianbool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) {
243a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer)
244a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
245a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
246a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, type))
247a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
248a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
249a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, size))
250a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
251a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
252a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return true;
253a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
254a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
255a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianbool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
256a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer)
257a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
258a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
259a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, type))
260a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
261a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
262a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 size = GetUIntSize(value);
263a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, size))
264a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
265a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
266a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, value, static_cast<int32>(size)))
267a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
268a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
269a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return true;
270a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
271a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
272a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianbool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
273a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer)
274a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
275a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
276a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, type))
277a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
278a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
279a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, 4))
280a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
281a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
282a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeFloat(writer, value))
283a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
284a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
285a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return true;
286a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
287a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
288a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianbool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
289a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer || !value)
290a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
291a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
292a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, type))
293a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
294a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
2956ac915abcdb404a00d927fe6308a47fcf09d9519hkuang  const uint64 length = strlen(value);
296a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, length))
297a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
298a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
2996ac915abcdb404a00d927fe6308a47fcf09d9519hkuang  if (writer->Write(value, static_cast<const uint32>(length)))
300a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
301a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
302a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return true;
303a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
304a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
305a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianbool WriteEbmlElement(IMkvWriter* writer,
306a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                      uint64 type,
307a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                      const uint8* value,
308a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                      uint64 size) {
309a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer || !value || size < 1)
310a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
311a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
312a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, type))
313a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
314a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
315a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, size))
316a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
317a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
318a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (writer->Write(value, static_cast<uint32>(size)))
319a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
320a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
321a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return true;
322a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
323a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
324a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 WriteSimpleBlock(IMkvWriter* writer,
325a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                        const uint8* data,
326a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                        uint64 length,
327a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                        uint64 track_number,
328a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                        int64 timecode,
329a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                        uint64 is_key) {
330a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer)
331a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
332a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
333a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!data || length < 1)
334a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
335a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
336a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  //  Here we only permit track number values to be no greater than
337a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  //  126, which the largest value we can store having a Matroska
338a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  //  integer representation of only 1 byte.
339a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
340a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (track_number < 1 || track_number > 126)
341a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
342a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
343a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  //  Technically the timestamp for a block can be less than the
344a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  //  timestamp for the cluster itself (remember that block timestamp
345a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  //  is a signed, 16-bit integer).  However, as a simplification we
346a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  //  only permit non-negative cluster-relative timestamps for blocks.
347a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
348a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (timecode < 0 || timecode > kMaxBlockTimecode)
349a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
350a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
351a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, kMkvSimpleBlock))
352a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
353a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
354a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const int32 size = static_cast<int32>(length) + 4;
355a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, size))
356a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
357a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
358a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, static_cast<uint64>(track_number)))
359a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
360a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
361a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, timecode, 2))
362a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
363a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
364a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  uint64 flags = 0;
365a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (is_key)
366a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    flags |= 0x80;
367a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
368a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, flags, 1))
369a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
370a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
371a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (writer->Write(data, static_cast<uint32>(length)))
372a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
373a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
374a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 element_size =
375a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    GetUIntSize(kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 + length;
376a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
377a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return element_size;
378a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
379a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
380a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// We must write the metadata (key)frame as a BlockGroup element,
381a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// because we need to specify a duration for the frame.  The
382a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// BlockGroup element comprises the frame itself and its duration,
383a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// and is laid out as follows:
384a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//
385a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//   BlockGroup tag
386a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//   BlockGroup size
387a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//     Block tag
388a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//     Block size
389a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//     (the frame is the block payload)
390a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//     Duration tag
391a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//     Duration size
392a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//     (duration payload)
393a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//
394a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 WriteMetadataBlock(IMkvWriter* writer,
395a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                          const uint8* data,
396a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                          uint64 length,
397a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                          uint64 track_number,
398a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                          int64 timecode,
399a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                          uint64 duration) {
400a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // We don't backtrack when writing to the stream, so we must
401a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // pre-compute the BlockGroup size, by summing the sizes of each
402a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // sub-element (the block and the duration).
403a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
404a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // We use a single byte for the track number of the block, which
405a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // means the block header is exactly 4 bytes.
406a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
407a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // TODO(matthewjheaney): use EbmlMasterElementSize and WriteEbmlMasterElement
408a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
409a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_payload_size = 4 + length;
410a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const int32 block_size = GetCodedUIntSize(block_payload_size);
411a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_elem_size = 1 + block_size + block_payload_size;
412a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
413a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const int32 duration_payload_size = GetUIntSize(duration);
414a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const int32 duration_size = GetCodedUIntSize(duration_payload_size);
415a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 duration_elem_size = 1 + duration_size + duration_payload_size;
416a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
417a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 blockg_payload_size = block_elem_size + duration_elem_size;
418a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const int32 blockg_size = GetCodedUIntSize(blockg_payload_size);
419a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 blockg_elem_size = 1 + blockg_size + blockg_payload_size;
420a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
421a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, kMkvBlockGroup))  // 1-byte ID size
422a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
423a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
424a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, blockg_payload_size))
425a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
426a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
427a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  //  Write Block element
428a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
429a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, kMkvBlock))  // 1-byte ID size
430a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
431a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
432a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, block_payload_size))
433a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
434a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
435a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Byte 1 of 4
436a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
437a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, track_number))
438a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
439a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
440a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Bytes 2 & 3 of 4
441a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
442a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, timecode, 2))
443a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
444a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
445a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Byte 4 of 4
446a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
447a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 flags = 0;
448a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
449a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, flags, 1))
450a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
451a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
452a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Now write the actual frame (of metadata)
453a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
454a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (writer->Write(data, static_cast<uint32>(length)))
455a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
456a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
457a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Write Duration element
458a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
459a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, kMkvBlockDuration))  // 1-byte ID size
460a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
461a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
462a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, duration_payload_size))
463a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
464a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
465a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, duration, duration_payload_size))
466a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
467a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
468a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Note that we don't write a reference time as part of the block
469a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // group; no reference time(s) indicates that this block is a
470a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // keyframe.  (Unlike the case for a SimpleBlock element, the header
471a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // bits of the Block sub-element of a BlockGroup element do not
472a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // indicate keyframe status.  The keyframe status is inferred from
473a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // the absence of reference time sub-elements.)
474a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
475a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return blockg_elem_size;
476a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
477a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
478a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// Writes a WebM BlockGroup with BlockAdditional data. The structure is as
479a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// follows:
480a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// Indentation shows sub-levels
481a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// BlockGroup
482a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//  Block
483a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//    Data
484a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//  BlockAdditions
485a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//    BlockMore
486a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//      BlockAddID
487a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//        1 (Denotes Alpha)
488a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//      BlockAdditional
489a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//        Data
490a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 WriteBlockWithAdditional(IMkvWriter* writer,
491a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                const uint8* data,
492a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                uint64 length,
493a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                const uint8* additional,
494a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                uint64 additional_length,
495a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                uint64 add_id,
496a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                uint64 track_number,
497a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                int64 timecode,
498a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                uint64 is_key) {
499a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!data || !additional || length < 1 || additional_length < 1)
500a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
501a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
502a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_payload_size = 4 + length;
503a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock,
504a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                                       block_payload_size) +
505a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                 block_payload_size;
506a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_additional_elem_size = EbmlElementSize(kMkvBlockAdditional,
507a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                                            additional,
508a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                                            additional_length);
509a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_addid_elem_size = EbmlElementSize(kMkvBlockAddID, add_id);
510a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
511a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_more_payload_size = block_addid_elem_size +
512a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                         block_additional_elem_size;
513a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_more_elem_size = EbmlMasterElementSize(
514a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                          kMkvBlockMore,
515a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                          block_more_payload_size) +
516a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                      block_more_payload_size;
517a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_additions_payload_size = block_more_elem_size;
518a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_additions_elem_size = EbmlMasterElementSize(
519a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                               kMkvBlockAdditions,
520a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                               block_additions_payload_size) +
521a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                           block_additions_payload_size;
522a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_group_payload_size = block_elem_size +
523a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                          block_additions_elem_size;
524a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_group_elem_size = EbmlMasterElementSize(
525a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                           kMkvBlockGroup,
526a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                           block_group_payload_size) +
527a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                       block_group_payload_size;
528a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
529a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
530a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                              block_group_payload_size))
531a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
532a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
533a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
534a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
535a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
536a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, track_number))
537a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
538a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
539a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, timecode, 2))
540a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
541a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
542a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  uint64 flags = 0;
543a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (is_key)
544a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    flags |= 0x80;
545a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, flags, 1))
546a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
547a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
548a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (writer->Write(data, static_cast<uint32>(length)))
549a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
550a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
551a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvBlockAdditions,
552a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                              block_additions_payload_size))
553a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
554a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
555a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvBlockMore, block_more_payload_size))
556a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
557a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
558a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvBlockAddID, add_id))
559a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
560a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
561a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!WriteEbmlElement(writer, kMkvBlockAdditional,
562a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                        additional, additional_length))
563a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
564a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
565a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return block_group_elem_size;
566a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
567a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
568a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// Writes a WebM BlockGroup with DiscardPadding. The structure is as follows:
569a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// Indentation shows sub-levels
570a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian// BlockGroup
571a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//  Block
572a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//    Data
573a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian//  DiscardPadding
574a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 WriteBlockWithDiscardPadding(IMkvWriter* writer,
575a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                    const uint8* data,
576a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                    uint64 length,
577a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                    int64 discard_padding,
578a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                    uint64 track_number,
579a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                    int64 timecode,
580a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                    uint64 is_key) {
581a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!data || length < 1 || discard_padding <= 0)
582a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
583a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
584a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_payload_size = 4 + length;
585a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock,
586a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                                       block_payload_size) +
587a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                 block_payload_size;
588a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 discard_padding_elem_size = EbmlElementSize(kMkvDiscardPadding,
589a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                                           discard_padding);
590a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_group_payload_size = block_elem_size +
591a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                          discard_padding_elem_size;
592a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 block_group_elem_size = EbmlMasterElementSize(
593a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                           kMkvBlockGroup,
594a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                           block_group_payload_size) +
595a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                                       block_group_payload_size;
596a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
597a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
598a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                              block_group_payload_size))
599a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
600a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
601a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
602a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
603a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
604a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, track_number))
605a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
606a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
607a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, timecode, 2))
608a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
609a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
610a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  uint64 flags = 0;
611a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (is_key)
612a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    flags |= 0x80;
613a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, flags, 1))
614a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
615a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
616a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (writer->Write(data, static_cast<uint32>(length)))
617a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
618a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
619a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, kMkvDiscardPadding))
620a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
621a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
622a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint64 size = GetUIntSize(discard_padding);
623a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, size))
624a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
625a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
626a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (SerializeInt(writer, discard_padding, static_cast<int32>(size)))
627a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
628a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
629a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return block_group_elem_size;
630a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
631a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
632a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianuint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
633a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (!writer)
634a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return false;
635a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
636a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  // Subtract one for the void ID and the coded size.
637a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  uint64 void_entry_size = size - 1 - GetCodedUIntSize(size-1);
638a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  uint64 void_size = EbmlMasterElementSize(kMkvVoid, void_entry_size) +
639a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian                     void_entry_size;
640a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
641a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (void_size != size)
642a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
643a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
644a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const int64 payload_position = writer->Position();
645a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (payload_position < 0)
646a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
647a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
648a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteID(writer, kMkvVoid))
649a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
650a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
651a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (WriteUInt(writer, void_entry_size))
652a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
653a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
654a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const uint8 value = 0;
655a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) {
656a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    if (writer->Write(&value, 1))
657a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      return 0;
658a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  }
659a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
660a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  const int64 stop_position = writer->Position();
661a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  if (stop_position < 0 ||
662a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      stop_position - payload_position != static_cast<int64>(void_size))
663a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    return 0;
664a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
665a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return void_size;
666a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
667a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
668a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianvoid GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
669a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  *major = 0;
670a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  *minor = 2;
671a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  *build = 1;
672a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  *revision = 0;
673a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
674a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
675a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}  // namespace mkvmuxer
676a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
677a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanianmkvmuxer::uint64 mkvmuxer::MakeUID(unsigned int* seed) {
678a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  uint64 uid = 0;
679a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
680a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#ifdef __MINGW32__
681a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  srand(*seed);
682a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#endif
683a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
684a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  for (int i = 0; i < 7; ++i) {  // avoid problems with 8-byte values
685a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    uid <<= 8;
686a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
687a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    // TODO(fgalligan): Move random number generation to platform specific code.
688a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#ifdef _MSC_VER
689a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    (void)seed;
690a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    unsigned int random_value;
691a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const errno_t e = rand_s(&random_value);
692a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    (void)e;
693a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 nn  = random_value;
694a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#elif __ANDROID__
695a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    int32 temp_num = 1;
696a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    int fd = open("/dev/urandom", O_RDONLY);
697a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    if (fd != -1) {
698a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      read(fd, &temp_num, sizeof(int32));
699a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian      close(fd);
700a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    }
701a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 nn = temp_num;
702a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#elif defined __MINGW32__
703a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 nn = rand();
704a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#else
705a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 nn = rand_r(seed);
706a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian#endif
707a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    const int32 n = 0xFF & (nn >> 4);  // throw away low-order bits
708a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
709a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian    uid |= n;
710a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  }
711a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian
712a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  return uid;
713a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian}
714