mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-06-16 04:32:47 +02:00
avcodec/mjpegdec: use new EXIF parse API
Switch over to the new API to parse EXIF metadata. Signed-off-by: Leo Izen <leo.izen@gmail.com>
This commit is contained in:
+14
-75
@@ -55,7 +55,6 @@
|
||||
#include "put_bits.h"
|
||||
#include "exif_internal.h"
|
||||
#include "bytestream.h"
|
||||
#include "tiff_common.h"
|
||||
|
||||
|
||||
static int init_default_huffman_tables(MJpegDecodeContext *s)
|
||||
@@ -2043,8 +2042,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
|
||||
|
||||
/* EXIF metadata */
|
||||
if (s->start_code == APP1 && id == AV_RB32("Exif") && len >= 2) {
|
||||
GetByteContext gbytes;
|
||||
int ret, le, ifd_offset, bytes_read;
|
||||
int ret;
|
||||
const uint8_t *aligned;
|
||||
|
||||
skip_bits(&s->gb, 16); // skip padding
|
||||
@@ -2052,26 +2050,15 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
|
||||
|
||||
// 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");
|
||||
} else {
|
||||
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");
|
||||
}
|
||||
ret = av_exif_parse_buffer(s->avctx, aligned, len, &s->exif_metadata, AV_EXIF_TIFF_HEADER);
|
||||
if (ret < 0) {
|
||||
av_log(s->avctx, AV_LOG_WARNING, "unable to parse EXIF buffer\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
bytes_read = bytestream2_tell(&gbytes);
|
||||
skip_bits(&s->gb, bytes_read << 3);
|
||||
len -= bytes_read;
|
||||
skip_bits(&s->gb, ret << 3);
|
||||
len -= ret;
|
||||
|
||||
goto out;
|
||||
}
|
||||
@@ -2384,13 +2371,12 @@ int ff_mjpeg_decode_frame_from_buf(AVCodecContext *avctx, AVFrame *frame,
|
||||
int index;
|
||||
int ret = 0;
|
||||
int is16bit;
|
||||
AVDictionaryEntry *e = NULL;
|
||||
|
||||
s->force_pal8 = 0;
|
||||
|
||||
s->buf_size = buf_size;
|
||||
|
||||
av_dict_free(&s->exif_metadata);
|
||||
av_exif_free(&s->exif_metadata);
|
||||
av_freep(&s->stereo3d);
|
||||
s->adobe_transform = -1;
|
||||
|
||||
@@ -2868,60 +2854,13 @@ the_end:
|
||||
}
|
||||
}
|
||||
|
||||
if (e = av_dict_get(s->exif_metadata, "Orientation", e, AV_DICT_IGNORE_SUFFIX)) {
|
||||
char *value = e->value + strspn(e->value, " \n\t\r"), *endptr;
|
||||
int orientation = strtol(value, &endptr, 0);
|
||||
|
||||
if (!*endptr) {
|
||||
AVFrameSideData *sd = NULL;
|
||||
|
||||
if (orientation >= 2 && orientation <= 8) {
|
||||
int32_t *matrix;
|
||||
|
||||
sd = av_frame_new_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9);
|
||||
if (!sd) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Could not allocate frame side data\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
matrix = (int32_t *)sd->data;
|
||||
|
||||
switch (orientation) {
|
||||
case 2:
|
||||
av_display_rotation_set(matrix, 0.0);
|
||||
av_display_matrix_flip(matrix, 1, 0);
|
||||
break;
|
||||
case 3:
|
||||
av_display_rotation_set(matrix, 180.0);
|
||||
break;
|
||||
case 4:
|
||||
av_display_rotation_set(matrix, 180.0);
|
||||
av_display_matrix_flip(matrix, 1, 0);
|
||||
break;
|
||||
case 5:
|
||||
av_display_rotation_set(matrix, 90.0);
|
||||
av_display_matrix_flip(matrix, 1, 0);
|
||||
break;
|
||||
case 6:
|
||||
av_display_rotation_set(matrix, 90.0);
|
||||
break;
|
||||
case 7:
|
||||
av_display_rotation_set(matrix, -90.0);
|
||||
av_display_matrix_flip(matrix, 1, 0);
|
||||
break;
|
||||
case 8:
|
||||
av_display_rotation_set(matrix, -90.0);
|
||||
break;
|
||||
default:
|
||||
av_assert0(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->exif_metadata.entries) {
|
||||
ret = ff_exif_attach_ifd(avctx, frame, &s->exif_metadata);
|
||||
av_exif_free(&s->exif_metadata);
|
||||
if (ret < 0)
|
||||
av_log(avctx, AV_LOG_WARNING, "couldn't attach EXIF metadata\n");
|
||||
}
|
||||
|
||||
av_dict_copy(&frame->metadata, s->exif_metadata, 0);
|
||||
av_dict_free(&s->exif_metadata);
|
||||
|
||||
if (avctx->codec_id != AV_CODEC_ID_SMVJPEG &&
|
||||
(avctx->codec_tag == MKTAG('A', 'V', 'R', 'n') ||
|
||||
avctx->codec_tag == MKTAG('A', 'V', 'D', 'J')) &&
|
||||
@@ -2973,7 +2912,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);
|
||||
av_exif_free(&s->exif_metadata);
|
||||
|
||||
reset_icc_profile(s);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "blockdsp.h"
|
||||
#include "exif.h"
|
||||
#include "get_bits.h"
|
||||
#include "hpeldsp.h"
|
||||
#include "idctdsp.h"
|
||||
@@ -138,7 +139,7 @@ typedef struct MJpegDecodeContext {
|
||||
unsigned int ljpeg_buffer_size;
|
||||
|
||||
int extern_huff;
|
||||
AVDictionary *exif_metadata;
|
||||
AVExifMetadata exif_metadata;
|
||||
|
||||
AVStereo3D *stereo3d; ///!< stereoscopic information (cached, since it is read before frame allocation)
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ color_transfer=unknown
|
||||
chroma_location=center
|
||||
TAG:ExifIFD/UserComment=AppleMark
|
||||
|
||||
[SIDE_DATA]
|
||||
side_data_type=EXIF metadata
|
||||
[/SIDE_DATA]
|
||||
[/FRAME]
|
||||
[FRAME]
|
||||
media_type=audio
|
||||
|
||||
@@ -197,4 +197,7 @@ TAG:ExifIFD/ExposureMode= 0
|
||||
TAG:ExifIFD/WhiteBalance= 0
|
||||
TAG:ExifIFD/DigitalZoomRatio= 4000:4000
|
||||
TAG:ExifIFD/SceneCaptureType= 0
|
||||
[SIDE_DATA]
|
||||
side_data_type=EXIF metadata
|
||||
[/SIDE_DATA]
|
||||
[/FRAME]
|
||||
|
||||
Reference in New Issue
Block a user