FFmpeg coverage


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