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 *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 }
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:241
TiffTypes
TiffTypes
data type identifiers for TIFF tags
Definition: tiff_common.h:37
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
exif_get_tag_name
static const char * exif_get_tag_name(uint16_t id)
Definition: exif.c:31
GetByteContext
Definition: bytestream.h:33
count
void INT64 INT64 count
Definition: avisynth_c.h:767
bytestream2_seek
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:208
name
const char * name
Definition: avisynth_c.h:867
TIFF_LONG
@ TIFF_LONG
Definition: tiff_common.h:41
TIFF_SLONG
@ TIFF_SLONG
Definition: tiff_common.h:46
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:144
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:82
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
bytestream2_get_bytes_left
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
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:116
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:43
TIFF_SHORT
@ TIFF_SHORT
Definition: tiff_common.h:40
ff_exif_decode_ifd
int ff_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le, int depth, AVDictionary **metadata)
Definition: exif.c:122
buf
void * buf
Definition: avisynth_c.h:766
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:39
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:178
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:43
NULL
#define NULL
Definition: coverity.c:32
TIFF_BYTE
@ TIFF_BYTE
Definition: tiff_common.h:38
TIFF_SRATIONAL
@ TIFF_SRATIONAL
Definition: tiff_common.h:47
bytestream2_tell
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:188
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:286
id
enum AVCodecID id
Definition: extract_extradata_bsf.c:329
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:31
TIFF_DOUBLE
@ TIFF_DOUBLE
Definition: tiff_common.h:49
size
int size
Definition: twinvq_data.h:11134
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
ff_tget_long
unsigned ff_tget_long(GetByteContext *gb, int le)
Reads a long from the bytestream using given endianness.
Definition: tiff_common.c:49
uint8_t
uint8_t
Definition: audio_convert.c:194
exif.h
TIFF_UNDEFINED
@ TIFF_UNDEFINED
Definition: tiff_common.h:44
ret
ret
Definition: filter_design.txt:187
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen_template.c:38
TIFF_RATIONAL
@ TIFF_RATIONAL
Definition: tiff_common.h:42
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:45
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:39
tag_list
static const struct exif_tag tag_list[]
Definition: exif.h:43
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
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:147
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
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:210
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:59
snprintf
#define snprintf
Definition: snprintf.h:34