[FFmpeg-devel] [PATCH v3 5/6] avcodec/decode: parse ICC profiles
Niklas Haas
ffmpeg at haasn.xyz
Tue Jul 19 15:26:07 EEST 2022
From: Niklas Haas <git at haasn.dev>
Implementation for the decode side of the ICC profile API, roughly
matching the behavior of the existing vf_iccdetect filter.
Closes: #9673
Signed-off-by: Niklas Haas <git at haasn.dev>
---
libavcodec/decode.c | 61 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 56 insertions(+), 5 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index cc4fe3b1d5..9f37d36f78 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -49,10 +49,6 @@
#include "internal.h"
#include "thread.h"
-#if CONFIG_LCMS2
-# include "fflcms2.h"
-#endif
-
static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt)
{
int ret;
@@ -508,6 +504,54 @@ FF_ENABLE_DEPRECATION_WARNINGS
return ret < 0 ? ret : 0;
}
+#if CONFIG_LCMS2
+static int detect_colorspace(AVCodecContext *avctx, AVFrame *frame)
+{
+ AVCodecInternal *avci = avctx->internal;
+ enum AVColorTransferCharacteristic trc;
+ AVColorPrimariesDesc coeffs;
+ enum AVColorPrimaries prim;
+ cmsHPROFILE profile;
+ AVFrameSideData *sd;
+ int ret;
+ if (!avctx->flags2 & AV_CODEC_FLAG2_ICC_PROFILES)
+ return 0;
+
+ sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE);
+ if (!sd || !sd->size)
+ return 0;
+
+ if (!avci->icc.avctx) {
+ ret = ff_icc_context_init(&avci->icc, avctx);
+ if (ret < 0)
+ return ret;
+ }
+
+ profile = cmsOpenProfileFromMemTHR(avci->icc.ctx, sd->data, sd->size);
+ if (!profile)
+ return AVERROR_INVALIDDATA;
+
+ ret = ff_icc_profile_read_primaries(&avci->icc, profile, &coeffs);
+ if (!ret)
+ ret = ff_icc_profile_detect_transfer(&avci->icc, profile, &trc);
+ cmsCloseProfile(profile);
+ if (ret < 0)
+ return ret;
+
+ prim = av_csp_primaries_id_from_desc(&coeffs);
+ if (prim != AVCOL_PRI_UNSPECIFIED)
+ frame->color_primaries = prim;
+ if (trc != AVCOL_TRC_UNSPECIFIED)
+ frame->color_trc = trc;
+ return 0;
+}
+#else /* !CONFIG_LCMS2 */
+static int detect_colorspace(av_unused AVCodecContext *c, av_unused AVFrame *f)
+{
+ return 0;
+}
+#endif
+
static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{
int ret;
@@ -528,7 +572,7 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
{
AVCodecInternal *avci = avctx->internal;
const FFCodec *const codec = ffcodec(avctx->codec);
- int ret;
+ int ret, ok;
av_assert0(!frame->buf[0]);
@@ -542,6 +586,13 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
if (ret == AVERROR_EOF)
avci->draining_done = 1;
+ /* preserve ret */
+ ok = detect_colorspace(avctx, frame);
+ if (ok < 0) {
+ av_frame_unref(frame);
+ return ok;
+ }
+
if (!(codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS) &&
IS_EMPTY(avci->last_pkt_props)) {
// May fail if the FIFO is empty.
--
2.37.1
More information about the ffmpeg-devel
mailing list