Coverage Report

Created: 2025-08-11 08:01

/src/libheif/libheif/api/libheif/heif_tai_timestamps.cc
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * HEIF 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 <libheif/heif_tai_timestamps.h>
22
#include "api_structs.h"
23
#include "box.h"
24
#include "file.h"
25
#include <memory>
26
27
28
void initialize_heif_tai_clock_info(heif_tai_clock_info* taic)
29
6
{
30
6
  taic->version = 1;
31
6
  taic->time_uncertainty = heif_tai_clock_info_time_uncertainty_unknown;
32
6
  taic->clock_resolution = 0;
33
6
  taic->clock_drift_rate = heif_tai_clock_info_clock_drift_rate_unknown;
34
6
  taic->clock_type = heif_tai_clock_info_clock_type_unknown;
35
6
}
36
37
heif_tai_clock_info* heif_tai_clock_info_alloc()
38
0
{
39
0
  auto* taic = new heif_tai_clock_info;
40
0
  initialize_heif_tai_clock_info(taic);
41
42
0
  return taic;
43
0
}
44
45
46
void initialize_heif_tai_timestamp_packet(heif_tai_timestamp_packet* itai)
47
10
{
48
10
  itai->version = 1;
49
10
  itai->tai_timestamp = 0;
50
10
  itai->synchronization_state = false;
51
10
  itai->timestamp_generation_failure = false;
52
10
  itai->timestamp_is_modified = false;
53
10
}
54
55
heif_tai_timestamp_packet* heif_tai_timestamp_packet_alloc()
56
0
{
57
0
  auto* itai = new heif_tai_timestamp_packet;
58
0
  initialize_heif_tai_timestamp_packet(itai);
59
60
0
  return itai;
61
0
}
62
63
64
65
void heif_tai_timestamp_packet_copy(heif_tai_timestamp_packet* dst, const heif_tai_timestamp_packet* src)
66
0
{
67
0
  if (dst->version >= 1 && src->version >= 1) {
68
0
    dst->tai_timestamp = src->tai_timestamp;
69
0
    dst->synchronization_state = src->synchronization_state;
70
0
    dst->timestamp_is_modified = src->timestamp_is_modified;
71
0
    dst->timestamp_generation_failure = src->timestamp_generation_failure;
72
0
  }
73
74
  // in the future when copying with "src->version > dst->version",
75
  // the remaining dst fields have to be filled with defaults
76
0
}
77
78
void heif_tai_clock_info_copy(heif_tai_clock_info* dst, const heif_tai_clock_info* src)
79
0
{
80
0
  if (dst->version >= 1 && src->version >= 1) {
81
0
    dst->time_uncertainty = src->time_uncertainty;
82
0
    dst->clock_resolution = src->clock_resolution;
83
0
    dst->clock_drift_rate = src->clock_drift_rate;
84
0
    dst->clock_type = src->clock_type;
85
0
  }
86
87
  // in the future when copying with "src->version > dst->version",
88
  // the remaining dst fields have to be filled with defaults
89
0
}
90
91
92
struct heif_error heif_item_set_property_tai_clock_info(struct heif_context* ctx,
93
                                                        heif_item_id itemId,
94
                                                        const heif_tai_clock_info* clock,
95
                                                        heif_property_id* out_propertyId)
96
0
{
97
0
  if (!ctx || !clock) {
98
0
    return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, "NULL passed"};
99
0
  }
100
101
  // Check if itemId exists
102
0
  auto file = ctx->context->get_heif_file();
103
0
  if (!file->item_exists(itemId)) {
104
0
    return {heif_error_Input_does_not_exist, heif_suberror_Invalid_parameter_value, "itemId does not exist"};
105
0
  }
106
107
  // make sure that we do not add two taic boxes to one image
108
109
0
  if (auto img= ctx->context->get_image(itemId, false)) {
110
0
    auto existing_taic = img->get_property<Box_taic>();
111
0
    if (existing_taic) {
112
0
      return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "item already has an taic property"};
113
0
    }
114
0
  }
115
116
  // Create new taic (it will be deduplicated automatically in add_property())
117
118
0
  auto taic = std::make_shared<Box_taic>();
119
0
  taic->set_from_tai_clock_info(clock);
120
121
0
  heif_property_id id = ctx->context->add_property(itemId, taic, false);
122
123
0
  if (out_propertyId) {
124
0
    *out_propertyId = id;
125
0
  }
126
127
0
  return heif_error_success;
128
0
}
129
130
131
struct heif_error heif_item_get_property_tai_clock_info(const struct heif_context* ctx,
132
                                                        heif_item_id itemId,
133
                                                        heif_tai_clock_info** out_clock)
134
0
{
135
0
  if (!ctx) {
136
0
    return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "NULL heif_context passed in"};
137
0
  }
138
0
  else if (!out_clock) {
139
0
    return {heif_error_Input_does_not_exist, heif_suberror_Invalid_parameter_value, "NULL heif_tai_clock_info passed in"};
140
0
  }
141
142
0
  *out_clock = nullptr;
143
144
  // Check if itemId exists
145
0
  auto file = ctx->context->get_heif_file();
