mirror of https://git.ffmpeg.org/ffmpeg.git
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>
This commit is contained in:
parent
c688ddc067
commit
77f8dcb265
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue