FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/exif.c
Date: 2025-10-10 03:51:19
Exec Total Coverage
Lines: 519 771 67.3%
Functions: 28 30 93.3%
Branches: 298 565 52.7%

Line Branch Exec Source
1 /*
2 * EXIF metadata parser
3 * Copyright (c) 2013 Thilo Borgmann <thilo.borgmann _at_ mail.de>
4 * Copyright (c) 2024-2025 Leo Izen <leo.izen@gmail.com>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * EXIF metadata parser
26 * @author Thilo Borgmann <thilo.borgmann _at_ mail.de>
27 * @author Leo Izen <leo.izen@gmail.com>
28 */
29
30 #include <inttypes.h>
31
32 #include "libavutil/avconfig.h"
33 #include "libavutil/bprint.h"
34 #include "libavutil/display.h"
35 #include "libavutil/intreadwrite.h"
36 #include "libavutil/mem.h"
37
38 #include "bytestream.h"
39 #include "exif_internal.h"
40 #include "tiff_common.h"
41
42 #define EXIF_II_LONG 0x49492a00
43 #define EXIF_MM_LONG 0x4d4d002a
44
45 #define BASE_TAG_SIZE 12
46 #define IFD_EXTRA_SIZE 6
47
48 #define EXIF_TAG_NAME_LENGTH 32
49 #define MAKERNOTE_TAG 0x927c
50 #define ORIENTATION_TAG 0x112
51 #define EXIFIFD_TAG 0x8769
52 #define IMAGE_WIDTH_TAG 0x100
53 #define IMAGE_LENGTH_TAG 0x101
54 #define PIXEL_X_TAG 0xa002
55 #define PIXEL_Y_TAG 0xa003
56
57 struct exif_tag {
58 const char name[EXIF_TAG_NAME_LENGTH];
59 uint16_t id;
60 };
61
62 static const struct exif_tag tag_list[] = { // JEITA CP-3451 EXIF specification:
63 {"GPSVersionID", 0x00}, // <- Table 12 GPS Attribute Information
64 {"GPSLatitudeRef", 0x01},
65 {"GPSLatitude", 0x02},
66 {"GPSLongitudeRef", 0x03},
67 {"GPSLongitude", 0x04},
68 {"GPSAltitudeRef", 0x05},
69 {"GPSAltitude", 0x06},
70 {"GPSTimeStamp", 0x07},
71 {"GPSSatellites", 0x08},
72 {"GPSStatus", 0x09},
73 {"GPSMeasureMode", 0x0A},
74 {"GPSDOP", 0x0B},
75 {"GPSSpeedRef", 0x0C},
76 {"GPSSpeed", 0x0D},
77 {"GPSTrackRef", 0x0E},
78 {"GPSTrack", 0x0F},
79 {"GPSImgDirectionRef", 0x10},
80 {"GPSImgDirection", 0x11},
81 {"GPSMapDatum", 0x12},
82 {"GPSDestLatitudeRef", 0x13},
83 {"GPSDestLatitude", 0x14},
84 {"GPSDestLongitudeRef", 0x15},
85 {"GPSDestLongitude", 0x16},
86 {"GPSDestBearingRef", 0x17},
87 {"GPSDestBearing", 0x18},
88 {"GPSDestDistanceRef", 0x19},
89 {"GPSDestDistance", 0x1A},
90 {"GPSProcessingMethod", 0x1B},
91 {"GPSAreaInformation", 0x1C},
92 {"GPSDateStamp", 0x1D},
93 {"GPSDifferential", 0x1E},
94 {"ImageWidth", 0x100}, // <- Table 3 TIFF Rev. 6.0 Attribute Information Used in Exif
95 {"ImageLength", 0x101},
96 {"BitsPerSample", 0x102},
97 {"Compression", 0x103},
98 {"PhotometricInterpretation", 0x106},
99 {"Orientation", 0x112},
100 {"SamplesPerPixel", 0x115},
101 {"PlanarConfiguration", 0x11C},
102 {"YCbCrSubSampling", 0x212},
103 {"YCbCrPositioning", 0x213},
104 {"XResolution", 0x11A},
105 {"YResolution", 0x11B},
106 {"ResolutionUnit", 0x128},
107 {"StripOffsets", 0x111},
108 {"RowsPerStrip", 0x116},
109 {"StripByteCounts", 0x117},
110 {"JPEGInterchangeFormat", 0x201},
111 {"JPEGInterchangeFormatLength",0x202},
112 {"TransferFunction", 0x12D},
113 {"WhitePoint", 0x13E},
114 {"PrimaryChromaticities", 0x13F},
115 {"YCbCrCoefficients", 0x211},
116 {"ReferenceBlackWhite", 0x214},
117 {"DateTime", 0x132},
118 {"ImageDescription", 0x10E},
119 {"Make", 0x10F},
120 {"Model", 0x110},
121 {"Software", 0x131},
122 {"Artist", 0x13B},
123 {"Copyright", 0x8298},
124 {"ExifVersion", 0x9000}, // <- Table 4 Exif IFD Attribute Information (1)
125 {"FlashpixVersion", 0xA000},
126 {"ColorSpace", 0xA001},
127 {"ComponentsConfiguration", 0x9101},
128 {"CompressedBitsPerPixel", 0x9102},
129 {"PixelXDimension", 0xA002},
130 {"PixelYDimension", 0xA003},
131 {"MakerNote", 0x927C},
132 {"UserComment", 0x9286},
133 {"RelatedSoundFile", 0xA004},
134 {"DateTimeOriginal", 0x9003},
135 {"DateTimeDigitized", 0x9004},
136 {"SubSecTime", 0x9290},
137 {"SubSecTimeOriginal", 0x9291},
138 {"SubSecTimeDigitized", 0x9292},
139 {"ImageUniqueID", 0xA420},
140 {"ExposureTime", 0x829A}, // <- Table 5 Exif IFD Attribute Information (2)
141 {"FNumber", 0x829D},
142 {"ExposureProgram", 0x8822},
143 {"SpectralSensitivity", 0x8824},
144 {"ISOSpeedRatings", 0x8827},
145 {"OECF", 0x8828},
146 {"ShutterSpeedValue", 0x9201},
147 {"ApertureValue", 0x9202},
148 {"BrightnessValue", 0x9203},
149 {"ExposureBiasValue", 0x9204},
150 {"MaxApertureValue", 0x9205},
151 {"SubjectDistance", 0x9206},
152 {"MeteringMode", 0x9207},
153 {"LightSource", 0x9208},
154 {"Flash", 0x9209},
155 {"FocalLength", 0x920A},
156 {"SubjectArea", 0x9214},
157 {"FlashEnergy", 0xA20B},
158 {"SpatialFrequencyResponse", 0xA20C},
159 {"FocalPlaneXResolution", 0xA20E},
160 {"FocalPlaneYResolution", 0xA20F},
161 {"FocalPlaneResolutionUnit", 0xA210},
162 {"SubjectLocation", 0xA214},
163 {"ExposureIndex", 0xA215},
164 {"SensingMethod", 0xA217},
165 {"FileSource", 0xA300},
166 {"SceneType", 0xA301},
167 {"CFAPattern", 0xA302},
168 {"CustomRendered", 0xA401},
169 {"ExposureMode", 0xA402},
170 {"WhiteBalance", 0xA403},
171 {"DigitalZoomRatio", 0xA404},
172 {"FocalLengthIn35mmFilm", 0xA405},
173 {"SceneCaptureType", 0xA406},
174 {"GainControl", 0xA407},
175 {"Contrast", 0xA408},
176 {"Saturation", 0xA409},
177 {"Sharpness", 0xA40A},
178 {"DeviceSettingDescription", 0xA40B},
179 {"SubjectDistanceRange", 0xA40C},
180
181 /* InteropIFD tags */
182 {"RelatedImageFileFormat", 0x1000},
183 {"RelatedImageWidth", 0x1001},
184 {"RelatedImageLength", 0x1002},
185
186 /* private EXIF tags */
187 {"PrintImageMatching", 0xC4A5}, // <- undocumented meaning
188
189 /* IFD tags */
190 {"ExifIFD", 0x8769}, // <- An IFD pointing to standard Exif metadata
191 {"GPSInfo", 0x8825}, // <- An IFD pointing to GPS Exif Metadata
192 {"InteropIFD", 0xA005}, // <- Table 13 Interoperability IFD Attribute Information
193 {"GlobalParametersIFD", 0x0190},
194 {"ProfileIFD", 0xc6f5},
195 };
196
197 /* same as type_sizes but with string == 1 */
198 static const size_t exif_sizes[] = {
199 [0] = 0,
200 [AV_TIFF_BYTE] = 1,
201 [AV_TIFF_STRING] = 1,
202 [AV_TIFF_SHORT] = 2,
203 [AV_TIFF_LONG] = 4,
204 [AV_TIFF_RATIONAL] = 8,
205 [AV_TIFF_SBYTE] = 1,
206 [AV_TIFF_UNDEFINED] = 1,
207 [AV_TIFF_SSHORT] = 2,
208 [AV_TIFF_SLONG] = 4,
209 [AV_TIFF_SRATIONAL] = 8,
210 [AV_TIFF_FLOAT] = 4,
211 [AV_TIFF_DOUBLE] = 8,
212 [AV_TIFF_IFD] = 4,
213 };
214
215 889 const char *av_exif_get_tag_name(uint16_t id)
216 {
217
2/2
✓ Branch 0 taken 66480 times.
✓ Branch 1 taken 288 times.
66768 for (size_t i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
218
2/2
✓ Branch 0 taken 601 times.
✓ Branch 1 taken 65879 times.
66480 if (tag_list[i].id == id)
219 601 return tag_list[i].name;
220 }
221
222 288 return NULL;
223 }
224
225 325 int32_t av_exif_get_tag_id(const char *name)
226 {
227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (!name)
228 return -1;
229
230
1/2
✓ Branch 0 taken 12025 times.
✗ Branch 1 not taken.
12025 for (size_t i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
231
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 11700 times.
12025 if (!strcmp(tag_list[i].name, name))
232 325 return tag_list[i].id;
233 }
234
235 return -1;
236 }
237
238 4386 static inline void tput16(PutByteContext *pb, const int le, const uint16_t value)
239 {
240
1/2
✓ Branch 0 taken 4386 times.
✗ Branch 1 not taken.
4386 le ? bytestream2_put_le16(pb, value) : bytestream2_put_be16(pb, value);
241 4386 }
242
243 4041 static inline void tput32(PutByteContext *pb, const int le, const uint32_t value)
244 {
245
1/2
✓ Branch 0 taken 4041 times.
✗ Branch 1 not taken.
4041 le ? bytestream2_put_le32(pb, value) : bytestream2_put_be32(pb, value);
246 4041 }
247
248 static inline void tput64(PutByteContext *pb, const int le, const uint64_t value)
249 {
250 le ? bytestream2_put_le64(pb, value) : bytestream2_put_be64(pb, value);
251 }
252
253 1798 static int exif_read_values(void *logctx, GetByteContext *gb, int le, AVExifEntry *entry)
254 {
255
5/9
✓ Branch 0 taken 1212 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 223 times.
✓ Branch 4 taken 194 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 149 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
1798 switch (entry->type) {
256 1212 case AV_TIFF_SHORT:
257 case AV_TIFF_LONG:
258 1212 entry->value.uint = av_calloc(entry->count, sizeof(*entry->value.uint));
259 1212 break;
260 case AV_TIFF_SSHORT:
261 case AV_TIFF_SLONG:
262 entry->value.sint = av_calloc(entry->count, sizeof(*entry->value.sint));
263 break;
264 20 case AV_TIFF_DOUBLE:
265 case AV_TIFF_FLOAT:
266 20 entry->value.dbl = av_calloc(entry->count, sizeof(*entry->value.dbl));
267 20 break;
268 223 case AV_TIFF_RATIONAL:
269 case AV_TIFF_SRATIONAL:
270 223 entry->value.rat = av_calloc(entry->count, sizeof(*entry->value.rat));
271 223 break;
272 194 case AV_TIFF_UNDEFINED:
273 case AV_TIFF_BYTE:
274 194 entry->value.ubytes = av_mallocz(entry->count);
275 194 break;
276 case AV_TIFF_SBYTE:
277 entry->value.sbytes = av_mallocz(entry->count);
278 break;
279 149 case AV_TIFF_STRING:
280 149 entry->value.str = av_mallocz(entry->count + 1);
281 149 break;
282 case AV_TIFF_IFD:
283 av_log(logctx, AV_LOG_WARNING, "Bad IFD type for non-IFD tag\n");
284 return AVERROR_INVALIDDATA;
285 }
286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1798 times.
1798 if (!entry->value.ptr)
287 return AVERROR(ENOMEM);
288
6/11
✓ Branch 0 taken 917 times.
✓ Branch 1 taken 295 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 223 times.
✓ Branch 7 taken 194 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 149 times.
✗ Branch 10 not taken.
1798 switch (entry->type) {
289 917 case AV_TIFF_SHORT:
290
2/2
✓ Branch 0 taken 2817 times.
✓ Branch 1 taken 917 times.
3734 for (size_t i = 0; i < entry->count; i++)
291 2817 entry->value.uint[i] = ff_tget_short(gb, le);
292 917 break;
293 295 case AV_TIFF_LONG:
294
2/2
✓ Branch 0 taken 2460 times.
✓ Branch 1 taken 295 times.
2755 for (size_t i = 0; i < entry->count; i++)
295 2460 entry->value.uint[i] = ff_tget_long(gb, le);
296 295 break;
297 case AV_TIFF_SSHORT:
298 for (size_t i = 0; i < entry->count; i++)
299 entry->value.sint[i] = (int16_t) ff_tget_short(gb, le);
300 break;
301 case AV_TIFF_SLONG:
302 for (size_t i = 0; i < entry->count; i++)
303 entry->value.sint[i] = (int32_t) ff_tget_long(gb, le);
304 break;
305 case AV_TIFF_DOUBLE:
306 for (size_t i = 0; i < entry->count; i++)
307 entry->value.dbl[i] = ff_tget_double(gb, le);
308 break;
309 20 case AV_TIFF_FLOAT:
310
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 20 times.
88 for (size_t i = 0; i < entry->count; i++) {
311 68 av_alias32 alias = { .u32 = ff_tget_long(gb, le) };
312 68 entry->value.dbl[i] = alias.f32;
313 }
314 20 break;
315 223 case AV_TIFF_RATIONAL:
316 case AV_TIFF_SRATIONAL:
317
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 223 times.
555 for (size_t i = 0; i < entry->count; i++) {
318 332 int32_t num = ff_tget_long(gb, le);
319 332 int32_t den = ff_tget_long(gb, le);
320 332 entry->value.rat[i] = av_make_q(num, den);
321 }
322 223 break;
323 194 case AV_TIFF_UNDEFINED:
324 case AV_TIFF_BYTE:
325 /* these three fields are aliased to entry->value.ptr via a union */
326 /* and entry->value.ptr will always be nonzero here */
327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194 times.
194 av_assert0(entry->value.ubytes);
328 194 bytestream2_get_buffer(gb, entry->value.ubytes, entry->count);
329 194 break;
330 case AV_TIFF_SBYTE:
331 av_assert0(entry->value.sbytes);
332 bytestream2_get_buffer(gb, entry->value.sbytes, entry->count);
333 break;
334 149 case AV_TIFF_STRING:
335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 149 times.
149 av_assert0(entry->value.str);
336 149 bytestream2_get_buffer(gb, entry->value.str, entry->count);
337 149 break;
338 }
339
340 1798 return 0;
341 }
342
343 1151 static void exif_write_values(PutByteContext *pb, int le, const AVExifEntry *entry)
344 {
345
6/11
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 199 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 147 times.
✓ Branch 7 taken 128 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 92 times.
✗ Branch 10 not taken.
1151 switch (entry->type) {
346 575 case AV_TIFF_SHORT:
347
2/2
✓ Branch 0 taken 1976 times.
✓ Branch 1 taken 575 times.
2551 for (size_t i = 0; i < entry->count; i++)
348 1976 tput16(pb, le, entry->value.uint[i]);
349 575 break;
350 199 case AV_TIFF_LONG:
351
2/2
✓ Branch 0 taken 1900 times.
✓ Branch 1 taken 199 times.
2099 for (size_t i = 0; i < entry->count; i++)
352 1900 tput32(pb, le, entry->value.uint[i]);
353 199 break;
354 case AV_TIFF_SSHORT:
355 for (size_t i = 0; i < entry->count; i++)
356 tput16(pb, le, entry->value.sint[i]);
357 break;
358 case AV_TIFF_SLONG:
359 for (size_t i = 0; i < entry->count; i++)
360 tput32(pb, le, entry->value.sint[i]);
361 break;
362 case AV_TIFF_DOUBLE:
363 for (size_t i = 0; i < entry->count; i++) {
364 const av_alias64 a = { .f64 = entry->value.dbl[i] };
365 tput64(pb, le, a.u64);
366 }
367 break;
368 10 case AV_TIFF_FLOAT:
369
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 10 times.
44 for (size_t i = 0; i < entry->count; i++) {
370 34 const av_alias32 a = { .f32 = entry->value.dbl[i] };
371 34 tput32(pb, le, a.u32);
372 }
373 10 break;
374 147 case AV_TIFF_RATIONAL:
375 case AV_TIFF_SRATIONAL:
376
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 147 times.
350 for (size_t i = 0; i < entry->count; i++) {
377 203 tput32(pb, le, entry->value.rat[i].num);
378 203 tput32(pb, le, entry->value.rat[i].den);
379 }
380 147 break;
381 128 case AV_TIFF_UNDEFINED:
382 case AV_TIFF_BYTE:
383 128 bytestream2_put_buffer(pb, entry->value.ubytes, entry->count);
384 128 break;
385 case AV_TIFF_SBYTE:
386 bytestream2_put_buffer(pb, entry->value.sbytes, entry->count);
387 break;
388 92 case AV_TIFF_STRING:
389 92 bytestream2_put_buffer(pb, entry->value.str, entry->count);
390 92 break;
391 }
392 1151 }
393
394 static const uint8_t aoc_header[] = { 'A', 'O', 'C', 0, };
395 static const uint8_t casio_header[] = { 'Q', 'V', 'C', 0, 0, 0, };
396 static const uint8_t foveon_header[] = { 'F', 'O', 'V', 'E', 'O', 'N', 0, 0, };
397 static const uint8_t fuji_header[] = { 'F', 'U', 'J', 'I', };
398 static const uint8_t nikon_header[] = { 'N', 'i', 'k', 'o', 'n', 0, };
399 static const uint8_t olympus1_header[] = { 'O', 'L', 'Y', 'M', 'P', 0, };
400 static const uint8_t olympus2_header[] = { 'O', 'L', 'Y', 'M', 'P', 'U', 'S', 0, 'I', 'I', };
401 static const uint8_t panasonic_header[] = { 'P', 'a', 'n', 'a', 's', 'o', 'n', 'i', 'c', 0, 0, 0, };
402 static const uint8_t sigma_header[] = { 'S', 'I', 'G', 'M', 'A', 0, 0, 0, };
403 static const uint8_t sony_header[] = { 'S', 'O', 'N', 'Y', ' ', 'D', 'S', 'C', ' ', 0, 0, 0, };
404
405 struct exif_makernote_data {
406 const uint8_t *header;
407 size_t header_size;
408 int result;
409 };
410
411 #define MAKERNOTE_STRUCT(h, r) { \
412 .header = (h), \
413 .header_size = sizeof((h)), \
414 .result = (r), \
415 }
416
417 static const struct exif_makernote_data makernote_data[] = {
418 MAKERNOTE_STRUCT(aoc_header, 6),
419 MAKERNOTE_STRUCT(casio_header, -1),
420 MAKERNOTE_STRUCT(foveon_header, 10),
421 MAKERNOTE_STRUCT(fuji_header, -1),
422 MAKERNOTE_STRUCT(olympus1_header, 8),
423 MAKERNOTE_STRUCT(olympus2_header, -1),
424 MAKERNOTE_STRUCT(panasonic_header, 12),
425 MAKERNOTE_STRUCT(sigma_header, 10),
426 MAKERNOTE_STRUCT(sony_header, 12),
427 };
428
429 /*
430 * derived from Exiv2 MakerNote's article
431 * https://exiv2.org/makernote.html or archived at
432 * https://web.archive.org/web/20250311155857/https://exiv2.org/makernote.html
433 */
434 7 static int exif_get_makernote_offset(GetByteContext *gb)
435 {
436
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (bytestream2_get_bytes_left(gb) < BASE_TAG_SIZE)
437 return -1;
438
439
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 4 times.
61 for (int i = 0; i < FF_ARRAY_ELEMS(makernote_data); i++) {
440
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 54 times.
57 if (!memcmp(gb->buffer, makernote_data[i].header, makernote_data[i].header_size))
441 3 return makernote_data[i].result;
442 }
443
444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!memcmp(gb->buffer, nikon_header, sizeof(nikon_header))) {
445 if (bytestream2_get_bytes_left(gb) < 14)
446 return -1;
447 else if (AV_RB32(gb->buffer + 10) == EXIF_MM_LONG || AV_RB32(gb->buffer + 10) == EXIF_II_LONG)
448 return -1;
449 return 8;
450 }
451
452 4 return 0;
453 }
454
455 static int exif_parse_ifd_list(void *logctx, GetByteContext *gb, int le,
456 int depth, AVExifMetadata *ifd, int guess);
457
458 1830 static int exif_decode_tag(void *logctx, GetByteContext *gb, int le,
459 int depth, AVExifEntry *entry)
460 {
461 1830 int ret = 0, makernote_offset = -1, tell, is_ifd, count;
462 enum AVTiffDataType type;
463 uint32_t payload;
464
465 /* safety check to prevent infinite recursion on malicious IFDs */
466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1830 times.
1830 if (depth > 3)
467 return AVERROR_INVALIDDATA;
468
469 1830 tell = bytestream2_tell(gb);
470
471 1830 entry->id = ff_tget_short(gb, le);
472 1830 type = ff_tget_short(gb, le);
473 1830 count = ff_tget_long(gb, le);
474 1830 payload = ff_tget_long(gb, le);
475
476 1830 av_log(logctx, AV_LOG_DEBUG, "TIFF Tag: id: 0x%04x, type: %d, count: %u, offset: %d, "
477 1830 "payload: %" PRIu32 "\n", entry->id, type, count, tell, payload);
478
479 /* AV_TIFF_IFD is the largest, numerically */
480
2/4
✓ Branch 0 taken 1830 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1830 times.
1830 if (type > AV_TIFF_IFD || count >= INT_MAX/8U)
481 return AVERROR_INVALIDDATA;
482
483
6/6
✓ Branch 0 taken 1825 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 1805 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 1798 times.
1830 is_ifd = type == AV_TIFF_IFD || ff_tis_ifd(entry->id) || entry->id == MAKERNOTE_TAG;
484
485
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1798 times.
1830 if (is_ifd) {
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!payload)
487 goto end;
488 32 bytestream2_seek(gb, payload, SEEK_SET);
489 }
490
491
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1823 times.
1830 if (entry->id == MAKERNOTE_TAG) {
492 7 makernote_offset = exif_get_makernote_offset(gb);
493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (makernote_offset < 0)
494 is_ifd = 0;
495 }
496
497
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1798 times.
1830 if (is_ifd) {
498 32 entry->type = AV_TIFF_IFD;
499 32 entry->count = 1;
500 32 entry->ifd_offset = makernote_offset > 0 ? makernote_offset : 0;
501
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 29 times.
32 if (entry->ifd_offset) {
502 3 entry->ifd_lead = av_malloc(entry->ifd_offset);
503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!entry->ifd_lead)
504 return AVERROR(ENOMEM);
505 3 bytestream2_get_buffer(gb, entry->ifd_lead, entry->ifd_offset);
506 }
507 32 ret = exif_parse_ifd_list(logctx, gb, le, depth + 1, &entry->value.ifd, entry->id == MAKERNOTE_TAG);
508
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
32 if (ret < 0 && entry->id == MAKERNOTE_TAG) {
509 /*
510 * we guessed that MakerNote was an IFD
511 * but we were probably incorrect at this
512 * point so we try again as a binary blob
513 */
514 av_exif_free(&entry->value.ifd);
515 av_log(logctx, AV_LOG_DEBUG, "unrecognized MakerNote IFD, retrying as blob\n");
516 is_ifd = 0;
517 }
518 }
519
520 /* inverted condition instead of else so we can fall through from above */
521
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1798 times.
1830 if (!is_ifd) {
522
1/2
✓ Branch 0 taken 1798 times.
✗ Branch 1 not taken.
1798 entry->type = type == AV_TIFF_IFD ? AV_TIFF_UNDEFINED : type;
523 1798 entry->count = count;
524
2/2
✓ Branch 0 taken 1186 times.
✓ Branch 1 taken 612 times.
1798 bytestream2_seek(gb, count * exif_sizes[type] > 4 ? payload : tell + 8, SEEK_SET);
525 1798 ret = exif_read_values(logctx, gb, le, entry);
526 }
527
528 32 end:
529 1830 bytestream2_seek(gb, tell + BASE_TAG_SIZE, SEEK_SET);
530
531 1830 return ret;
532 }
533
534 107 static int exif_parse_ifd_list(void *logctx, GetByteContext *gb, int le,
535 int depth, AVExifMetadata *ifd, int guess)
536 {
537 uint32_t entries;
538 size_t required_size;
539 void *temp;
540
541 107 av_log(logctx, AV_LOG_DEBUG, "parsing IFD list at offset: %d\n", bytestream2_tell(gb));
542
543
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 if (bytestream2_get_bytes_left(gb) < 2) {
544 av_log(logctx, guess ? AV_LOG_DEBUG : AV_LOG_ERROR,
545 "not enough bytes remaining in EXIF buffer: 2 required\n");
546 return AVERROR_INVALIDDATA;
547 }
548
549 107 entries = ff_tget_short(gb, le);
550
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 if (bytestream2_get_bytes_left(gb) < entries * BASE_TAG_SIZE) {
551 av_log(logctx, guess ? AV_LOG_DEBUG : AV_LOG_ERROR,
552 "not enough bytes remaining in EXIF buffer. entries: %" PRIu32 "\n", entries);
553 return AVERROR_INVALIDDATA;
554 }
555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (entries > 4096) {
556 /* that is a lot of entries, probably an error */
557 av_log(logctx, guess ? AV_LOG_DEBUG : AV_LOG_ERROR,
558 "too many entries: %" PRIu32 "\n", entries);
559 return AVERROR_INVALIDDATA;
560 }
561
562 107 ifd->count = entries;
563 107 av_log(logctx, AV_LOG_DEBUG, "entry count for IFD: %u\n", ifd->count);
564
565 /* empty IFD is technically legal but equivalent to no metadata present */
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (!ifd->count)
567 goto end;
568
569
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 if (av_size_mult(ifd->count, sizeof(*ifd->entries), &required_size) < 0)
570 return AVERROR(ENOMEM);
571 107 temp = av_fast_realloc(ifd->entries, &ifd->size, required_size);
572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (!temp) {
573 av_freep(&ifd->entries);
574 return AVERROR(ENOMEM);
575 }
576 107 ifd->entries = temp;
577
578 /* entries have pointers in them which can cause issues if */
579 /* they are freed or realloc'd when garbage */
580 107 memset(ifd->entries, 0, required_size);
581
582
2/2
✓ Branch 0 taken 1830 times.
✓ Branch 1 taken 107 times.
1937 for (uint32_t i = 0; i < entries; i++) {
583 1830 int ret = exif_decode_tag(logctx, gb, le, depth, &ifd->entries[i]);
584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1830 times.
1830 if (ret < 0)
585 return ret;
586 }
587
588 107 end:
589 /*
590 * at the end of an IFD is an pointer to the next IFD
591 * or zero if there are no more IFDs, which is usually the case
592 */
593 107 return ff_tget_long(gb, le);
594 }
595
596 /*
597 * note that this function does not free the entry pointer itself
598 * because it's probably part of a larger array that should be freed
599 * all at once
600 */
601 2287 static void exif_free_entry(AVExifEntry *entry)
602 {
603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2287 times.
2287 if (!entry)
604 return;
605
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 2242 times.
2287 if (entry->type == AV_TIFF_IFD)
606 45 av_exif_free(&entry->value.ifd);
607 else
608 2242 av_freep(&entry->value.ptr);
609 2287 av_freep(&entry->ifd_lead);
610 }
611
612 2995 void av_exif_free(AVExifMetadata *ifd)
613 {
614
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2977 times.
2995 if (!ifd)
615 18 return;
616
2/2
✓ Branch 0 taken 2838 times.
✓ Branch 1 taken 139 times.
2977 if (!ifd->entries) {
617 2838 ifd->count = 0;
618 2838 ifd->size = 0;
619 2838 return;
620 }
621
2/2
✓ Branch 0 taken 2266 times.
✓ Branch 1 taken 139 times.
2405 for (size_t i = 0; i < ifd->count; i++) {
622 2266 AVExifEntry *entry = &ifd->entries[i];
623 2266 exif_free_entry(entry);
624 }
625 139 av_freep(&ifd->entries);
626 139 ifd->count = 0;
627 139 ifd->size = 0;
628 }
629
630 69 static size_t exif_get_ifd_size(const AVExifMetadata *ifd)
631 {
632 /* 6 == 4 + 2; 2-byte entry-count at the beginning */
633 /* plus 4-byte next-IFD pointer at the end */
634 69 size_t total_size = IFD_EXTRA_SIZE;
635
2/2
✓ Branch 0 taken 1650 times.
✓ Branch 1 taken 69 times.
1719 for (size_t i = 0; i < ifd->count; i++) {
636 1650 const AVExifEntry *entry = &ifd->entries[i];
637
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 1628 times.
1650 if (entry->type == AV_TIFF_IFD) {
638 22 total_size += BASE_TAG_SIZE + exif_get_ifd_size(&entry->value.ifd) + entry->ifd_offset;
639 } else {
640 1628 size_t payload_size = entry->count * exif_sizes[entry->type];
641
2/2
✓ Branch 0 taken 550 times.
✓ Branch 1 taken 1078 times.
1628 total_size += BASE_TAG_SIZE + (payload_size > 4 ? payload_size : 0);
642 }
643 }
644 69 return total_size;
645 }
646
647 64 static int exif_write_ifd(void *logctx, PutByteContext *pb, int le, int depth, const AVExifMetadata *ifd)
648 {
649 int offset, ret, tell, tell2;
650 64 tell = bytestream2_tell_p(pb);
651 64 tput16(pb, le, ifd->count);
652 64 offset = tell + IFD_EXTRA_SIZE + BASE_TAG_SIZE * (uint32_t) ifd->count;
653 64 av_log(logctx, AV_LOG_DEBUG, "writing IFD with %u entries and initial offset %d\n", ifd->count, offset);
654
2/2
✓ Branch 0 taken 1173 times.
✓ Branch 1 taken 64 times.
1237 for (size_t i = 0; i < ifd->count; i++) {
655 1173 const AVExifEntry *entry = &ifd->entries[i];
656 1173 av_log(logctx, AV_LOG_DEBUG, "writing TIFF entry: id: 0x%04" PRIx16 ", type: %d, count: %"
657 PRIu32 ", offset: %d, offset value: %d\n",
658 1173 entry->id, entry->type, entry->count,
659 bytestream2_tell_p(pb), offset);
660 1173 tput16(pb, le, entry->id);
661
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1168 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
1178 if (entry->id == MAKERNOTE_TAG && entry->type == AV_TIFF_IFD) {
662 5 size_t ifd_size = exif_get_ifd_size(&entry->value.ifd);
663 5 tput16(pb, le, AV_TIFF_UNDEFINED);
664 5 tput32(pb, le, ifd_size);
665 } else {
666 1168 tput16(pb, le, entry->type);
667 1168 tput32(pb, le, entry->count);
668 }
669
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 1151 times.
1173 if (entry->type == AV_TIFF_IFD) {
670 22 tput32(pb, le, offset);
671 22 tell2 = bytestream2_tell_p(pb);
672 22 bytestream2_seek_p(pb, offset, SEEK_SET);
673
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 20 times.
22 if (entry->ifd_offset)
674 2 bytestream2_put_buffer(pb, entry->ifd_lead, entry->ifd_offset);
675 22 ret = exif_write_ifd(logctx, pb, le, depth + 1, &entry->value.ifd);
676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (ret < 0)
677 return ret;
678 22 offset += ret + entry->ifd_offset;
679 22 bytestream2_seek_p(pb, tell2, SEEK_SET);
680 } else {
681 1151 size_t payload_size = entry->count * exif_sizes[entry->type];
682
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 751 times.
1151 if (payload_size > 4) {
683 400 tput32(pb, le, offset);
684 400 tell2 = bytestream2_tell_p(pb);
685 400 bytestream2_seek_p(pb, offset, SEEK_SET);
686 400 exif_write_values(pb, le, entry);
687 400 offset += payload_size;
688 400 bytestream2_seek_p(pb, tell2, SEEK_SET);
689 } else {
690 /* zero uninitialized excess payload values */
691 751 AV_WN32(pb->buffer, 0);
692 751 exif_write_values(pb, le, entry);
693 751 bytestream2_seek_p(pb, 4 - payload_size, SEEK_CUR);
694 }
695 }
696 }
697
698 /*
699 * we write 0 if this is the top-level exif IFD
700 * indicating that there are no more IFD pointers
701 */
702
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 42 times.
64 tput32(pb, le, depth ? offset : 0);
703 64 return offset - tell;
704 }
705
706 42 int av_exif_write(void *logctx, const AVExifMetadata *ifd, AVBufferRef **buffer, enum AVExifHeaderMode header_mode)
707 {
708 42 AVBufferRef *buf = NULL;
709 42 size_t size, headsize = 8;
710 PutByteContext pb;
711 42 int ret, off = 0;
712
713 42 int le = 1;
714
715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (*buffer)
716 return AVERROR(EINVAL);
717
718 42 size = exif_get_ifd_size(ifd);
719
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 40 times.
42 switch (header_mode) {
720 case AV_EXIF_EXIF00:
721 off = 6;
722 break;
723 2 case AV_EXIF_T_OFF:
724 2 off = 4;
725 2 break;
726 case AV_EXIF_ASSUME_BE:
727 le = 0;
728 headsize = 0;
729 break;
730 case AV_EXIF_ASSUME_LE:
731 le = 1;
732 headsize = 0;
733 break;
734 }
735 42 buf = av_buffer_alloc(size + off + headsize);
736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!buf)
737 return AVERROR(ENOMEM);
738
739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (header_mode == AV_EXIF_EXIF00) {
740 AV_WL32(buf->data, MKTAG('E','x','i','f'));
741 AV_WN16(buf->data + 4, 0);
742
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40 times.
42 } else if (header_mode == AV_EXIF_T_OFF) {
743 2 AV_WN32(buf->data, 0);
744 }
745
746 42 bytestream2_init_writer(&pb, buf->data + off, buf->size - off);
747
748
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
42 if (header_mode != AV_EXIF_ASSUME_BE && header_mode != AV_EXIF_ASSUME_LE) {
749 /* these constants are be32 in both cases */
750 /* le == 1 always in this case */
751 42 bytestream2_put_be32(&pb, EXIF_II_LONG);
752 42 tput32(&pb, le, 8);
753 }
754
755 42 ret = exif_write_ifd(logctx, &pb, le, 0, ifd);
756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0) {
757 av_buffer_unref(&buf);
758 av_log(logctx, AV_LOG_ERROR, "error writing EXIF data: %s\n", av_err2str(ret));
759 return ret;
760 }
761
762 42 *buffer = buf;
763
764 42 return 0;
765 }
766
767 75 int av_exif_parse_buffer(void *logctx, const uint8_t *buf, size_t size,
768 AVExifMetadata *ifd, enum AVExifHeaderMode header_mode)
769 {
770 int ret, le;
771 GetByteContext gbytes;
772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (size > INT_MAX)
773 return AVERROR(EINVAL);
774 75 size_t off = 0;
775
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
75 switch (header_mode) {
776 case AV_EXIF_EXIF00:
777 if (size < 6)
778 return AVERROR_INVALIDDATA;
779 off = 6;
780 /* fallthrough */
781 2 case AV_EXIF_T_OFF:
782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (size < 4)
783 return AVERROR_INVALIDDATA;
784
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!off)
785 2 off = AV_RB32(buf) + 4;
786 /* fallthrough */
787 case AV_EXIF_TIFF_HEADER: {
788 int ifd_offset;
789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (size <= off)
790 return AVERROR_INVALIDDATA;
791 75 bytestream2_init(&gbytes, buf + off, size - off);
792 // read TIFF header
793 75 ret = ff_tdecode_header(&gbytes, &le, &ifd_offset);
794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0) {
795 av_log(logctx, AV_LOG_ERROR, "invalid TIFF header in EXIF data: %s\n", av_err2str(ret));
796 return ret;
797 }
798 75 bytestream2_seek(&gbytes, ifd_offset, SEEK_SET);
799 75 break;
800 }
801 case AV_EXIF_ASSUME_LE:
802 le = 1;
803 bytestream2_init(&gbytes, buf, size);
804 break;
805 case AV_EXIF_ASSUME_BE:
806 le = 0;
807 bytestream2_init(&gbytes, buf, size);
808 break;
809 default:
810 return AVERROR(EINVAL);
811 }
812
813 /*
814 * parse IFD0 here. If the return value is positive that tells us
815 * there is subimage metadata, but we don't parse that IFD here
816 */
817 75 ret = exif_parse_ifd_list(logctx, &gbytes, le, 0, ifd, 0);
818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0) {
819 av_exif_free(ifd);
820 av_log(logctx, AV_LOG_ERROR, "error decoding EXIF data: %s\n", av_err2str(ret));
821 return ret;
822 }
823
824 75 return bytestream2_tell(&gbytes);
825 }
826
827 #define COLUMN_SEP(i, c) ((i) ? ((i) % (c) ? ", " : "\n") : "")
828
829 54 static int exif_ifd_to_dict(void *logctx, const char *prefix, const AVExifMetadata *ifd, AVDictionary **metadata)
830 {
831 AVBPrint bp;
832 54 int ret = 0;
833 54 char *key = NULL;
834 54 char *value = NULL;
835
836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!prefix)
837 prefix = "";
838
839
2/2
✓ Branch 0 taken 889 times.
✓ Branch 1 taken 54 times.
943 for (uint16_t i = 0; i < ifd->count; i++) {
840 889 const AVExifEntry *entry = &ifd->entries[i];
841 889 const char *name = av_exif_get_tag_name(entry->id);
842 889 av_bprint_init(&bp, entry->count * 10, AV_BPRINT_SIZE_UNLIMITED);
843
2/2
✓ Branch 0 taken 436 times.
✓ Branch 1 taken 453 times.
889 if (*prefix)
844 436 av_bprintf(&bp, "%s/", prefix);
845
2/2
✓ Branch 0 taken 601 times.
✓ Branch 1 taken 288 times.
889 if (name)
846 601 av_bprintf(&bp, "%s", name);
847 else
848 288 av_bprintf(&bp, "0x%04X", entry->id);
849 889 ret = av_bprint_finalize(&bp, &key);
850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 889 times.
889 if (ret < 0)
851 goto end;
852 889 av_bprint_init(&bp, entry->count * 10, AV_BPRINT_SIZE_UNLIMITED);
853
6/9
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 598 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 124 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 65 times.
✓ Branch 6 taken 76 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
889 switch (entry->type) {
854 16 case AV_TIFF_IFD:
855 16 ret = exif_ifd_to_dict(logctx, key, &entry->value.ifd, metadata);
856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ret < 0)
857 goto end;
858 16 break;
859 598 case AV_TIFF_SHORT:
860 case AV_TIFF_LONG:
861
2/2
✓ Branch 0 taken 3689 times.
✓ Branch 1 taken 598 times.
4287 for (uint32_t j = 0; j < entry->count; j++)
862
4/4
✓ Branch 0 taken 3091 times.
✓ Branch 1 taken 598 times.
✓ Branch 2 taken 2743 times.
✓ Branch 3 taken 348 times.
3689 av_bprintf(&bp, "%s%7" PRIu32, COLUMN_SEP(j, 8), (uint32_t)entry->value.uint[j]);
863 598 break;
864 case AV_TIFF_SSHORT:
865 case AV_TIFF_SLONG:
866 for (uint32_t j = 0; j < entry->count; j++)
867 av_bprintf(&bp, "%s%7" PRId32, COLUMN_SEP(j, 8), (int32_t)entry->value.sint[j]);
868 break;
869 124 case AV_TIFF_RATIONAL:
870 case AV_TIFF_SRATIONAL:
871
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 124 times.
301 for (uint32_t j = 0; j < entry->count; j++)
872
4/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 9 times.
177 av_bprintf(&bp, "%s%7i:%-7i", COLUMN_SEP(j, 4), entry->value.rat[j].num, entry->value.rat[j].den);
873 124 break;
874 10 case AV_TIFF_DOUBLE:
875 case AV_TIFF_FLOAT:
876
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 10 times.
44 for (uint32_t j = 0; j < entry->count; j++)
877
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
34 av_bprintf(&bp, "%s%.15g", COLUMN_SEP(j, 4), entry->value.dbl[j]);
878 10 break;
879 65 case AV_TIFF_STRING:
880 65 av_bprintf(&bp, "%s", entry->value.str);
881 65 break;
882 76 case AV_TIFF_UNDEFINED:
883 case AV_TIFF_BYTE:
884
2/2
✓ Branch 0 taken 27795 times.
✓ Branch 1 taken 76 times.
27871 for (uint32_t j = 0; j < entry->count; j++)
885
4/4
✓ Branch 0 taken 27719 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 26012 times.
✓ Branch 3 taken 1707 times.
27795 av_bprintf(&bp, "%s%3i", COLUMN_SEP(j, 16), entry->value.ubytes[j]);
886 76 break;
887 case AV_TIFF_SBYTE:
888 for (uint32_t j = 0; j < entry->count; j++)
889 av_bprintf(&bp, "%s%3i", COLUMN_SEP(j, 16), entry->value.sbytes[j]);
890 break;
891 }
892
2/2
✓ Branch 0 taken 873 times.
✓ Branch 1 taken 16 times.
889 if (entry->type != AV_TIFF_IFD) {
893
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 873 times.
873 if (!av_bprint_is_complete(&bp)) {
894 av_bprint_finalize(&bp, NULL);
895 ret = AVERROR(ENOMEM);
896 goto end;
897 }
898 873 ret = av_bprint_finalize(&bp, &value);
899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 873 times.
873 if (ret < 0)
900 goto end;
901 873 ret = av_dict_set(metadata, key, value, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
902 873 key = NULL;
903 873 value = NULL;
904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 873 times.
873 if (ret < 0)
905 goto end;
906 } else {
907 16 av_freep(&key);
908 }
909 }
910
911 54 end:
912 54 av_freep(&key);
913 54 av_freep(&value);
914 54 return ret;
915 }
916
917 38 int av_exif_ifd_to_dict(void *logctx, const AVExifMetadata *ifd, AVDictionary **metadata)
918 {
919 38 return exif_ifd_to_dict(logctx, "", ifd, metadata);
920 }
921
922 #if LIBAVCODEC_VERSION_MAJOR < 63
923 int avpriv_exif_decode_ifd(void *logctx, const uint8_t *buf, int size,
924 int le, int depth, AVDictionary **metadata)
925 {
926 AVExifMetadata ifd = { 0 };
927 GetByteContext gb;
928 int ret;
929 bytestream2_init(&gb, buf, size);
930 ret = exif_parse_ifd_list(logctx, &gb, le, depth, &ifd, 0);
931 if (ret < 0)
932 return ret;
933 ret = av_exif_ifd_to_dict(logctx, &ifd, metadata);
934 av_exif_free(&ifd);
935 return ret;
936 }
937 #endif
938
939 #define EXIF_COPY(fname, srcname) do { \
940 size_t sz; \
941 if (av_size_mult(src->count, sizeof(*(fname)), &sz) < 0) { \
942 ret = AVERROR(ENOMEM); \
943 goto end; \
944 } \
945 (fname) = av_memdup((srcname), sz); \
946 if (!(fname)) { \
947 ret = AVERROR(ENOMEM); \
948 goto end; \
949 } \
950 } while (0)
951
952 457 static int exif_clone_entry(AVExifEntry *dst, const AVExifEntry *src)
953 {
954 457 int ret = 0;
955
956 457 memset(dst, 0, sizeof(*dst));
957
958 457 dst->count = src->count;
959 457 dst->id = src->id;
960 457 dst->type = src->type;
961
962 457 dst->ifd_offset = src->ifd_offset;
963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 457 times.
457 if (src->ifd_lead) {
964 dst->ifd_lead = av_memdup(src->ifd_lead, src->ifd_offset);
965 if (!dst->ifd_lead) {
966 ret = AVERROR(ENOMEM);
967 goto end;
968 }
969 } else {
970 457 dst->ifd_lead = NULL;
971 }
972
973
6/9
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 302 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 71 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 37 times.
✗ Branch 8 not taken.
457 switch(src->type) {
974 13 case AV_TIFF_IFD: {
975 13 AVExifMetadata *cloned = av_exif_clone_ifd(&src->value.ifd);
976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (!cloned) {
977 ret = AVERROR(ENOMEM);
978 goto end;
979 }
980 13 dst->value.ifd = *cloned;
981 13 av_freep(&cloned);
982 13 break;
983 }
984 302 case AV_TIFF_SHORT:
985 case AV_TIFF_LONG:
986
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 302 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 302 times.
302 EXIF_COPY(dst->value.uint, src->value.uint);
987 302 break;
988 case AV_TIFF_SLONG:
989 case AV_TIFF_SSHORT:
990 EXIF_COPY(dst->value.sint, src->value.sint);
991 break;
992 71 case AV_TIFF_RATIONAL:
993 case AV_TIFF_SRATIONAL:
994
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 71 times.
71 EXIF_COPY(dst->value.rat, src->value.rat);
995 71 break;
996 10 case AV_TIFF_DOUBLE:
997 case AV_TIFF_FLOAT:
998
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
10 EXIF_COPY(dst->value.dbl, src->value.dbl);
999 10 break;
1000 24 case AV_TIFF_BYTE:
1001 case AV_TIFF_UNDEFINED:
1002
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
24 EXIF_COPY(dst->value.ubytes, src->value.ubytes);
1003 24 break;
1004 case AV_TIFF_SBYTE:
1005 EXIF_COPY(dst->value.sbytes, src->value.sbytes);
1006 break;
1007 37 case AV_TIFF_STRING:
1008 37 dst->value.str = av_memdup(src->value.str, src->count+1);
1009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (!dst->value.str) {
1010 ret = AVERROR(ENOMEM);
1011 goto end;
1012 }
1013 37 break;
1014 }
1015
1016 457 return 0;
1017
1018 end:
1019 av_freep(&dst->ifd_lead);
1020 if (src->type == AV_TIFF_IFD)
1021 av_exif_free(&dst->value.ifd);
1022 else
1023 av_freep(&dst->value.ptr);
1024 memset(dst, 0, sizeof(*dst));
1025
1026 return ret;
1027 }
1028
1029 19 static int exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int depth, AVExifEntry **value)
1030 {
1031 19 int offset = 1;
1032
1033
5/8
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 19 times.
19 if (!ifd || ifd->count && !ifd->entries || !value)
1034 return AVERROR(EINVAL);
1035
1036
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 18 times.
89 for (size_t i = 0; i < ifd->count; i++) {
1037
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 70 times.
71 if (ifd->entries[i].id == id) {
1038 1 *value = &ifd->entries[i];
1039 1 return i + offset;
1040 }
1041
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 67 times.
70 if (ifd->entries[i].type == AV_TIFF_IFD) {
1042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (depth < 3) {
1043 int ret = exif_get_entry(logctx, &ifd->entries[i].value.ifd, id, depth + 1, value);
1044 if (ret)
1045 return ret < 0 ? ret : ret + offset;
1046 }
1047 3 offset += ifd->entries[i].value.ifd.count;
1048 }
1049 }
1050
1051 18 return 0;
1052 }
1053
1054 19 int av_exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int flags, AVExifEntry **value)
1055 {
1056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 return exif_get_entry(logctx, ifd, id, (flags & AV_EXIF_FLAG_RECURSIVE) ? 0 : INT_MAX, value);
1057 }
1058
1059 15 int av_exif_set_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, enum AVTiffDataType type,
1060 uint32_t count, const uint8_t *ifd_lead, uint32_t ifd_offset, const void *value)
1061 {
1062 void *temp;
1063 15 int ret = 0;
1064 15 AVExifEntry *entry = NULL;
1065 15 AVExifEntry src = { 0 };
1066
1067
4/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
15 if (!ifd || ifd->count && !ifd->entries
1068
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
15 || ifd_lead && !ifd_offset || !ifd_lead && ifd_offset
1069
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 || !value || ifd->count == 0xFFFFu)
1070 return AVERROR(EINVAL);
1071
1072 15 ret = av_exif_get_entry(logctx, ifd, id, 0, &entry);
1073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
1074 return ret;
1075
1076
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (entry) {
1077 exif_free_entry(entry);
1078 } else {
1079 size_t required_size;
1080 15 ret = av_size_mult(ifd->count + 1, sizeof(*ifd->entries), &required_size);
1081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
1082 return AVERROR(ENOMEM);
1083 15 temp = av_fast_realloc(ifd->entries, &ifd->size, required_size);
1084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!temp)
1085 return AVERROR(ENOMEM);
1086 15 ifd->entries = temp;
1087 15 entry = &ifd->entries[ifd->count++];
1088 }
1089
1090 15 src.count = count;
1091 15 src.id = id;
1092 15 src.type = type;
1093 15 src.ifd_lead = (uint8_t *) ifd_lead;
1094 15 src.ifd_offset = ifd_offset;
1095
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
15 if (type == AV_TIFF_IFD)
1096 2 src.value.ifd = * (const AVExifMetadata *) value;
1097 else
1098 13 src.value.ptr = (void *) value;
1099
1100 15 ret = exif_clone_entry(entry, &src);
1101
1102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0)
1103 ifd->count--;
1104
1105 15 return ret;
1106 }
1107
1108 21 static int exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int depth)
1109 {
1110 21 int32_t index = -1;
1111 21 int ret = 0;
1112
1113
3/6
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
21 if (!ifd || ifd->count && !ifd->entries)
1114 return AVERROR(EINVAL);
1115
1116
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
127 for (size_t i = 0; i < ifd->count; i++) {
1117
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 106 times.
127 if (ifd->entries[i].id == id) {
1118 21 index = i;
1119 21 break;
1120 }
1121
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
106 if (ifd->entries[i].type == AV_TIFF_IFD && depth < 3) {
1122 ret = exif_remove_entry(logctx, &ifd->entries[i].value.ifd, id, depth + 1);
1123 if (ret)
1124 return ret;
1125 }
1126 }
1127
1128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (index < 0)
1129 return 0;
1130 21 exif_free_entry(&ifd->entries[index]);
1131
1132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (index == --ifd->count) {
1133 if (!index)
1134 av_freep(&ifd->entries);
1135 return 1;
1136 }
1137
1138 21 memmove(&ifd->entries[index], &ifd->entries[index + 1], (ifd->count - index) * sizeof(*ifd->entries));
1139
1140 21 return 1 + (ifd->count - index);
1141 }
1142
1143 21 int av_exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int flags)
1144 {
1145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 return exif_remove_entry(logctx, ifd, id, (flags & AV_EXIF_FLAG_RECURSIVE) ? 0 : INT_MAX);
1146 }
1147
1148 32 AVExifMetadata *av_exif_clone_ifd(const AVExifMetadata *ifd)
1149 {
1150 32 AVExifMetadata *ret = av_mallocz(sizeof(*ret));
1151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!ret)
1152 return NULL;
1153
1154 32 ret->count = ifd->count;
1155
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 2 times.
32 if (ret->count) {
1156 size_t required_size;
1157
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (av_size_mult(ret->count, sizeof(*ret->entries), &required_size) < 0)
1158 goto fail;
1159 30 av_fast_mallocz(&ret->entries, &ret->size, required_size);
1160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!ret->entries)
1161 goto fail;
1162 }
1163
1164
2/2
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 32 times.
474 for (size_t i = 0; i < ret->count; i++) {
1165 442 const AVExifEntry *entry = &ifd->entries[i];
1166 442 AVExifEntry *ret_entry = &ret->entries[i];
1167 442 int status = exif_clone_entry(ret_entry, entry);
1168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 442 times.
442 if (status < 0)
1169 goto fail;
1170 }
1171
1172 32 return ret;
1173
1174 fail:
1175 av_exif_free(ret);
1176 av_free(ret);
1177 return NULL;
1178 }
1179
1180 static const int rotation_lut[2][4] = {
1181 {1, 8, 3, 6}, {4, 7, 2, 5},
1182 };
1183
1184 2 int av_exif_matrix_to_orientation(const int32_t *matrix)
1185 {
1186 2 double rotation = av_display_rotation_get(matrix);
1187 // determinant
1188 2 int vflip = ((int64_t)matrix[0] * (int64_t)matrix[4]
1189 2 - (int64_t)matrix[1] * (int64_t)matrix[3]) < 0;
1190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!isfinite(rotation))
1191 return 0;
1192 2 int rot = (int)(rotation + 0.5);
1193 2 rot = (((rot % 360) + 360) % 360) / 90;
1194 2 return rotation_lut[vflip][rot];
1195 }
1196
1197 18 int av_exif_orientation_to_matrix(int32_t *matrix, int orientation)
1198 {
1199
2/9
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
18 switch (orientation) {
1200 14 case 1:
1201 14 av_display_rotation_set(matrix, 0.0);
1202 14 break;
1203 case 2:
1204 av_display_rotation_set(matrix, 0.0);
1205 av_display_matrix_flip(matrix, 1, 0);
1206 break;
1207 case 3:
1208 av_display_rotation_set(matrix, 180.0);
1209 break;
1210 case 4:
1211 av_display_rotation_set(matrix, 180.0);
1212 av_display_matrix_flip(matrix, 1, 0);
1213 break;
1214 4 case 5:
1215 4 av_display_rotation_set(matrix, 90.0);
1216 4 av_display_matrix_flip(matrix, 1, 0);
1217 4 break;
1218 case 6:
1219 av_display_rotation_set(matrix, 90.0);
1220 break;
1221 case 7:
1222 av_display_rotation_set(matrix, -90.0);
1223 av_display_matrix_flip(matrix, 1, 0);
1224 break;
1225 case 8:
1226 av_display_rotation_set(matrix, -90.0);
1227 break;
1228 default:
1229 return AVERROR(EINVAL);
1230 }
1231
1232 18 return 0;
1233 }
1234
1235 3 int ff_exif_sanitize_ifd(void *logctx, const AVFrame *frame, AVExifMetadata *ifd)
1236 {
1237 3 int ret = 0;
1238 3 AVFrameSideData *sd_orient = NULL;
1239 3 AVExifEntry *or = NULL;
1240 3 AVExifEntry *iw = NULL;
1241 3 AVExifEntry *ih = NULL;
1242 3 AVExifEntry *pw = NULL;
1243 3 AVExifEntry *ph = NULL;
1244 3 uint64_t orientation = 1;
1245 3 uint64_t w = frame->width;
1246 3 uint64_t h = frame->height;
1247 3 int rewrite = 0;
1248
1249 3 sd_orient = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
1250
1251
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (sd_orient)
1252 1 orientation = av_exif_matrix_to_orientation((int32_t *) sd_orient->data);
1253
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (orientation != 1)
1254 1 av_log(logctx, AV_LOG_DEBUG, "matrix contains nontrivial EXIF orientation: %" PRIu64 "\n", orientation);
1255
1256
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 for (size_t i = 0; i < ifd->count; i++) {
1257 9 AVExifEntry *entry = &ifd->entries[i];
1258
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
9 if (entry->id == ORIENTATION_TAG && entry->count > 0 && entry->type == AV_TIFF_SHORT) {
1259 or = entry;
1260 continue;
1261 }
1262
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
9 if (entry->id == IMAGE_WIDTH_TAG && entry->count > 0 && entry->type == AV_TIFF_LONG) {
1263 iw = entry;
1264 continue;
1265 }
1266
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
9 if (entry->id == IMAGE_LENGTH_TAG && entry->count > 0 && entry->type == AV_TIFF_LONG) {
1267 ih = entry;
1268 continue;
1269 }
1270
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
9 if (entry->id == EXIFIFD_TAG && entry->type == AV_TIFF_IFD) {
1271 1 AVExifMetadata *exif = &entry->value.ifd;
1272
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (size_t j = 0; j < exif->count; j++) {
1273 1 AVExifEntry *exifentry = &exif->entries[j];
1274
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (exifentry->id == PIXEL_X_TAG && exifentry->count > 0 && exifentry->type == AV_TIFF_SHORT) {
1275 pw = exifentry;
1276 continue;
1277 }
1278
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (exifentry->id == PIXEL_Y_TAG && exifentry->count > 0 && exifentry->type == AV_TIFF_SHORT) {
1279 ph = exifentry;
1280 continue;
1281 }
1282 }
1283 }
1284 }
1285
1286
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (or && or->value.uint[0] != orientation) {
1287 rewrite = 1;
1288 or->value.uint[0] = orientation;
1289 }
1290
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (iw && iw->value.uint[0] != w) {
1291 rewrite = 1;
1292 iw->value.uint[0] = w;
1293 }
1294
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (ih && ih->value.uint[0] != h) {
1295 rewrite = 1;
1296 ih->value.uint[0] = h;
1297 }
1298
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (pw && pw->value.uint[0] != w) {
1299 rewrite = 1;
1300 pw->value.uint[0] = w;
1301 }
1302
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (ph && ph->value.uint[0] != h) {
1303 rewrite = 1;
1304 ph->value.uint[0] = h;
1305 }
1306
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (!or && orientation != 1) {
1307 1 rewrite = 1;
1308 1 ret = av_exif_set_entry(logctx, ifd, ORIENTATION_TAG, AV_TIFF_SHORT, 1, NULL, 0, &orientation);
1309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
1310 goto end;
1311 }
1312
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (!iw && w) {
1313 3 rewrite = 1;
1314 3 ret = av_exif_set_entry(logctx, ifd, IMAGE_WIDTH_TAG, AV_TIFF_LONG, 1, NULL, 0, &w);
1315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1316 goto end;
1317 }
1318
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (!ih && h) {
1319 3 rewrite = 1;
1320 3 ret = av_exif_set_entry(logctx, ifd, IMAGE_LENGTH_TAG, AV_TIFF_LONG, 1, NULL, 0, &h);
1321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1322 goto end;
1323 }
1324
3/12
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
3 if (!pw && w && w < 0xFFFFu || !ph && h && h < 0xFFFFu) {
1325 AVExifMetadata *exif;
1326 AVExifEntry *exif_entry;
1327 3 int exif_found = av_exif_get_entry(logctx, ifd, EXIFIFD_TAG, 0, &exif_entry);
1328 3 rewrite = 1;
1329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (exif_found < 0)
1330 goto end;
1331
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (exif_found > 0) {
1332 1 exif = &exif_entry->value.ifd;
1333 } else {
1334 2 AVExifMetadata exif_new = { 0 };
1335 2 ret = av_exif_set_entry(logctx, ifd, EXIFIFD_TAG, AV_TIFF_IFD, 1, NULL, 0, &exif_new);
1336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
1337 av_exif_free(&exif_new);
1338 goto end;
1339 }
1340 2 exif = &ifd->entries[ifd->count - 1].value.ifd;
1341 }
1342
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 if (!pw && w && w < 0xFFFFu) {
1343 3 ret = av_exif_set_entry(logctx, exif, PIXEL_X_TAG, AV_TIFF_SHORT, 1, NULL, 0, &w);
1344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1345 goto end;
1346 }
1347
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 if (!ph && h && h < 0xFFFFu) {
1348 3 ret = av_exif_set_entry(logctx, exif, PIXEL_Y_TAG, AV_TIFF_SHORT, 1, NULL, 0, &h);
1349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1350 goto end;
1351 }
1352 }
1353
1354 3 return rewrite;
1355
1356 end:
1357 return ret;
1358 }
1359
1360 249 int ff_exif_get_buffer(void *logctx, const AVFrame *frame, AVBufferRef **buffer_ptr, enum AVExifHeaderMode header_mode)
1361 {
1362 249 AVFrameSideData *sd_exif = NULL;
1363 249 AVBufferRef *buffer = NULL;
1364 249 AVExifMetadata ifd = { 0 };
1365 249 int ret = 0;
1366 249 int rewrite = 0;
1367
1368
2/4
✓ Branch 0 taken 249 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 249 times.
249 if (!buffer_ptr || *buffer_ptr)
1369 return AVERROR(EINVAL);
1370
1371 249 sd_exif = av_frame_get_side_data(frame, AV_FRAME_DATA_EXIF);
1372
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 3 times.
249 if (!sd_exif)
1373 246 return 0;
1374
1375 3 ret = av_exif_parse_buffer(logctx, sd_exif->data, sd_exif->size, &ifd, AV_EXIF_TIFF_HEADER);
1376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1377 goto end;
1378
1379 3 rewrite = ff_exif_sanitize_ifd(logctx, frame, &ifd);
1380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (rewrite < 0) {
1381 ret = rewrite;
1382 goto end;
1383 }
1384
1385
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (rewrite) {
1386 3 ret = av_exif_write(logctx, &ifd, &buffer, header_mode);
1387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1388 goto end;
1389
1390 3 *buffer_ptr = buffer;
1391 } else {
1392 *buffer_ptr = av_buffer_ref(sd_exif->buf);
1393 if (!*buffer_ptr) {
1394 ret = AVERROR(ENOMEM);
1395 goto end;
1396 }
1397 }
1398
1399 3 av_exif_free(&ifd);
1400 3 return rewrite;
1401
1402 end:
1403 av_exif_free(&ifd);
1404 return ret;
1405 }
1406