FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/exif.c
Date: 2025-08-19 23:55:23
Exec Total Coverage
Lines: 468 816 57.4%
Functions: 26 34 76.5%
Branches: 276 609 45.3%

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 552 const char *av_exif_get_tag_name(uint16_t id)
216 {
217
2/2
✓ Branch 0 taken 33023 times.
✓ Branch 1 taken 80 times.
33103 for (size_t i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
218
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 32551 times.
33023 if (tag_list[i].id == id)
219 472 return tag_list[i].name;
220 }
221
222 80 return NULL;
223 }
224
225 int32_t av_exif_get_tag_id(const char *name)
226 {
227 if (!name)
228 return -1;
229
230 for (size_t i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
231 if (!strcmp(tag_list[i].name, name))
232 return tag_list[i].id;
233 }
234
235 return -1;
236 }
237
238 1592 static inline void tput16(PutByteContext *pb, const int le, const uint16_t value)
239 {
240
1/2
✓ Branch 0 taken 1592 times.
✗ Branch 1 not taken.
1592 le ? bytestream2_put_le16(pb, value) : bytestream2_put_be16(pb, value);
241 1592 }
242
243 2251 static inline void tput32(PutByteContext *pb, const int le, const uint32_t value)
244 {
245
1/2
✓ Branch 0 taken 2251 times.
✗ Branch 1 not taken.
2251 le ? bytestream2_put_le32(pb, value) : bytestream2_put_be32(pb, value);
246 2251 }
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 852 static int exif_read_values(void *logctx, GetByteContext *gb, int le, AVExifEntry *entry)
254 {
255
5/9
✓ Branch 0 taken 599 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 118 times.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 74 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
852 switch (entry->type) {
256 599 case AV_TIFF_SHORT:
257 case AV_TIFF_LONG:
258 599 entry->value.uint = av_calloc(entry->count, sizeof(*entry->value.uint));
259 599 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 118 case AV_TIFF_RATIONAL:
269 case AV_TIFF_SRATIONAL:
270 118 entry->value.rat = av_calloc(entry->count, sizeof(*entry->value.rat));
271 118 break;
272 41 case AV_TIFF_UNDEFINED:
273 case AV_TIFF_BYTE:
274 41 entry->value.ubytes = av_mallocz(entry->count);
275 41 break;
276 case AV_TIFF_SBYTE:
277 entry->value.sbytes = av_mallocz(entry->count);
278 break;
279 74 case AV_TIFF_STRING:
280 74 entry->value.str = av_mallocz(entry->count + 1);
281 74 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 852 times.
852 if (!entry->value.ptr)
287 return AVERROR(ENOMEM);
288
6/11
✓ Branch 0 taken 419 times.
✓ Branch 1 taken 180 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 118 times.
✓ Branch 7 taken 41 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 74 times.
✗ Branch 10 not taken.
852 switch (entry->type) {
289 419 case AV_TIFF_SHORT:
290
2/2
✓ Branch 0 taken 2265 times.
✓ Branch 1 taken 419 times.
2684 for (size_t i = 0; i < entry->count; i++)
291 2265 entry->value.uint[i] = ff_tget_short(gb, le);
292 419 break;
293 180 case AV_TIFF_LONG:
294
2/2
✓ Branch 0 taken 2174 times.
✓ Branch 1 taken 180 times.
2354 for (size_t i = 0; i < entry->count; i++)
295 2174 entry->value.uint[i] = ff_tget_long(gb, le);
296 180 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 118 case AV_TIFF_RATIONAL:
316 case AV_TIFF_SRATIONAL:
317
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 118 times.
296 for (size_t i = 0; i < entry->count; i++) {
318 178 int32_t num = ff_tget_long(gb, le);
319 178 int32_t den = ff_tget_long(gb, le);
320 178 entry->value.rat[i] = av_make_q(num, den);
321 }
322 118 break;
323 41 case AV_TIFF_UNDEFINED:
324 case AV_TIFF_BYTE:
325 41 bytestream2_get_buffer(gb, entry->value.ubytes, entry->count);
326 41 break;
327 case AV_TIFF_SBYTE:
328 bytestream2_get_buffer(gb, entry->value.sbytes, entry->count);
329 break;
330 74 case AV_TIFF_STRING:
331 74 bytestream2_get_buffer(gb, entry->value.str, entry->count);
332 74 break;
333 }
334
335 852 return 0;
336 }
337
338 418 static void exif_write_values(PutByteContext *pb, int le, const AVExifEntry *entry)
339 {
340
6/11
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 113 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 55 times.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 22 times.
✗ Branch 10 not taken.
418 switch (entry->type) {
341 208 case AV_TIFF_SHORT:
342
2/2
✓ Branch 0 taken 707 times.
✓ Branch 1 taken 208 times.
915 for (size_t i = 0; i < entry->count; i++)
343 707 tput16(pb, le, entry->value.uint[i]);
344 208 break;
345 113 case AV_TIFF_LONG:
346
2/2
✓ Branch 0 taken 1394 times.
✓ Branch 1 taken 113 times.
1507 for (size_t i = 0; i < entry->count; i++)
347 1394 tput32(pb, le, entry->value.uint[i]);
348 113 break;
349 case AV_TIFF_SSHORT:
350 for (size_t i = 0; i < entry->count; i++)
351 tput16(pb, le, entry->value.sint[i]);
352 break;
353 case AV_TIFF_SLONG:
354 for (size_t i = 0; i < entry->count; i++)
355 tput32(pb, le, entry->value.sint[i]);
356 break;
357 case AV_TIFF_DOUBLE:
358 for (size_t i = 0; i < entry->count; i++) {
359 const av_alias64 a = { .f64 = entry->value.dbl[i] };
360 tput64(pb, le, a.u64);
361 }
362 break;
363 10 case AV_TIFF_FLOAT:
364
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 10 times.
44 for (size_t i = 0; i < entry->count; i++) {
365 34 const av_alias32 a = { .f32 = entry->value.dbl[i] };
366 34 tput32(pb, le, a.u32);
367 }
368 10 break;
369 55 case AV_TIFF_RATIONAL:
370 case AV_TIFF_SRATIONAL:
371
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 55 times.
140 for (size_t i = 0; i < entry->count; i++) {
372 85 tput32(pb, le, entry->value.rat[i].num);
373 85 tput32(pb, le, entry->value.rat[i].den);
374 }
375 55 break;
376 10 case AV_TIFF_UNDEFINED:
377 case AV_TIFF_BYTE:
378 10 bytestream2_put_buffer(pb, entry->value.ubytes, entry->count);
379 10 break;
380 case AV_TIFF_SBYTE:
381 bytestream2_put_buffer(pb, entry->value.sbytes, entry->count);
382 break;
383 22 case AV_TIFF_STRING:
384 22 bytestream2_put_buffer(pb, entry->value.str, entry->count);
385 22 break;
386 }
387 418 }
388
389 static const uint8_t aoc_header[] = { 'A', 'O', 'C', 0, };
390 static const uint8_t casio_header[] = { 'Q', 'V', 'C', 0, 0, 0, };
391 static const uint8_t foveon_header[] = { 'F', 'O', 'V', 'E', 'O', 'N', 0, 0, };
392 static const uint8_t fuji_header[] = { 'F', 'U', 'J', 'I', };
393 static const uint8_t nikon_header[] = { 'N', 'i', 'k', 'o', 'n', 0, };
394 static const uint8_t olympus1_header[] = { 'O', 'L', 'Y', 'M', 'P', 0, };
395 static const uint8_t olympus2_header[] = { 'O', 'L', 'Y', 'M', 'P', 'U', 'S', 0, 'I', 'I', };
396 static const uint8_t panasonic_header[] = { 'P', 'a', 'n', 'a', 's', 'o', 'n', 'i', 'c', 0, 0, 0, };
397 static const uint8_t sigma_header[] = { 'S', 'I', 'G', 'M', 'A', 0, 0, 0, };
398 static const uint8_t sony_header[] = { 'S', 'O', 'N', 'Y', ' ', 'D', 'S', 'C', ' ', 0, 0, 0, };
399
400 struct exif_makernote_data {
401 const uint8_t *header;
402 size_t header_size;
403 int result;
404 };
405
406 #define MAKERNOTE_STRUCT(h, r) { \
407 .header = (h), \
408 .header_size = sizeof((h)), \
409 .result = (r), \
410 }
411
412 static const struct exif_makernote_data makernote_data[] = {
413 MAKERNOTE_STRUCT(aoc_header, 6),
414 MAKERNOTE_STRUCT(casio_header, -1),
415 MAKERNOTE_STRUCT(foveon_header, 10),
416 MAKERNOTE_STRUCT(fuji_header, -1),
417 MAKERNOTE_STRUCT(olympus1_header, 8),
418 MAKERNOTE_STRUCT(olympus2_header, -1),
419 MAKERNOTE_STRUCT(panasonic_header, 12),
420 MAKERNOTE_STRUCT(sigma_header, 10),
421 MAKERNOTE_STRUCT(sony_header, 12),
422 };
423
424 /*
425 * derived from Exiv2 MakerNote's article
426 * https://exiv2.org/makernote.html or archived at
427 * https://web.archive.org/web/20250311155857/https://exiv2.org/makernote.html
428 */
429 4 static int exif_get_makernote_offset(GetByteContext *gb)
430 {
431
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (bytestream2_get_bytes_left(gb) < BASE_TAG_SIZE)
432 return -1;
433
434
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4 times.
40 for (int i = 0; i < FF_ARRAY_ELEMS(makernote_data); i++) {
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!memcmp(gb->buffer, makernote_data[i].header, makernote_data[i].header_size))
436 return makernote_data[i].result;
437 }
438
439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!memcmp(gb->buffer, nikon_header, sizeof(nikon_header))) {
440 if (bytestream2_get_bytes_left(gb) < 14)
441 return -1;
442 else if (AV_RB32(gb->buffer + 10) == EXIF_MM_LONG || AV_RB32(gb->buffer + 10) == EXIF_II_LONG)
443 return -1;
444 return 8;
445 }
446
447 4 return 0;
448 }
449
450 static int exif_parse_ifd_list(void *logctx, GetByteContext *gb, int le,
451 int depth, AVExifMetadata *ifd);
452
453 873 static int exif_decode_tag(void *logctx, GetByteContext *gb, int le,
454 int depth, AVExifEntry *entry)
455 {
456 873 int ret = 0, makernote_offset = -1, tell, is_ifd, count;
457 enum AVTiffDataType type;
458 uint32_t payload;
459
460 /* safety check to prevent infinite recursion on malicious IFDs */
461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 873 times.
873 if (depth > 3)
462 return AVERROR_INVALIDDATA;
463
464 873 tell = bytestream2_tell(gb);
465
466 873 entry->id = ff_tget_short(gb, le);
467 873 type = ff_tget_short(gb, le);
468 873 count = ff_tget_long(gb, le);
469 873 payload = ff_tget_long(gb, le);
470
471 873 av_log(logctx, AV_LOG_DEBUG, "TIFF Tag: id: 0x%04x, type: %d, count: %u, offset: %d, "
472 873 "payload: %" PRIu32 "\n", entry->id, type, count, tell, payload);
473
474
6/6
✓ Branch 0 taken 872 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 856 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 852 times.
873 is_ifd = type == AV_TIFF_IFD || ff_tis_ifd(entry->id) || entry->id == MAKERNOTE_TAG;
475
476
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 852 times.
873 if (is_ifd) {
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (!payload)
478 goto end;
479 21 bytestream2_seek(gb, payload, SEEK_SET);
480 }
481
482
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 869 times.
873 if (entry->id == MAKERNOTE_TAG) {
483 4 makernote_offset = exif_get_makernote_offset(gb);
484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (makernote_offset < 0)
485 is_ifd = 0;
486 }
487
488
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 852 times.
873 if (is_ifd) {
489 21 entry->type = AV_TIFF_IFD;
490 21 entry->count = 1;
491 21 entry->ifd_offset = makernote_offset > 0 ? makernote_offset : 0;
492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (entry->ifd_offset) {
493 entry->ifd_lead = av_malloc(entry->ifd_offset);
494 if (!entry->ifd_lead)
495 return AVERROR(ENOMEM);
496 bytestream2_get_buffer(gb, entry->ifd_lead, entry->ifd_offset);
497 }
498 21 ret = exif_parse_ifd_list(logctx, gb, le, depth + 1, &entry->value.ifd);
499
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
21 if (ret < 0 && entry->id == MAKERNOTE_TAG) {
500 /*
501 * we guessed that MakerNote was an IFD
502 * but we were probably incorrect at this
503 * point so we try again as a binary blob
504 */
505 av_exif_free(&entry->value.ifd);
506 av_log(logctx, AV_LOG_DEBUG, "unrecognized MakerNote IFD, retrying as blob\n");
507 is_ifd = 0;
508 }
509 }
510
511 /* inverted condition instead of else so we can fall through from above */
512
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 852 times.
873 if (!is_ifd) {
513
1/2
✓ Branch 0 taken 852 times.
✗ Branch 1 not taken.
852 entry->type = type == AV_TIFF_IFD ? AV_TIFF_UNDEFINED : type;
514 852 entry->count = count;
515
2/2
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 351 times.
852 bytestream2_seek(gb, count * exif_sizes[type] > 4 ? payload : tell + 8, SEEK_SET);
516 852 ret = exif_read_values(logctx, gb, le, entry);
517 }
518
519 21 end:
520 873 bytestream2_seek(gb, tell + BASE_TAG_SIZE, SEEK_SET);
521
522 873 return ret;
523 }
524
525 76 static int exif_parse_ifd_list(void *logctx, GetByteContext *gb, int le,
526 int depth, AVExifMetadata *ifd)
527 {
528 uint32_t entries;
529 size_t required_size;
530 void *temp;
531
532 76 av_log(logctx, AV_LOG_DEBUG, "parsing IFD list at offset: %d\n", bytestream2_tell(gb));
533
534
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
76 if (bytestream2_get_bytes_left(gb) < 2) {
535 av_log(logctx, AV_LOG_ERROR, "not enough bytes remaining in EXIF buffer: 2 required\n");
536 return AVERROR_INVALIDDATA;
537 }
538
539 76 entries = ff_tget_short(gb, le);
540
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
76 if (bytestream2_get_bytes_left(gb) < entries * BASE_TAG_SIZE) {
541 av_log(logctx, AV_LOG_ERROR, "not enough bytes remaining in EXIF buffer. entries: %" PRIu32 "\n", entries);
542 return AVERROR_INVALIDDATA;
543 }
544
545 76 ifd->count = entries;
546 76 av_log(logctx, AV_LOG_DEBUG, "entry count for IFD: %u\n", ifd->count);
547
548
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
76 if (av_size_mult(ifd->count, sizeof(*ifd->entries), &required_size) < 0)
549 return AVERROR(ENOMEM);
550 76 temp = av_fast_realloc(ifd->entries, &ifd->size, required_size);
551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (!temp) {
552 av_freep(&ifd->entries);
553 return AVERROR(ENOMEM);
554 }
555 76 ifd->entries = temp;
556
557 /* entries have pointers in them which can cause issues if */
558 /* they are freed or realloc'd when garbage */
559 76 memset(ifd->entries, 0, required_size);
560
561
2/2
✓ Branch 0 taken 873 times.
✓ Branch 1 taken 76 times.
949 for (uint32_t i = 0; i < entries; i++) {
562 873 int ret = exif_decode_tag(logctx, gb, le, depth, &ifd->entries[i]);
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 873 times.
873 if (ret < 0)
564 return ret;
565 }
566
567 /*
568 * at the end of an IFD is an pointer to the next IFD
569 * or zero if there are no more IFDs, which is usually the case
570 */
571 76 return ff_tget_long(gb, le);
572 }
573
574 /*
575 * note that this function does not free the entry pointer itself
576 * because it's probably part of a larger array that should be freed
577 * all at once
578 */
579 882 static void exif_free_entry(AVExifEntry *entry)
580 {
581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882 times.
882 if (!entry)
582 return;
583
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 860 times.
882 if (entry->type == AV_TIFF_IFD)
584 22 av_exif_free(&entry->value.ifd);
585 else
586 860 av_freep(&entry->value.ptr);
587 882 av_freep(&entry->ifd_lead);
588 }
589
590 2922 void av_exif_free(AVExifMetadata *ifd)
591 {
592
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 2894 times.
2922 if (!ifd)
593 28 return;
594
2/2
✓ Branch 0 taken 2817 times.
✓ Branch 1 taken 77 times.
2894 if (!ifd->entries) {
595 2817 ifd->count = 0;
596 2817 ifd->size = 0;
597 2817 return;
598 }
599
2/2
✓ Branch 0 taken 882 times.
✓ Branch 1 taken 77 times.
959 for (size_t i = 0; i < ifd->count; i++) {
600 882 AVExifEntry *entry = &ifd->entries[i];
601 882 exif_free_entry(entry);
602 }
603 77 av_freep(&ifd->entries);
604 77 ifd->count = 0;
605 77 ifd->size = 0;
606 }
607
608 36 static size_t exif_get_ifd_size(const AVExifMetadata *ifd)
609 {
610 /* 6 == 4 + 2; 2-byte entry-count at the beginning */
611 /* plus 4-byte next-IFD pointer at the end */
612 36 size_t total_size = IFD_EXTRA_SIZE;
613
2/2
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 36 times.
486 for (size_t i = 0; i < ifd->count; i++) {
614 450 const AVExifEntry *entry = &ifd->entries[i];
615
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 443 times.
450 if (entry->type == AV_TIFF_IFD) {
616 7 total_size += BASE_TAG_SIZE + exif_get_ifd_size(&entry->value.ifd) + entry->ifd_offset;
617 } else {
618 443 size_t payload_size = entry->count * exif_sizes[entry->type];
619
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 267 times.
443 total_size += BASE_TAG_SIZE + (payload_size > 4 ? payload_size : 0);
620 }
621 }
622 36 return total_size;
623 }
624
625 35 static int exif_write_ifd(void *logctx, PutByteContext *pb, int le, int depth, const AVExifMetadata *ifd)
626 {
627 int offset, ret, tell, tell2;
628 35 tell = bytestream2_tell_p(pb);
629 35 tput16(pb, le, ifd->count);
630 35 offset = tell + IFD_EXTRA_SIZE + BASE_TAG_SIZE * (uint32_t) ifd->count;
631 35 av_log(logctx, AV_LOG_DEBUG, "writing IFD with %u entries and initial offset %d\n", ifd->count, offset);
632
2/2
✓ Branch 0 taken 425 times.
✓ Branch 1 taken 35 times.
460 for (size_t i = 0; i < ifd->count; i++) {
633 425 const AVExifEntry *entry = &ifd->entries[i];
634 425 av_log(logctx, AV_LOG_DEBUG, "writing TIFF entry: id: 0x%04" PRIx16 ", type: %d, count: %"
635 PRIu32 ", offset: %d, offset value: %d\n",
636 425 entry->id, entry->type, entry->count,
637 bytestream2_tell_p(pb), offset);
638 425 tput16(pb, le, entry->id);
639
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 424 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
426 if (entry->id == MAKERNOTE_TAG && entry->type == AV_TIFF_IFD) {
640 1 size_t ifd_size = exif_get_ifd_size(&entry->value.ifd);
641 1 tput16(pb, le, AV_TIFF_UNDEFINED);
642 1 tput32(pb, le, ifd_size);
643 } else {
644 424 tput16(pb, le, entry->type);
645 424 tput32(pb, le, entry->count);
646 }
647
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 418 times.
425 if (entry->type == AV_TIFF_IFD) {
648 7 tput32(pb, le, offset);
649 7 tell2 = bytestream2_tell_p(pb);
650 7 bytestream2_seek_p(pb, offset, SEEK_SET);
651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (entry->ifd_offset)
652 bytestream2_put_buffer(pb, entry->ifd_lead, entry->ifd_offset);
653 7 ret = exif_write_ifd(logctx, pb, le, depth + 1, &entry->value.ifd);
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
655 return ret;
656 7 offset += ret + entry->ifd_offset;
657 7 bytestream2_seek_p(pb, tell2, SEEK_SET);
658 } else {
659 418 size_t payload_size = entry->count * exif_sizes[entry->type];
660
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 260 times.
418 if (payload_size > 4) {
661 158 tput32(pb, le, offset);
662 158 tell2 = bytestream2_tell_p(pb);
663 158 bytestream2_seek_p(pb, offset, SEEK_SET);
664 158 exif_write_values(pb, le, entry);
665 158 offset += payload_size;
666 158 bytestream2_seek_p(pb, tell2, SEEK_SET);
667 } else {
668 /* zero uninitialized excess payload values */
669 260 AV_WN32(pb->buffer, 0);
670 260 exif_write_values(pb, le, entry);
671 260 bytestream2_seek_p(pb, 4 - payload_size, SEEK_CUR);
672 }
673 }
674 }
675
676 /*
677 * we write 0 if this is the top-level exif IFD
678 * indicating that there are no more IFD pointers
679 */
680
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 28 times.
35 tput32(pb, le, depth ? offset : 0);
681 35 return offset - tell;
682 }
683
684 28 int av_exif_write(void *logctx, const AVExifMetadata *ifd, AVBufferRef **buffer, enum AVExifHeaderMode header_mode)
685 {
686 28 AVBufferRef *buf = NULL;
687 28 size_t size, headsize = 8;
688 PutByteContext pb;
689 28 int ret, off = 0;
690
691 #if AV_HAVE_BIGENDIAN
692 int le = 0;
693 #else
694 28 int le = 1;
695 #endif
696
697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (*buffer)
698 return AVERROR(EINVAL);
699
700 28 size = exif_get_ifd_size(ifd);
701
1/5
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
28 switch (header_mode) {
702 case AV_EXIF_EXIF00:
703 off = 6;
704 break;
705 case AV_EXIF_T_OFF:
706 off = 4;
707 break;
708 case AV_EXIF_ASSUME_BE:
709 le = 0;
710 headsize = 0;
711 break;
712 case AV_EXIF_ASSUME_LE:
713 le = 1;
714 headsize = 0;
715 break;
716 }
717 28 buf = av_buffer_alloc(size + off + headsize);
718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!buf)
719 return AVERROR(ENOMEM);
720
721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (header_mode == AV_EXIF_EXIF00) {
722 AV_WL32(buf->data, MKTAG('E','x','i','f'));
723 AV_WN16(buf->data + 4, 0);
724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 } else if (header_mode == AV_EXIF_T_OFF) {
725 AV_WN32(buf->data, 0);
726 }
727
728 28 bytestream2_init_writer(&pb, buf->data + off, buf->size - off);
729
730
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 if (header_mode != AV_EXIF_ASSUME_BE && header_mode != AV_EXIF_ASSUME_LE) {
731 /* these constants are be32 in both cases */
732
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 bytestream2_put_be32(&pb, le ? EXIF_II_LONG : EXIF_MM_LONG);
733 28 tput32(&pb, le, 8);
734 }
735
736 28 ret = exif_write_ifd(logctx, &pb, le, 0, ifd);
737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0) {
738 av_buffer_unref(&buf);
739 av_log(logctx, AV_LOG_ERROR, "error writing EXIF data: %s\n", av_err2str(ret));
740 return ret;
741 }
742
743 28 *buffer = buf;
744
745 28 return 0;
746 }
747
748 55 int av_exif_parse_buffer(void *logctx, const uint8_t *buf, size_t size,
749 AVExifMetadata *ifd, enum AVExifHeaderMode header_mode)
750 {
751 int ret, le;
752 GetByteContext gbytes;
753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (size > INT_MAX)
754 return AVERROR(EINVAL);
755 55 size_t off = 0;
756
1/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
55 switch (header_mode) {
757 case AV_EXIF_EXIF00:
758 if (size < 6)
759 return AVERROR_INVALIDDATA;
760 off = 6;
761 /* fallthrough */
762 case AV_EXIF_T_OFF:
763 if (size < 4)
764 return AVERROR_INVALIDDATA;
765 if (!off)
766 off = AV_RB32(buf) + 4;
767 /* fallthrough */
768 case AV_EXIF_TIFF_HEADER: {
769 int ifd_offset;
770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (size <= off)
771 return AVERROR_INVALIDDATA;
772 55 bytestream2_init(&gbytes, buf + off, size - off);
773 // read TIFF header
774 55 ret = ff_tdecode_header(&gbytes, &le, &ifd_offset);
775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (ret < 0) {
776 av_log(logctx, AV_LOG_ERROR, "invalid TIFF header in EXIF data: %s\n", av_err2str(ret));
777 return ret;
778 }
779 55 bytestream2_seek(&gbytes, ifd_offset, SEEK_SET);
780 55 break;
781 }
782 case AV_EXIF_ASSUME_LE:
783 le = 1;
784 bytestream2_init(&gbytes, buf, size);
785 break;
786 case AV_EXIF_ASSUME_BE:
787 le = 0;
788 bytestream2_init(&gbytes, buf, size);
789 break;
790 default:
791 return AVERROR(EINVAL);
792 }
793
794 /*
795 * parse IFD0 here. If the return value is positive that tells us
796 * there is subimage metadata, but we don't parse that IFD here
797 */
798 55 ret = exif_parse_ifd_list(logctx, &gbytes, le, 0, ifd);
799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 if (ret < 0) {
800 av_exif_free(ifd);
801 av_log(logctx, AV_LOG_ERROR, "error decoding EXIF data: %s\n", av_err2str(ret));
802 return ret;
803 }
804
805 55 return bytestream2_tell(&gbytes);
806 }
807
808 static int attach_displaymatrix(void *logctx, AVFrame *frame, int orientation)
809 {
810 AVFrameSideData *sd;
811 int32_t *matrix;
812 /* invalid orientation */
813 if (orientation < 2 || orientation > 8)
814 return AVERROR_INVALIDDATA;
815 sd = av_frame_new_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9);
816 if (!sd) {
817 av_log(logctx, AV_LOG_ERROR, "Could not allocate frame side data\n");
818 return AVERROR(ENOMEM);
819 }
820 matrix = (int32_t *) sd->data;
821
822 return av_exif_orientation_to_matrix(matrix, orientation);
823 }
824
825 #define COLUMN_SEP(i, c) ((i) ? ((i) % (c) ? ", " : "\n") : "")
826
827 39 static int exif_ifd_to_dict(void *logctx, const char *prefix, const AVExifMetadata *ifd, AVDictionary **metadata)
828 {
829 AVBPrint bp;
830 39 int ret = 0;
831 39 char *key = NULL;
832 39 char *value = NULL;
833
834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (!prefix)
835 prefix = "";
836
837
2/2
✓ Branch 0 taken 552 times.
✓ Branch 1 taken 39 times.
591 for (uint16_t i = 0; i < ifd->count; i++) {
838 552 const AVExifEntry *entry = &ifd->entries[i];
839 552 const char *name = av_exif_get_tag_name(entry->id);
840 552 av_bprint_init(&bp, entry->count * 10, AV_BPRINT_SIZE_UNLIMITED);
841
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 367 times.
552 if (*prefix)
842 185 av_bprintf(&bp, "%s/", prefix);
843
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 80 times.
552 if (name)
844 472 av_bprintf(&bp, "%s", name);
845 else
846 80 av_bprintf(&bp, "0x%04X", entry->id);
847 552 ret = av_bprint_finalize(&bp, &key);
848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
552 if (ret < 0)
849 goto end;
850 552 av_bprint_init(&bp, entry->count * 10, AV_BPRINT_SIZE_UNLIMITED);
851
6/9
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 385 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 40 times.
✓ Branch 6 taken 25 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
552 switch (entry->type) {
852 11 case AV_TIFF_IFD:
853 11 ret = exif_ifd_to_dict(logctx, key, &entry->value.ifd, metadata);
854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
855 goto end;
856 11 break;
857 385 case AV_TIFF_SHORT:
858 case AV_TIFF_LONG:
859
2/2
✓ Branch 0 taken 3369 times.
✓ Branch 1 taken 385 times.
3754 for (uint32_t j = 0; j < entry->count; j++)
860
4/4
✓ Branch 0 taken 2984 times.
✓ Branch 1 taken 385 times.
✓ Branch 2 taken 2644 times.
✓ Branch 3 taken 340 times.
3369 av_bprintf(&bp, "%s%7" PRIu32, COLUMN_SEP(j, 8), (uint32_t)entry->value.uint[j]);
861 385 break;
862 case AV_TIFF_SSHORT:
863 case AV_TIFF_SLONG:
864 for (uint32_t j = 0; j < entry->count; j++)
865 av_bprintf(&bp, "%s%7" PRId32, COLUMN_SEP(j, 8), (int32_t)entry->value.sint[j]);
866 break;
867 81 case AV_TIFF_RATIONAL:
868 case AV_TIFF_SRATIONAL:
869
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 81 times.
192 for (uint32_t j = 0; j < entry->count; j++)
870
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 81 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 5 times.
111 av_bprintf(&bp, "%s%7i:%-7i", COLUMN_SEP(j, 4), entry->value.rat[j].num, entry->value.rat[j].den);
871 81 break;
872 10 case AV_TIFF_DOUBLE:
873 case AV_TIFF_FLOAT:
874
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 10 times.
44 for (uint32_t j = 0; j < entry->count; j++)
875
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]);
876 10 break;
877 40 case AV_TIFF_STRING:
878 40 av_bprintf(&bp, "%s", entry->value.str);
879 40 break;
880 25 case AV_TIFF_UNDEFINED:
881 case AV_TIFF_BYTE:
882
2/2
✓ Branch 0 taken 1660 times.
✓ Branch 1 taken 25 times.
1685 for (uint32_t j = 0; j < entry->count; j++)
883
4/4
✓ Branch 0 taken 1635 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 1542 times.
✓ Branch 3 taken 93 times.
1660 av_bprintf(&bp, "%s%3i", COLUMN_SEP(j, 16), entry->value.ubytes[j]);
884 25 break;
885 case AV_TIFF_SBYTE:
886 for (uint32_t j = 0; j < entry->count; j++)
887 av_bprintf(&bp, "%s%3i", COLUMN_SEP(j, 16), entry->value.sbytes[j]);
888 break;
889 }
890
2/2
✓ Branch 0 taken 541 times.
✓ Branch 1 taken 11 times.
552 if (entry->type != AV_TIFF_IFD) {
891
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 541 times.
541 if (!av_bprint_is_complete(&bp)) {
892 av_bprint_finalize(&bp, NULL);
893 ret = AVERROR(ENOMEM);
894 goto end;
895 }
896 541 ret = av_bprint_finalize(&bp, &value);
897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 541 times.
541 if (ret < 0)
898 goto end;
899 541 ret = av_dict_set(metadata, key, value, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 541 times.
541 if (ret < 0)
901 goto end;
902 541 key = NULL;
903 541 value = NULL;
904 } else {
905 11 av_freep(&key);
906 }
907 }
908
909 39 end:
910 39 av_freep(&key);
911 39 av_freep(&value);
912 39 return ret;
913 }
914
915 28 int av_exif_ifd_to_dict(void *logctx, const AVExifMetadata *ifd, AVDictionary **metadata)
916 {
917 28 return exif_ifd_to_dict(logctx, "", ifd, metadata);
918 }
919
920 #if FF_API_OLD_EXIF
921 int avpriv_exif_decode_ifd(void *logctx, const uint8_t *buf, int size,
922 int le, int depth, AVDictionary **metadata)
923 {
924 AVExifMetadata ifd = { 0 };
925 GetByteContext gb;
926 int ret;
927 bytestream2_init(&gb, buf, size);
928 ret = exif_parse_ifd_list(logctx, &gb, le, depth, &ifd);
929 if (ret < 0)
930 return ret;
931 ret = av_exif_ifd_to_dict(logctx, &ifd, metadata);
932 av_exif_free(&ifd);
933 return ret;
934 }
935 #endif /* FF_API_OLD_EXIF */
936
937 28 static int exif_attach_ifd(void *logctx, AVFrame *frame, const AVExifMetadata *ifd, AVBufferRef *og)
938 {
939 28 const AVExifEntry *orient = NULL;
940 AVFrameSideData *sd;
941 28 AVExifMetadata *cloned = NULL;
942 28 AVBufferRef *written = NULL;
943 int ret;
944
945
2/2
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 16 times.
279 for (size_t i = 0; i < ifd->count; i++) {
946 263 const AVExifEntry *entry = &ifd->entries[i];
947
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 251 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
263 if (entry->id == ORIENTATION_TAG && entry->count > 0 && entry->type == AV_TIFF_SHORT) {
948 12 orient = entry;
949 12 break;
950 }
951 }
952
953
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
28 if (orient && orient->value.uint[0] > 1) {
954 av_log(logctx, AV_LOG_DEBUG, "found nontrivial EXIF orientation: %" PRIu64 "\n", orient->value.uint[0]);
955 ret = attach_displaymatrix(logctx, frame, orient->value.uint[0]);
956 if (ret < 0) {
957 av_log(logctx, AV_LOG_WARNING, "unable to attach displaymatrix from EXIF\n");
958 } else {
959 const AVExifEntry *cloned_orient;
960 cloned = av_exif_clone_ifd(ifd);
961 if (!cloned) {
962 ret = AVERROR(ENOMEM);
963 goto end;
964 }
965 // will have the same offset in the clone as in the original
966 cloned_orient = &cloned->entries[orient - ifd->entries];
967 cloned_orient->value.uint[0] = 1;
968 }
969 }
970
971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 ret = av_exif_ifd_to_dict(logctx, cloned ? cloned : ifd, &frame->metadata);
972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
973 return ret;
974
975
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 2 times.
28 if (cloned || !og) {
976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 ret = av_exif_write(logctx, cloned ? cloned : ifd, &written, AV_EXIF_TIFF_HEADER);
977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (ret < 0)
978 goto end;
979 }
980
981
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2 times.
28 sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_EXIF, written ? written : og);
982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!sd) {
983 if (written)
984 av_buffer_unref(&written);
985 ret = AVERROR(ENOMEM);
986 goto end;
987 }
988
989 28 ret = 0;
990
991 28 end:
992
3/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
28 if (og && written && ret >= 0)
993 av_buffer_unref(&og); // as though we called new_side_data on og;
994 28 av_exif_free(cloned);
995 28 av_free(cloned);
996 28 return ret;
997 }
998
999 #define EXIF_COPY(fname, srcname) do { \
1000 size_t sz; \
1001 if (av_size_mult(src->count, sizeof(*(fname)), &sz) < 0) { \
1002 ret = AVERROR(ENOMEM); \
1003 goto end; \
1004 } \
1005 (fname) = av_memdup((srcname), sz); \
1006 if (!(fname)) { \
1007 ret = AVERROR(ENOMEM); \
1008 goto end; \
1009 } \
1010 } while (0)
1011
1012 9 static int exif_clone_entry(AVExifEntry *dst, const AVExifEntry *src)
1013 {
1014 9 int ret = 0;
1015
1016 9 dst->count = src->count;
1017 9 dst->id = src->id;
1018 9 dst->type = src->type;
1019
1020 9 dst->ifd_offset = src->ifd_offset;
1021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (src->ifd_lead) {
1022 dst->ifd_lead = av_memdup(src->ifd_lead, src->ifd_offset);
1023 if (!dst->ifd_lead) {
1024 ret = AVERROR(ENOMEM);
1025 goto end;
1026 }
1027 } else {
1028 9 dst->ifd_lead = NULL;
1029 }
1030
1031
2/9
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
9 switch(src->type) {
1032 1 case AV_TIFF_IFD: {
1033 1 AVExifMetadata *cloned = av_exif_clone_ifd(&src->value.ifd);
1034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!cloned) {
1035 ret = AVERROR(ENOMEM);
1036 goto end;
1037 }
1038 1 dst->value.ifd = *cloned;
1039 1 av_freep(&cloned);
1040 1 break;
1041 }
1042 8 case AV_TIFF_SHORT:
1043 case AV_TIFF_LONG:
1044
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
8 EXIF_COPY(dst->value.uint, src->value.uint);
1045 8 break;
1046 case AV_TIFF_SLONG:
1047 case AV_TIFF_SSHORT:
1048 EXIF_COPY(dst->value.sint, src->value.sint);
1049 break;
1050 case AV_TIFF_RATIONAL:
1051 case AV_TIFF_SRATIONAL:
1052 EXIF_COPY(dst->value.rat, src->value.rat);
1053 break;
1054 case AV_TIFF_DOUBLE:
1055 case AV_TIFF_FLOAT:
1056 EXIF_COPY(dst->value.dbl, src->value.dbl);
1057 break;
1058 case AV_TIFF_BYTE:
1059 case AV_TIFF_UNDEFINED:
1060 EXIF_COPY(dst->value.ubytes, src->value.ubytes);
1061 break;
1062 case AV_TIFF_SBYTE:
1063 EXIF_COPY(dst->value.sbytes, src->value.sbytes);
1064 break;
1065 case AV_TIFF_STRING:
1066 EXIF_COPY(dst->value.str, src->value.str);
1067 break;
1068 }
1069
1070 9 return 0;
1071
1072 end:
1073 av_freep(&dst->ifd_lead);
1074 if (src->type == AV_TIFF_IFD)
1075 av_exif_free(&dst->value.ifd);
1076 else
1077 av_freep(&dst->value.ptr);
1078 memset(dst, 0, sizeof(*dst));
1079
1080 return ret;
1081 }
1082
1083 11 static int exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int depth, AVExifEntry **value)
1084 {
1085 11 int offset = 1;
1086
1087
8/12
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 11 times.
11 if (!ifd || ifd->entries && !ifd->count || ifd->count && !ifd->entries || !value)
1088 return AVERROR(EINVAL);
1089
1090
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 10 times.
39 for (size_t i = 0; i < ifd->count; i++) {
1091
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
29 if (ifd->entries[i].id == id) {
1092 1 *value = &ifd->entries[i];
1093 1 return i + offset;
1094 }
1095
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
28 if (ifd->entries[i].type == AV_TIFF_IFD) {
1096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (depth < 3) {
1097 int ret = exif_get_entry(logctx, &ifd->entries[i].value.ifd, id, depth + 1, value);
1098 if (ret)
1099 return ret < 0 ? ret : ret + offset;
1100 }
1101 2 offset += ifd->entries[i].value.ifd.count;
1102 }
1103 }
1104
1105 10 return 0;
1106 }
1107
1108 11 int av_exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int recursive, AVExifEntry **value)
1109 {
1110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 return exif_get_entry(logctx, ifd, id, recursive ? 0 : INT_MAX, value);
1111 }
1112
1113 9 int av_exif_set_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, enum AVTiffDataType type,
1114 uint32_t count, const uint8_t *ifd_lead, uint32_t ifd_offset, const void *value)
1115 {
1116 void *temp;
1117 9 int ret = 0;
1118 9 AVExifEntry *entry = NULL;
1119 9 AVExifEntry src = { 0 };
1120
1121
7/10
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
9 if (!ifd || ifd->entries && !ifd->count || ifd->count && !ifd->entries
1122
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
9 || ifd_lead && !ifd_offset || !ifd_lead && ifd_offset
1123
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 || !value || ifd->count == 0xFFFFu)
1124 return AVERROR(EINVAL);
1125
1126 9 ret = av_exif_get_entry(logctx, ifd, id, 0, &entry);
1127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
1128 return ret;
1129
1130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (entry) {
1131 exif_free_entry(entry);
1132 } else {
1133 size_t required_size;
1134 9 ret = av_size_mult(ifd->count + 1, sizeof(*ifd->entries), &required_size);
1135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
1136 return AVERROR(ENOMEM);
1137 9 temp = av_fast_realloc(ifd->entries, &ifd->size, required_size);
1138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!temp)
1139 return AVERROR(ENOMEM);
1140 9 ifd->entries = temp;
1141 9 entry = &ifd->entries[ifd->count++];
1142 }
1143
1144 9 src.count = count;
1145 9 src.id = id;
1146 9 src.type = type;
1147 9 src.ifd_lead = (uint8_t *) ifd_lead;
1148 9 src.ifd_offset = ifd_offset;
1149
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (type == AV_TIFF_IFD)
1150 1 src.value.ifd = * (const AVExifMetadata *) value;
1151 else
1152 8 src.value.ptr = (void *) value;
1153
1154 9 ret = exif_clone_entry(entry, &src);
1155
1156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
1157 ifd->count--;
1158
1159 9 return ret;
1160 }
1161
1162 static int exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int depth)
1163 {
1164 int32_t index = -1;
1165 int ret = 0;
1166
1167 if (!ifd || ifd->entries && !ifd->count || ifd->count && !ifd->entries)
1168 return AVERROR(EINVAL);
1169
1170 for (size_t i = 0; i < ifd->count; i++) {
1171 if (ifd->entries[i].id == id) {
1172 index = i;
1173 break;
1174 }
1175 if (ifd->entries[i].type == AV_TIFF_IFD && depth < 3) {
1176 ret = exif_remove_entry(logctx, &ifd->entries[i].value.ifd, id, depth + 1);
1177 if (ret)
1178 return ret;
1179 }
1180 }
1181
1182 if (index < 0)
1183 return 0;
1184 exif_free_entry(&ifd->entries[index]);
1185
1186 if (index == --ifd->count) {
1187 if (!index)
1188 av_freep(&ifd->entries);
1189 return 1;
1190 }
1191
1192 memmove(&ifd->entries[index], &ifd->entries[index + 1], (ifd->count - index) * sizeof(*ifd->entries));
1193
1194 return 1 + (ifd->count - index);
1195 }
1196
1197 int av_exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int recursive)
1198 {
1199 return exif_remove_entry(logctx, ifd, id, recursive ? 0 : INT_MAX);
1200 }
1201
1202 1 AVExifMetadata *av_exif_clone_ifd(const AVExifMetadata *ifd)
1203 {
1204 1 AVExifMetadata *ret = av_mallocz(sizeof(*ret));
1205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ret)
1206 return NULL;
1207
1208 1 ret->count = ifd->count;
1209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret->count) {
1210 size_t required_size;
1211 if (av_size_mult(ret->count, sizeof(*ret->entries), &required_size) < 0)
1212 goto fail;
1213 ret->entries = av_fast_realloc(NULL, &ret->size, required_size);
1214 if (!ret->entries)
1215 goto fail;
1216 }
1217
1218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for (size_t i = 0; i < ret->count; i++) {
1219 const AVExifEntry *entry = &ifd->entries[i];
1220 AVExifEntry *ret_entry = &ret->entries[i];
1221 int status = exif_clone_entry(ret_entry, entry);
1222 if (status < 0)
1223 goto fail;
1224 }
1225
1226 1 return ret;
1227
1228 fail:
1229 av_exif_free(ret);
1230 av_free(ret);
1231 return NULL;
1232 }
1233
1234 26 int ff_exif_attach_ifd(void *logctx, AVFrame *frame, const AVExifMetadata *ifd)
1235 {
1236 26 return exif_attach_ifd(logctx, frame, ifd, NULL);
1237 }
1238
1239 2 int ff_exif_attach_buffer(void *logctx, AVFrame *frame, AVBufferRef *data, enum AVExifHeaderMode header_mode)
1240 {
1241 int ret;
1242 2 AVExifMetadata ifd = { 0 };
1243
1244 2 ret = av_exif_parse_buffer(logctx, data->data, data->size, &ifd, header_mode);
1245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1246 goto end;
1247
1248 2 ret = exif_attach_ifd(logctx, frame, &ifd, data);
1249
1250 2 end:
1251 2 av_exif_free(&ifd);
1252 2 return ret;
1253 }
1254
1255 static const int rotation_lut[2][4] = {
1256 {1, 8, 3, 6}, {4, 7, 2, 5},
1257 };
1258
1259 int av_exif_matrix_to_orientation(const int32_t *matrix)
1260 {
1261 double rotation = av_display_rotation_get(matrix);
1262 // determinant
1263 int vflip = ((int64_t)matrix[0] * (int64_t)matrix[4]
1264 - (int64_t)matrix[1] * (int64_t)matrix[3]) < 0;
1265 if (!isfinite(rotation))
1266 return 0;
1267 int rot = (int)(rotation + 0.5);
1268 rot = (((rot % 360) + 360) % 360) / 90;
1269 return rotation_lut[vflip][rot];
1270 }
1271
1272 int av_exif_orientation_to_matrix(int32_t *matrix, int orientation)
1273 {
1274 switch (orientation) {
1275 case 1:
1276 av_display_rotation_set(matrix, 0.0);
1277 break;
1278 case 2:
1279 av_display_rotation_set(matrix, 0.0);
1280 av_display_matrix_flip(matrix, 1, 0);
1281 break;
1282 case 3:
1283 av_display_rotation_set(matrix, 180.0);
1284 break;
1285 case 4:
1286 av_display_rotation_set(matrix, 180.0);
1287 av_display_matrix_flip(matrix, 1, 0);
1288 break;
1289 case 5:
1290 av_display_rotation_set(matrix, 90.0);
1291 av_display_matrix_flip(matrix, 1, 0);
1292 break;
1293 case 6:
1294 av_display_rotation_set(matrix, 90.0);
1295 break;
1296 case 7:
1297 av_display_rotation_set(matrix, -90.0);
1298 av_display_matrix_flip(matrix, 1, 0);
1299 break;
1300 case 8:
1301 av_display_rotation_set(matrix, -90.0);
1302 break;
1303 default:
1304 return AVERROR(EINVAL);
1305 }
1306
1307 return 0;
1308 }
1309
1310 2 int ff_exif_sanitize_ifd(void *logctx, const AVFrame *frame, AVExifMetadata *ifd)
1311 {
1312 2 int ret = 0;
1313 2 AVFrameSideData *sd_orient = NULL;
1314 2 AVExifEntry *or = NULL;
1315 2 AVExifEntry *iw = NULL;
1316 2 AVExifEntry *ih = NULL;
1317 2 AVExifEntry *pw = NULL;
1318 2 AVExifEntry *ph = NULL;
1319 2 uint64_t orientation = 1;
1320 2 uint64_t w = frame->width;
1321 2 uint64_t h = frame->height;
1322 2 int rewrite = 0;
1323
1324 2 sd_orient = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
1325
1326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (sd_orient)
1327 orientation = av_exif_matrix_to_orientation((int32_t *) sd_orient->data);
1328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (orientation != 1)
1329 av_log(logctx, AV_LOG_DEBUG, "matrix contains nontrivial EXIF orientation: %" PRIu64 "\n", orientation);
1330
1331
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 for (size_t i = 0; i < ifd->count; i++) {
1332 5 AVExifEntry *entry = &ifd->entries[i];
1333
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
5 if (entry->id == ORIENTATION_TAG && entry->count > 0 && entry->type == AV_TIFF_SHORT) {
1334 or = entry;
1335 continue;
1336 }
1337
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
5 if (entry->id == IMAGE_WIDTH_TAG && entry->count > 0 && entry->type == AV_TIFF_LONG) {
1338 iw = entry;
1339 continue;
1340 }
1341
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
5 if (entry->id == IMAGE_LENGTH_TAG && entry->count > 0 && entry->type == AV_TIFF_LONG) {
1342 ih = entry;
1343 continue;
1344 }
1345
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
5 if (entry->id == EXIFIFD_TAG && entry->type == AV_TIFF_IFD) {
1346 1 AVExifMetadata *exif = &entry->value.ifd;
1347
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (size_t j = 0; j < exif->count; j++) {
1348 1 AVExifEntry *exifentry = &exif->entries[j];
1349
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) {
1350 pw = exifentry;
1351 continue;
1352 }
1353
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) {
1354 ph = exifentry;
1355 continue;
1356 }
1357 }
1358 }
1359 }
1360
1361
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (or && or->value.uint[0] != orientation) {
1362 rewrite = 1;
1363 or->value.uint[0] = orientation;
1364 }
1365
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (iw && iw->value.uint[0] != w) {
1366 rewrite = 1;
1367 iw->value.uint[0] = w;
1368 }
1369
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (ih && ih->value.uint[0] != h) {
1370 rewrite = 1;
1371 ih->value.uint[0] = h;
1372 }
1373
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (pw && pw->value.uint[0] != w) {
1374 rewrite = 1;
1375 pw->value.uint[0] = w;
1376 }
1377
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (ph && ph->value.uint[0] != h) {
1378 rewrite = 1;
1379 ph->value.uint[0] = h;
1380 }
1381
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!or && orientation != 1) {
1382 rewrite = 1;
1383 ret = av_exif_set_entry(logctx, ifd, ORIENTATION_TAG, AV_TIFF_SHORT, 1, NULL, 0, &orientation);
1384 if (ret < 0)
1385 goto end;
1386 }
1387
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (!iw && w) {
1388 2 rewrite = 1;
1389 2 ret = av_exif_set_entry(logctx, ifd, IMAGE_WIDTH_TAG, AV_TIFF_LONG, 1, NULL, 0, &w);
1390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1391 goto end;
1392 }
1393
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (!ih && h) {
1394 2 rewrite = 1;
1395 2 ret = av_exif_set_entry(logctx, ifd, IMAGE_LENGTH_TAG, AV_TIFF_LONG, 1, NULL, 0, &h);
1396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1397 goto end;
1398 }
1399
3/12
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 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.
2 if (!pw && w && w < 0xFFFFu || !ph && h && h < 0xFFFFu) {
1400 AVExifMetadata *exif;
1401 AVExifEntry *exif_entry;
1402 2 int exif_found = av_exif_get_entry(logctx, ifd, EXIFIFD_TAG, 0, &exif_entry);
1403 2 rewrite = 1;
1404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (exif_found < 0)
1405 goto end;
1406
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (exif_found > 0) {
1407 1 exif = &exif_entry->value.ifd;
1408 } else {
1409 1 AVExifMetadata exif_new = { 0 };
1410 1 ret = av_exif_set_entry(logctx, ifd, EXIFIFD_TAG, AV_TIFF_IFD, 1, NULL, 0, &exif_new);
1411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
1412 av_exif_free(&exif_new);
1413 goto end;
1414 }
1415 1 exif = &ifd->entries[ifd->count - 1].value.ifd;
1416 }
1417
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 if (!pw && w && w < 0xFFFFu) {
1418 2 ret = av_exif_set_entry(logctx, exif, PIXEL_X_TAG, AV_TIFF_SHORT, 1, NULL, 0, &w);
1419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1420 goto end;
1421 }
1422
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 if (!ph && h && h < 0xFFFFu) {
1423 2 ret = av_exif_set_entry(logctx, exif, PIXEL_Y_TAG, AV_TIFF_SHORT, 1, NULL, 0, &h);
1424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1425 goto end;
1426 }
1427 }
1428
1429 2 return rewrite;
1430
1431 end:
1432 return ret;
1433 }
1434
1435 248 int ff_exif_get_buffer(void *logctx, const AVFrame *frame, AVBufferRef **buffer_ptr, enum AVExifHeaderMode header_mode)
1436 {
1437 248 AVFrameSideData *sd_exif = NULL;
1438 248 AVBufferRef *buffer = NULL;
1439 248 AVExifMetadata ifd = { 0 };
1440 248 int ret = 0;
1441 248 int rewrite = 0;
1442
1443
2/4
✓ Branch 0 taken 248 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 248 times.
248 if (!buffer_ptr || *buffer_ptr)
1444 return AVERROR(EINVAL);
1445
1446 248 sd_exif = av_frame_get_side_data(frame, AV_FRAME_DATA_EXIF);
1447
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 2 times.
248 if (!sd_exif)
1448 246 return 0;
1449
1450 2 ret = av_exif_parse_buffer(logctx, sd_exif->data, sd_exif->size, &ifd, AV_EXIF_TIFF_HEADER);
1451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1452 goto end;
1453
1454 2 rewrite = ff_exif_sanitize_ifd(logctx, frame, &ifd);
1455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (rewrite < 0) {
1456 ret = rewrite;
1457 goto end;
1458 }
1459
1460
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (rewrite) {
1461 2 ret = av_exif_write(logctx, &ifd, &buffer, header_mode);
1462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0)
1463 goto end;
1464
1465 2 *buffer_ptr = buffer;
1466 } else {
1467 *buffer_ptr = av_buffer_ref(sd_exif->buf);
1468 if (!*buffer_ptr) {
1469 ret = AVERROR(ENOMEM);
1470 goto end;
1471 }
1472 }
1473
1474 2 av_exif_free(&ifd);
1475 2 return rewrite;
1476
1477 end:
1478 av_exif_free(&ifd);
1479 return ret;
1480 }
1481