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 
30 
31 static const char *exif_get_tag_name(uint16_t id)
32 {
33  int i;
34 
35  for (i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
36  if (tag_list[i].id == id)
37  return tag_list[i].name;
38  }
39 
40  return NULL;
41 }
42 
43 
44 static int exif_add_metadata(void *logctx, int count, int type,
45  const char *name, const char *sep,
46  GetByteContext *gb, int le,
47  AVDictionary **metadata)
48 {
49  switch(type) {
50  case 0:
51  av_log(logctx, AV_LOG_WARNING,
52  "Invalid TIFF tag type 0 found for %s with size %d\n",
53  name, count);
54  return 0;
55  case TIFF_DOUBLE : return ff_tadd_doubles_metadata(count, name, sep, gb, le, metadata);
56  case TIFF_SSHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, 1, metadata);
57  case TIFF_SHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, 0, metadata);
58  case TIFF_SBYTE : return ff_tadd_bytes_metadata(count, name, sep, gb, le, 1, metadata);
59  case TIFF_BYTE :
60  case TIFF_UNDEFINED: return ff_tadd_bytes_metadata(count, name, sep, gb, le, 0, metadata);
61  case TIFF_STRING : return ff_tadd_string_metadata(count, name, gb, le, metadata);
62  case TIFF_SRATIONAL:
63  case TIFF_RATIONAL : return ff_tadd_rational_metadata(count, name, sep, gb, le, metadata);
64  case TIFF_SLONG :
65  case TIFF_LONG : return ff_tadd_long_metadata(count, name, sep, gb, le, metadata);
66  default:
67  avpriv_request_sample(logctx, "TIFF tag type (%u)", type);
68  return 0;
69  };
70 }
71 
72 
73 static int exif_decode_tag(void *logctx, GetByteContext *gbytes, int le,
74  int depth, AVDictionary **metadata)
75 {
76  int ret, cur_pos;
77  unsigned id, count;
78  enum TiffTypes type;
79 
80  if (depth > 2) {
81  return 0;
82  }
83 
84  ff_tread_tag(gbytes, le, &id, &type, &count, &cur_pos);
85 
86  if (!bytestream2_tell(gbytes)) {
87  bytestream2_seek(gbytes, cur_pos, SEEK_SET);
88  return 0;
89  }
90 
91  // read count values and add it metadata
92  // store metadata or proceed with next IFD
93  ret = ff_tis_ifd(id);
94  if (ret) {
95  ret = ff_exif_decode_ifd(logctx, gbytes, le, depth + 1, metadata);
96  } else {
97  const char *name = exif_get_tag_name(id);
98  char buf[7];
99 
100  if (!name) {
101  name = buf;
102  snprintf(buf, sizeof(buf), "0x%04X", id);
103  }
104 
105  ret = exif_add_metadata(logctx, count, type, name, NULL,
106  gbytes, le, metadata);
107  }
108 
109  bytestream2_seek(gbytes, cur_pos, SEEK_SET);
110 
111  return ret;
112 }
113 
114 
115 int ff_exif_decode_ifd(void *logctx, GetByteContext *gbytes,
116  int le, int depth, AVDictionary **metadata)
117 {
118  int i, ret;
119  int entries;
120 
121  entries = ff_tget_short(gbytes, le);
122 
123  if (bytestream2_get_bytes_left(gbytes) < entries * 12) {
124  return AVERROR_INVALIDDATA;
125  }
126 
127  for (i = 0; i < entries; i++) {
128  if ((ret = exif_decode_tag(logctx, gbytes, le, depth, metadata)) < 0) {
129  return ret;
130  }
131  }
132 
133  // return next IDF offset or 0x000000000 or a value < 0 for failure
134  return ff_tget_long(gbytes, le);
135 }
136 
137 int avpriv_exif_decode_ifd(void *logctx, const uint8_t *buf, int size,
138  int le, int depth, AVDictionary **metadata)
139 {
140  GetByteContext gb;
141 
142  bytestream2_init(&gb, buf, size);
143 
144  return ff_exif_decode_ifd(logctx, &gb, le, depth, metadata);
145 }
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:242
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:31
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
AVDictionary
Definition: dict.c:30
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:137
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:83
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:117
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:115
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:73
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:179
exif_tag::name
char name[EXIF_TAG_NAME_LENGTH]
Definition: exif.h:39
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_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:287
id
enum AVCodecID id
Definition: extract_extradata_bsf.c:325
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
int i
Definition: input.c:406
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
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:44
TIFF_SSHORT
@ TIFF_SSHORT
Definition: tiff_common.h:44
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:37
tag_list
static const struct exif_tag tag_list[]
Definition: exif.h:43
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:148
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:211
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
snprintf
#define snprintf
Definition: snprintf.h:34