1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "box/item_movie_box.h"
17
18 #include <algorithm>
19
20 namespace {
21 const uint32_t MVHD_MATRIX_OFFSET = 9;
22 const uint32_t MVHD_PREDEFINED_OFFSET = 6;
23 const uint32_t TKHD_MATRIX_OFFSET = 9;
24 const uint32_t VMHD_OPCOLOR_OFFSET = 3;
25 const uint32_t HVC1_RESERVED_OFFSET = 8;
26 const uint32_t HVC1_PREDEFINE_OFFSET = 16;
27 const uint32_t HVC1_SKIP_OFFSET = 50;
28 }
29
30 namespace OHOS {
31 namespace ImagePlugin {
ParseContentChildren(HeifStreamReader & reader,uint32_t & recursionCount)32 heif_error HeifMoovBox::ParseContentChildren(HeifStreamReader &reader, uint32_t &recursionCount)
33 {
34 return ParseContentChildrenByReadChildren(reader, recursionCount);
35 }
36
ParseContent(HeifStreamReader & reader)37 heif_error HeifMvhdBox::ParseContent(HeifStreamReader &reader)
38 {
39 ParseFullHeader(reader);
40 if (GetVersion() == HEIF_BOX_VERSION_ONE) {
41 creationTime_ = reader.Read64();
42 modificationTime_ = reader.Read64();
43 timescale_ = reader.Read32();
44 duration_ = reader.Read32();
45 } else {
46 creationTime_ = reader.Read32();
47 modificationTime_ = reader.Read32();
48 timescale_ = reader.Read32();
49 duration_ = reader.Read32();
50 }
51 rate_ = reader.Read32();
52 volume_ = reader.Read16();
53 reserved_ = reader.Read16();
54 reserved2_[0] = reader.Read32();
55 reserved2_[1] = reader.Read32();
56 for (int i = 0; i < MVHD_MATRIX_OFFSET; i++) {
57 matrix_[i] = reader.Read32();
58 }
59 for (int i = 0; i < MVHD_PREDEFINED_OFFSET; i++) {
60 preDefined_[i] = reader.Read32();
61 }
62 nextTrackId_ = reader.Read32();
63 return reader.GetError();
64 }
65
Write(HeifStreamWriter & writer) const66 heif_error HeifMvhdBox::Write(HeifStreamWriter &writer) const
67 {
68 size_t boxStart = ReserveHeader(writer);
69 if (GetVersion() == HEIF_BOX_VERSION_ONE) {
70 writer.Write64(creationTime_);
71 writer.Write64(modificationTime_);
72 writer.Write32(timescale_);
73 writer.Write64(duration_);
74 } else {
75 writer.Write32(creationTime_);
76 writer.Write32(modificationTime_);
77 writer.Write32(timescale_);
78 writer.Write32(duration_);
79 }
80 writer.Write32(rate_);
81 writer.Write16(volume_);
82 writer.Write16(reserved_);
83 writer.Write32(reserved2_[0]);
84 writer.Write32(reserved2_[1]);
85 for (int i = 0; i < MVHD_MATRIX_OFFSET; i++) {
86 writer.Write32(matrix_[i]);
87 }
88 for (int i = 0; i < MVHD_PREDEFINED_OFFSET; i++) {
89 writer.Write32(preDefined_[i]);
90 }
91 writer.Write32(nextTrackId_);
92 WriteCalculatedHeader(writer, boxStart);
93 return heif_error_ok;
94 }
95
ParseContentChildren(HeifStreamReader & reader,uint32_t & recursionCount)96 heif_error HeifTrakBox::ParseContentChildren(HeifStreamReader &reader, uint32_t &recursionCount)
97 {
98 return ParseContentChildrenByReadChildren(reader, recursionCount);
99 }
100
ParseContent(HeifStreamReader & reader)101 heif_error HeifTkhdBox::ParseContent(HeifStreamReader &reader)
102 {
103 ParseFullHeader(reader);
104 if (GetVersion() == HEIF_BOX_VERSION_ONE) {
105 creationTime_ = reader.Read64();
106 modificationTime_ = reader.Read64();
107 trackId_ = reader.Read32();
108 reserved1_ = reader.Read32();
109 duration_ = reader.Read64();
110 } else {
111 creationTime_ = reader.Read32();
112 modificationTime_ = reader.Read32();
113 trackId_ = reader.Read32();
114 reserved1_ = reader.Read32();
115 duration_ = reader.Read32();
116 }
117 reserved2_[0] = reader.Read32();
118 reserved2_[1] = reader.Read32();
119 layer_ = reader.Read16();
120 alternateGroup_ = reader.Read16();
121 volume_ = reader.Read16();
122 reserved3_ = reader.Read16();
123 for (int i = 0; i < TKHD_MATRIX_OFFSET; i++) {
124 matrix_[i] = reader.Read32();
125 }
126 width_ = reader.Read32();
127 height_ = reader.Read32();
128 return reader.GetError();
129 }
130
Write(HeifStreamWriter & writer) const131 heif_error HeifTkhdBox::Write(HeifStreamWriter &writer) const
132 {
133 size_t boxStart = ReserveHeader(writer);
134 if (GetVersion() == HEIF_BOX_VERSION_ONE) {
135 writer.Write64(creationTime_);
136 writer.Write64(modificationTime_);
137 writer.Write32(trackId_);
138 writer.Write32(reserved1_);
139 writer.Write64(duration_);
140 } else {
141 writer.Write32(creationTime_);
142 writer.Write32(modificationTime_);
143 writer.Write32(trackId_);
144 writer.Write32(reserved1_);
145 writer.Write32(duration_);
146 }
147 writer.Write32(reserved2_[0]);
148 writer.Write32(reserved2_[1]);
149 writer.Write16(layer_);
150 writer.Write16(alternateGroup_);
151 writer.Write16(volume_);
152 writer.Write16(reserved3_);
153 for (int i = 0; i < TKHD_MATRIX_OFFSET; i++) {
154 writer.Write32(matrix_[i]);
155 }
156 writer.Write32(width_);
157 writer.Write32(height_);
158
159 WriteCalculatedHeader(writer, boxStart);
160 return heif_error_ok;
161 }
162
ParseContentChildren(HeifStreamReader & reader,uint32_t & recursionCount)163 heif_error HeifMdiaBox::ParseContentChildren(HeifStreamReader &reader, uint32_t &recursionCount)
164 {
165 return ParseContentChildrenByReadChildren(reader, recursionCount);
166 }
167
ParseContent(HeifStreamReader & reader)168 heif_error HeifMdhdBox::ParseContent(HeifStreamReader &reader)
169 {
170 ParseFullHeader(reader);
171 if (GetVersion() == HEIF_BOX_VERSION_ONE) {
172 creationTime_ = reader.Read64();
173 modificationTime_ = reader.Read64();
174 timescale_ = reader.Read32();
175 duration_ = reader.Read64();
176 } else {
177 creationTime_ = reader.Read32();
178 modificationTime_ = reader.Read32();
179 timescale_ = reader.Read32();
180 duration_ = reader.Read32();
181 }
182 language_ = reader.Read16();
183 preDefined_ = reader.Read16();
184 return reader.GetError();
185 }
186
Write(HeifStreamWriter & writer) const187 heif_error HeifMdhdBox::Write(HeifStreamWriter &writer) const
188 {
189 size_t boxStart = ReserveHeader(writer);
190 if (GetVersion() == HEIF_BOX_VERSION_ONE) {
191 writer.Write64(creationTime_);
192 writer.Write64(modificationTime_);
193 writer.Write32(timescale_);
194 writer.Write64(duration_);
195 } else {
196 writer.Write32(creationTime_);
197 writer.Write32(modificationTime_);
198 writer.Write32(timescale_);
199 writer.Write32(duration_);
200 }
201 writer.Write16(language_);
202 writer.Write16(preDefined_);
203 WriteCalculatedHeader(writer, boxStart);
204 return heif_error_ok;
205 }
206
ParseContentChildren(HeifStreamReader & reader,uint32_t & recursionCount)207 heif_error HeifMinfBox::ParseContentChildren(HeifStreamReader &reader, uint32_t &recursionCount)
208 {
209 return ParseContentChildrenByReadChildren(reader, recursionCount);
210 }
211
ParseContent(HeifStreamReader & reader)212 heif_error HeifVmhdBox::ParseContent(HeifStreamReader &reader)
213 {
214 ParseFullHeader(reader);
215 graphicsMode_ = reader.Read16();
216 for (int i = 0; i < VMHD_OPCOLOR_OFFSET; i++) {
217 opColor_[i] = reader.Read16();
218 }
219 return reader.GetError();
220 }
221
Write(HeifStreamWriter & writer) const222 heif_error HeifVmhdBox::Write(HeifStreamWriter &writer) const
223 {
224 size_t boxStart = ReserveHeader(writer);
225 writer.Write16(graphicsMode_);
226 for (int i = 0; i < VMHD_OPCOLOR_OFFSET; i++) {
227 writer.Write16(opColor_[i]);
228 }
229 WriteCalculatedHeader(writer, boxStart);
230 return heif_error_ok;
231 }
232
ParseContentChildren(HeifStreamReader & reader,uint32_t & recursionCount)233 heif_error HeifDinfBox::ParseContentChildren(HeifStreamReader &reader, uint32_t &recursionCount)
234 {
235 return ParseContentChildrenByReadChildren(reader, recursionCount);
236 }
237
ParseContent(HeifStreamReader & reader)238 heif_error HeifDrefBox::ParseContent(HeifStreamReader &reader)
239 {
240 ParseFullHeader(reader);
241 entryCount_ = reader.Read32();
242 for (uint32_t i = 0; i < entryCount_; i++) {
243 uint32_t recursionCount = 0;
244 std::shared_ptr<HeifBox> entry;
245 heif_error error = HeifBox::MakeFromReader(reader, &entry, recursionCount);
246 if (error != heif_error_ok) {
247 return error;
248 }
249 entries_.push_back(entry);
250 }
251 return reader.GetError();
252 }
253
Write(HeifStreamWriter & writer) const254 heif_error HeifDrefBox::Write(HeifStreamWriter &writer) const
255 {
256 size_t boxStart = ReserveHeader(writer);
257 writer.Write32(entryCount_);
258 for (const auto& entry : entries_) {
259 entry->Write(writer);
260 }
261 WriteCalculatedHeader(writer, boxStart);
262 return heif_error_ok;
263 }
264
ParseContentChildren(HeifStreamReader & reader,uint32_t & recursionCount)265 heif_error HeifStblBox::ParseContentChildren(HeifStreamReader &reader, uint32_t &recursionCount)
266 {
267 return ParseContentChildrenByReadChildren(reader, recursionCount);
268 }
269
ParseContent(HeifStreamReader & reader)270 heif_error HeifStsdBox::ParseContent(HeifStreamReader &reader)
271 {
272 ParseFullHeader(reader);
273 entryCount_ = reader.Read32();
274 for (uint32_t i = 0; i < entryCount_; i++) {
275 uint32_t recursionCount = 0;
276 std::shared_ptr<HeifBox> entry;
277 heif_error error = HeifBox::MakeFromReader(reader, &entry, recursionCount);
278 if (error != heif_error_ok) {
279 return error;
280 }
281 entries_.push_back(entry);
282 }
283 return reader.GetError();
284 }
285
GetSampleEntryWidthHeight(uint32_t index,uint32_t & width,uint32_t & height)286 heif_error HeifStsdBox::GetSampleEntryWidthHeight(uint32_t index, uint32_t &width, uint32_t &height)
287 {
288 if (index >= entries_.size()) {
289 return heif_error_invalid_index;
290 }
291 if (entries_[index] && entries_[index]->GetBoxType() == BOX_TYPE_HVC1) {
292 auto hvc1Entry = std::dynamic_pointer_cast<HeifHvc1Box>(entries_[index]);
293 width = hvc1Entry->GetWidth();
294 height = hvc1Entry->GetHeight();
295 }
296 return heif_error_ok;
297 }
298
GetHvccBox(uint32_t index)299 std::shared_ptr<HeifBox> HeifStsdBox::GetHvccBox(uint32_t index)
300 {
301 if (index >= entries_.size()) {
302 return nullptr;
303 }
304 if (entries_[index] && entries_[index]->GetBoxType() == BOX_TYPE_HVC1) {
305 auto hvc1Entry = std::dynamic_pointer_cast<HeifHvc1Box>(entries_[index]);
306 return hvc1Entry->GetHvccBox();
307 }
308 return nullptr;
309 }
310
Write(HeifStreamWriter & writer) const311 heif_error HeifStsdBox::Write(HeifStreamWriter &writer) const
312 {
313 size_t boxStart = ReserveHeader(writer);
314 writer.Write32(entryCount_);
315 for (const auto& entry : entries_) {
316 entry->Write(writer);
317 }
318 WriteCalculatedHeader(writer, boxStart);
319 return heif_error_ok;
320 }
321
ParseContent(HeifStreamReader & reader)322 heif_error HeifSttsBox::ParseContent(HeifStreamReader &reader)
323 {
324 ParseFullHeader(reader);
325 entryCount_ = reader.Read32();
326 for (uint32_t i = 0; i < entryCount_; i++) {
327 TimeToSampleEntry entry;
328 entry.sampleCount = reader.Read32();
329 entry.sampleDelta = reader.Read32();
330 entries_.push_back(entry);
331 }
332 return reader.GetError();
333 }
334
Write(HeifStreamWriter & writer) const335 heif_error HeifSttsBox::Write(HeifStreamWriter &writer) const
336 {
337 size_t boxStart = ReserveHeader(writer);
338 writer.Write32(entryCount_);
339 for (const auto& entry : entries_) {
340 writer.Write32(entry.sampleCount);
341 writer.Write32(entry.sampleDelta);
342 }
343 WriteCalculatedHeader(writer, boxStart);
344 return heif_error_ok;
345 }
346
ParseContent(HeifStreamReader & reader)347 heif_error HeifStscBox::ParseContent(HeifStreamReader &reader)
348 {
349 ParseFullHeader(reader);
350 entryCount_ = reader.Read32();
351 for (uint32_t i = 0; i < entryCount_; i++) {
352 SampleToChunkEntry entry;
353 entry.firstChunk = reader.Read32();
354 entry.samplesPerChunk = reader.Read32();
355 entry.sampleDescriptionIndex = reader.Read32();
356 entries_.push_back(entry);
357 }
358 return reader.GetError();
359 }
360
Write(HeifStreamWriter & writer) const361 heif_error HeifStscBox::Write(HeifStreamWriter &writer) const
362 {
363 size_t boxStart = ReserveHeader(writer);
364 writer.Write32(entryCount_);
365 for (const auto& entry : entries_) {
366 writer.Write32(entry.firstChunk);
367 writer.Write32(entry.samplesPerChunk);
368 writer.Write32(entry.sampleDescriptionIndex);
369 }
370 WriteCalculatedHeader(writer, boxStart);
371 return heif_error_ok;
372 }
373
ParseContent(HeifStreamReader & reader)374 heif_error HeifStcoBox::ParseContent(HeifStreamReader &reader)
375 {
376 ParseFullHeader(reader);
377 entryCount_ = reader.Read32();
378 for (uint32_t i = 0; i < entryCount_; i++) {
379 chunkOffsets_.push_back(reader.Read32());
380 }
381 return reader.GetError();
382 }
383
GetChunkOffset(uint32_t chunkIndex,uint32_t & chunkOffset)384 heif_error HeifStcoBox::GetChunkOffset(uint32_t chunkIndex, uint32_t &chunkOffset)
385 {
386 if (chunkIndex >= chunkOffsets_.size()) {
387 return heif_error_invalid_index;
388 }
389 chunkOffset = chunkOffsets_[chunkIndex];
390 return heif_error_ok;
391 }
392
Write(HeifStreamWriter & writer) const393 heif_error HeifStcoBox::Write(HeifStreamWriter &writer) const
394 {
395 size_t boxStart = ReserveHeader(writer);
396 writer.Write32(entryCount_);
397 for (uint32_t offset : chunkOffsets_) {
398 writer.Write32(offset);
399 }
400 WriteCalculatedHeader(writer, boxStart);
401 return heif_error_ok;
402 }
403
ParseContent(HeifStreamReader & reader)404 heif_error HeifStszBox::ParseContent(HeifStreamReader &reader)
405 {
406 ParseFullHeader(reader);
407 sampleSize_ = reader.Read32();
408 sampleCount_ = reader.Read32();
409 if (sampleSize_ == 0) {
410 for (uint32_t i = 0; i < sampleCount_; i++) {
411 entrySizes_.push_back(reader.Read32());
412 }
413 }
414 return reader.GetError();
415 }
416
GetSampleSize(uint32_t sampleIndex,uint32_t & sampleSize)417 heif_error HeifStszBox::GetSampleSize(uint32_t sampleIndex, uint32_t &sampleSize)
418 {
419 if (sampleIndex >= entrySizes_.size()) {
420 return heif_error_invalid_index;
421 }
422 sampleSize = entrySizes_[sampleIndex];
423 return heif_error_ok;
424 }
425
Write(HeifStreamWriter & writer) const426 heif_error HeifStszBox::Write(HeifStreamWriter &writer) const
427 {
428 size_t boxStart = ReserveHeader(writer);
429 writer.Write32(sampleSize_);
430 writer.Write32(sampleCount_);
431 if (sampleSize_ == 0) {
432 for (uint32_t size : entrySizes_) {
433 writer.Write32(size);
434 }
435 }
436 WriteCalculatedHeader(writer, boxStart);
437 return heif_error_ok;
438 }
439
ParseContent(HeifStreamReader & reader)440 heif_error HeifHvc1Box::ParseContent(HeifStreamReader &reader)
441 {
442 for (uint32_t i = 0; i < HVC1_RESERVED_OFFSET; i++) {
443 reserved_[i] = reader.Read8();
444 }
445 for (uint32_t i = 0; i < HVC1_PREDEFINE_OFFSET; i++) {
446 reader.Read8();
447 }
448 width_ = reader.Read16();
449 height_ = reader.Read16();
450 for (uint32_t i = 0; i < HVC1_SKIP_OFFSET; i++) {
451 reader.Read8();
452 }
453 uint32_t recursionCount = 0;
454 heif_error error = HeifBox::MakeFromReader(reader, &hvccBox_, recursionCount);
455 if (error != heif_error_ok) {
456 return error;
457 }
458 return reader.GetError();
459 }
460 } // namespace ImagePlugin
461 } // namespace OHOS
462