avcodec/decode: use ff_frame_new_side_data() to export Exif side data

Otherwise, the user requested priority of packet side data will be ignored.

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer
2025-08-21 20:03:03 -03:00
parent 75bd5056a4
commit fa1938c574
4 changed files with 19 additions and 29 deletions

View File

@@ -2268,12 +2268,10 @@ static int attach_displaymatrix(AVCodecContext *avctx, AVFrame *frame, int orien
return ret; return ret;
} }
static int exif_attach_ifd(AVCodecContext *avctx, AVFrame *frame, const AVExifMetadata *ifd, AVBufferRef *og) static int exif_attach_ifd(AVCodecContext *avctx, AVFrame *frame, const AVExifMetadata *ifd, AVBufferRef **pbuf)
{ {
const AVExifEntry *orient = NULL; const AVExifEntry *orient = NULL;
AVFrameSideData *sd;
AVExifMetadata *cloned = NULL; AVExifMetadata *cloned = NULL;
AVBufferRef *written = NULL;
int ret; int ret;
for (size_t i = 0; i < ifd->count; i++) { for (size_t i = 0; i < ifd->count; i++) {
@@ -2305,25 +2303,21 @@ static int exif_attach_ifd(AVCodecContext *avctx, AVFrame *frame, const AVExifMe
if (ret < 0) if (ret < 0)
goto end; goto end;
if (cloned || !og) { if (cloned || !*pbuf) {
ret = av_exif_write(avctx, ifd, &written, AV_EXIF_TIFF_HEADER); av_buffer_unref(pbuf);
ret = av_exif_write(avctx, ifd, pbuf, AV_EXIF_TIFF_HEADER);
if (ret < 0) if (ret < 0)
goto end; goto end;
} }
sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_EXIF, written ? written : og); ret = ff_frame_new_side_data_from_buf(avctx, frame, AV_FRAME_DATA_EXIF, pbuf);
if (!sd) { if (ret < 0)
if (written)
av_buffer_unref(&written);
ret = AVERROR(ENOMEM);
goto end; goto end;
}
ret = 0; ret = 0;
end: end:
if (og && written && ret >= 0) av_buffer_unref(pbuf);
av_buffer_unref(&og); // as though we called new_side_data on og;
av_exif_free(cloned); av_exif_free(cloned);
av_free(cloned); av_free(cloned);
return ret; return ret;
@@ -2331,22 +2325,25 @@ end:
int ff_decode_exif_attach_ifd(AVCodecContext *avctx, AVFrame *frame, const AVExifMetadata *ifd) int ff_decode_exif_attach_ifd(AVCodecContext *avctx, AVFrame *frame, const AVExifMetadata *ifd)
{ {
return exif_attach_ifd(avctx, frame, ifd, NULL); AVBufferRef *dummy = NULL;
return exif_attach_ifd(avctx, frame, ifd, &dummy);
} }
int ff_decode_exif_attach_buffer(AVCodecContext *avctx, AVFrame *frame, AVBufferRef *data, int ff_decode_exif_attach_buffer(AVCodecContext *avctx, AVFrame *frame, AVBufferRef **pbuf,
enum AVExifHeaderMode header_mode) enum AVExifHeaderMode header_mode)
{ {
int ret; int ret;
AVBufferRef *data = *pbuf;
AVExifMetadata ifd = { 0 }; AVExifMetadata ifd = { 0 };
ret = av_exif_parse_buffer(avctx, data->data, data->size, &ifd, header_mode); ret = av_exif_parse_buffer(avctx, data->data, data->size, &ifd, header_mode);
if (ret < 0) if (ret < 0)
goto end; goto end;
ret = exif_attach_ifd(avctx, frame, &ifd, data); ret = exif_attach_ifd(avctx, frame, &ifd, pbuf);
end: end:
av_buffer_unref(pbuf);
av_exif_free(&ifd); av_exif_free(&ifd);
return ret; return ret;
} }

View File

@@ -230,11 +230,10 @@ enum AVExifHeaderMode;
* attaches that information as an AV_FRAME_DATA_DISPLAYMATRIX instead * attaches that information as an AV_FRAME_DATA_DISPLAYMATRIX instead
* of including it in the AV_FRAME_DATA_EXIF side data buffer. * of including it in the AV_FRAME_DATA_EXIF side data buffer.
* *
* On a success, the caller loses ownership of the data buffer. Either it is * *buf is ALWAYS consumed by this function and NULL written in its place, even
* unrefed, or its ownership is transferred to the frame directly. On failure, * on failure.
* the data buffer is left owned by the caller.
*/ */
int ff_decode_exif_attach_buffer(AVCodecContext *avctx, AVFrame *frame, AVBufferRef *data, int ff_decode_exif_attach_buffer(AVCodecContext *avctx, AVFrame *frame, AVBufferRef **buf,
enum AVExifHeaderMode header_mode); enum AVExifHeaderMode header_mode);
struct AVExifMetadata; struct AVExifMetadata;

View File

@@ -1753,15 +1753,12 @@ exit_loop:
if (s->exif_data) { if (s->exif_data) {
// we swap because ff_decode_exif_attach_buffer adds to p->metadata // we swap because ff_decode_exif_attach_buffer adds to p->metadata
FFSWAP(AVDictionary *, p->metadata, s->frame_metadata); FFSWAP(AVDictionary *, p->metadata, s->frame_metadata);
ret = ff_decode_exif_attach_buffer(avctx, p, s->exif_data, AV_EXIF_TIFF_HEADER); ret = ff_decode_exif_attach_buffer(avctx, p, &s->exif_data, AV_EXIF_TIFF_HEADER);
FFSWAP(AVDictionary *, p->metadata, s->frame_metadata); FFSWAP(AVDictionary *, p->metadata, s->frame_metadata);
if (ret < 0) { if (ret < 0) {
av_log(avctx, AV_LOG_WARNING, "unable to attach EXIF buffer\n"); av_log(avctx, AV_LOG_WARNING, "unable to attach EXIF buffer\n");
return ret; return ret;
} }
// ff_decode_exif_attach_buffer takes ownership so
// we do not want to call av_buffer_unref here
s->exif_data = NULL;
} }
if (s->color_type == PNG_COLOR_TYPE_PALETTE && avctx->codec_id == AV_CODEC_ID_APNG) { if (s->color_type == PNG_COLOR_TYPE_PALETTE && avctx->codec_id == AV_CODEC_ID_APNG) {

View File

@@ -1479,12 +1479,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
s->has_exif = 1; s->has_exif = 1;
memcpy(exif_buf->data, gb.buffer, chunk_size); memcpy(exif_buf->data, gb.buffer, chunk_size);
/* if this succeeds then exif_buf is either freed or transferred to the AVFrame */ ret = ff_decode_exif_attach_buffer(avctx, p, &exif_buf, AV_EXIF_TIFF_HEADER);
ret = ff_decode_exif_attach_buffer(avctx, p, exif_buf, AV_EXIF_TIFF_HEADER); if (ret < 0)
if (ret < 0) {
av_log(avctx, AV_LOG_WARNING, "unable to attach EXIF buffer\n"); av_log(avctx, AV_LOG_WARNING, "unable to attach EXIF buffer\n");
av_buffer_unref(&exif_buf);
}
exif_end: exif_end:
bytestream2_skip(&gb, chunk_size); bytestream2_skip(&gb, chunk_size);