Coverage Report

Created: 2026-05-16 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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