[FFmpeg-devel] [Read EXIF metadata 2/3] Add EXIF metadata parser to libavcodec.

Michael Niedermayer michaelni at gmx.at
Mon Aug 12 15:59:52 CEST 2013


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

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Many that live deserve death. And some that die deserve life. Can you give
it to them? Then do not be too eager to deal out death in judgement. For
even the very wise cannot see all ends. -- Gandalf
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130812/4c1acc9f/attachment.asc>


More information about the ffmpeg-devel mailing list