GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/exif.c Lines: 35 52 67.3 %
Date: 2021-04-20 04:37:23 Branches: 19 28 67.9 %

Line Branch Exec Source
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
232
static const char *exif_get_tag_name(uint16_t id)
32
{
33
    int i;
34
35
17894
    for (i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
36
17862
        if (tag_list[i].id == id)
37
200
            return tag_list[i].name;
38
    }
39
40
32
    return NULL;
41
}
42
43
44
232
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


232
    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
74
    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
36
    case TIFF_BYTE     :
60
36
    case TIFF_UNDEFINED: return ff_tadd_bytes_metadata(count, name, sep, gb, le, 0, metadata);
61
46
    case TIFF_STRING   : return ff_tadd_string_metadata(count, name, gb, le, metadata);
62
56
    case TIFF_SRATIONAL:
63
56
    case TIFF_RATIONAL : return ff_tadd_rational_metadata(count, name, sep, gb, le, metadata);
64
20
    case TIFF_SLONG    :
65
20
    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
248
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
248
    if (depth > 2) {
81
        return 0;
82
    }
83
84
248
    ff_tread_tag(gbytes, le, &id, &type, &count, &cur_pos);
85
86
248
    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
248
    ret = ff_tis_ifd(id);
94
248
    if (ret) {
95
16
        ret = ff_exif_decode_ifd(logctx, gbytes, le, depth + 1, metadata);
96
    } else {
97
232
        const char *name = exif_get_tag_name(id);
98
        char buf[7];
99
100
232
        if (!name) {
101
32
            name = buf;
102
32
            snprintf(buf, sizeof(buf), "0x%04X", id);
103
        }
104
105
232
        ret = exif_add_metadata(logctx, count, type, name, NULL,
106
                                gbytes, le, metadata);
107
    }
108
109
248
    bytestream2_seek(gbytes, cur_pos, SEEK_SET);
110
111
248
    return ret;
112
}
113
114
115
36
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
36
    entries = ff_tget_short(gbytes, le);
122
123
36
    if (bytestream2_get_bytes_left(gbytes) < entries * 12) {
124
        return AVERROR_INVALIDDATA;
125
    }
126
127
284
    for (i = 0; i < entries; i++) {
128
248
        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
36
    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
}