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

Thilo Borgmann thilo.borgmann at googlemail.com
Tue Jul 30 20:35:07 CEST 2013


---
 libavcodec/mjpegdec.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 0e5ae74..f22aaeb 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,
@@ -215,6 +218,8 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
     int len, nb_components, i, width, height, pix_fmt_id;
     int h_count[MAX_COMPONENTS];
     int v_count[MAX_COMPONENTS];
+    AVDictionary **metadata = avpriv_frame_get_metadatap(s->picture_ptr);
+    AVDictionary *tmp;

     s->cur_scan = 0;
     s->upscale_h = s->upscale_v = 0;
@@ -449,6 +454,10 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
             s->avctx->pix_fmt = AV_PIX_FMT_GRAY16;
     }

+    // keep metadata alive by hiding AVDictioniary behind *tmp
+    tmp       = *metadata;
+    *metadata = NULL;
+
     av_frame_unref(s->picture_ptr);
     if (ff_get_buffer(s->avctx, s->picture_ptr, AV_GET_BUFFER_FLAG_REF) < 0)
         return -1;
@@ -456,6 +465,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
     s->picture_ptr->key_frame = 1;
     s->got_picture            = 1;

+    // restore metadata in current buffer
+    *avpriv_frame_get_metadatap(s->picture_ptr) = tmp;
+
     for (i = 0; i < 3; i++)
         s->linesize[i] = s->picture_ptr->linesize[i] << s->interlaced;

@@ -1477,6 +1489,37 @@ 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;
+
+        skip_bits(&s->gb, 16); // skip padding
+
+        // init byte wise reading
+        bytestream2_init(&gbytes, align_get_bits(&s->gb), get_bits_left(&s->gb)
>> 3);
+
+        // read TIFF header
+        ret = tiff_decode_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 all IFDs and store the metadata
+        while ((ifd_offset = exif_decode_ifd(s->avctx, &gbytes, le,
avpriv_frame_get_metadatap(s->picture_ptr))) > 0) {
+            bytestream2_seek(&gbytes, ifd_offset, SEEK_SET);
+        }
+
+        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);
-- 1.7.4.3



More information about the ffmpeg-devel mailing list