diff mbox series

[FFmpeg-devel,v3,5/6] avcodec/decode: parse ICC profiles

Message ID 20220719122608.43974-6-ffmpeg@haasn.xyz
State New
Headers show
Series ICC profile support in avcodec | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Niklas Haas July 19, 2022, 12:26 p.m. UTC
From: Niklas Haas <git@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@haasn.dev>
---
 libavcodec/decode.c | 61 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 56 insertions(+), 5 deletions(-)
diff mbox series

Patch

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.