You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-10 06:10:52 +02:00
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:
@@ -49,10 +49,6 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
|
||||||
#if CONFIG_LCMS2
|
|
||||||
# include "fflcms2.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt)
|
static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -508,6 +504,54 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
|||||||
return ret < 0 ? ret : 0;
|
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)
|
static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -528,7 +572,7 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
|
|||||||
{
|
{
|
||||||
AVCodecInternal *avci = avctx->internal;
|
AVCodecInternal *avci = avctx->internal;
|
||||||
const FFCodec *const codec = ffcodec(avctx->codec);
|
const FFCodec *const codec = ffcodec(avctx->codec);
|
||||||
int ret;
|
int ret, ok;
|
||||||
|
|
||||||
av_assert0(!frame->buf[0]);
|
av_assert0(!frame->buf[0]);
|
||||||
|
|
||||||
@@ -542,6 +586,13 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
|
|||||||
if (ret == AVERROR_EOF)
|
if (ret == AVERROR_EOF)
|
||||||
avci->draining_done = 1;
|
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) &&
|
if (!(codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS) &&
|
||||||
IS_EMPTY(avci->last_pkt_props)) {
|
IS_EMPTY(avci->last_pkt_props)) {
|
||||||
// May fail if the FIFO is empty.
|
// May fail if the FIFO is empty.
|
||||||
|
Reference in New Issue
Block a user