FFmpeg
exif.c
Go to the documentation of this file.
1 /*
2  * EXIF metadata parser
3  * Copyright (c) 2013 Thilo Borgmann <thilo.borgmann _at_ mail.de>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * EXIF metadata parser
25  * @author Thilo Borgmann <thilo.borgmann _at_ mail.de>
26  */
27 
28 #include "exif.h"
29 #include "tiff_common.h"
30 
31 #define EXIF_TAG_NAME_LENGTH 32
32 
33 struct exif_tag {
35  uint16_t id;
36 };
37 
38 static const struct exif_tag tag_list[] = { // JEITA CP-3451 EXIF specification:
39  {"GPSVersionID", 0x00}, // <- Table 12 GPS Attribute Information
40  {"GPSLatitudeRef", 0x01},
41  {"GPSLatitude", 0x02},
42  {"GPSLongitudeRef", 0x03},
43  {"GPSLongitude", 0x04},
44  {"GPSAltitudeRef", 0x05},
45  {"GPSAltitude", 0x06},
46  {"GPSTimeStamp", 0x07},
47  {"GPSSatellites", 0x08},
48  {"GPSStatus", 0x09},
49  {"GPSMeasureMode", 0x0A},
50  {"GPSDOP", 0x0B},
51  {"GPSSpeedRef", 0x0C},
52  {"GPSSpeed", 0x0D},
53  {"GPSTrackRef", 0x0E},
54  {"GPSTrack", 0x0F},
55  {"GPSImgDirectionRef", 0x10},
56  {"GPSImgDirection", 0x11},
57  {"GPSMapDatum", 0x12},
58  {"GPSDestLatitudeRef", 0x13},
59  {"GPSDestLatitude", 0x14},
60  {"GPSDestLongitudeRef", 0x15},
61  {"GPSDestLongitude", 0x16},
62  {"GPSDestBearingRef", 0x17},
63  {"GPSDestBearing", 0x18},
64  {"GPSDestDistanceRef", 0x19},
65  {"GPSDestDistance", 0x1A},
66  {"GPSProcessingMethod", 0x1B},
67  {"GPSAreaInformation", 0x1C},
68  {"GPSDateStamp", 0x1D},
69  {"GPSDifferential", 0x1E},
70  {"ImageWidth", 0x100}, // <- Table 3 TIFF Rev. 6.0 Attribute Information Used in Exif
71  {"ImageLength", 0x101},
72  {"BitsPerSample", 0x102},
73  {"Compression", 0x103},
74  {"PhotometricInterpretation", 0x106},
75  {"Orientation", 0x112},
76  {"SamplesPerPixel", 0x115},
77  {"PlanarConfiguration", 0x11C},
78  {"YCbCrSubSampling", 0x212},
79  {"YCbCrPositioning", 0x213},
80  {"XResolution", 0x11A},
81  {"YResolution", 0x11B},
82  {"ResolutionUnit", 0x128},
83  {"StripOffsets", 0x111},
84  {"RowsPerStrip", 0x116},
85  {"StripByteCounts", 0x117},
86  {"JPEGInterchangeFormat", 0x201},
87  {"JPEGInterchangeFormatLength",0x202},
88  {"TransferFunction", 0x12D},
89  {"WhitePoint", 0x13E},
90  {"PrimaryChromaticities", 0x13F},
91  {"YCbCrCoefficients", 0x211},
92  {"ReferenceBlackWhite", 0x214},
93  {"DateTime", 0x132},
94  {"ImageDescription", 0x10E},
95  {"Make", 0x10F},
96  {"Model", 0x110},
97  {"Software", 0x131},
98  {"Artist", 0x13B},
99  {"Copyright", 0x8298},
100  {"ExifVersion", 0x9000}, // <- Table 4 Exif IFD Attribute Information (1)
101  {"FlashpixVersion", 0xA000},
102  {"ColorSpace", 0xA001},
103  {"ComponentsConfiguration", 0x9101},
104  {"CompressedBitsPerPixel", 0x9102},
105  {"PixelXDimension", 0xA002},
106  {"PixelYDimension", 0xA003},
107  {"MakerNote", 0x927C},
108  {"UserComment", 0x9286},
109  {"RelatedSoundFile", 0xA004},
110  {"DateTimeOriginal", 0x9003},
111  {"DateTimeDigitized", 0x9004},
112  {"SubSecTime", 0x9290},
113  {"SubSecTimeOriginal", 0x9291},
114  {"SubSecTimeDigitized", 0x9292},
115  {"ImageUniqueID", 0xA420},
116  {"ExposureTime", 0x829A}, // <- Table 5 Exif IFD Attribute Information (2)
117  {"FNumber", 0x829D},
118  {"ExposureProgram", 0x8822},
119  {"SpectralSensitivity", 0x8824},
120  {"ISOSpeedRatings", 0x8827},
121  {"OECF", 0x8828},
122  {"ShutterSpeedValue", 0x9201},
123  {"ApertureValue", 0x9202},
124  {"BrightnessValue", 0x9203},
125  {"ExposureBiasValue", 0x9204},
126  {"MaxApertureValue", 0x9205},
127  {"SubjectDistance", 0x9206},
128  {"MeteringMode", 0x9207},
129  {"LightSource", 0x9208},
130  {"Flash", 0x9209},
131  {"FocalLength", 0x920A},
132  {"SubjectArea", 0x9214},
133  {"FlashEnergy", 0xA20B},
134  {"SpatialFrequencyResponse", 0xA20C},
135  {"FocalPlaneXResolution", 0xA20E},
136  {"FocalPlaneYResolution", 0xA20F},
137  {"FocalPlaneResolutionUnit", 0xA210},
138  {"SubjectLocation", 0xA214},
139  {"ExposureIndex", 0xA215},
140  {"SensingMethod", 0xA217},
141  {"FileSource", 0xA300},
142  {"SceneType", 0xA301},
143  {"CFAPattern", 0xA302},
144  {"CustomRendered", 0xA401},
145  {"ExposureMode", 0xA402},
146  {"WhiteBalance", 0xA403},
147  {"DigitalZoomRatio", 0xA404},
148  {"FocalLengthIn35mmFilm", 0xA405},
149  {"SceneCaptureType", 0xA406},
150  {"GainControl", 0xA407},
151  {"Contrast", 0xA408},
152  {"Saturation", 0xA409},
153  {"Sharpness", 0xA40A},
154  {"DeviceSettingDescription", 0xA40B},
155  {"SubjectDistanceRange", 0xA40C}
156 // {"InteroperabilityIndex", 0x1}, // <- Table 13 Interoperability IFD Attribute Information
157 };
158 
159 static const char *exif_get_tag_name(uint16_t id)
160 {
161  int i;
162 
163  for (i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
164  if (tag_list[i].id == id)
165  return tag_list[i].name;
166  }
167 
168  return NULL;
169 }
170 
171 
172 static int exif_add_metadata(void *logctx, int count, int type,
173  const char *name, const char *sep,
174  GetByteContext *gb, int le,
175  AVDictionary **metadata)
176 {
177  switch(type) {
178  case 0:
179  av_log(logctx, AV_LOG_WARNING,
180  "Invalid TIFF tag type 0 found for %s with size %d\n",
181  name, count);
182  return 0;
183  case TIFF_DOUBLE : return ff_tadd_doubles_metadata(count, name, sep, gb, le, metadata);
184  case TIFF_SSHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, 1, metadata);
185  case TIFF_SHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, 0, metadata);
186  case TIFF_SBYTE : return ff_tadd_bytes_metadata(count, name, sep, gb, le, 1, metadata);
187  case TIFF_BYTE :
188  case TIFF_UNDEFINED: return ff_tadd_bytes_metadata(count, name, sep, gb, le, 0, metadata);
189  case TIFF_STRING : return ff_tadd_string_metadata(count, name, gb, le, metadata);
190  case TIFF_SRATIONAL:
191  case TIFF_RATIONAL : return ff_tadd_rational_metadata(count, name, sep, gb, le, metadata);
192  case TIFF_SLONG :
193  case TIFF_LONG : return ff_tadd_long_metadata(count, name, sep, gb, le, metadata);
194  default:
195  avpriv_request_sample(logctx, "TIFF tag type (%u)", type);
196  return 0;
197  };
198 }
199 
200 
201 static int exif_decode_tag(void *logctx, GetByteContext *gbytes, int le,
202  int depth, AVDictionary **metadata)
203 {
204  int ret, cur_pos;
205  unsigned id, count;
206  enum TiffTypes type;
207 
208  if (depth > 2) {
209  return 0;
210  }
211 
212  ff_tread_tag(gbytes, le, &id, &type, &count, &cur_pos);
213 
214  if (!bytestream2_tell(gbytes)) {
215  bytestream2_seek(gbytes, cur_pos, SEEK_SET);
216  return 0;
217  }
218 
219  // read count values and add it metadata
220  // store metadata or proceed with next IFD
221  ret = ff_tis_ifd(id);
222  if (ret) {
223  ret = ff_exif_decode_ifd(logctx, gbytes, le, depth + 1, metadata);
224  } else {
225  const char *name = exif_get_tag_name(id);
226  char buf[7];
227 
228  if (!name) {
229  name = buf;
230  snprintf(buf, sizeof(buf), "0x%04X", id);
231  }
232 
233  ret = exif_add_metadata(logctx, count, type, name, NULL,
234  gbytes, le, metadata);
235  }
236 
237  bytestream2_seek(gbytes, cur_pos, SEEK_SET);
238 
239  return ret;
240 }
241 
242 
243 int ff_exif_decode_ifd(void *logctx, GetByteContext *gbytes,
244  int le, int depth, AVDictionary **metadata)
245 {
246  int i, ret;
247  int entries;
248 
249  entries = ff_tget_short(gbytes, le);
250 
251  if (bytestream2_get_bytes_left(gbytes) < entries * 12) {
252  return AVERROR_INVALIDDATA;
253  }
254 
255  for (i = 0; i < entries; i++) {
256  if ((ret = exif_decode_tag(logctx, gbytes, le, depth, metadata)) < 0) {
257  return ret;
258  }
259  }
260 
261  // return next IDF offset or 0x000000000 or a value < 0 for failure
262  return ff_tget_long(gbytes, le);
263 }
264 
265 int avpriv_exif_decode_ifd(void *logctx, const uint8_t *buf, int size,
266  int le, int depth, AVDictionary **metadata)
267 {
268  GetByteContext gb;
269 
270  bytestream2_init(&gb, buf, size);
271 
272  return ff_exif_decode_ifd(logctx, &gb, le, depth, metadata);
273 }
ff_tadd_string_metadata
int ff_tadd_string_metadata(int count, const char *name, GetByteContext *gb, int le, AVDictionary **metadata)
Adds a string of count characters into the metadata dictionary.
Definition: tiff_common.c:208
TiffTypes
TiffTypes
data type identifiers for TIFF tags
Definition: tiff_common.h:36
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
exif_get_tag_name
static const char * exif_get_tag_name(uint16_t id)
Definition: exif.c:159
GetByteContext
Definition: bytestream.h:33
bytestream2_seek
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:212
TIFF_LONG
@ TIFF_LONG
Definition: tiff_common.h:40
TIFF_SLONG
@ TIFF_SLONG
Definition: tiff_common.h:45
exif_tag::id
uint16_t id
Definition: exif.c:35
AVDictionary
Definition: dict.c:34
avpriv_exif_decode_ifd
int avpriv_exif_decode_ifd(void *logctx, const uint8_t *buf, int size, int le, int depth, AVDictionary **metadata)
Recursively decodes all IFD's and adds included TAGS into the metadata dictionary.
Definition: exif.c:265
ff_tadd_rational_metadata
int ff_tadd_rational_metadata(int count, const char *name, const char *sep, GetByteContext *gb, int le, AVDictionary **metadata)
Adds count rationals converted to a string into the metadata dictionary.
Definition: tiff_common.c:99
ff_tadd_long_metadata
int ff_tadd_long_metadata(int count, const char *name, const char *sep, GetByteContext *gb, int le, AVDictionary **metadata)
Adds count longs converted to a string into the metadata dictionary.
Definition: tiff_common.c:123
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
TIFF_SBYTE
@ TIFF_SBYTE
Definition: tiff_common.h:42
TIFF_SHORT
@ TIFF_SHORT
Definition: tiff_common.h:39
ff_exif_decode_ifd
int ff_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le, int depth, AVDictionary **metadata)
Definition: exif.c:243
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
exif_decode_tag
static int exif_decode_tag(void *logctx, GetByteContext *gbytes, int le, int depth, AVDictionary **metadata)
Definition: exif.c:201
TIFF_STRING
@ TIFF_STRING
Definition: tiff_common.h:38
ff_tadd_shorts_metadata
int ff_tadd_shorts_metadata(int count, const char *name, const char *sep, GetByteContext *gb, int le, int is_signed, AVDictionary **metadata)
Adds count shorts converted to a string into the metadata dictionary.
Definition: tiff_common.c:165
exif_tag::name
char name[EXIF_TAG_NAME_LENGTH]
Definition: exif.c:34
ff_tget_short
unsigned ff_tget_short(GetByteContext *gb, int le)
Reads a short from the bytestream using given endianness.
Definition: tiff_common.c:44
NULL
#define NULL
Definition: coverity.c:32
tiff_common.h
TIFF_BYTE
@ TIFF_BYTE
Definition: tiff_common.h:37
TIFF_SRATIONAL
@ TIFF_SRATIONAL
Definition: tiff_common.h:46
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:192
ff_tread_tag
int ff_tread_tag(GetByteContext *gb, int le, unsigned *tag, unsigned *type, unsigned *count, int *next)
Reads the first 3 fields of a TIFF tag, which are the tag id, the tag type and the count of values fo...
Definition: tiff_common.c:253
ff_tis_ifd
int ff_tis_ifd(unsigned tag)
Returns a value > 0 if the tag is a known IFD-tag.
Definition: tiff_common.c:32
TIFF_DOUBLE
@ TIFF_DOUBLE
Definition: tiff_common.h:48
size
int size
Definition: twinvq_data.h:10344
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
ff_tget_long
unsigned ff_tget_long(GetByteContext *gb, int le)
Reads a long from the bytestream using given endianness.
Definition: tiff_common.c:50
exif.h
TIFF_UNDEFINED
@ TIFF_UNDEFINED
Definition: tiff_common.h:43
ret
ret
Definition: filter_design.txt:187
exif_tag
Definition: exif.c:33
id
enum AVCodecID id
Definition: dts2pts.c:364
EXIF_TAG_NAME_LENGTH
#define EXIF_TAG_NAME_LENGTH
Definition: exif.c:31
TIFF_RATIONAL
@ TIFF_RATIONAL
Definition: tiff_common.h:41
exif_add_metadata
static int exif_add_metadata(void *logctx, int count, int type, const char *name, const char *sep, GetByteContext *gb, int le, AVDictionary **metadata)
Definition: exif.c:172
TIFF_SSHORT
@ TIFF_SSHORT
Definition: tiff_common.h:44
tag_list
static const struct exif_tag tag_list[]
Definition: exif.c:38
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:36
ff_tadd_doubles_metadata
int ff_tadd_doubles_metadata(int count, const char *name, const char *sep, GetByteContext *gb, int le, AVDictionary **metadata)
Adds count doubles converted to a string into the metadata dictionary.
Definition: tiff_common.c:144
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
ff_tadd_bytes_metadata
int ff_tadd_bytes_metadata(int count, const char *name, const char *sep, GetByteContext *gb, int le, int is_signed, AVDictionary **metadata)
Adds count bytes converted to a string into the metadata dictionary.
Definition: tiff_common.c:187
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
snprintf
#define snprintf
Definition: snprintf.h:34