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 31static 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 44static int exif_add_metadata(AVCodecContext *avctx, 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 TIFF_DOUBLE : return ff_tadd_doubles_metadata(count, name, sep, gb, le, metadata); 51 case TIFF_SSHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, 1, metadata); 52 case TIFF_SHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, 0, metadata); 53 case TIFF_SBYTE : return ff_tadd_bytes_metadata(count, name, sep, gb, le, 1, metadata); 54 case TIFF_BYTE : 55 case TIFF_UNDEFINED: return ff_tadd_bytes_metadata(count, name, sep, gb, le, 0, metadata); 56 case TIFF_STRING : return ff_tadd_string_metadata(count, name, gb, le, metadata); 57 case TIFF_SRATIONAL: 58 case TIFF_RATIONAL : return ff_tadd_rational_metadata(count, name, sep, gb, le, metadata); 59 case TIFF_SLONG : 60 case TIFF_LONG : return ff_tadd_long_metadata(count, name, sep, gb, le, metadata); 61 default: 62 avpriv_request_sample(avctx, "TIFF tag type (%u)", type); 63 return 0; 64 }; 65} 66 67 68static int exif_decode_tag(AVCodecContext *avctx, GetByteContext *gbytes, int le, 69 int depth, AVDictionary **metadata) 70{ 71 int ret, cur_pos; 72 unsigned id, count; 73 enum TiffTypes type; 74 75 if (depth > 2) { 76 return 0; 77 } 78 79 ff_tread_tag(gbytes, le, &id, &type, &count, &cur_pos); 80 81 if (!bytestream2_tell(gbytes)) { 82 bytestream2_seek(gbytes, cur_pos, SEEK_SET); 83 return 0; 84 } 85 86 // read count values and add it metadata 87 // store metadata or proceed with next IFD 88 ret = ff_tis_ifd(id); 89 if (ret) { 90 ret = avpriv_exif_decode_ifd(avctx, gbytes, le, depth + 1, metadata); 91 } else { 92 const char *name = exif_get_tag_name(id); 93 char *use_name = (char*) name; 94 95 if (!use_name) { 96 use_name = av_malloc(7); 97 if (!use_name) { 98 return AVERROR(ENOMEM); 99 } 100 snprintf(use_name, 7, "0x%04X", id); 101 } 102 103 ret = exif_add_metadata(avctx, count, type, use_name, NULL, 104 gbytes, le, metadata); 105 106 if (!name) { 107 av_freep(&use_name); 108 } 109 } 110 111 bytestream2_seek(gbytes, cur_pos, SEEK_SET); 112 113 return ret; 114} 115 116 117int avpriv_exif_decode_ifd(AVCodecContext *avctx, GetByteContext *gbytes, int le, 118 int depth, AVDictionary **metadata) 119{ 120 int i, ret; 121 int entries; 122 123 entries = ff_tget_short(gbytes, le); 124 125 if (bytestream2_get_bytes_left(gbytes) < entries * 12) { 126 return AVERROR_INVALIDDATA; 127 } 128 129 for (i = 0; i < entries; i++) { 130 if ((ret = exif_decode_tag(avctx, gbytes, le, depth, metadata)) < 0) { 131 return ret; 132 } 133 } 134 135 // return next IDF offset or 0x000000000 or a value < 0 for failure 136 return ff_tget_long(gbytes, le); 137} 138