[FFmpeg-devel] [PATCH v4 6/7] avcodec/encode:: generate ICC profiles

Niklas Haas ffmpeg at haasn.xyz
Thu Jul 28 17:50:01 EEST 2022


From: Niklas Haas <git at haasn.dev>

Only if requested, and only if the codec signals support for ICC
profiles. Implementation roughly matches the functionality of the
existing vf_iccgen filter, albeit with some reduced flexibility and no
caching.

Ideally, we'd also only do this on the first frame (e.g. mjpeg, apng),
but there's no meaningful way for us to distinguish between this case
and e.g. somebody using the image2 muxer, in which case we'd want to
attach ICC profiles to every frame in the stream.

Closes: #9672

Signed-off-by: Niklas Haas <git at haasn.dev>
---
 libavcodec/encode.c | 53 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 310fe20777..7cf13bf6d6 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -308,6 +308,53 @@ static int encode_receive_packet_internal(AVCodecContext *avctx, AVPacket *avpkt
     return ret;
 }
 
+#if CONFIG_LCMS2
+static int encode_generate_icc_profile(AVCodecContext *avctx, AVFrame *frame)
+{
+    enum AVColorTransferCharacteristic trc = frame->color_trc;
+    enum AVColorPrimaries prim = frame->color_primaries;
+    const FFCodec *const codec = ffcodec(avctx->codec);
+    AVCodecInternal *avci = avctx->internal;
+    cmsHPROFILE profile;
+    int ret;
+
+    /* don't generate ICC profiles if disabled or unsupported */
+    if (!(avctx->flags2 & AV_CODEC_FLAG2_ICC_PROFILES))
+        return 0;
+    if (!(codec->caps_internal & FF_CODEC_CAP_ICC_PROFILES))
+        return 0;
+
+    if (trc == AVCOL_TRC_UNSPECIFIED)
+        trc = avctx->color_trc;
+    if (prim == AVCOL_PRI_UNSPECIFIED)
+        prim = avctx->color_primaries;
+    if (trc == AVCOL_TRC_UNSPECIFIED || prim == AVCOL_PRI_UNSPECIFIED)
+        return 0; /* can't generate ICC profile with missing csp tags */
+
+    if (av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE))
+        return 0; /* don't overwrite existing ICC profile */
+
+    if (!avci->icc.avctx) {
+        ret = ff_icc_context_init(&avci->icc, avctx);
+        if (ret < 0)
+            return ret;
+    }
+
+    ret = ff_icc_profile_generate(&avci->icc, prim, trc, &profile);
+    if (ret < 0)
+        return ret;
+
+    ret = ff_icc_profile_attach(&avci->icc, profile, frame);
+    cmsCloseProfile(profile);
+    return ret;
+}
+#else /* !CONFIG_LCMS2 */
+static int encode_generate_icc_profile(av_unused AVCodecContext *c, av_unused AVFrame *f)
+{
+    return 0;
+}
+#endif
+
 static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src)
 {
     AVCodecInternal *avci = avctx->internal;
@@ -360,6 +407,12 @@ FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
+    if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) {
+        ret = encode_generate_icc_profile(avctx, dst);
+        if (ret < 0)
+            return ret;
+    }
+
     return 0;
 }
 
-- 
2.37.1



More information about the ffmpeg-devel mailing list