summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.dev>2022-06-28 15:15:40 +0200
committerNiklas Haas <git@haasn.dev>2022-07-30 11:42:06 +0200
commit77f8dcb26582b00c53caf35f05eedef2523a2578 (patch)
tree78a9f6a3a15c5b4a688cd9febe3791472fa3b603
parentc688ddc067e0d9ade731b3adb5c6fde259cbc5f6 (diff)
avcodec/decode: parse ICC profiles
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@haasn.dev>
-rw-r--r--libavcodec/decode.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 8922222271..92958745df 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.