GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/exif.c Lines: 39 57 68.4 %
Date: 2019-11-18 18:00:01 Branches: 22 32 68.8 %

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
300
static const char *exif_get_tag_name(uint16_t id)
32
{
33
    int i;
34
35
22600
    for (i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
36
22576
        if (tag_list[i].id == id)
37
276
            return tag_list[i].name;
38
    }
39
40
24
    return NULL;
41
}
42
43
44
300
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


300
    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
108
    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
46
    case TIFF_BYTE     :
60
46
    case TIFF_UNDEFINED: return ff_tadd_bytes_metadata(count, name, sep, gb, le, 0, metadata);
61
52
    case TIFF_STRING   : return ff_tadd_string_metadata(count, name, gb, le, metadata);
62
82
    case TIFF_SRATIONAL:
63
82
    case TIFF_RATIONAL : return ff_tadd_rational_metadata(count, name, sep, gb, le, metadata);
64
12
    case TIFF_SLONG    :
65
12
    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
316
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
316
    if (depth > 2) {
81
        return 0;
82
    }
83
84
316
    ff_tread_tag(gbytes, le, &id, &type, &count, &cur_pos);
85
86
316
    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
316
    ret = ff_tis_ifd(id);
94
316
    if (ret) {
95
16
        ret = ff_exif_decode_ifd(logctx, gbytes, le, depth + 1, metadata);
96
    } else {
97
300
        const char *name = exif_get_tag_name(id);
98
300
        char *use_name   = (char*) name;
99
100
300
        if (!use_name) {
101
24
            use_name = av_malloc(7);
102
24
            if (!use_name) {
103
                return AVERROR(ENOMEM);
104
            }
105
24
            snprintf(use_name, 7, "0x%04X", id);
106
        }
107
108
300
        ret = exif_add_metadata(logctx, count, type, use_name, NULL,
109
                                gbytes, le, metadata);
110
111
300
        if (!name) {
112
24
            av_freep(&use_name);
113
        }
114
    }
115
116
316
    bytestream2_seek(gbytes, cur_pos, SEEK_SET);
117
118
316
    return ret;
119
}
120
121
122
30
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
30
    entries = ff_tget_short(gbytes, le);
129
130
30
    if (bytestream2_get_bytes_left(gbytes) < entries * 12) {
131
        return AVERROR_INVALIDDATA;
132
    }
133
134
346
    for (i = 0; i < entries; i++) {
135
316
        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
30
    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
}