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

Thilo Borgmann thilo.borgmann at googlemail.com
Sat Aug 10 13:25:23 CEST 2013


>> @@ -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;
>> @@ -459,6 +464,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;
>> @@ -466,6 +475,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;
>>
>
> this looks quite odd, metadata should only be stored in the correct
> frame, not the old frame

Yes a hack. However, my alternative solution does somehow loose
the metadata after _decode_frame() is finished and I don't know why.......
attached as follow-up patch 4/3 of rev 5 (0004-Remove-hack).
So I need another idea or a hint how to fix that alternative.


>> +        // read all IFDs and store the metadata
>> +        ifds_read = 0;
>> +        while ((ifd_offset = ff_exif_decode_ifd(s->avctx, &gbytes, le,
avpriv_frame_get_metadatap(s->picture_ptr))) > 0) {
>> +            if (++ifds_read > FF_ARRAY_ELEMS(ifd_tags)) {
>> +                av_log(s->avctx, AV_LOG_INFO, "mjpeg: found more IFD's in
EXIF data than expected. Skipping.\n");
>> +                break;
>> +            }
>> +            bytestream2_seek(&gbytes, ifd_offset, SEEK_SET);
>> +        }
>
> I would assume that offsets always move forward but that theres no
> real limit om the number of tags

TIFF 6 spec says:
"This file offset may point anywhere in the file, even after the image data."
So it might also point backwards again. Also, according to EXIF specs, there are
exactly these three IFD's defined.

Everything else applied in rev 5.

Thanks!
-Thilo
-------------- next part --------------
>From 0d3e39180b4e08e1f53605b117d2e766419757c7 Mon Sep 17 00:00:00 2001
From: Thilo Borgmann <thilo.borgmann at googlemail.com>
Date: Sat, 10 Aug 2013 13:22:24 +0200
Subject: [PATCH 4/4] Remove hack.

---
 libavcodec/mjpegdec.c |   14 ++++----------
 libavcodec/mjpegdec.h |    1 +
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 1fda985..54a8812 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -218,8 +218,6 @@ 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;
@@ -464,10 +462,6 @@ 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;
@@ -475,9 +469,6 @@ 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;
 
@@ -1529,7 +1520,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
 
         // read all IFDs and store the metadata
         ifds_read = 0;
-        while ((ifd_offset = ff_exif_decode_ifd(s->avctx, &gbytes, le, avpriv_frame_get_metadatap(s->picture_ptr))) > 0) {
+        while ((ifd_offset = ff_exif_decode_ifd(s->avctx, &gbytes, le, &s->exif_metadata)) > 0) {
             if (++ifds_read > FF_ARRAY_ELEMS(ifd_tags)) {
                 av_log(s->avctx, AV_LOG_INFO, "mjpeg: found more IFD's in EXIF data than expected. Skipping.\n");
                 break;
@@ -1967,6 +1958,9 @@ the_end:
         }
     }
 
+    av_dict_copy(avpriv_frame_get_metadatap(s->picture_ptr), 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;
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.7.4.3



More information about the ffmpeg-devel mailing list