[FFmpeg-devel] [Read EXIF metadata 2/3] Add EXIF metadata parser to libavcodec.
Thilo Borgmann
thilo.borgmann at mail.de
Mon Aug 12 17:26:17 CEST 2013
Am 12.08.13 15:59, schrieb Michael Niedermayer:
> On Sun, Aug 11, 2013 at 07:08:33PM +0200, Thilo Borgmann wrote:
>> 2/3 rev 7
>>
>> -Thilo
>
>> exif.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++
>> exif.h | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 291 insertions(+)
>> f7ca776c9b4669bc0c75304712c3a0a684b98c1c 0002-Add-EXIF-metadata-parser-to-libavcodec.patch
>> From 343806eb8e49c8ea3ca8044a04a1e221e8eef4fa Mon Sep 17 00:00:00 2001
>> From: Thilo Borgmann <thilo.borgmann at googlemail.com>
>> Date: Sun, 11 Aug 2013 18:18:35 +0200
>> Subject: [PATCH 2/3] Add EXIF metadata parser to libavcodec.
>>
>> ---
>> libavcodec/exif.c | 123 ++++++++++++++++++++++++++++++++++++++
>> libavcodec/exif.h | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 291 insertions(+), 0 deletions(-)
>> create mode 100644 libavcodec/exif.c
>> create mode 100644 libavcodec/exif.h
>>
>> diff --git a/libavcodec/exif.c b/libavcodec/exif.c
>> new file mode 100644
>> index 0000000..f577f3c
>> --- /dev/null
>> +++ b/libavcodec/exif.c
>> @@ -0,0 +1,123 @@
>> +/*
>> + * EXIF metadata parser
>> + * Copyright (c) 2013 Thilo Borgmann <thilo.borgmann _at_ googlemail.com>
>> + *
>> + * This file is part of FFmpeg.
>> + *
>> + * FFmpeg is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2.1 of the License, or (at your option) any later version.
>> + *
>> + * FFmpeg is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with FFmpeg; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>> + */
>> +
>> +/**
>> + * @file
>> + * EXIF metadata parser
>> + * @author Thilo Borgmann <thilo.borgmann _at_ googlemail.com>
>> + */
>> +
>> +#include "exif.h"
>> +
>> +
>> +static const char *exif_get_tag_name(uint16_t id)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
>> + if (tag_list[i].id == id)
>> + return tag_list[i].name;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> +
>> +static int exif_add_metadata(AVCodecContext *avctx, int count, int type,
>> + const char *name, const char *sep,
>> + GetByteContext *gb, int le,
>> + AVDictionary **metadata)
>> +{
>> + switch(type) {
>> + case TIFF_DOUBLE : return ff_tadd_doubles_metadata(count, name, sep, gb, le, metadata);
>> + case TIFF_SHORT : return ff_tadd_shorts_metadata(count, name, sep, gb, le, metadata);
>> + case TIFF_BYTE :
>> + case TIFF_UNDEFINED:
>> + case TIFF_STRING : return ff_tadd_string_metadata(count, name, gb, le, metadata);
>> + case TIFF_SRATIONAL:
>> + case TIFF_RATIONAL : return ff_tadd_rational_metadata(count, name, sep, gb, le, metadata);
>> + case TIFF_SLONG :
>> + case TIFF_LONG : return ff_tadd_long_metadata(count, name, sep, gb, le, metadata);
>> + default:
>> + avpriv_request_sample(avctx, "TIFF tag type (%u)", type);
>> + return 0;
>> + };
>> +}
>> +
>> +
>
>
>> +static int exif_decode_tag(AVCodecContext *avctx, GetByteContext *gbytes, int le, AVDictionary **metadata)
>> +{
>> + int ret, cur_pos;
>> + unsigned id, count;
>> + enum TiffTypes type;
>> +
>> + ff_tread_tag(gbytes, le, &id, &type, &count, &cur_pos);
>> +
>> + // read count values and add it metadata
>> + // store metadata or proceed with next IFD
>> + if (ff_tis_ifd(id)) {
>> + ret = ff_exif_decode_ifd(avctx, gbytes, le, metadata);
>> + } else {
>> + const char *name = exif_get_tag_name(id);
>> + char *use_name = (char*) name;
>> +
>> + if (!use_name) {
>> + use_name = av_malloc(7);
>> + if (!use_name) {
>> + return AVERROR(ENOMEM);
>> + }
>> + snprintf(use_name, 7, "0x%04X", id);
>> + }
>> +
>> + ret = exif_add_metadata(avctx, count, type, use_name, NULL,
>> + gbytes, le, metadata);
>> +
>> + if (!name) {
>> + av_freep(&use_name);
>> + }
>> + }
>> +
>> + bytestream2_seek(gbytes, cur_pos, SEEK_SET);
>> +
>> + return ret;
>> +}
>> +
>> +
>> +int ff_exif_decode_ifd(AVCodecContext *avctx, GetByteContext *gbytes, int le, AVDictionary **metadata)
>> +{
>> + int i, ret;
>> + int entries;
>> +
>> + entries = ff_tget_short(gbytes, le);
>> +
>> + if (bytestream2_get_bytes_left(gbytes) < entries * 12) {
>> + return AVERROR_INVALIDDATA;
>> + }
>> +
>> + for (i = 0; i < entries; i++) {
>> + if ((ret = exif_decode_tag(avctx, gbytes, le, metadata)) < 0) {
>> + return ret;
>> + }
>> + }
>> +
>> + // return next IDF offset or 0x000000000 or a value < 0 for failure
>> + return ff_tget_long(gbytes, le);
>> +}
>
> this recursive calling of the 2 functions can be used to cause a
> stack overflow
> also iam not sure how what is implemented aligns to the spec.
> From a quick glance the tiff spec seems describing a flat system
> without recursion, but i might be missing something
See tables 14 and 15 in Exif spec...
-> 0th IFD can contain "Exif Tag" (0x8298) and "GPS Tag" (0x8825)
-> Exif IFD can contain "Interoperability Tag" (0xA005)
In rev 8 it tracks all IFD-tags and reads each of them once at most.
-Thilo
More information about the ffmpeg-devel
mailing list