diff options
author | Thilo Borgmann <thilo.borgmann@googlemail.com> | 2013-08-12 19:36:08 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-08-13 00:30:34 +0200 |
commit | bb4e1b4cf910af0de2bc884c75544603c40010cc (patch) | |
tree | f9b0a43dade39cee5d7cba468083df737d387120 /libavcodec | |
parent | ad0f7574effe25afaa32684291adfe6943d67836 (diff) | |
download | ffmpeg-bb4e1b4cf910af0de2bc884c75544603c40010cc.tar.gz |
avcodec/mjpegdec: Read EXIF metadata in JPEG input.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/Makefile | 2 | ||||
-rw-r--r-- | libavcodec/mjpegdec.c | 46 | ||||
-rw-r--r-- | libavcodec/mjpegdec.h | 1 |
3 files changed, 48 insertions, 1 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5ba8a1ab9e..e9ba2fa239 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 c92738f727..76a4a31caf 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,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; + const uint8_t *aligned; + + 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, 0, &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 +1728,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 +1958,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 +1987,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 0cb26f1c81..fa69d50389 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); |