/src/libheif/libheif/sequences/seq_boxes.h
Line | Count | Source |
1 | | /* |
2 | | * HEIF codec. |
3 | | * Copyright (c) 2024 Dirk Farin <dirk.farin@gmail.com> |
4 | | * |
5 | | * This file is part of libheif. |
6 | | * |
7 | | * libheif is free software: you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser General Public License as |
9 | | * published by the Free Software Foundation, either version 3 of |
10 | | * the License, or (at your option) any later version. |
11 | | * |
12 | | * libheif is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public License |
18 | | * along with libheif. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #ifndef SEQ_BOXES_H |
22 | | #define SEQ_BOXES_H |
23 | | |
24 | | #include "box.h" |
25 | | #include "security_limits.h" |
26 | | |
27 | | #include <string> |
28 | | #include <memory> |
29 | | #include <vector> |
30 | | #include <limits> |
31 | | |
32 | | |
33 | | class Box_container : public Box { |
34 | | public: |
35 | | Box_container(const char* type) |
36 | 9.75k | { |
37 | 9.75k | set_short_type(fourcc(type)); |
38 | 9.75k | } |
39 | | |
40 | | std::string dump(Indent&) const override; |
41 | | |
42 | | protected: |
43 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
44 | | }; |
45 | | |
46 | | |
47 | | // Movie Box |
48 | | class Box_moov : public Box_container { |
49 | | public: |
50 | 2.49k | Box_moov() : Box_container("moov") {} |
51 | | |
52 | 0 | const char* debug_box_name() const override { return "Movie"; } |
53 | | }; |
54 | | |
55 | | |
56 | | // Movie Header Box |
57 | | class Box_mvhd : public FullBox { |
58 | | public: |
59 | | Box_mvhd() |
60 | 50 | { |
61 | 50 | set_short_type(fourcc("mvhd")); |
62 | 50 | } |
63 | | |
64 | | std::string dump(Indent&) const override; |
65 | | |
66 | 0 | const char* debug_box_name() const override { return "Movie Header"; } |
67 | | |
68 | | Error write(StreamWriter& writer) const override; |
69 | | |
70 | | void derive_box_version() override; |
71 | | |
72 | 0 | double get_rate() const { return m_rate / double(0x10000); } |
73 | | |
74 | 0 | float get_volume() const { return float(m_volume) / float(0x100); } |
75 | | |
76 | | double get_matrix_element(int idx) const; |
77 | | |
78 | 0 | uint32_t get_time_scale() const { return m_timescale; } |
79 | | |
80 | 0 | uint64_t get_duration() const { return m_duration; } |
81 | | |
82 | | // True when the duration field carries the ISOBMFF "duration unknown / indefinite" |
83 | | // sentinel (all-1s for the field width corresponding to the box version). |
84 | | // Files written with such a duration alongside an editlist in repeat mode signal |
85 | | // that the media should be looped indefinitely. |
86 | | bool is_duration_indefinite() const |
87 | 0 | { |
88 | 0 | if (get_version() == 1) { |
89 | 0 | return m_duration == std::numeric_limits<uint64_t>::max(); |
90 | 0 | } |
91 | 0 | return m_duration == std::numeric_limits<uint32_t>::max(); |
92 | 0 | } |
93 | | |
94 | 0 | void set_duration(uint64_t duration) { m_duration = duration; } |
95 | | |
96 | 0 | void set_time_scale(uint32_t timescale) { m_timescale = timescale; } |
97 | | |
98 | 0 | void set_next_track_id(uint32_t next_id) { m_next_track_ID = next_id; } |
99 | | |
100 | | protected: |
101 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
102 | | |
103 | | private: |
104 | | uint64_t m_creation_time = 0; |
105 | | uint64_t m_modification_time = 0; |
106 | | uint32_t m_timescale = 0; |
107 | | uint64_t m_duration = 0; |
108 | | |
109 | | uint32_t m_rate = 0x00010000; // typically 1.0 |
110 | | uint16_t m_volume = 0x0100; // typically, full volume |
111 | | |
112 | | uint32_t m_matrix[9] = {0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000}; |
113 | | uint32_t m_next_track_ID = 0; |
114 | | }; |
115 | | |
116 | | |
117 | | // Track Box |
118 | | class Box_trak : public Box_container { |
119 | | public: |
120 | 1.92k | Box_trak() : Box_container("trak") {} |
121 | | |
122 | 0 | const char* debug_box_name() const override { return "Track"; } |
123 | | }; |
124 | | |
125 | | |
126 | | // Track Header Box |
127 | | class Box_tkhd : public FullBox { |
128 | | public: |
129 | | Box_tkhd() |
130 | 14 | { |
131 | 14 | set_short_type(fourcc("tkhd")); |
132 | | |
133 | | // set default flags according to ISO 14496-12 |
134 | 14 | set_flags(Track_enabled | Track_in_movie | Track_in_preview); |
135 | 14 | } |
136 | | |
137 | | enum Flags : uint32_t { |
138 | | Track_enabled = 0x01, |
139 | | Track_in_movie = 0x02, |
140 | | Track_in_preview = 0x04, |
141 | | Track_size_is_aspect_ratio = 0x08 |
142 | | }; |
143 | | |
144 | | std::string dump(Indent&) const override; |
145 | | |
146 | 0 | const char* debug_box_name() const override { return "Track Header"; } |
147 | | |
148 | | Error write(StreamWriter& writer) const override; |
149 | | |
150 | | void derive_box_version() override; |
151 | | |
152 | 0 | float get_volume() const { return float(m_volume) / float(0x100); } |
153 | | |
154 | | double get_matrix_element(int idx) const; |
155 | | |
156 | 0 | double get_width() const { return float(m_width) / double(0x10000); } |
157 | | |
158 | 0 | double get_height() const { return float(m_height) / double(0x10000); } |
159 | | |
160 | 0 | uint32_t get_track_id() const { return m_track_id; } |
161 | | |
162 | 0 | void set_track_id(uint32_t track_id) { m_track_id = track_id; } |
163 | | |
164 | | void set_resolution(double width, double height) |
165 | 0 | { |
166 | 0 | m_width = (uint32_t) (width * 0x10000); |
167 | 0 | m_height = (uint32_t) (height * 0x10000); |
168 | 0 | } |
169 | | |
170 | 0 | uint64_t get_duration() const { return m_duration; } |
171 | | |
172 | 0 | void set_duration(uint64_t duration) { m_duration = duration; } |
173 | | |
174 | | protected: |
175 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
176 | | |
177 | | private: |
178 | | uint64_t m_creation_time = 0; |
179 | | uint64_t m_modification_time = 0; |
180 | | uint32_t m_track_id = 0; |
181 | | uint64_t m_duration = 0; |
182 | | |
183 | | uint16_t m_layer = 0; |
184 | | uint16_t m_alternate_group = 0; |
185 | | uint16_t m_volume = 0x0100; // typically, full volume |
186 | | |
187 | | uint32_t m_matrix[9] = {0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000}; |
188 | | |
189 | | uint32_t m_width = 0; |
190 | | uint32_t m_height = 0; |
191 | | }; |
192 | | |
193 | | |
194 | | // Media Box |
195 | | class Box_mdia : public Box_container { |
196 | | public: |
197 | 1.84k | Box_mdia() : Box_container("mdia") {} |
198 | | |
199 | 0 | const char* debug_box_name() const override { return "Media"; } |
200 | | }; |
201 | | |
202 | | |
203 | | // Media Header Box |
204 | | class Box_mdhd : public FullBox { |
205 | | public: |
206 | | Box_mdhd() |
207 | 11 | { |
208 | 11 | set_short_type(fourcc("mdhd")); |
209 | 11 | } |
210 | | |
211 | | std::string dump(Indent&) const override; |
212 | | |
213 | 0 | const char* debug_box_name() const override { return "Media Header"; } |
214 | | |
215 | | Error write(StreamWriter& writer) const override; |
216 | | |
217 | | void derive_box_version() override; |
218 | | |
219 | | double get_matrix_element(int idx) const; |
220 | | |
221 | 0 | uint32_t get_timescale() const { return m_timescale; } |
222 | | |
223 | 0 | void set_timescale(uint32_t timescale) { m_timescale = timescale; } |
224 | | |
225 | 0 | uint64_t get_duration() const { return m_duration; } |
226 | | |
227 | 0 | void set_duration(uint64_t duration) { m_duration = duration; } |
228 | | |
229 | | protected: |
230 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
231 | | |
232 | | private: |
233 | | uint64_t m_creation_time = 0; |
234 | | uint64_t m_modification_time = 0; |
235 | | uint32_t m_timescale = 0; |
236 | | uint64_t m_duration = 0; |
237 | | |
238 | | char m_language[4] = {'u', 'n', 'k', 0}; |
239 | | }; |
240 | | |
241 | | |
242 | | // Media Information Box (container) |
243 | | class Box_minf : public Box_container { |
244 | | public: |
245 | 1.77k | Box_minf() : Box_container("minf") {} |
246 | | |
247 | 0 | const char* debug_box_name() const override { return "Media Information"; } |
248 | | }; |
249 | | |
250 | | |
251 | | // Video Media Header |
252 | | class Box_vmhd : public FullBox { |
253 | | public: |
254 | | Box_vmhd() |
255 | 4 | { |
256 | 4 | set_short_type(fourcc("vmhd")); |
257 | 4 | set_flags(1); |
258 | 4 | } |
259 | | |
260 | | std::string dump(Indent&) const override; |
261 | | |
262 | 0 | const char* debug_box_name() const override { return "Video Media Header"; } |
263 | | |
264 | | Error write(StreamWriter& writer) const override; |
265 | | |
266 | | protected: |
267 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
268 | | |
269 | | private: |
270 | | uint16_t m_graphics_mode = 0; |
271 | | uint16_t m_op_color[3] = {0, 0, 0}; |
272 | | }; |
273 | | |
274 | | |
275 | | // Null Media Header |
276 | | class Box_nmhd : public FullBox { |
277 | | public: |
278 | | Box_nmhd() |
279 | 33 | { |
280 | 33 | set_short_type(fourcc("nmhd")); |
281 | 33 | set_flags(1); |
282 | 33 | } |
283 | | |
284 | | std::string dump(Indent&) const override; |
285 | | |
286 | 0 | const char* debug_box_name() const override { return "Null Media Header"; } |
287 | | |
288 | | Error write(StreamWriter& writer) const override; |
289 | | |
290 | | protected: |
291 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
292 | | }; |
293 | | |
294 | | |
295 | | // Sample Table Box (container) |
296 | | class Box_stbl : public Box_container { |
297 | | public: |
298 | 1.70k | Box_stbl() : Box_container("stbl") {} |
299 | | |
300 | 0 | const char* debug_box_name() const override { return "Sample Table"; } |
301 | | }; |
302 | | |
303 | | |
304 | | // Sample Description Box |
305 | | class Box_stsd : public FullBox { |
306 | | public: |
307 | | Box_stsd() |
308 | 43 | { |
309 | 43 | set_short_type(fourcc("stsd")); |
310 | 43 | } |
311 | | |
312 | | std::string dump(Indent&) const override; |
313 | | |
314 | 0 | const char* debug_box_name() const override { return "Sample Description"; } |
315 | | |
316 | | Error write(StreamWriter& writer) const override; |
317 | | |
318 | | std::shared_ptr<const class Box> get_sample_entry(size_t idx) const |
319 | 0 | { |
320 | 0 | if (idx >= m_sample_entries.size()) { |
321 | 0 | return nullptr; |
322 | 0 | } else { |
323 | 0 | return m_sample_entries[idx]; |
324 | 0 | } |
325 | 0 | } |
326 | | |
327 | | void add_sample_entry(std::shared_ptr<class Box> entry) |
328 | 0 | { |
329 | 0 | m_sample_entries.push_back(entry); |
330 | 0 | } |
331 | | |
332 | 0 | size_t get_num_sample_entries() const { return m_sample_entries.size(); } |
333 | | |
334 | | protected: |
335 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
336 | | |
337 | | private: |
338 | | std::vector<std::shared_ptr<class Box>> m_sample_entries; |
339 | | }; |
340 | | |
341 | | |
342 | | // Decoding Time to Sample Box |
343 | | class Box_stts : public FullBox { |
344 | | public: |
345 | | Box_stts() |
346 | 57 | { |
347 | 57 | set_short_type(fourcc("stts")); |
348 | 57 | } |
349 | | |
350 | | std::string dump(Indent&) const override; |
351 | | |
352 | 0 | const char* debug_box_name() const override { return "Decoding Time to Sample"; } |
353 | | |
354 | | Error write(StreamWriter& writer) const override; |
355 | | |
356 | | struct TimeToSample { |
357 | | uint32_t sample_count; |
358 | | uint32_t sample_delta; |
359 | | }; |
360 | | |
361 | | uint32_t get_sample_duration(uint32_t sample_idx); |
362 | | |
363 | | void append_sample_duration(uint32_t duration); |
364 | | |
365 | | uint64_t get_total_duration(bool include_last_frame_duration); |
366 | | |
367 | | uint32_t get_number_of_samples() const; |
368 | | |
369 | | protected: |
370 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
371 | | |
372 | | private: |
373 | | std::vector<TimeToSample> m_entries; |
374 | | MemoryHandle m_memory_handle; |
375 | | }; |
376 | | |
377 | | |
378 | | // Composition Time to Sample Box |
379 | | class Box_ctts : public FullBox { |
380 | | public: |
381 | | Box_ctts() |
382 | 52 | { |
383 | 52 | set_short_type(fourcc("ctts")); |
384 | 52 | } |
385 | | |
386 | | std::string dump(Indent&) const override; |
387 | | |
388 | 0 | const char* debug_box_name() const override { return "Composition Time to Sample"; } |
389 | | |
390 | | Error write(StreamWriter& writer) const override; |
391 | | |
392 | | struct OffsetToSample { |
393 | | uint32_t sample_count; |
394 | | int32_t sample_offset; // either uint32_t or int32_t, we assume that all uint32_t values will also fit into int32_t |
395 | | }; |
396 | | |
397 | | int32_t get_sample_offset(uint32_t sample_idx); |
398 | | |
399 | | void append_sample_offset(int32_t offset); |
400 | | |
401 | | bool is_constant_offset() const; |
402 | | |
403 | | void derive_box_version() override; |
404 | | |
405 | | int32_t compute_min_offset() const; |
406 | | |
407 | | uint32_t get_number_of_samples() const; |
408 | | |
409 | | protected: |
410 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
411 | | |
412 | | private: |
413 | | std::vector<OffsetToSample> m_entries; |
414 | | MemoryHandle m_memory_handle; |
415 | | }; |
416 | | |
417 | | |
418 | | // Sample to Chunk Box |
419 | | class Box_stsc : public FullBox { |
420 | | public: |
421 | | Box_stsc() |
422 | 54 | { |
423 | 54 | set_short_type(fourcc("stsc")); |
424 | 54 | } |
425 | | |
426 | | std::string dump(Indent&) const override; |
427 | | |
428 | 0 | const char* debug_box_name() const override { return "Sample to Chunk"; } |
429 | | |
430 | | Error write(StreamWriter& writer) const override; |
431 | | |
432 | | struct SampleToChunk { |
433 | | uint32_t first_chunk; |
434 | | uint32_t samples_per_chunk; |
435 | | uint32_t sample_description_index; |
436 | | }; |
437 | | |
438 | 0 | const std::vector<SampleToChunk>& get_chunks() const { return m_entries; } |
439 | | |
440 | | // idx counting starts at 1 |
441 | | const SampleToChunk* get_chunk(uint32_t idx) const; |
442 | | |
443 | | void add_chunk(uint32_t description_index); |
444 | | |
445 | | void increase_samples_in_chunk(uint32_t nFrames); |
446 | | |
447 | 0 | bool last_chunk_empty() const { |
448 | 0 | assert(!m_entries.empty()); |
449 | 0 |
|
450 | 0 | return m_entries.back().samples_per_chunk == 0; |
451 | 0 | } |
452 | | |
453 | | protected: |
454 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
455 | | |
456 | | private: |
457 | | std::vector<SampleToChunk> m_entries; |
458 | | MemoryHandle m_memory_handle; |
459 | | }; |
460 | | |
461 | | |
462 | | // Chunk Offset Box |
463 | | class Box_stco : public FullBox { |
464 | | public: |
465 | | Box_stco() |
466 | 1.44k | { |
467 | 1.44k | set_short_type(fourcc("stco")); |
468 | 1.44k | } |
469 | | |
470 | | std::string dump(Indent&) const override; |
471 | | |
472 | 0 | const char* debug_box_name() const override { return "Sample Offset"; } |
473 | | |
474 | | Error write(StreamWriter& writer) const override; |
475 | | |
476 | 0 | void add_chunk_offset(uint32_t offset) { m_offsets.push_back(offset); } |
477 | | |
478 | 0 | const std::vector<uint32_t>& get_offsets() const { return m_offsets; } |
479 | | |
480 | 0 | size_t get_number_of_chunks() const { return m_offsets.size(); } |
481 | | |
482 | | void patch_file_pointers(StreamWriter&, size_t offset) override; |
483 | | |
484 | | protected: |
485 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
486 | | |
487 | | private: |
488 | | std::vector<uint32_t> m_offsets; |
489 | | MemoryHandle m_memory_handle; |
490 | | |
491 | | mutable size_t m_offset_start_pos = 0; |
492 | | }; |
493 | | |
494 | | |
495 | | // Sample Size Box |
496 | | class Box_stsz : public FullBox { |
497 | | public: |
498 | | Box_stsz() |
499 | 32 | { |
500 | 32 | set_short_type(fourcc("stsz")); |
501 | 32 | } |
502 | | |
503 | | std::string dump(Indent&) const override; |
504 | | |
505 | 0 | const char* debug_box_name() const override { return "Sample Size"; } |
506 | | |
507 | | Error write(StreamWriter& writer) const override; |
508 | | |
509 | 0 | bool has_fixed_sample_size() const { return m_fixed_sample_size != 0; } |
510 | | |
511 | 0 | uint32_t get_fixed_sample_size() const { return m_fixed_sample_size; } |
512 | | |
513 | 0 | uint32_t num_samples() const { return m_sample_count; } |
514 | | |
515 | 0 | const std::vector<uint32_t>& get_sample_sizes() const { return m_sample_sizes; } |
516 | | |
517 | | void append_sample_size(uint32_t size); |
518 | | |
519 | | protected: |
520 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
521 | | |
522 | | private: |
523 | | uint32_t m_fixed_sample_size = 0; |
524 | | uint32_t m_sample_count = 0; |
525 | | std::vector<uint32_t> m_sample_sizes; |
526 | | MemoryHandle m_memory_handle; |
527 | | }; |
528 | | |
529 | | |
530 | | // Sync Sample Box |
531 | | class Box_stss : public FullBox { |
532 | | public: |
533 | | Box_stss() |
534 | 27 | { |
535 | 27 | set_short_type(fourcc("stss")); |
536 | 27 | } |
537 | | |
538 | | std::string dump(Indent&) const override; |
539 | | |
540 | 0 | const char* debug_box_name() const override { return "Sync Sample"; } |
541 | | |
542 | | Error write(StreamWriter& writer) const override; |
543 | | |
544 | 0 | void add_sync_sample(uint32_t sample_idx) { m_sync_samples.push_back(sample_idx); } |
545 | | |
546 | | // when this is set, the Box will compute whether it can be skipped |
547 | | void set_total_number_of_samples(uint32_t num_samples); |
548 | | |
549 | | // bool skip_box() const override { return m_all_samples_are_sync_samples; } |
550 | | |
551 | | protected: |
552 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
553 | | |
554 | | private: |
555 | | std::vector<uint32_t> m_sync_samples; |
556 | | MemoryHandle m_memory_handle; |
557 | | |
558 | | bool m_all_samples_are_sync_samples = false; |
559 | | }; |
560 | | |
561 | | |
562 | | struct CodingConstraints { |
563 | | bool all_ref_pics_intra = false; |
564 | | bool intra_pred_used = false; |
565 | | uint8_t max_ref_per_pic = 0; // 4 bit |
566 | | }; |
567 | | |
568 | | |
569 | | // Coding Constraints Box |
570 | | class Box_ccst : public FullBox { |
571 | | public: |
572 | | Box_ccst() |
573 | 32 | { |
574 | 32 | set_short_type(fourcc("ccst")); |
575 | 32 | } |
576 | | |
577 | | std::string dump(Indent&) const override; |
578 | | |
579 | 0 | const char* debug_box_name() const override { return "Coding Constraints"; } |
580 | | |
581 | | Error write(StreamWriter& writer) const override; |
582 | | |
583 | 0 | void set_coding_constraints(const CodingConstraints& c) { m_codingConstraints = c; } |
584 | | |
585 | 0 | const CodingConstraints& get_coding_constraints() const { return m_codingConstraints; } |
586 | | |
587 | | protected: |
588 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
589 | | |
590 | | private: |
591 | | CodingConstraints m_codingConstraints; |
592 | | }; |
593 | | |
594 | | |
595 | | class Box_auxi : public FullBox { |
596 | | public: |
597 | | Box_auxi() |
598 | 15 | { |
599 | 15 | set_short_type(fourcc("auxi")); |
600 | 15 | } |
601 | | |
602 | | std::string dump(Indent&) const override; |
603 | | |
604 | 0 | const char* debug_box_name() const override { return "Auxiliary Info Type"; } |
605 | | |
606 | | Error write(StreamWriter& writer) const override; |
607 | | |
608 | 0 | void set_aux_track_type_urn(const std::string& t) { m_aux_track_type = t; } |
609 | | |
610 | 0 | std::string get_aux_track_type_urn() const { return m_aux_track_type; } |
611 | | |
612 | | protected: |
613 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
614 | | |
615 | | private: |
616 | | std::string m_aux_track_type; |
617 | | }; |
618 | | |
619 | | |
620 | | struct VisualSampleEntry { |
621 | | // from SampleEntry |
622 | | //const unsigned int(8)[6] reserved = 0; |
623 | | uint16_t data_reference_index = 1; |
624 | | |
625 | | // VisualSampleEntry |
626 | | |
627 | | uint16_t pre_defined = 0; |
628 | | //uint16_t reserved = 0; |
629 | | uint32_t pre_defined2[3] = {0, 0, 0}; |
630 | | uint16_t width = 0; |
631 | | uint16_t height = 0; |
632 | | uint32_t horizresolution = 0x00480000; // 72 dpi |
633 | | uint32_t vertresolution = 0x00480000; // 72 dpi |
634 | | //uint32_t reserved = 0; |
635 | | uint16_t frame_count = 1; |
636 | | std::string compressorname; // max 32 characters |
637 | | uint16_t depth = 0x0018; |
638 | | int16_t pre_defined3 = -1; |
639 | | // other boxes from derived specifications |
640 | | //std::shared_ptr<Box_clap> clap; // optional |
641 | | //std::shared_ptr<Box_pixi> pixi; // optional |
642 | | |
643 | 0 | double get_horizontal_resolution() const { return horizresolution / double(0x10000); } |
644 | | |
645 | 0 | double get_vertical_resolution() const { return vertresolution / double(0x10000); } |
646 | | |
647 | | Error parse(BitstreamRange& range, const heif_security_limits*); |
648 | | |
649 | | Error write(StreamWriter& writer) const; |
650 | | |
651 | | std::string dump(Indent&) const; |
652 | | }; |
653 | | |
654 | | |
655 | | class Box_VisualSampleEntry : public Box { |
656 | | public: |
657 | | Error write(StreamWriter& writer) const override; |
658 | | |
659 | | std::string dump(Indent&) const override; |
660 | | |
661 | 0 | const VisualSampleEntry& get_VisualSampleEntry_const() const { return m_visualSampleEntry; } |
662 | | |
663 | 0 | VisualSampleEntry& get_VisualSampleEntry() { return m_visualSampleEntry; } |
664 | | |
665 | | protected: |
666 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
667 | | |
668 | | private: |
669 | | VisualSampleEntry m_visualSampleEntry; |
670 | | }; |
671 | | |
672 | | |
673 | | class Box_URIMetaSampleEntry : public Box { |
674 | | public: |
675 | | Box_URIMetaSampleEntry() |
676 | 75 | { |
677 | 75 | set_short_type(fourcc("urim")); |
678 | 75 | } |
679 | | |
680 | | Error write(StreamWriter& writer) const override; |
681 | | |
682 | | std::string dump(Indent&) const override; |
683 | | |
684 | 0 | const char* debug_box_name() const override { return "URI Meta Sample Entry"; } |
685 | | |
686 | | protected: |
687 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
688 | | |
689 | | private: |
690 | | // from SampleEntry |
691 | | //const unsigned int(8)[6] reserved = 0; |
692 | | uint16_t data_reference_index; |
693 | | }; |
694 | | |
695 | | |
696 | | class Box_uri : public FullBox { |
697 | | public: |
698 | | Box_uri() |
699 | 56 | { |
700 | 56 | set_short_type(fourcc("uri ")); |
701 | 56 | } |
702 | | |
703 | 0 | void set_uri(std::string uri) { m_uri = uri; } |
704 | | |
705 | 0 | std::string get_uri() const { return m_uri; } |
706 | | |
707 | | Error write(StreamWriter& writer) const override; |
708 | | |
709 | | std::string dump(Indent&) const override; |
710 | | |
711 | 0 | const char* debug_box_name() const override { return "URI"; } |
712 | | |
713 | | protected: |
714 | | Error parse(BitstreamRange& range, const heif_security_limits* limits) override; |
715 | | |
716 | | private: |
717 | | std::string m_uri; |
718 | | }; |
719 | | |
720 | | |
721 | | // Sample to Group |
722 | | class Box_sbgp : public FullBox { |
723 | | public: |
724 | | Box_sbgp() |
725 | 23 | { |
726 | 23 | set_short_type(fourcc("sbgp")); |
727 | 23 | } |
728 | | |
729 | | void derive_box_version() override; |
730 | | |
731 | | std::string dump(Indent&) const override; |
732 | | |
733 | 0 | const char* debug_box_name() const override { return "Sample to Group"; } |
734 | | |
735 | | Error write(StreamWriter& writer) const override; |
736 | | |
737 | | protected: |
738 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
739 | | |
740 | | private: |
741 | | uint32_t m_grouping_type = 0; // 4cc |
742 | | std::optional<uint32_t> m_grouping_type_parameter; |
743 | | |
744 | | struct Entry { |
745 | | uint32_t sample_count; |
746 | | uint32_t group_description_index; |
747 | | }; |
748 | | |
749 | | std::vector<Entry> m_entries; |
750 | | MemoryHandle m_memory_handle; |
751 | | }; |
752 | | |
753 | | |
754 | | class SampleGroupEntry |
755 | | { |
756 | | public: |
757 | 12 | virtual ~SampleGroupEntry() = default; |
758 | | |
759 | | virtual std::string dump() const = 0; |
760 | | |
761 | | virtual Error write(StreamWriter& writer) const = 0; |
762 | | |
763 | | virtual Error parse(BitstreamRange& range, const heif_security_limits*) = 0; |
764 | | }; |
765 | | |
766 | | |
767 | | class SampleGroupEntry_refs : public SampleGroupEntry |
768 | | { |
769 | | public: |
770 | | std::string dump() const override; |
771 | | |
772 | | Error write(StreamWriter& writer) const override; |
773 | | |
774 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
775 | | |
776 | | private: |
777 | | uint32_t m_sample_id; |
778 | | std::vector<uint32_t> m_direct_reference_sample_id; |
779 | | }; |
780 | | |
781 | | |
782 | | // Sample Group Description |
783 | | class Box_sgpd : public FullBox { |
784 | | public: |
785 | | Box_sgpd() |
786 | 146 | { |
787 | 146 | set_short_type(fourcc("sgpd")); |
788 | 146 | } |
789 | | |
790 | | void derive_box_version() override; |
791 | | |
792 | | std::string dump(Indent&) const override; |
793 | | |
794 | 0 | const char* debug_box_name() const override { return "Sample Group Description"; } |
795 | | |
796 | | Error write(StreamWriter& writer) const override; |
797 | | |
798 | | protected: |
799 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
800 | | |
801 | | private: |
802 | | uint32_t m_grouping_type = 0; // 4cc |
803 | | std::optional<uint32_t> m_default_length; // version 1 (0 -> variable length) |
804 | | std::optional<uint32_t> m_default_sample_description_index;; // version >= 2 |
805 | | |
806 | | struct Entry { |
807 | | uint32_t description_length = 0; // if version==1 && m_default_length == 0 |
808 | | std::shared_ptr<SampleGroupEntry> sample_group_entry; |
809 | | }; |
810 | | |
811 | | std::vector<Entry> m_entries; |
812 | | }; |
813 | | |
814 | | // Bitrate |
815 | | class Box_btrt : public FullBox { |
816 | | public: |
817 | | Box_btrt() |
818 | 13 | { |
819 | 13 | set_short_type(fourcc("btrt")); |
820 | 13 | } |
821 | | |
822 | | std::string dump(Indent&) const override; |
823 | | |
824 | 0 | const char* debug_box_name() const override { return "Bitrate"; } |
825 | | |
826 | | Error write(StreamWriter& writer) const override; |
827 | | |
828 | | protected: |
829 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
830 | | |
831 | | private: |
832 | | uint32_t m_bufferSizeDB; |
833 | | uint32_t m_maxBitrate; |
834 | | uint32_t m_avgBitrate; |
835 | | }; |
836 | | |
837 | | |
838 | | class Box_saiz : public FullBox { |
839 | | public: |
840 | | Box_saiz() |
841 | 6 | { |
842 | 6 | set_short_type(fourcc("saiz")); |
843 | 6 | } |
844 | | |
845 | | void set_aux_info_type(uint32_t aux_info_type, uint32_t aux_info_type_parameter = 0); |
846 | | |
847 | 0 | uint32_t get_aux_info_type() const { return m_aux_info_type; } |
848 | | |
849 | 0 | uint32_t get_aux_info_type_parameter() const { return m_aux_info_type_parameter; } |
850 | | |
851 | | void add_sample_size(uint8_t s); |
852 | | |
853 | 0 | void add_nonpresent_sample() { add_sample_size(0); } |
854 | | |
855 | | uint8_t get_sample_size(uint32_t idx); |
856 | | |
857 | 0 | bool have_samples_constant_size() const { return m_default_sample_info_size != 0; } |
858 | | |
859 | 0 | uint32_t get_num_samples() const { return m_num_samples; } |
860 | | |
861 | | std::string dump(Indent&) const override; |
862 | | |
863 | 0 | const char* debug_box_name() const override { return "Sample Auxiliary Information Sizes"; } |
864 | | |
865 | | Error write(StreamWriter& writer) const override; |
866 | | |
867 | | protected: |
868 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
869 | | |
870 | | private: |
871 | | uint32_t m_aux_info_type = 0; |
872 | | uint32_t m_aux_info_type_parameter = 0; |
873 | | uint8_t m_default_sample_info_size = 0; // 0 -> variable length |
874 | | uint32_t m_num_samples = 0; // needed in case we are using the default sample size |
875 | | |
876 | | std::vector<uint8_t> m_sample_sizes; |
877 | | MemoryHandle m_memory_handle; |
878 | | }; |
879 | | |
880 | | |
881 | | class Box_saio : public FullBox { |
882 | | public: |
883 | | Box_saio() |
884 | 46 | { |
885 | 46 | set_short_type(fourcc("saio")); |
886 | 46 | } |
887 | | |
888 | | void set_aux_info_type(uint32_t aux_info_type, uint32_t aux_info_type_parameter = 0); |
889 | | |
890 | 0 | uint32_t get_aux_info_type() const { return m_aux_info_type; } |
891 | | |
892 | 0 | uint32_t get_aux_info_type_parameter() const { return m_aux_info_type_parameter; } |
893 | | |
894 | | void add_chunk_offset(uint64_t offset); |
895 | | |
896 | | // If this is 1, the SAI data of all samples is written contiguously in the file. |
897 | 0 | size_t get_num_chunks() const { return m_chunk_offset.size(); } |
898 | | |
899 | | uint64_t get_chunk_offset(uint32_t idx) const; |
900 | | |
901 | | std::string dump(Indent&) const override; |
902 | | |
903 | 0 | const char* debug_box_name() const override { return "Sample Auxiliary Information Offsets"; } |
904 | | |
905 | | Error write(StreamWriter& writer) const override; |
906 | | |
907 | | protected: |
908 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
909 | | |
910 | | void patch_file_pointers(StreamWriter& writer, size_t offset) override; |
911 | | |
912 | | private: |
913 | | uint32_t m_aux_info_type = 0; |
914 | | uint32_t m_aux_info_type_parameter = 0; |
915 | | |
916 | | bool m_need_64bit = false; |
917 | | mutable uint64_t m_offset_start_pos; |
918 | | |
919 | | // If |chunk_offset|==1, the SAI data of all samples is stored contiguously in the file |
920 | | std::vector<uint64_t> m_chunk_offset; |
921 | | |
922 | | MemoryHandle m_memory_handle; |
923 | | }; |
924 | | |
925 | | |
926 | | class Box_sdtp : public FullBox { |
927 | | public: |
928 | | Box_sdtp() |
929 | 80 | { |
930 | 80 | set_short_type(fourcc("sdtp")); |
931 | 80 | } |
932 | | |
933 | | std::string dump(Indent&) const override; |
934 | | |
935 | 0 | const char* debug_box_name() const override { return "Independent and Disposable Samples"; } |
936 | | |
937 | | // Error write(StreamWriter& writer) const override; |
938 | | |
939 | 0 | uint8_t get_is_leading(uint32_t sampleIdx) const { return (m_sample_information[sampleIdx] >> 6) & 3; } |
940 | | |
941 | 0 | uint8_t get_depends_on(uint32_t sampleIdx) const { return (m_sample_information[sampleIdx] >> 4) & 3; } |
942 | | |
943 | 0 | uint8_t get_is_depended_on(uint32_t sampleIdx) const { return (m_sample_information[sampleIdx] >> 2) & 3; } |
944 | | |
945 | 0 | uint8_t get_has_redundancy(uint32_t sampleIdx) const { return (m_sample_information[sampleIdx]) & 3; } |
946 | | |
947 | | protected: |
948 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
949 | | |
950 | | private: |
951 | | std::vector<uint8_t> m_sample_information; |
952 | | }; |
953 | | |
954 | | |
955 | | class Box_tref : public Box |
956 | | { |
957 | | public: |
958 | | Box_tref() |
959 | 274 | { |
960 | 274 | set_short_type(fourcc("tref")); |
961 | 274 | } |
962 | | |
963 | | struct Reference { |
964 | | uint32_t reference_type; |
965 | | std::vector<uint32_t> to_track_id; |
966 | | }; |
967 | | |
968 | | std::string dump(Indent&) const override; |
969 | | |
970 | 0 | const char* debug_box_name() const override { return "Track Reference"; } |
971 | | |
972 | | std::vector<uint32_t> get_references(uint32_t ref_type) const; |
973 | | |
974 | | size_t get_number_of_references_of_type(uint32_t ref_type) const; |
975 | | |
976 | 0 | size_t get_number_of_reference_types() const { return m_references.size(); } |
977 | | |
978 | | std::vector<uint32_t> get_reference_types() const; |
979 | | |
980 | | void add_references(uint32_t to_track_id, uint32_t type); |
981 | | |
982 | | protected: |
983 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
984 | | |
985 | | Error write(StreamWriter& writer) const override; |
986 | | |
987 | | Error check_for_double_references() const; |
988 | | |
989 | | private: |
990 | | std::vector<Reference> m_references; |
991 | | }; |
992 | | |
993 | | |
994 | | // Edit List container |
995 | | class Box_edts : public Box_container { |
996 | | public: |
997 | 1 | Box_edts() : Box_container("edts") {} |
998 | | |
999 | 0 | const char* debug_box_name() const override { return "Edit List Container"; } |
1000 | | }; |
1001 | | |
1002 | | |
1003 | | class Box_elst : public FullBox |
1004 | | { |
1005 | | public: |
1006 | | Box_elst() |
1007 | 58 | { |
1008 | 58 | set_short_type(fourcc("elst")); |
1009 | 58 | } |
1010 | | |
1011 | | enum Flags { |
1012 | | Repeat_EditList = 0x01 |
1013 | | }; |
1014 | | |
1015 | | std::string dump(Indent&) const override; |
1016 | | |
1017 | 0 | const char* debug_box_name() const override { return "Edit List"; } |
1018 | | |
1019 | | void enable_repeat_mode(bool enable); |
1020 | | |
1021 | 0 | bool is_repeat_mode() const { return get_flags() & Flags::Repeat_EditList; } |
1022 | | |
1023 | | struct Entry { |
1024 | | uint64_t segment_duration = 0; |
1025 | | int64_t media_time = 0; |
1026 | | int16_t media_rate_integer = 1; |
1027 | | int16_t media_rate_fraction = 0; |
1028 | | }; |
1029 | | |
1030 | | void add_entry(const Entry&); |
1031 | | |
1032 | 0 | size_t num_entries() const { return m_entries.size(); } |
1033 | | |
1034 | 0 | Entry get_entry(uint32_t entry) const { return m_entries[entry]; } |
1035 | | |
1036 | | protected: |
1037 | | Error parse(BitstreamRange& range, const heif_security_limits*) override; |
1038 | | |
1039 | | Error write(StreamWriter& writer) const override; |
1040 | | |
1041 | | public: |
1042 | | void derive_box_version() override; |
1043 | | |
1044 | | private: |
1045 | | std::vector<Entry> m_entries; |
1046 | | }; |
1047 | | |
1048 | | #endif //SEQ_BOXES_H |