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:
Leo Izen
2025-03-12 09:54:09 -04:00
parent bfb17d2630
commit 52dba25661
4 changed files with 22 additions and 76 deletions
+14 -75
View File
@@ -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);
+2 -1
View File
@@ -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)
+3
View File
@@ -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
+3
View File
@@ -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]