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