Skip to content

Commit 8377ef4

Browse files
committed
avcodec/encode:: generate ICC profiles
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 <[email protected]>
1 parent 77f8dcb commit 8377ef4

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

libavcodec/encode.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,53 @@ static int encode_receive_packet_internal(AVCodecContext *avctx, AVPacket *avpkt
308308
return ret;
309309
}
310310

311+
#if CONFIG_LCMS2
312+
static int encode_generate_icc_profile(AVCodecContext *avctx, AVFrame *frame)
313+
{
314+
enum AVColorTransferCharacteristic trc = frame->color_trc;
315+
enum AVColorPrimaries prim = frame->color_primaries;
316+
const FFCodec *const codec = ffcodec(avctx->codec);
317+
AVCodecInternal *avci = avctx->internal;
318+
cmsHPROFILE profile;
319+
int ret;
320+
321+
/* don't generate ICC profiles if disabled or unsupported */
322+
if (!(avctx->flags2 & AV_CODEC_FLAG2_ICC_PROFILES))
323+
return 0;
324+
if (!(codec->caps_internal & FF_CODEC_CAP_ICC_PROFILES))
325+
return 0;
326+
327+
if (trc == AVCOL_TRC_UNSPECIFIED)
328+
trc = avctx->color_trc;
329+
if (prim == AVCOL_PRI_UNSPECIFIED)
330+
prim = avctx->color_primaries;
331+
if (trc == AVCOL_TRC_UNSPECIFIED || prim == AVCOL_PRI_UNSPECIFIED)
332+
return 0; /* can't generate ICC profile with missing csp tags */
333+
334+
if (av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE))
335+
return 0; /* don't overwrite existing ICC profile */
336+
337+
if (!avci->icc.avctx) {
338+
ret = ff_icc_context_init(&avci->icc, avctx);
339+
if (ret < 0)
340+
return ret;
341+
}
342+
343+
ret = ff_icc_profile_generate(&avci->icc, prim, trc, &profile);
344+
if (ret < 0)
345+
return ret;
346+
347+
ret = ff_icc_profile_attach(&avci->icc, profile, frame);
348+
cmsCloseProfile(profile);
349+
return ret;
350+
}
351+
#else /* !CONFIG_LCMS2 */
352+
static int encode_generate_icc_profile(av_unused AVCodecContext *c, av_unused AVFrame *f)
353+
{
354+
return 0;
355+
}
356+
#endif
357+
311358
static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src)
312359
{
313360
AVCodecInternal *avci = avctx->internal;
@@ -360,6 +407,12 @@ FF_DISABLE_DEPRECATION_WARNINGS
360407
FF_ENABLE_DEPRECATION_WARNINGS
361408
#endif
362409

410+
if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) {
411+
ret = encode_generate_icc_profile(avctx, dst);
412+
if (ret < 0)
413+
return ret;
414+
}
415+
363416
return 0;
364417
}
365418

0 commit comments

Comments
 (0)