FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 *use_name = (char*) name;
99 
100  if (!use_name) {
101  use_name = av_malloc(7);
102  if (!use_name) {
103  return AVERROR(ENOMEM);
104  }
105  snprintf(use_name, 7, "0x%04X", id);
106  }
107 
108  ret = exif_add_metadata(logctx, count, type, use_name, NULL,
109  gbytes, le, metadata);
110 
111  if (!name) {
112  av_freep(&use_name);
113  }
114  }
115 
116  bytestream2_seek(gbytes, cur_pos, SEEK_SET);
117 
118  return ret;
119 }
120 
121 
122 int ff_exif_decode_ifd(void *logctx, GetByteContext *gbytes,
123  int le, int depth, AVDictionary **metadata)
124 {
125  int i, ret;
126  int entries;
127 
128  entries = ff_tget_short(gbytes, le);
129 
130  if (bytestream2_get_bytes_left(gbytes) < entries * 12) {
131  return AVERROR_INVALIDDATA;
132  }
133 
134  for (i = 0; i < entries; i++) {
135  if ((ret = exif_decode_tag(logctx, gbytes, le, depth, metadata)) < 0) {
136  return ret;
137  }
138  }
139 
140  // return next IDF offset or 0x000000000 or a value < 0 for failure
141  return ff_tget_long(gbytes, le);
142 }
143 
144 int avpriv_exif_decode_ifd(void *logctx, const uint8_t *buf, int size,
145  int le, int depth, AVDictionary **metadata)
146 {
147  GetByteContext gb;
148 
149  bytestream2_init(&gb, buf, size);
150 
151  return ff_exif_decode_ifd(logctx, &gb, le, depth, metadata);
152 }
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int ff_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le, int depth, AVDictionary **metadata)
Definition: exif.c:122
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static const struct exif_tag tag_list[]
Definition: exif.h:43
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:147
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
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:82
EXIF metadata parser.
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
void void avpriv_request_sample(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
uint8_t
#define av_malloc(s)
ptrdiff_t size
Definition: opengl_enc.c:101
#define av_log(a,...)
#define AVERROR(e)
Definition: error.h:43
static const char * exif_get_tag_name(uint16_t id)
Definition: exif.c:31
unsigned ff_tget_short(GetByteContext *gb, int le)
Reads a short from the bytestream using given endianness.
Definition: tiff_common.c:43
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
GLsizei count
Definition: opengl_enc.c:109
static int exif_decode_tag(void *logctx, GetByteContext *gbytes, int le, int depth, AVDictionary **metadata)
Definition: exif.c:73
unsigned ff_tget_long(GetByteContext *gb, int le)
Reads a long from the bytestream using given endianness.
Definition: tiff_common.c:49
TiffTypes
data type identifiers for TIFF tags
Definition: tiff_common.h:37
#define FF_ARRAY_ELEMS(a)
int ff_tis_ifd(unsigned tag)
Returns a value > 0 if the tag is a known IFD-tag.
Definition: tiff_common.c:31
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:188
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:144
void * buf
Definition: avisynth_c.h:690
GLint GLenum type
Definition: opengl_enc.c:105
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:116
#define snprintf
Definition: snprintf.h:34
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:178
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:210
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:241
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:208
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:286
#define av_freep(p)
char name[EXIF_TAG_NAME_LENGTH]
Definition: exif.h:39
enum AVCodecID id
const char * name
Definition: opengl_enc.c:103