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