146
0
  if (!file->item_exists(itemId)) {
147
0
    return {heif_error_Input_does_not_exist, heif_suberror_Invalid_parameter_value, "item ID does not exist"};
148
0
  }
149
150
  // Check if taic exists for itemId
151
0
  auto taic = file->get_property_for_item<Box_taic>(itemId);
152
0
  if (!taic) {
153
    // return NULL heif_tai_clock_info
154
0
    return heif_error_success;
155
0
  }
156
157
0
  *out_clock = new heif_tai_clock_info;
158
0
  **out_clock = *taic->get_tai_clock_info();
159
160
0
  return heif_error_success;
161
0
}
162
163
164
void heif_tai_clock_info_release(struct heif_tai_clock_info* clock_info)
165
0
{
166
0
  delete clock_info;
167
0
}
168
169
170
void heif_tai_timestamp_packet_release(struct heif_tai_timestamp_packet* tai)
171
20.4k
{
172
20.4k
  delete tai;
173
20.4k
}
174
175
176
struct heif_error heif_item_set_property_tai_timestamp(struct heif_context* ctx,
177
                                                       heif_item_id itemId,
178
                                                       const heif_tai_timestamp_packet* timestamp,
179
                                                       heif_property_id* out_propertyId)
180
0
{
181
0
  if (!ctx) {
182
0
    return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, "NULL passed"};
183
0
  }
184
185
  // Check if itemId exists
186
0
  auto file = ctx->context->get_heif_file();
187
0
  if (!file->item_exists(itemId)) {
188
0
    return {heif_error_Input_does_not_exist, heif_suberror_Invalid_parameter_value, "item does not exist"};
189
0
  }
190
191
  // make sure that we do not add two TAI timestamps to one image
192
193
0
  if (auto img= ctx->context->get_image(itemId, false)) {
194
0
    auto existing_itai = img->get_property<Box_itai>();
195
0
    if (existing_itai) {
196
0
      return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "item already has an itai property"};
197
0
    }
198
0
  }
199
200
  // Create new itai (it will be deduplicated automatically in add_property())
201
202
0
  auto itai = std::make_shared<Box_itai>();
203
0
  itai->set_from_tai_timestamp_packet(timestamp);
204
205
0
  heif_property_id id = ctx->context->add_property(itemId, itai, false);
206
207
0
  if (out_propertyId) {
208
0
    *out_propertyId = id;
209
0
  }
210
211
0
  return heif_error_success;
212
0
}
213
214
215
struct heif_error heif_item_get_property_tai_timestamp(const struct heif_context* ctx,
216
                                                       heif_item_id itemId,
217
                                                       struct heif_tai_timestamp_packet** out_timestamp)
218
0
{
219
0
  if (!ctx) {
220
0
    return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "NULL passed"};
221
0
  }
222
0
  else if (!out_timestamp) {
223
0
    return {heif_error_Input_does_not_exist, heif_suberror_Invalid_parameter_value, "NULL heif_tai_timestamp_packet passed in"};
224
0
  }
225
226
0
  *out_timestamp = nullptr;
227
228
  // Check if itemId exists
229
0
  auto file = ctx->context->get_heif_file();
230
0
  if (!file->item_exists(itemId)) {
231
0
    return {heif_error_Input_does_not_exist, heif_suberror_Invalid_parameter_value, "item does not exist"};
232
0
  }
233
234
  // Check if itai exists for itemId
235
0
  auto itai = file->get_property_for_item<Box_itai>(itemId);
236
0
  if (!itai) {
237
    // return NULL heif_tai_timestamp_packet;
238
0
    return heif_error_success;
239
0
  }
240
241
0
  *out_timestamp = new heif_tai_timestamp_packet;
242
0
  **out_timestamp = *itai->get_tai_timestamp_packet();
243
244
0
  return heif_error_success;
245
0
}
246
247
248
struct heif_error heif_image_set_tai_timestamp(struct heif_image* img,
249
                                               const struct heif_tai_timestamp_packet* timestamp)
250
0
{
251
0
  Error err = img->image->set_tai_timestamp(timestamp);
252
0
  if (err) {
253
0
    return err.error_struct(img->image.get());
254
0
  }
255
0
  else {
256
0
    return heif_error_success;
257
0
  }
258
0
}
259
260
261
struct heif_error heif_image_get_tai_timestamp(const struct heif_image* img,
262
                                               struct heif_tai_timestamp_packet** out_timestamp)
263
0
{
264
0
  if (!out_timestamp) {
265
0
    return {heif_error_Input_does_not_exist, heif_suberror_Invalid_parameter_value, "NULL heif_tai_timestamp_packet passed in"};
266
0
  }
267
268
0
  *out_timestamp = nullptr;
269
270
0
  auto* tai = img->image->get_tai_timestamp();
271
0
  if (!tai) {
272
0
    *out_timestamp = nullptr;
273
0
    return heif_error_success;
274
0
  }
275
276
0
  *out_timestamp = new heif_tai_timestamp_packet;
277
0
  **out_timestamp = *tai;
278
279
0
  return heif_error_success;
280
0
}
281