aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeo Izen <leo.izen@gmail.com>2025-03-12 09:54:09 -0400
committerLeo Izen <leo.izen@gmail.com>2025-08-19 11:26:47 -0400
commit52dba25661305e3c4a6209d46aea43cd327c960e (patch)
tree3fc3bb637cb87f243f57dce3c1588a5ba89a043f
parentbfb17d26306592c85cf0c4e909099c621177b062 (diff)
downloadffmpeg-52dba25661305e3c4a6209d46aea43cd327c960e.tar.gz
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>
-rw-r--r--libavcodec/mjpegdec.c89
-rw-r--r--libavcodec/mjpegdec.h3
-rw-r--r--tests/ref/fate/exif-image-embedded3
-rw-r--r--tests/ref/fate/exif-image-jpg3
4 files changed, 22 insertions, 76 deletions
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 983a30cb59..46ec3eb938 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -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);
diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h
index 13c524d597..8b9ed67856 100644
--- a/libavcodec/mjpegdec.h
+++ b/libavcodec/mjpegdec.h
@@ -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)
diff --git a/tests/ref/fate/exif-image-embedded b/tests/ref/fate/exif-image-embedded
index 574a3af848..a6617bd89f 100644
--- a/tests/ref/fate/exif-image-embedded
+++ b/tests/ref/fate/exif-image-embedded
@@ -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
diff --git a/tests/ref/fate/exif-image-jpg b/tests/ref/fate/exif-image-jpg
index 5a8cd10063..5135ae32f8 100644
--- a/tests/ref/fate/exif-image-jpg
+++ b/tests/ref/fate/exif-image-jpg
@@ -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]