1*fb1b10abSAndroid Build Coastguard Worker // Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2*fb1b10abSAndroid Build Coastguard Worker //
3*fb1b10abSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license
4*fb1b10abSAndroid Build Coastguard Worker // that can be found in the LICENSE file in the root of the source
5*fb1b10abSAndroid Build Coastguard Worker // tree. An additional intellectual property rights grant can be found
6*fb1b10abSAndroid Build Coastguard Worker // in the file PATENTS. All contributing project authors may
7*fb1b10abSAndroid Build Coastguard Worker // be found in the AUTHORS file in the root of the source tree.
8*fb1b10abSAndroid Build Coastguard Worker
9*fb1b10abSAndroid Build Coastguard Worker #include "mkvmuxer/mkvmuxerutil.h"
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker #ifdef __ANDROID__
12*fb1b10abSAndroid Build Coastguard Worker #include <fcntl.h>
13*fb1b10abSAndroid Build Coastguard Worker #include <unistd.h>
14*fb1b10abSAndroid Build Coastguard Worker #endif
15*fb1b10abSAndroid Build Coastguard Worker
16*fb1b10abSAndroid Build Coastguard Worker #include <cassert>
17*fb1b10abSAndroid Build Coastguard Worker #include <cmath>
18*fb1b10abSAndroid Build Coastguard Worker #include <cstdio>
19*fb1b10abSAndroid Build Coastguard Worker #include <cstdlib>
20*fb1b10abSAndroid Build Coastguard Worker #include <cstring>
21*fb1b10abSAndroid Build Coastguard Worker #include <ctime>
22*fb1b10abSAndroid Build Coastguard Worker #include <new>
23*fb1b10abSAndroid Build Coastguard Worker
24*fb1b10abSAndroid Build Coastguard Worker #include "common/webmids.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "mkvmuxer/mkvmuxer.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "mkvmuxer/mkvwriter.h"
27*fb1b10abSAndroid Build Coastguard Worker
28*fb1b10abSAndroid Build Coastguard Worker namespace mkvmuxer {
29*fb1b10abSAndroid Build Coastguard Worker
30*fb1b10abSAndroid Build Coastguard Worker namespace {
31*fb1b10abSAndroid Build Coastguard Worker
32*fb1b10abSAndroid Build Coastguard Worker // Date elements are always 8 octets in size.
33*fb1b10abSAndroid Build Coastguard Worker const int kDateElementSize = 8;
34*fb1b10abSAndroid Build Coastguard Worker
WriteBlock(IMkvWriter * writer,const Frame * const frame,int64 timecode,uint64 timecode_scale)35*fb1b10abSAndroid Build Coastguard Worker uint64 WriteBlock(IMkvWriter* writer, const Frame* const frame, int64 timecode,
36*fb1b10abSAndroid Build Coastguard Worker uint64 timecode_scale) {
37*fb1b10abSAndroid Build Coastguard Worker uint64 block_additional_elem_size = 0;
38*fb1b10abSAndroid Build Coastguard Worker uint64 block_addid_elem_size = 0;
39*fb1b10abSAndroid Build Coastguard Worker uint64 block_more_payload_size = 0;
40*fb1b10abSAndroid Build Coastguard Worker uint64 block_more_elem_size = 0;
41*fb1b10abSAndroid Build Coastguard Worker uint64 block_additions_payload_size = 0;
42*fb1b10abSAndroid Build Coastguard Worker uint64 block_additions_elem_size = 0;
43*fb1b10abSAndroid Build Coastguard Worker if (frame->additional()) {
44*fb1b10abSAndroid Build Coastguard Worker block_additional_elem_size =
45*fb1b10abSAndroid Build Coastguard Worker EbmlElementSize(libwebm::kMkvBlockAdditional, frame->additional(),
46*fb1b10abSAndroid Build Coastguard Worker frame->additional_length());
47*fb1b10abSAndroid Build Coastguard Worker block_addid_elem_size = EbmlElementSize(
48*fb1b10abSAndroid Build Coastguard Worker libwebm::kMkvBlockAddID, static_cast<uint64>(frame->add_id()));
49*fb1b10abSAndroid Build Coastguard Worker
50*fb1b10abSAndroid Build Coastguard Worker block_more_payload_size =
51*fb1b10abSAndroid Build Coastguard Worker block_addid_elem_size + block_additional_elem_size;
52*fb1b10abSAndroid Build Coastguard Worker block_more_elem_size =
53*fb1b10abSAndroid Build Coastguard Worker EbmlMasterElementSize(libwebm::kMkvBlockMore, block_more_payload_size) +
54*fb1b10abSAndroid Build Coastguard Worker block_more_payload_size;
55*fb1b10abSAndroid Build Coastguard Worker block_additions_payload_size = block_more_elem_size;
56*fb1b10abSAndroid Build Coastguard Worker block_additions_elem_size =
57*fb1b10abSAndroid Build Coastguard Worker EbmlMasterElementSize(libwebm::kMkvBlockAdditions,
58*fb1b10abSAndroid Build Coastguard Worker block_additions_payload_size) +
59*fb1b10abSAndroid Build Coastguard Worker block_additions_payload_size;
60*fb1b10abSAndroid Build Coastguard Worker }
61*fb1b10abSAndroid Build Coastguard Worker
62*fb1b10abSAndroid Build Coastguard Worker uint64 discard_padding_elem_size = 0;
63*fb1b10abSAndroid Build Coastguard Worker if (frame->discard_padding() != 0) {
64*fb1b10abSAndroid Build Coastguard Worker discard_padding_elem_size =
65*fb1b10abSAndroid Build Coastguard Worker EbmlElementSize(libwebm::kMkvDiscardPadding,
66*fb1b10abSAndroid Build Coastguard Worker static_cast<int64>(frame->discard_padding()));
67*fb1b10abSAndroid Build Coastguard Worker }
68*fb1b10abSAndroid Build Coastguard Worker
69*fb1b10abSAndroid Build Coastguard Worker const uint64 reference_block_timestamp =
70*fb1b10abSAndroid Build Coastguard Worker frame->reference_block_timestamp() / timecode_scale;
71*fb1b10abSAndroid Build Coastguard Worker uint64 reference_block_elem_size = 0;
72*fb1b10abSAndroid Build Coastguard Worker if (!frame->is_key()) {
73*fb1b10abSAndroid Build Coastguard Worker reference_block_elem_size =
74*fb1b10abSAndroid Build Coastguard Worker EbmlElementSize(libwebm::kMkvReferenceBlock, reference_block_timestamp);
75*fb1b10abSAndroid Build Coastguard Worker }
76*fb1b10abSAndroid Build Coastguard Worker
77*fb1b10abSAndroid Build Coastguard Worker const uint64 duration = frame->duration() / timecode_scale;
78*fb1b10abSAndroid Build Coastguard Worker uint64 block_duration_elem_size = 0;
79*fb1b10abSAndroid Build Coastguard Worker if (duration > 0)
80*fb1b10abSAndroid Build Coastguard Worker block_duration_elem_size =
81*fb1b10abSAndroid Build Coastguard Worker EbmlElementSize(libwebm::kMkvBlockDuration, duration);
82*fb1b10abSAndroid Build Coastguard Worker
83*fb1b10abSAndroid Build Coastguard Worker const uint64 block_payload_size = 4 + frame->length();
84*fb1b10abSAndroid Build Coastguard Worker const uint64 block_elem_size =
85*fb1b10abSAndroid Build Coastguard Worker EbmlMasterElementSize(libwebm::kMkvBlock, block_payload_size) +
86*fb1b10abSAndroid Build Coastguard Worker block_payload_size;
87*fb1b10abSAndroid Build Coastguard Worker
88*fb1b10abSAndroid Build Coastguard Worker const uint64 block_group_payload_size =
89*fb1b10abSAndroid Build Coastguard Worker block_elem_size + block_additions_elem_size + block_duration_elem_size +
90*fb1b10abSAndroid Build Coastguard Worker discard_padding_elem_size + reference_block_elem_size;
91*fb1b10abSAndroid Build Coastguard Worker
92*fb1b10abSAndroid Build Coastguard Worker if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockGroup,
93*fb1b10abSAndroid Build Coastguard Worker block_group_payload_size)) {
94*fb1b10abSAndroid Build Coastguard Worker return 0;
95*fb1b10abSAndroid Build Coastguard Worker }
96*fb1b10abSAndroid Build Coastguard Worker
97*fb1b10abSAndroid Build Coastguard Worker if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlock, block_payload_size))
98*fb1b10abSAndroid Build Coastguard Worker return 0;
99*fb1b10abSAndroid Build Coastguard Worker
100*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, frame->track_number()))
101*fb1b10abSAndroid Build Coastguard Worker return 0;
102*fb1b10abSAndroid Build Coastguard Worker
103*fb1b10abSAndroid Build Coastguard Worker if (SerializeInt(writer, timecode, 2))
104*fb1b10abSAndroid Build Coastguard Worker return 0;
105*fb1b10abSAndroid Build Coastguard Worker
106*fb1b10abSAndroid Build Coastguard Worker // For a Block, flags is always 0.
107*fb1b10abSAndroid Build Coastguard Worker if (SerializeInt(writer, 0, 1))
108*fb1b10abSAndroid Build Coastguard Worker return 0;
109*fb1b10abSAndroid Build Coastguard Worker
110*fb1b10abSAndroid Build Coastguard Worker if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
111*fb1b10abSAndroid Build Coastguard Worker return 0;
112*fb1b10abSAndroid Build Coastguard Worker
113*fb1b10abSAndroid Build Coastguard Worker if (frame->additional()) {
114*fb1b10abSAndroid Build Coastguard Worker if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockAdditions,
115*fb1b10abSAndroid Build Coastguard Worker block_additions_payload_size)) {
116*fb1b10abSAndroid Build Coastguard Worker return 0;
117*fb1b10abSAndroid Build Coastguard Worker }
118*fb1b10abSAndroid Build Coastguard Worker
119*fb1b10abSAndroid Build Coastguard Worker if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockMore,
120*fb1b10abSAndroid Build Coastguard Worker block_more_payload_size))
121*fb1b10abSAndroid Build Coastguard Worker return 0;
122*fb1b10abSAndroid Build Coastguard Worker
123*fb1b10abSAndroid Build Coastguard Worker if (!WriteEbmlElement(writer, libwebm::kMkvBlockAddID,
124*fb1b10abSAndroid Build Coastguard Worker static_cast<uint64>(frame->add_id())))
125*fb1b10abSAndroid Build Coastguard Worker return 0;
126*fb1b10abSAndroid Build Coastguard Worker
127*fb1b10abSAndroid Build Coastguard Worker if (!WriteEbmlElement(writer, libwebm::kMkvBlockAdditional,
128*fb1b10abSAndroid Build Coastguard Worker frame->additional(), frame->additional_length())) {
129*fb1b10abSAndroid Build Coastguard Worker return 0;
130*fb1b10abSAndroid Build Coastguard Worker }
131*fb1b10abSAndroid Build Coastguard Worker }
132*fb1b10abSAndroid Build Coastguard Worker
133*fb1b10abSAndroid Build Coastguard Worker if (frame->discard_padding() != 0 &&
134*fb1b10abSAndroid Build Coastguard Worker !WriteEbmlElement(writer, libwebm::kMkvDiscardPadding,
135*fb1b10abSAndroid Build Coastguard Worker static_cast<int64>(frame->discard_padding()))) {
136*fb1b10abSAndroid Build Coastguard Worker return false;
137*fb1b10abSAndroid Build Coastguard Worker }
138*fb1b10abSAndroid Build Coastguard Worker
139*fb1b10abSAndroid Build Coastguard Worker if (!frame->is_key() && !WriteEbmlElement(writer, libwebm::kMkvReferenceBlock,
140*fb1b10abSAndroid Build Coastguard Worker reference_block_timestamp)) {
141*fb1b10abSAndroid Build Coastguard Worker return false;
142*fb1b10abSAndroid Build Coastguard Worker }
143*fb1b10abSAndroid Build Coastguard Worker
144*fb1b10abSAndroid Build Coastguard Worker if (duration > 0 &&
145*fb1b10abSAndroid Build Coastguard Worker !WriteEbmlElement(writer, libwebm::kMkvBlockDuration, duration)) {
146*fb1b10abSAndroid Build Coastguard Worker return false;
147*fb1b10abSAndroid Build Coastguard Worker }
148*fb1b10abSAndroid Build Coastguard Worker return EbmlMasterElementSize(libwebm::kMkvBlockGroup,
149*fb1b10abSAndroid Build Coastguard Worker block_group_payload_size) +
150*fb1b10abSAndroid Build Coastguard Worker block_group_payload_size;
151*fb1b10abSAndroid Build Coastguard Worker }
152*fb1b10abSAndroid Build Coastguard Worker
WriteSimpleBlock(IMkvWriter * writer,const Frame * const frame,int64 timecode)153*fb1b10abSAndroid Build Coastguard Worker uint64 WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame,
154*fb1b10abSAndroid Build Coastguard Worker int64 timecode) {
155*fb1b10abSAndroid Build Coastguard Worker if (WriteID(writer, libwebm::kMkvSimpleBlock))
156*fb1b10abSAndroid Build Coastguard Worker return 0;
157*fb1b10abSAndroid Build Coastguard Worker
158*fb1b10abSAndroid Build Coastguard Worker const int32 size = static_cast<int32>(frame->length()) + 4;
159*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, size))
160*fb1b10abSAndroid Build Coastguard Worker return 0;
161*fb1b10abSAndroid Build Coastguard Worker
162*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, static_cast<uint64>(frame->track_number())))
163*fb1b10abSAndroid Build Coastguard Worker return 0;
164*fb1b10abSAndroid Build Coastguard Worker
165*fb1b10abSAndroid Build Coastguard Worker if (SerializeInt(writer, timecode, 2))
166*fb1b10abSAndroid Build Coastguard Worker return 0;
167*fb1b10abSAndroid Build Coastguard Worker
168*fb1b10abSAndroid Build Coastguard Worker uint64 flags = 0;
169*fb1b10abSAndroid Build Coastguard Worker if (frame->is_key())
170*fb1b10abSAndroid Build Coastguard Worker flags |= 0x80;
171*fb1b10abSAndroid Build Coastguard Worker
172*fb1b10abSAndroid Build Coastguard Worker if (SerializeInt(writer, flags, 1))
173*fb1b10abSAndroid Build Coastguard Worker return 0;
174*fb1b10abSAndroid Build Coastguard Worker
175*fb1b10abSAndroid Build Coastguard Worker if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
176*fb1b10abSAndroid Build Coastguard Worker return 0;
177*fb1b10abSAndroid Build Coastguard Worker
178*fb1b10abSAndroid Build Coastguard Worker return GetUIntSize(libwebm::kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 +
179*fb1b10abSAndroid Build Coastguard Worker frame->length();
180*fb1b10abSAndroid Build Coastguard Worker }
181*fb1b10abSAndroid Build Coastguard Worker
182*fb1b10abSAndroid Build Coastguard Worker } // namespace
183*fb1b10abSAndroid Build Coastguard Worker
GetCodedUIntSize(uint64 value)184*fb1b10abSAndroid Build Coastguard Worker int32 GetCodedUIntSize(uint64 value) {
185*fb1b10abSAndroid Build Coastguard Worker if (value < 0x000000000000007FULL)
186*fb1b10abSAndroid Build Coastguard Worker return 1;
187*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x0000000000003FFFULL)
188*fb1b10abSAndroid Build Coastguard Worker return 2;
189*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x00000000001FFFFFULL)
190*fb1b10abSAndroid Build Coastguard Worker return 3;
191*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x000000000FFFFFFFULL)
192*fb1b10abSAndroid Build Coastguard Worker return 4;
193*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x00000007FFFFFFFFULL)
194*fb1b10abSAndroid Build Coastguard Worker return 5;
195*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x000003FFFFFFFFFFULL)
196*fb1b10abSAndroid Build Coastguard Worker return 6;
197*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x0001FFFFFFFFFFFFULL)
198*fb1b10abSAndroid Build Coastguard Worker return 7;
199*fb1b10abSAndroid Build Coastguard Worker return 8;
200*fb1b10abSAndroid Build Coastguard Worker }
201*fb1b10abSAndroid Build Coastguard Worker
GetUIntSize(uint64 value)202*fb1b10abSAndroid Build Coastguard Worker int32 GetUIntSize(uint64 value) {
203*fb1b10abSAndroid Build Coastguard Worker if (value < 0x0000000000000100ULL)
204*fb1b10abSAndroid Build Coastguard Worker return 1;
205*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x0000000000010000ULL)
206*fb1b10abSAndroid Build Coastguard Worker return 2;
207*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x0000000001000000ULL)
208*fb1b10abSAndroid Build Coastguard Worker return 3;
209*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x0000000100000000ULL)
210*fb1b10abSAndroid Build Coastguard Worker return 4;
211*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x0000010000000000ULL)
212*fb1b10abSAndroid Build Coastguard Worker return 5;
213*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x0001000000000000ULL)
214*fb1b10abSAndroid Build Coastguard Worker return 6;
215*fb1b10abSAndroid Build Coastguard Worker else if (value < 0x0100000000000000ULL)
216*fb1b10abSAndroid Build Coastguard Worker return 7;
217*fb1b10abSAndroid Build Coastguard Worker return 8;
218*fb1b10abSAndroid Build Coastguard Worker }
219*fb1b10abSAndroid Build Coastguard Worker
GetIntSize(int64 value)220*fb1b10abSAndroid Build Coastguard Worker int32 GetIntSize(int64 value) {
221*fb1b10abSAndroid Build Coastguard Worker // Doubling the requested value ensures positive values with their high bit
222*fb1b10abSAndroid Build Coastguard Worker // set are written with 0-padding to avoid flipping the signedness.
223*fb1b10abSAndroid Build Coastguard Worker const uint64 v = (value < 0) ? value ^ -1LL : value;
224*fb1b10abSAndroid Build Coastguard Worker return GetUIntSize(2 * v);
225*fb1b10abSAndroid Build Coastguard Worker }
226*fb1b10abSAndroid Build Coastguard Worker
EbmlMasterElementSize(uint64 type,uint64 value)227*fb1b10abSAndroid Build Coastguard Worker uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
228*fb1b10abSAndroid Build Coastguard Worker // Size of EBML ID
229*fb1b10abSAndroid Build Coastguard Worker int32 ebml_size = GetUIntSize(type);
230*fb1b10abSAndroid Build Coastguard Worker
231*fb1b10abSAndroid Build Coastguard Worker // Datasize
232*fb1b10abSAndroid Build Coastguard Worker ebml_size += GetCodedUIntSize(value);
233*fb1b10abSAndroid Build Coastguard Worker
234*fb1b10abSAndroid Build Coastguard Worker return ebml_size;
235*fb1b10abSAndroid Build Coastguard Worker }
236*fb1b10abSAndroid Build Coastguard Worker
EbmlElementSize(uint64 type,int64 value)237*fb1b10abSAndroid Build Coastguard Worker uint64 EbmlElementSize(uint64 type, int64 value) {
238*fb1b10abSAndroid Build Coastguard Worker // Size of EBML ID
239*fb1b10abSAndroid Build Coastguard Worker int32 ebml_size = GetUIntSize(type);
240*fb1b10abSAndroid Build Coastguard Worker
241*fb1b10abSAndroid Build Coastguard Worker // Datasize
242*fb1b10abSAndroid Build Coastguard Worker ebml_size += GetIntSize(value);
243*fb1b10abSAndroid Build Coastguard Worker
244*fb1b10abSAndroid Build Coastguard Worker // Size of Datasize
245*fb1b10abSAndroid Build Coastguard Worker ebml_size++;
246*fb1b10abSAndroid Build Coastguard Worker
247*fb1b10abSAndroid Build Coastguard Worker return ebml_size;
248*fb1b10abSAndroid Build Coastguard Worker }
249*fb1b10abSAndroid Build Coastguard Worker
EbmlElementSize(uint64 type,uint64 value)250*fb1b10abSAndroid Build Coastguard Worker uint64 EbmlElementSize(uint64 type, uint64 value) {
251*fb1b10abSAndroid Build Coastguard Worker return EbmlElementSize(type, value, 0);
252*fb1b10abSAndroid Build Coastguard Worker }
253*fb1b10abSAndroid Build Coastguard Worker
EbmlElementSize(uint64 type,uint64 value,uint64 fixed_size)254*fb1b10abSAndroid Build Coastguard Worker uint64 EbmlElementSize(uint64 type, uint64 value, uint64 fixed_size) {
255*fb1b10abSAndroid Build Coastguard Worker // Size of EBML ID
256*fb1b10abSAndroid Build Coastguard Worker uint64 ebml_size = GetUIntSize(type);
257*fb1b10abSAndroid Build Coastguard Worker
258*fb1b10abSAndroid Build Coastguard Worker // Datasize
259*fb1b10abSAndroid Build Coastguard Worker ebml_size += (fixed_size > 0) ? fixed_size : GetUIntSize(value);
260*fb1b10abSAndroid Build Coastguard Worker
261*fb1b10abSAndroid Build Coastguard Worker // Size of Datasize
262*fb1b10abSAndroid Build Coastguard Worker ebml_size++;
263*fb1b10abSAndroid Build Coastguard Worker
264*fb1b10abSAndroid Build Coastguard Worker return ebml_size;
265*fb1b10abSAndroid Build Coastguard Worker }
266*fb1b10abSAndroid Build Coastguard Worker
EbmlElementSize(uint64 type,float)267*fb1b10abSAndroid Build Coastguard Worker uint64 EbmlElementSize(uint64 type, float /* value */) {
268*fb1b10abSAndroid Build Coastguard Worker // Size of EBML ID
269*fb1b10abSAndroid Build Coastguard Worker uint64 ebml_size = GetUIntSize(type);
270*fb1b10abSAndroid Build Coastguard Worker
271*fb1b10abSAndroid Build Coastguard Worker // Datasize
272*fb1b10abSAndroid Build Coastguard Worker ebml_size += sizeof(float);
273*fb1b10abSAndroid Build Coastguard Worker
274*fb1b10abSAndroid Build Coastguard Worker // Size of Datasize
275*fb1b10abSAndroid Build Coastguard Worker ebml_size++;
276*fb1b10abSAndroid Build Coastguard Worker
277*fb1b10abSAndroid Build Coastguard Worker return ebml_size;
278*fb1b10abSAndroid Build Coastguard Worker }
279*fb1b10abSAndroid Build Coastguard Worker
EbmlElementSize(uint64 type,const char * value)280*fb1b10abSAndroid Build Coastguard Worker uint64 EbmlElementSize(uint64 type, const char* value) {
281*fb1b10abSAndroid Build Coastguard Worker if (!value)
282*fb1b10abSAndroid Build Coastguard Worker return 0;
283*fb1b10abSAndroid Build Coastguard Worker
284*fb1b10abSAndroid Build Coastguard Worker // Size of EBML ID
285*fb1b10abSAndroid Build Coastguard Worker uint64 ebml_size = GetUIntSize(type);
286*fb1b10abSAndroid Build Coastguard Worker
287*fb1b10abSAndroid Build Coastguard Worker // Datasize
288*fb1b10abSAndroid Build Coastguard Worker ebml_size += strlen(value);
289*fb1b10abSAndroid Build Coastguard Worker
290*fb1b10abSAndroid Build Coastguard Worker // Size of Datasize
291*fb1b10abSAndroid Build Coastguard Worker ebml_size += GetCodedUIntSize(strlen(value));
292*fb1b10abSAndroid Build Coastguard Worker
293*fb1b10abSAndroid Build Coastguard Worker return ebml_size;
294*fb1b10abSAndroid Build Coastguard Worker }
295*fb1b10abSAndroid Build Coastguard Worker
EbmlElementSize(uint64 type,const uint8 * value,uint64 size)296*fb1b10abSAndroid Build Coastguard Worker uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
297*fb1b10abSAndroid Build Coastguard Worker if (!value)
298*fb1b10abSAndroid Build Coastguard Worker return 0;
299*fb1b10abSAndroid Build Coastguard Worker
300*fb1b10abSAndroid Build Coastguard Worker // Size of EBML ID
301*fb1b10abSAndroid Build Coastguard Worker uint64 ebml_size = GetUIntSize(type);
302*fb1b10abSAndroid Build Coastguard Worker
303*fb1b10abSAndroid Build Coastguard Worker // Datasize
304*fb1b10abSAndroid Build Coastguard Worker ebml_size += size;
305*fb1b10abSAndroid Build Coastguard Worker
306*fb1b10abSAndroid Build Coastguard Worker // Size of Datasize
307*fb1b10abSAndroid Build Coastguard Worker ebml_size += GetCodedUIntSize(size);
308*fb1b10abSAndroid Build Coastguard Worker
309*fb1b10abSAndroid Build Coastguard Worker return ebml_size;
310*fb1b10abSAndroid Build Coastguard Worker }
311*fb1b10abSAndroid Build Coastguard Worker
EbmlDateElementSize(uint64 type)312*fb1b10abSAndroid Build Coastguard Worker uint64 EbmlDateElementSize(uint64 type) {
313*fb1b10abSAndroid Build Coastguard Worker // Size of EBML ID
314*fb1b10abSAndroid Build Coastguard Worker uint64 ebml_size = GetUIntSize(type);
315*fb1b10abSAndroid Build Coastguard Worker
316*fb1b10abSAndroid Build Coastguard Worker // Datasize
317*fb1b10abSAndroid Build Coastguard Worker ebml_size += kDateElementSize;
318*fb1b10abSAndroid Build Coastguard Worker
319*fb1b10abSAndroid Build Coastguard Worker // Size of Datasize
320*fb1b10abSAndroid Build Coastguard Worker ebml_size++;
321*fb1b10abSAndroid Build Coastguard Worker
322*fb1b10abSAndroid Build Coastguard Worker return ebml_size;
323*fb1b10abSAndroid Build Coastguard Worker }
324*fb1b10abSAndroid Build Coastguard Worker
SerializeInt(IMkvWriter * writer,int64 value,int32 size)325*fb1b10abSAndroid Build Coastguard Worker int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
326*fb1b10abSAndroid Build Coastguard Worker if (!writer || size < 1 || size > 8)
327*fb1b10abSAndroid Build Coastguard Worker return -1;
328*fb1b10abSAndroid Build Coastguard Worker
329*fb1b10abSAndroid Build Coastguard Worker for (int32 i = 1; i <= size; ++i) {
330*fb1b10abSAndroid Build Coastguard Worker const int32 byte_count = size - i;
331*fb1b10abSAndroid Build Coastguard Worker const int32 bit_count = byte_count * 8;
332*fb1b10abSAndroid Build Coastguard Worker
333*fb1b10abSAndroid Build Coastguard Worker const int64 bb = value >> bit_count;
334*fb1b10abSAndroid Build Coastguard Worker const uint8 b = static_cast<uint8>(bb);
335*fb1b10abSAndroid Build Coastguard Worker
336*fb1b10abSAndroid Build Coastguard Worker const int32 status = writer->Write(&b, 1);
337*fb1b10abSAndroid Build Coastguard Worker
338*fb1b10abSAndroid Build Coastguard Worker if (status < 0)
339*fb1b10abSAndroid Build Coastguard Worker return status;
340*fb1b10abSAndroid Build Coastguard Worker }
341*fb1b10abSAndroid Build Coastguard Worker
342*fb1b10abSAndroid Build Coastguard Worker return 0;
343*fb1b10abSAndroid Build Coastguard Worker }
344*fb1b10abSAndroid Build Coastguard Worker
SerializeFloat(IMkvWriter * writer,float f)345*fb1b10abSAndroid Build Coastguard Worker int32 SerializeFloat(IMkvWriter* writer, float f) {
346*fb1b10abSAndroid Build Coastguard Worker if (!writer)
347*fb1b10abSAndroid Build Coastguard Worker return -1;
348*fb1b10abSAndroid Build Coastguard Worker
349*fb1b10abSAndroid Build Coastguard Worker assert(sizeof(uint32) == sizeof(float));
350*fb1b10abSAndroid Build Coastguard Worker // This union is merely used to avoid a reinterpret_cast from float& to
351*fb1b10abSAndroid Build Coastguard Worker // uint32& which will result in violation of strict aliasing.
352*fb1b10abSAndroid Build Coastguard Worker union U32 {
353*fb1b10abSAndroid Build Coastguard Worker uint32 u32;
354*fb1b10abSAndroid Build Coastguard Worker float f;
355*fb1b10abSAndroid Build Coastguard Worker } value;
356*fb1b10abSAndroid Build Coastguard Worker value.f = f;
357*fb1b10abSAndroid Build Coastguard Worker
358*fb1b10abSAndroid Build Coastguard Worker for (int32 i = 1; i <= 4; ++i) {
359*fb1b10abSAndroid Build Coastguard Worker const int32 byte_count = 4 - i;
360*fb1b10abSAndroid Build Coastguard Worker const int32 bit_count = byte_count * 8;
361*fb1b10abSAndroid Build Coastguard Worker
362*fb1b10abSAndroid Build Coastguard Worker const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
363*fb1b10abSAndroid Build Coastguard Worker
364*fb1b10abSAndroid Build Coastguard Worker const int32 status = writer->Write(&byte, 1);
365*fb1b10abSAndroid Build Coastguard Worker
366*fb1b10abSAndroid Build Coastguard Worker if (status < 0)
367*fb1b10abSAndroid Build Coastguard Worker return status;
368*fb1b10abSAndroid Build Coastguard Worker }
369*fb1b10abSAndroid Build Coastguard Worker
370*fb1b10abSAndroid Build Coastguard Worker return 0;
371*fb1b10abSAndroid Build Coastguard Worker }
372*fb1b10abSAndroid Build Coastguard Worker
WriteUInt(IMkvWriter * writer,uint64 value)373*fb1b10abSAndroid Build Coastguard Worker int32 WriteUInt(IMkvWriter* writer, uint64 value) {
374*fb1b10abSAndroid Build Coastguard Worker if (!writer)
375*fb1b10abSAndroid Build Coastguard Worker return -1;
376*fb1b10abSAndroid Build Coastguard Worker
377*fb1b10abSAndroid Build Coastguard Worker int32 size = GetCodedUIntSize(value);
378*fb1b10abSAndroid Build Coastguard Worker
379*fb1b10abSAndroid Build Coastguard Worker return WriteUIntSize(writer, value, size);
380*fb1b10abSAndroid Build Coastguard Worker }
381*fb1b10abSAndroid Build Coastguard Worker
WriteUIntSize(IMkvWriter * writer,uint64 value,int32 size)382*fb1b10abSAndroid Build Coastguard Worker int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) {
383*fb1b10abSAndroid Build Coastguard Worker if (!writer || size < 0 || size > 8)
384*fb1b10abSAndroid Build Coastguard Worker return -1;
385*fb1b10abSAndroid Build Coastguard Worker
386*fb1b10abSAndroid Build Coastguard Worker if (size > 0) {
387*fb1b10abSAndroid Build Coastguard Worker const uint64 bit = 1LL << (size * 7);
388*fb1b10abSAndroid Build Coastguard Worker
389*fb1b10abSAndroid Build Coastguard Worker if (value > (bit - 2))
390*fb1b10abSAndroid Build Coastguard Worker return -1;
391*fb1b10abSAndroid Build Coastguard Worker
392*fb1b10abSAndroid Build Coastguard Worker value |= bit;
393*fb1b10abSAndroid Build Coastguard Worker } else {
394*fb1b10abSAndroid Build Coastguard Worker size = 1;
395*fb1b10abSAndroid Build Coastguard Worker int64 bit;
396*fb1b10abSAndroid Build Coastguard Worker
397*fb1b10abSAndroid Build Coastguard Worker for (;;) {
398*fb1b10abSAndroid Build Coastguard Worker bit = 1LL << (size * 7);
399*fb1b10abSAndroid Build Coastguard Worker const uint64 max = bit - 2;
400*fb1b10abSAndroid Build Coastguard Worker
401*fb1b10abSAndroid Build Coastguard Worker if (value <= max)
402*fb1b10abSAndroid Build Coastguard Worker break;
403*fb1b10abSAndroid Build Coastguard Worker
404*fb1b10abSAndroid Build Coastguard Worker ++size;
405*fb1b10abSAndroid Build Coastguard Worker }
406*fb1b10abSAndroid Build Coastguard Worker
407*fb1b10abSAndroid Build Coastguard Worker if (size > 8)
408*fb1b10abSAndroid Build Coastguard Worker return false;
409*fb1b10abSAndroid Build Coastguard Worker
410*fb1b10abSAndroid Build Coastguard Worker value |= bit;
411*fb1b10abSAndroid Build Coastguard Worker }
412*fb1b10abSAndroid Build Coastguard Worker
413*fb1b10abSAndroid Build Coastguard Worker return SerializeInt(writer, value, size);
414*fb1b10abSAndroid Build Coastguard Worker }
415*fb1b10abSAndroid Build Coastguard Worker
WriteID(IMkvWriter * writer,uint64 type)416*fb1b10abSAndroid Build Coastguard Worker int32 WriteID(IMkvWriter* writer, uint64 type) {
417*fb1b10abSAndroid Build Coastguard Worker if (!writer)
418*fb1b10abSAndroid Build Coastguard Worker return -1;
419*fb1b10abSAndroid Build Coastguard Worker
420*fb1b10abSAndroid Build Coastguard Worker writer->ElementStartNotify(type, writer->Position());
421*fb1b10abSAndroid Build Coastguard Worker
422*fb1b10abSAndroid Build Coastguard Worker const int32 size = GetUIntSize(type);
423*fb1b10abSAndroid Build Coastguard Worker
424*fb1b10abSAndroid Build Coastguard Worker return SerializeInt(writer, type, size);
425*fb1b10abSAndroid Build Coastguard Worker }
426*fb1b10abSAndroid Build Coastguard Worker
WriteEbmlMasterElement(IMkvWriter * writer,uint64 type,uint64 size)427*fb1b10abSAndroid Build Coastguard Worker bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) {
428*fb1b10abSAndroid Build Coastguard Worker if (!writer)
429*fb1b10abSAndroid Build Coastguard Worker return false;
430*fb1b10abSAndroid Build Coastguard Worker
431*fb1b10abSAndroid Build Coastguard Worker if (WriteID(writer, type))
432*fb1b10abSAndroid Build Coastguard Worker return false;
433*fb1b10abSAndroid Build Coastguard Worker
434*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, size))
435*fb1b10abSAndroid Build Coastguard Worker return false;
436*fb1b10abSAndroid Build Coastguard Worker
437*fb1b10abSAndroid Build Coastguard Worker return true;
438*fb1b10abSAndroid Build Coastguard Worker }
439*fb1b10abSAndroid Build Coastguard Worker
WriteEbmlElement(IMkvWriter * writer,uint64 type,uint64 value)440*fb1b10abSAndroid Build Coastguard Worker bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
441*fb1b10abSAndroid Build Coastguard Worker return WriteEbmlElement(writer, type, value, 0);
442*fb1b10abSAndroid Build Coastguard Worker }
443*fb1b10abSAndroid Build Coastguard Worker
WriteEbmlElement(IMkvWriter * writer,uint64 type,uint64 value,uint64 fixed_size)444*fb1b10abSAndroid Build Coastguard Worker bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value,
445*fb1b10abSAndroid Build Coastguard Worker uint64 fixed_size) {
446*fb1b10abSAndroid Build Coastguard Worker if (!writer)
447*fb1b10abSAndroid Build Coastguard Worker return false;
448*fb1b10abSAndroid Build Coastguard Worker
449*fb1b10abSAndroid Build Coastguard Worker if (WriteID(writer, type))
450*fb1b10abSAndroid Build Coastguard Worker return false;
451*fb1b10abSAndroid Build Coastguard Worker
452*fb1b10abSAndroid Build Coastguard Worker uint64 size = GetUIntSize(value);
453*fb1b10abSAndroid Build Coastguard Worker if (fixed_size > 0) {
454*fb1b10abSAndroid Build Coastguard Worker if (size > fixed_size)
455*fb1b10abSAndroid Build Coastguard Worker return false;
456*fb1b10abSAndroid Build Coastguard Worker size = fixed_size;
457*fb1b10abSAndroid Build Coastguard Worker }
458*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, size))
459*fb1b10abSAndroid Build Coastguard Worker return false;
460*fb1b10abSAndroid Build Coastguard Worker
461*fb1b10abSAndroid Build Coastguard Worker if (SerializeInt(writer, value, static_cast<int32>(size)))
462*fb1b10abSAndroid Build Coastguard Worker return false;
463*fb1b10abSAndroid Build Coastguard Worker
464*fb1b10abSAndroid Build Coastguard Worker return true;
465*fb1b10abSAndroid Build Coastguard Worker }
466*fb1b10abSAndroid Build Coastguard Worker
WriteEbmlElement(IMkvWriter * writer,uint64 type,int64 value)467*fb1b10abSAndroid Build Coastguard Worker bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value) {
468*fb1b10abSAndroid Build Coastguard Worker if (!writer)
469*fb1b10abSAndroid Build Coastguard Worker return false;
470*fb1b10abSAndroid Build Coastguard Worker
471*fb1b10abSAndroid Build Coastguard Worker if (WriteID(writer, type))
472*fb1b10abSAndroid Build Coastguard Worker return 0;
473*fb1b10abSAndroid Build Coastguard Worker
474*fb1b10abSAndroid Build Coastguard Worker const uint64 size = GetIntSize(value);
475*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, size))
476*fb1b10abSAndroid Build Coastguard Worker return false;
477*fb1b10abSAndroid Build Coastguard Worker
478*fb1b10abSAndroid Build Coastguard Worker if (SerializeInt(writer, value, static_cast<int32>(size)))
479*fb1b10abSAndroid Build Coastguard Worker return false;
480*fb1b10abSAndroid Build Coastguard Worker
481*fb1b10abSAndroid Build Coastguard Worker return true;
482*fb1b10abSAndroid Build Coastguard Worker }
483*fb1b10abSAndroid Build Coastguard Worker
WriteEbmlElement(IMkvWriter * writer,uint64 type,float value)484*fb1b10abSAndroid Build Coastguard Worker bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
485*fb1b10abSAndroid Build Coastguard Worker if (!writer)
486*fb1b10abSAndroid Build Coastguard Worker return false;
487*fb1b10abSAndroid Build Coastguard Worker
488*fb1b10abSAndroid Build Coastguard Worker if (WriteID(writer, type))
489*fb1b10abSAndroid Build Coastguard Worker return false;
490*fb1b10abSAndroid Build Coastguard Worker
491*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, 4))
492*fb1b10abSAndroid Build Coastguard Worker return false;
493*fb1b10abSAndroid Build Coastguard Worker
494*fb1b10abSAndroid Build Coastguard Worker if (SerializeFloat(writer, value))
495*fb1b10abSAndroid Build Coastguard Worker return false;
496*fb1b10abSAndroid Build Coastguard Worker
497*fb1b10abSAndroid Build Coastguard Worker return true;
498*fb1b10abSAndroid Build Coastguard Worker }
499*fb1b10abSAndroid Build Coastguard Worker
WriteEbmlElement(IMkvWriter * writer,uint64 type,const char * value)500*fb1b10abSAndroid Build Coastguard Worker bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
501*fb1b10abSAndroid Build Coastguard Worker if (!writer || !value)
502*fb1b10abSAndroid Build Coastguard Worker return false;
503*fb1b10abSAndroid Build Coastguard Worker
504*fb1b10abSAndroid Build Coastguard Worker if (WriteID(writer, type))
505*fb1b10abSAndroid Build Coastguard Worker return false;
506*fb1b10abSAndroid Build Coastguard Worker
507*fb1b10abSAndroid Build Coastguard Worker const uint64 length = strlen(value);
508*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, length))
509*fb1b10abSAndroid Build Coastguard Worker return false;
510*fb1b10abSAndroid Build Coastguard Worker
511*fb1b10abSAndroid Build Coastguard Worker if (writer->Write(value, static_cast<uint32>(length)))
512*fb1b10abSAndroid Build Coastguard Worker return false;
513*fb1b10abSAndroid Build Coastguard Worker
514*fb1b10abSAndroid Build Coastguard Worker return true;
515*fb1b10abSAndroid Build Coastguard Worker }
516*fb1b10abSAndroid Build Coastguard Worker
WriteEbmlElement(IMkvWriter * writer,uint64 type,const uint8 * value,uint64 size)517*fb1b10abSAndroid Build Coastguard Worker bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
518*fb1b10abSAndroid Build Coastguard Worker uint64 size) {
519*fb1b10abSAndroid Build Coastguard Worker if (!writer || !value || size < 1)
520*fb1b10abSAndroid Build Coastguard Worker return false;
521*fb1b10abSAndroid Build Coastguard Worker
522*fb1b10abSAndroid Build Coastguard Worker if (WriteID(writer, type))
523*fb1b10abSAndroid Build Coastguard Worker return false;
524*fb1b10abSAndroid Build Coastguard Worker
525*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, size))
526*fb1b10abSAndroid Build Coastguard Worker return false;
527*fb1b10abSAndroid Build Coastguard Worker
528*fb1b10abSAndroid Build Coastguard Worker if (writer->Write(value, static_cast<uint32>(size)))
529*fb1b10abSAndroid Build Coastguard Worker return false;
530*fb1b10abSAndroid Build Coastguard Worker
531*fb1b10abSAndroid Build Coastguard Worker return true;
532*fb1b10abSAndroid Build Coastguard Worker }
533*fb1b10abSAndroid Build Coastguard Worker
WriteEbmlDateElement(IMkvWriter * writer,uint64 type,int64 value)534*fb1b10abSAndroid Build Coastguard Worker bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
535*fb1b10abSAndroid Build Coastguard Worker if (!writer)
536*fb1b10abSAndroid Build Coastguard Worker return false;
537*fb1b10abSAndroid Build Coastguard Worker
538*fb1b10abSAndroid Build Coastguard Worker if (WriteID(writer, type))
539*fb1b10abSAndroid Build Coastguard Worker return false;
540*fb1b10abSAndroid Build Coastguard Worker
541*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, kDateElementSize))
542*fb1b10abSAndroid Build Coastguard Worker return false;
543*fb1b10abSAndroid Build Coastguard Worker
544*fb1b10abSAndroid Build Coastguard Worker if (SerializeInt(writer, value, kDateElementSize))
545*fb1b10abSAndroid Build Coastguard Worker return false;
546*fb1b10abSAndroid Build Coastguard Worker
547*fb1b10abSAndroid Build Coastguard Worker return true;
548*fb1b10abSAndroid Build Coastguard Worker }
549*fb1b10abSAndroid Build Coastguard Worker
WriteFrame(IMkvWriter * writer,const Frame * const frame,Cluster * cluster)550*fb1b10abSAndroid Build Coastguard Worker uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
551*fb1b10abSAndroid Build Coastguard Worker Cluster* cluster) {
552*fb1b10abSAndroid Build Coastguard Worker if (!writer || !frame || !frame->IsValid() || !cluster ||
553*fb1b10abSAndroid Build Coastguard Worker !cluster->timecode_scale())
554*fb1b10abSAndroid Build Coastguard Worker return 0;
555*fb1b10abSAndroid Build Coastguard Worker
556*fb1b10abSAndroid Build Coastguard Worker // Technically the timecode for a block can be less than the
557*fb1b10abSAndroid Build Coastguard Worker // timecode for the cluster itself (remember that block timecode
558*fb1b10abSAndroid Build Coastguard Worker // is a signed, 16-bit integer). However, as a simplification we
559*fb1b10abSAndroid Build Coastguard Worker // only permit non-negative cluster-relative timecodes for blocks.
560*fb1b10abSAndroid Build Coastguard Worker const int64 relative_timecode = cluster->GetRelativeTimecode(
561*fb1b10abSAndroid Build Coastguard Worker frame->timestamp() / cluster->timecode_scale());
562*fb1b10abSAndroid Build Coastguard Worker if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
563*fb1b10abSAndroid Build Coastguard Worker return 0;
564*fb1b10abSAndroid Build Coastguard Worker
565*fb1b10abSAndroid Build Coastguard Worker return frame->CanBeSimpleBlock()
566*fb1b10abSAndroid Build Coastguard Worker ? WriteSimpleBlock(writer, frame, relative_timecode)
567*fb1b10abSAndroid Build Coastguard Worker : WriteBlock(writer, frame, relative_timecode,
568*fb1b10abSAndroid Build Coastguard Worker cluster->timecode_scale());
569*fb1b10abSAndroid Build Coastguard Worker }
570*fb1b10abSAndroid Build Coastguard Worker
WriteVoidElement(IMkvWriter * writer,uint64 size)571*fb1b10abSAndroid Build Coastguard Worker uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
572*fb1b10abSAndroid Build Coastguard Worker if (!writer)
573*fb1b10abSAndroid Build Coastguard Worker return false;
574*fb1b10abSAndroid Build Coastguard Worker
575*fb1b10abSAndroid Build Coastguard Worker // Subtract one for the void ID and the coded size.
576*fb1b10abSAndroid Build Coastguard Worker uint64 void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
577*fb1b10abSAndroid Build Coastguard Worker uint64 void_size = EbmlMasterElementSize(libwebm::kMkvVoid, void_entry_size) +
578*fb1b10abSAndroid Build Coastguard Worker void_entry_size;
579*fb1b10abSAndroid Build Coastguard Worker
580*fb1b10abSAndroid Build Coastguard Worker if (void_size != size)
581*fb1b10abSAndroid Build Coastguard Worker return 0;
582*fb1b10abSAndroid Build Coastguard Worker
583*fb1b10abSAndroid Build Coastguard Worker const int64 payload_position = writer->Position();
584*fb1b10abSAndroid Build Coastguard Worker if (payload_position < 0)
585*fb1b10abSAndroid Build Coastguard Worker return 0;
586*fb1b10abSAndroid Build Coastguard Worker
587*fb1b10abSAndroid Build Coastguard Worker if (WriteID(writer, libwebm::kMkvVoid))
588*fb1b10abSAndroid Build Coastguard Worker return 0;
589*fb1b10abSAndroid Build Coastguard Worker
590*fb1b10abSAndroid Build Coastguard Worker if (WriteUInt(writer, void_entry_size))
591*fb1b10abSAndroid Build Coastguard Worker return 0;
592*fb1b10abSAndroid Build Coastguard Worker
593*fb1b10abSAndroid Build Coastguard Worker const uint8 value = 0;
594*fb1b10abSAndroid Build Coastguard Worker for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) {
595*fb1b10abSAndroid Build Coastguard Worker if (writer->Write(&value, 1))
596*fb1b10abSAndroid Build Coastguard Worker return 0;
597*fb1b10abSAndroid Build Coastguard Worker }
598*fb1b10abSAndroid Build Coastguard Worker
599*fb1b10abSAndroid Build Coastguard Worker const int64 stop_position = writer->Position();
600*fb1b10abSAndroid Build Coastguard Worker if (stop_position < 0 ||
601*fb1b10abSAndroid Build Coastguard Worker stop_position - payload_position != static_cast<int64>(void_size))
602*fb1b10abSAndroid Build Coastguard Worker return 0;
603*fb1b10abSAndroid Build Coastguard Worker
604*fb1b10abSAndroid Build Coastguard Worker return void_size;
605*fb1b10abSAndroid Build Coastguard Worker }
606*fb1b10abSAndroid Build Coastguard Worker
GetVersion(int32 * major,int32 * minor,int32 * build,int32 * revision)607*fb1b10abSAndroid Build Coastguard Worker void GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
608*fb1b10abSAndroid Build Coastguard Worker *major = 0;
609*fb1b10abSAndroid Build Coastguard Worker *minor = 3;
610*fb1b10abSAndroid Build Coastguard Worker *build = 3;
611*fb1b10abSAndroid Build Coastguard Worker *revision = 0;
612*fb1b10abSAndroid Build Coastguard Worker }
613*fb1b10abSAndroid Build Coastguard Worker
MakeUID(unsigned int * seed)614*fb1b10abSAndroid Build Coastguard Worker uint64 MakeUID(unsigned int* seed) {
615*fb1b10abSAndroid Build Coastguard Worker uint64 uid = 0;
616*fb1b10abSAndroid Build Coastguard Worker
617*fb1b10abSAndroid Build Coastguard Worker for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values
618*fb1b10abSAndroid Build Coastguard Worker uid <<= 8;
619*fb1b10abSAndroid Build Coastguard Worker
620*fb1b10abSAndroid Build Coastguard Worker // TODO(fgalligan): Move random number generation to platform specific code.
621*fb1b10abSAndroid Build Coastguard Worker #ifdef _WIN32
622*fb1b10abSAndroid Build Coastguard Worker (void)seed;
623*fb1b10abSAndroid Build Coastguard Worker const int32 nn = rand();
624*fb1b10abSAndroid Build Coastguard Worker #elif defined(__ANDROID__)
625*fb1b10abSAndroid Build Coastguard Worker (void)seed;
626*fb1b10abSAndroid Build Coastguard Worker int32 temp_num = 1;
627*fb1b10abSAndroid Build Coastguard Worker int fd = open("/dev/urandom", O_RDONLY);
628*fb1b10abSAndroid Build Coastguard Worker if (fd != -1) {
629*fb1b10abSAndroid Build Coastguard Worker read(fd, &temp_num, sizeof(temp_num));
630*fb1b10abSAndroid Build Coastguard Worker close(fd);
631*fb1b10abSAndroid Build Coastguard Worker }
632*fb1b10abSAndroid Build Coastguard Worker const int32 nn = temp_num;
633*fb1b10abSAndroid Build Coastguard Worker #else
634*fb1b10abSAndroid Build Coastguard Worker const int32 nn = rand_r(seed);
635*fb1b10abSAndroid Build Coastguard Worker #endif
636*fb1b10abSAndroid Build Coastguard Worker const int32 n = 0xFF & (nn >> 4); // throw away low-order bits
637*fb1b10abSAndroid Build Coastguard Worker
638*fb1b10abSAndroid Build Coastguard Worker uid |= n;
639*fb1b10abSAndroid Build Coastguard Worker }
640*fb1b10abSAndroid Build Coastguard Worker
641*fb1b10abSAndroid Build Coastguard Worker return uid;
642*fb1b10abSAndroid Build Coastguard Worker }
643*fb1b10abSAndroid Build Coastguard Worker
IsMatrixCoefficientsValueValid(uint64_t value)644*fb1b10abSAndroid Build Coastguard Worker bool IsMatrixCoefficientsValueValid(uint64_t value) {
645*fb1b10abSAndroid Build Coastguard Worker switch (value) {
646*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kGbr:
647*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kBt709:
648*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kUnspecifiedMc:
649*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kReserved:
650*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kFcc:
651*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kBt470bg:
652*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kSmpte170MMc:
653*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kSmpte240MMc:
654*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kYcocg:
655*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kBt2020NonConstantLuminance:
656*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kBt2020ConstantLuminance:
657*fb1b10abSAndroid Build Coastguard Worker return true;
658*fb1b10abSAndroid Build Coastguard Worker }
659*fb1b10abSAndroid Build Coastguard Worker return false;
660*fb1b10abSAndroid Build Coastguard Worker }
661*fb1b10abSAndroid Build Coastguard Worker
IsChromaSitingHorzValueValid(uint64_t value)662*fb1b10abSAndroid Build Coastguard Worker bool IsChromaSitingHorzValueValid(uint64_t value) {
663*fb1b10abSAndroid Build Coastguard Worker switch (value) {
664*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kUnspecifiedCsh:
665*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kLeftCollocated:
666*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kHalfCsh:
667*fb1b10abSAndroid Build Coastguard Worker return true;
668*fb1b10abSAndroid Build Coastguard Worker }
669*fb1b10abSAndroid Build Coastguard Worker return false;
670*fb1b10abSAndroid Build Coastguard Worker }
671*fb1b10abSAndroid Build Coastguard Worker
IsChromaSitingVertValueValid(uint64_t value)672*fb1b10abSAndroid Build Coastguard Worker bool IsChromaSitingVertValueValid(uint64_t value) {
673*fb1b10abSAndroid Build Coastguard Worker switch (value) {
674*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kUnspecifiedCsv:
675*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kTopCollocated:
676*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kHalfCsv:
677*fb1b10abSAndroid Build Coastguard Worker return true;
678*fb1b10abSAndroid Build Coastguard Worker }
679*fb1b10abSAndroid Build Coastguard Worker return false;
680*fb1b10abSAndroid Build Coastguard Worker }
681*fb1b10abSAndroid Build Coastguard Worker
IsColourRangeValueValid(uint64_t value)682*fb1b10abSAndroid Build Coastguard Worker bool IsColourRangeValueValid(uint64_t value) {
683*fb1b10abSAndroid Build Coastguard Worker switch (value) {
684*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kUnspecifiedCr:
685*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kBroadcastRange:
686*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kFullRange:
687*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kMcTcDefined:
688*fb1b10abSAndroid Build Coastguard Worker return true;
689*fb1b10abSAndroid Build Coastguard Worker }
690*fb1b10abSAndroid Build Coastguard Worker return false;
691*fb1b10abSAndroid Build Coastguard Worker }
692*fb1b10abSAndroid Build Coastguard Worker
IsTransferCharacteristicsValueValid(uint64_t value)693*fb1b10abSAndroid Build Coastguard Worker bool IsTransferCharacteristicsValueValid(uint64_t value) {
694*fb1b10abSAndroid Build Coastguard Worker switch (value) {
695*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIturBt709Tc:
696*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kUnspecifiedTc:
697*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kReservedTc:
698*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kGamma22Curve:
699*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kGamma28Curve:
700*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kSmpte170MTc:
701*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kSmpte240MTc:
702*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kLinear:
703*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kLog:
704*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kLogSqrt:
705*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIec6196624:
706*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIturBt1361ExtendedColourGamut:
707*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIec6196621:
708*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIturBt202010bit:
709*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIturBt202012bit:
710*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kSmpteSt2084:
711*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kSmpteSt4281Tc:
712*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kAribStdB67Hlg:
713*fb1b10abSAndroid Build Coastguard Worker return true;
714*fb1b10abSAndroid Build Coastguard Worker }
715*fb1b10abSAndroid Build Coastguard Worker return false;
716*fb1b10abSAndroid Build Coastguard Worker }
717*fb1b10abSAndroid Build Coastguard Worker
IsPrimariesValueValid(uint64_t value)718*fb1b10abSAndroid Build Coastguard Worker bool IsPrimariesValueValid(uint64_t value) {
719*fb1b10abSAndroid Build Coastguard Worker switch (value) {
720*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kReservedP0:
721*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIturBt709P:
722*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kUnspecifiedP:
723*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kReservedP3:
724*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIturBt470M:
725*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIturBt470Bg:
726*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kSmpte170MP:
727*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kSmpte240MP:
728*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kFilm:
729*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kIturBt2020:
730*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kSmpteSt4281P:
731*fb1b10abSAndroid Build Coastguard Worker case mkvmuxer::Colour::kJedecP22Phosphors:
732*fb1b10abSAndroid Build Coastguard Worker return true;
733*fb1b10abSAndroid Build Coastguard Worker }
734*fb1b10abSAndroid Build Coastguard Worker return false;
735*fb1b10abSAndroid Build Coastguard Worker }
736*fb1b10abSAndroid Build Coastguard Worker
737*fb1b10abSAndroid Build Coastguard Worker } // namespace mkvmuxer
738