mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
avcodec/mjpegdec: Read EXIF metadata in JPEG input.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
ad0f7574ef
commit
bb4e1b4cf9
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user