Coverage Report

Created: 2025-12-31 07:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libheif/libheif/sequences/track_metadata.cc
Line
Count
Source
1
/*
2
 * HEIF image base codec.
3
 * Copyright (c) 2025 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
#include "track_metadata.h"
22
#include "chunk.h"
23
#include "context.h"
24
#include "api_structs.h"
25
#include <utility>
26
27
28
Track_Metadata::Track_Metadata(HeifContext* ctx)
29
4
    : Track(ctx)
30
4
{
31
4
}
32
33
Error Track_Metadata::load(const std::shared_ptr<Box_trak>& trak)
34
4
{
35
4
  Error parentLoadError = Track::load(trak);
36
4
  if (parentLoadError) {
37
4
    return parentLoadError;
38
4
  }
39
40
0
  const std::vector<uint32_t>& chunk_offsets = m_stco->get_offsets();
41
42
  // Metadata tracks are not meant for display
43
44
0
  m_tkhd->set_flags(m_tkhd->get_flags() & ~(Box_tkhd::Flags::Track_in_movie |
45
0
                                            Box_tkhd::Flags::Track_in_preview));
46
47
  // Find sequence resolution
48
49
0
  if (!chunk_offsets.empty())  {
50
0
    auto* s2c = m_stsc->get_chunk(static_cast<uint32_t>(1));
51
0
    if (!s2c) {
52
0
      return {
53
0
        heif_error_Invalid_input,
54
0
        heif_suberror_Unspecified,
55
0
        "Metadata track has no chunk 1"
56
0
      };
57
0
    }
58
59
0
    Box_stsc::SampleToChunk sampleToChunk = *s2c;
60
61
0
    auto sample_description = m_stsd->get_sample_entry(sampleToChunk.sample_description_index - 1);
62
0
    if (!sample_description) {
63
0
      return {
64
0
        heif_error_Invalid_input,
65
0
        heif_suberror_Unspecified,
66
0
        "Metadata track has no sample description"
67
0
      };
68
0
    }
69
70
    // TODO: read URI
71
0
  }
72
73
0
  return {};
74
0
}
75
76
77
Track_Metadata::Track_Metadata(HeifContext* ctx, uint32_t track_id, std::string uri, const TrackOptions* options)
78
0
    : Track(ctx, track_id, options, fourcc("meta")),
79
0
      m_uri(std::move(uri))
80
0
{
81
0
  auto nmhd = std::make_shared<Box_nmhd>();
82
0
  m_minf->append_child_box(nmhd);
83
0
}
84
85
86
#if 0
87
Result<std::shared_ptr<const Track_Metadata::Metadata>> Track_Metadata::read_next_metadata_sample()
88
{
89
  if (m_current_chunk > m_chunks.size()) {
90
    return Error{heif_error_End_of_sequence,
91
                 heif_suberror_Unspecified,
92
                 "End of sequence"};
93
  }
94
95
  while (m_next_sample_to_be_decoded > m_chunks[m_current_chunk]->last_sample_number()) {
96
    m_current_chunk++;
97
98
    if (m_current_chunk > m_chunks.size()) {
99
      return Error{heif_error_End_of_sequence,
100
                   heif_suberror_Unspecified,
101
                   "End of sequence"};
102
    }
103
  }
104
105
  const std::shared_ptr<Chunk>& chunk = m_chunks[m_current_chunk];
106
107
  auto decoder = chunk->get_decoder();
108
  assert(decoder);
109
110
  decoder->set_data_extent(chunk->get_data_extent_for_sample(m_next_sample_to_be_decoded));
111
112
  Result<std::shared_ptr<HeifPixelImage>> decodingResult = decoder->decode_single_frame_from_compressed_data(options);
113
  if (decodingResult.error) {
114
    m_next_sample_to_be_decoded++;
115
    return decodingResult.error;
116
  }
117
118
  auto image = decodingResult.value;
119
120
  if (m_stts) {
121
    image->set_sample_duration(m_stts->get_sample_duration(m_next_sample_to_be_decoded));
122
  }
123
124
  // --- read sample auxiliary data
125
126
  if (m_aux_reader_content_ids) {
127
    auto readResult = m_aux_reader_content_ids->get_sample_info(get_file().get(), m_next_sample_to_be_decoded);
128
    if (readResult.error) {
129
      return readResult.error;
130
    }
131
132
    Result<std::string> convResult = vector_to_string(readResult.value);
133
    if (convResult.error) {
134
      return convResult.error;
135
    }
136
137
    image->set_gimi_content_id(convResult.value);
138
  }
139
140
  if (m_aux_reader_tai_timestamps) {
141
    auto readResult = m_aux_reader_tai_timestamps->get_sample_info(get_file().get(), m_next_sample_to_be_decoded);
142
    if (readResult.error) {
143
      return readResult.error;
144
    }
145
146
    auto resultTai = Box_itai::decode_tai_from_vector(readResult.value);
147
    if (resultTai.error) {
148
      return resultTai.error;
149
    }
150
151
    image->set_tai_timestamp(&resultTai.value);
152
  }
153
154
  m_next_sample_to_be_decoded++;
155
156
  return image;
157
}
158
#endif
159
160
161
Error Track_Metadata::write_raw_metadata(const heif_raw_sequence_sample* raw_sample)
162
0
{
163
  // generate new chunk for first metadata packet
164
165
0
  if (m_chunks.empty()) {
166
167
    // --- write URIMetaSampleEntry ('urim')
168
169
0
    auto sample_description_box = std::make_shared<Box_URIMetaSampleEntry>();
170
0
    auto uri = std::make_shared<Box_uri>();
171
0
    uri->set_uri(m_uri);
172
0
    sample_description_box->append_child_box(uri);
173
174
0
    add_chunk(heif_compression_undefined);
175
0
    set_sample_description_box(sample_description_box);
176
0
  }
177
178
0
  Error err = write_sample_data(raw_sample->data,
179
0
                                raw_sample->duration,
180
0
                                0,
181
0
                                true,
182
0
                                raw_sample->timestamp,
183
0
                                raw_sample->gimi_sample_content_id);
184
0
  if (err) {
185
0
    return err;
186
0
  }
187
188
0
  return Error::Ok;
189
0
}