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