[FFmpeg-devel] [Read EXIF metadata 3/3] Read EXIF metadata in JPEG input.

Thilo Borgmann thilo.borgmann at mail.de
Mon Aug 12 17:26:05 CEST 2013


3/3 rev 8

-Thilo

-------------- next part --------------
>From 1b6dacf9b2731ec5836703a824de520a9bf12745 Mon Sep 17 00:00:00 2001
From: Thilo Borgmann <thilo.borgmann at googlemail.com>
Date: Mon, 12 Aug 2013 17:17:12 +0200
Subject: [PATCH 3/3] Read EXIF metadata in JPEG input.

---
 Changelog             |  1 +
 libavcodec/Makefile   |  2 +-
 libavcodec/mjpegdec.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/mjpegdec.h |  1 +
 4 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/Changelog b/Changelog
index f1d7fa6..4a6c60c 100644
--- a/Changelog
+++ b/Changelog
@@ -14,6 +14,7 @@ version <next>
 - ffmpeg -t option can now be used for inputs, to limit the duration of
   data read from an input file
 - incomplete Voxware MetaSound decoder
+- read EXIF metadata from JPEG
 
 
 version 2.0:
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 5ba8a1a..e9ba2fa 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -267,7 +267,7 @@ OBJS-$(CONFIG_METASOUND_DECODER)       += metasound.o metasound_data.o \
                                           twinvq.o
 OBJS-$(CONFIG_MICRODVD_DECODER)        += microdvddec.o ass.o
 OBJS-$(CONFIG_MIMIC_DECODER)           += mimic.o
-OBJS-$(CONFIG_MJPEG_DECODER)           += mjpegdec.o mjpeg.o
+OBJS-$(CONFIG_MJPEG_DECODER)           += mjpegdec.o mjpeg.o exif.o tiff_common.o
 OBJS-$(CONFIG_MJPEG_ENCODER)           += mjpegenc.o mjpeg.o
 OBJS-$(CONFIG_MJPEGB_DECODER)          += mjpegbdec.o mjpegdec.o mjpeg.o
 OBJS-$(CONFIG_MLP_DECODER)             += mlpdec.o mlpdsp.o
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index c92738f..bed4675 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -39,6 +39,9 @@
 #include "mjpeg.h"
 #include "mjpegdec.h"
 #include "jpeglsdec.h"
+#include "tiff.h"
+#include "exif.h"
+#include "bytestream.h"
 
 
 static int build_vlc(VLC *vlc, const uint8_t *bits_table,
@@ -1493,6 +1496,44 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
         goto out;
     }
 
+    /* EXIF metadata */
+    if (s->start_code == APP1 && id == AV_RB32("Exif")) {
+        GetByteContext gbytes;
+        int ret, le, ifd_offset, bytes_read;
+        const uint8_t *aligned;
+        unsigned child_ifds[FF_ARRAY_ELEMS(ifd_tags)] = {0,};
+
+        skip_bits(&s->gb, 16); // skip padding
+        len -= 2;
+
+        // init byte wise reading
+        aligned = align_get_bits(&s->gb);
+        bytestream2_init(&gbytes, aligned, len);
+
+        // read TIFF header
+        ret = ff_tdecode_header(&gbytes, &le, &ifd_offset);
+        if (ret) {
+            av_log(s->avctx, AV_LOG_ERROR, "mjpeg: invalid TIFF header in EXIF data\n");
+            return ret;
+        }
+
+        bytestream2_seek(&gbytes, ifd_offset, SEEK_SET);
+
+        // read 0th IFD and store the metadata
+        // (return values > 0 indicate the presence of subimage metadata)
+        ret = ff_exif_decode_ifd(s->avctx, &gbytes, le, child_ifds, &s->exif_metadata);
+        if (ret < 0) {
+            av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error decoding EXIF data\n");
+            return ret;
+        }
+
+        bytes_read = bytestream2_tell(&gbytes);
+        skip_bits(&s->gb, bytes_read << 3);
+        len -= bytes_read;
+
+        goto out;
+    }
+
     /* Apple MJPEG-A */
     if ((s->start_code == APP1) && (len > (0x28 - 8))) {
         id   = get_bits_long(&s->gb, 32);
@@ -1688,6 +1729,8 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     int i, index;
     int ret = 0;
 
+    av_dict_free(&s->exif_metadata);
+
     buf_ptr = buf;
     buf_end = buf + buf_size;
     while (buf_ptr < buf_end) {
@@ -1916,6 +1959,9 @@ the_end:
         }
     }
 
+    av_dict_copy(avpriv_frame_get_metadatap(data), s->exif_metadata, 0);
+    av_dict_free(&s->exif_metadata);
+
     av_log(avctx, AV_LOG_DEBUG, "decode frame unused %td bytes\n",
            buf_end - buf_ptr);
 //  return buf_end - buf_ptr;
@@ -1942,6 +1988,7 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx)
         av_freep(&s->blocks[i]);
         av_freep(&s->last_nnz[i]);
     }
+    av_dict_free(&s->exif_metadata);
     return 0;
 }
 
diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h
index 0cb26f1..fa69d50 100644
--- a/libavcodec/mjpegdec.h
+++ b/libavcodec/mjpegdec.h
@@ -119,6 +119,7 @@ typedef struct MJpegDecodeContext {
     unsigned int ljpeg_buffer_size;
 
     int extern_huff;
+    AVDictionary *exif_metadata;
 } MJpegDecodeContext;
 
 int ff_mjpeg_decode_init(AVCodecContext *avctx);
-- 
1.8.3.2



More information about the ffmpeg-devel mailing list