[FFmpeg-devel] [Read EXIF metadata 3/3] Read EXIF metadata in JPEG input.
Michael Niedermayer
michaelni at gmx.at
Sat Aug 10 00:34:16 CEST 2013
On Fri, Aug 09, 2013 at 10:59:56PM +0200, Thilo Borgmann wrote:
> 3/3 rev 4
>
> -Thilo
> Changelog | 1 +
> libavcodec/Makefile | 2 +-
> libavcodec/mjpegdec.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 51 insertions(+), 1 deletion(-)
> 2ff375e133c2fe09791c4f4571f85073b9d44ab1 0003-Read-EXIF-metadata-in-JPEG-input.patch
> From 0c01936b5ff2e4926356b200484c5592f9fdc9fe Mon Sep 17 00:00:00 2001
> From: Thilo Borgmann <thilo.borgmann at googlemail.com>
> Date: Fri, 9 Aug 2013 22:52:16 +0200
> Subject: [PATCH 3/3] Read EXIF metadata in JPEG input.
>
> ---
> Changelog | 1 +
> libavcodec/Makefile | 2 +-
> libavcodec/mjpegdec.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 51 insertions(+), 1 deletions(-)
>
> 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 487153c..6c800e0 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -265,7 +265,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..195b0c6 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;
> @@ -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
> @@ -1493,6 +1505,43 @@ 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, ifds_read;
> +
> + skip_bits(&s->gb, 16); // skip padding
> + len -= 2;
> +
> + // init byte wise reading
> + bytestream2_init(&gbytes, align_get_bits(&s->gb), get_bits_left(&s->gb) >> 3);
nothing gurantees that align_get_bits() and get_bits_left() will be
executed in that order
> +
> + // 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 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
> +
> + 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
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
You can kill me, but you cannot change the truth.
-------------- 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/20130810/f01473c2/attachment.asc>
More information about the ffmpeg-devel
mailing list