Skip to content

Commit 77f8dcb

Browse files
committed
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 <[email protected]>
1 parent c688ddc commit 77f8dcb

File tree

1 file changed

+56
-5
lines changed

1 file changed

+56
-5
lines changed

libavcodec/decode.c

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@
4949
#include "internal.h"
5050
#include "thread.h"
5151

52-
#if CONFIG_LCMS2
53-
# include "fflcms2.h"
54-
#endif
55-
5652
static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt)
5753
{
5854
int ret;
@@ -508,6 +504,54 @@ FF_ENABLE_DEPRECATION_WARNINGS
508504
return ret < 0 ? ret : 0;
509505
}
510506

507+
#if CONFIG_LCMS2
508+
static int detect_colorspace(AVCodecContext *avctx, AVFrame *frame)
509+
{
510+
AVCodecInternal *avci = avctx->internal;
511+
enum AVColorTransferCharacteristic trc;
512+
AVColorPrimariesDesc coeffs;
513+
enum AVColorPrimaries prim;
514+
cmsHPROFILE profile;
515+
AVFrameSideData *sd;
516+
int ret;
517+
if (!(avctx->flags2 & AV_CODEC_FLAG2_ICC_PROFILES))
518+
return 0;
519+
520+
sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE);
521+
if (!sd || !sd->size)
522+
return 0;
523+
524+
if (!avci->icc.avctx) {
525+
ret = ff_icc_context_init(&avci->icc, avctx);
526+
if (ret < 0)
527+
return ret;
528+
}
529+
530+
profile = cmsOpenProfileFromMemTHR(avci->icc.ctx, sd->data, sd->size);
531+
if (!profile)
532+
return AVERROR_INVALIDDATA;
533+
534+
ret = ff_icc_profile_read_primaries(&avci->icc, profile, &coeffs);
535+
if (!ret)
536+
ret = ff_icc_profile_detect_transfer(&avci->icc, profile, &trc);
537+
cmsCloseProfile(profile);
538+
if (ret < 0)
539+
return ret;
540+
541+
prim = av_csp_primaries_id_from_desc(&coeffs);
542+
if (prim != AVCOL_PRI_UNSPECIFIED)
543+
frame->color_primaries = prim;
544+
if (trc != AVCOL_TRC_UNSPECIFIED)
545+
frame->color_trc = trc;
546+
return 0;
547+
}
548+
#else /* !CONFIG_LCMS2 */
549+
static int detect_colorspace(av_unused AVCodecContext *c, av_unused AVFrame *f)
550+
{
551+
return 0;
552+
}
553+
#endif
554+
511555
static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame)
512556
{
513557
int ret;
@@ -528,7 +572,7 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
528572
{
529573
AVCodecInternal *avci = avctx->internal;
530574
const FFCodec *const codec = ffcodec(avctx->codec);
531-
int ret;
575+
int ret, ok;
532576

533577
av_assert0(!frame->buf[0]);
534578

@@ -542,6 +586,13 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
542586
if (ret == AVERROR_EOF)
543587
avci->draining_done = 1;
544588

589+
/* preserve ret */
590+
ok = detect_colorspace(avctx, frame);
591+
if (ok < 0) {
592+
av_frame_unref(frame);
593+
return ok;
594+
}
595+
545596
if (!(codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS) &&
546597
IS_EMPTY(avci->last_pkt_props)) {
547598
// May fail if the FIFO is empty.

0 commit comments

Comments
 (0)