From 949fa28f4fda6182314fbae538aacb57140f63cb Mon Sep 17 00:00:00 2001 From: Brad Werth Date: Mon, 10 Oct 2022 20:12:58 +0000 Subject: [PATCH] Bug 1765187 Part 1: Track color primaries independently from coefficients. r=media-playback-reviewers,jgilbert,alwu This patch attempts to read color primary information from platform agnostic decoders. It doesn't use any of this information to change how the video frame is displayed. It also cleans up some VPX transfer characteristics, to ensure they are actually retrieved from the codec information, when available. Differential Revision: https://phabricator.services.mozilla.com/D156362 --- dom/media/MediaData.cpp | 1 + dom/media/MediaData.h | 2 ++ dom/media/MediaInfo.h | 3 +- dom/media/ipc/MediaIPCUtils.h | 2 ++ dom/media/platforms/agnostic/AOMDecoder.cpp | 12 +++++++ .../platforms/agnostic/BlankDecoderModule.cpp | 1 + dom/media/platforms/agnostic/DAV1DDecoder.cpp | 19 ++++++++++-- dom/media/platforms/agnostic/DAV1DDecoder.h | 3 ++ dom/media/platforms/agnostic/VPXDecoder.cpp | 17 ++++++---- dom/media/platforms/agnostic/VPXDecoder.h | 31 +++++++++++++++++++ .../platforms/ffmpeg/FFmpegVideoDecoder.cpp | 17 ++++++++++ .../platforms/ffmpeg/FFmpegVideoDecoder.h | 1 + dom/media/platforms/omx/OmxDataDecoder.cpp | 6 ++++ .../platforms/wrappers/MediaChangeMonitor.cpp | 8 +++++ dom/media/webm/WebMDemuxer.cpp | 4 +++ gfx/layers/ImageContainer.h | 1 + gfx/thebes/gfxUtils.cpp | 23 ++++++++++++-- gfx/thebes/gfxUtils.h | 4 +++ image/decoders/nsAVIFDecoder.cpp | 12 +++++++ 19 files changed, 156 insertions(+), 11 deletions(-) diff --git a/dom/media/MediaData.cpp b/dom/media/MediaData.cpp index be91711f4c6a..c90dc7211fbd 100644 --- a/dom/media/MediaData.cpp +++ b/dom/media/MediaData.cpp @@ -280,6 +280,7 @@ PlanarYCbCrData ConstructPlanarYCbCrData(const VideoInfo& aInfo, data.mPictureRect = aPicture; data.mStereoMode = aInfo.mStereoMode; data.mYUVColorSpace = aBuffer.mYUVColorSpace; + data.mColorPrimaries = aBuffer.mColorPrimaries; data.mColorDepth = aBuffer.mColorDepth; if (aInfo.mTransferFunction) { data.mTransferFunction = *aInfo.mTransferFunction; diff --git a/dom/media/MediaData.h b/dom/media/MediaData.h index 402207d6bd0f..c32a5a6ca526 100644 --- a/dom/media/MediaData.h +++ b/dom/media/MediaData.h @@ -421,6 +421,7 @@ class VideoData : public MediaData { typedef gfx::ColorDepth ColorDepth; typedef gfx::ColorRange ColorRange; typedef gfx::YUVColorSpace YUVColorSpace; + typedef gfx::ColorSpace2 ColorSpace2; typedef gfx::ChromaSubsampling ChromaSubsampling; typedef layers::ImageContainer ImageContainer; typedef layers::Image Image; @@ -444,6 +445,7 @@ class VideoData : public MediaData { Plane mPlanes[3]; YUVColorSpace mYUVColorSpace = YUVColorSpace::Identity; + ColorSpace2 mColorPrimaries = ColorSpace2::UNKNOWN; ColorDepth mColorDepth = ColorDepth::COLOR_8; ColorRange mColorRange = ColorRange::LIMITED; ChromaSubsampling mChromaSubsampling = ChromaSubsampling::FULL; diff --git a/dom/media/MediaInfo.h b/dom/media/MediaInfo.h index 4431e4339fc8..cff69c744470 100644 --- a/dom/media/MediaInfo.h +++ b/dom/media/MediaInfo.h @@ -433,7 +433,8 @@ class VideoInfo : public TrackInfo { // Matrix coefficients (if specified by the video) imply a colorspace. Maybe mColorSpace; - // Color primaries are assumed to match the colorspace. + // Color primaries are independent from the coefficients. + Maybe mColorPrimaries; // Transfer functions get their own member, which may not be strongly // correlated to the colorspace. diff --git a/dom/media/ipc/MediaIPCUtils.h b/dom/media/ipc/MediaIPCUtils.h index 37af9d969c88..06848242811a 100644 --- a/dom/media/ipc/MediaIPCUtils.h +++ b/dom/media/ipc/MediaIPCUtils.h @@ -33,6 +33,7 @@ struct ParamTraits { WriteParam(aWriter, aParam.mRotation); WriteParam(aWriter, aParam.mColorDepth); WriteParam(aWriter, aParam.mColorSpace); + WriteParam(aWriter, aParam.mColorPrimaries); WriteParam(aWriter, aParam.mTransferFunction); WriteParam(aWriter, aParam.mColorRange); WriteParam(aWriter, aParam.HasAlpha()); @@ -51,6 +52,7 @@ struct ParamTraits { ReadParam(aReader, &aResult->mRotation) && ReadParam(aReader, &aResult->mColorDepth) && ReadParam(aReader, &aResult->mColorSpace) && + ReadParam(aReader, &aResult->mColorPrimaries) && ReadParam(aReader, &aResult->mTransferFunction) && ReadParam(aReader, &aResult->mColorRange) && ReadParam(aReader, &alphaPresent)) { diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp index 20b3e8b289ed..95cad471df24 100644 --- a/dom/media/platforms/agnostic/AOMDecoder.cpp +++ b/dom/media/platforms/agnostic/AOMDecoder.cpp @@ -220,6 +220,18 @@ RefPtr AOMDecoder::ProcessDecode( b.mColorRange = img->range == AOM_CR_FULL_RANGE ? ColorRange::FULL : ColorRange::LIMITED; + switch (img->cp) { + case AOM_CICP_CP_BT_709: + b.mColorPrimaries = ColorSpace2::BT709; + break; + case AOM_CICP_CP_BT_2020: + b.mColorPrimaries = ColorSpace2::BT2020; + break; + default: + b.mColorPrimaries = ColorSpace2::BT709; + break; + } + RefPtr v; v = VideoData::CreateAndCopyData( mInfo, mImageContainer, aSample->mOffset, aSample->mTime, diff --git a/dom/media/platforms/agnostic/BlankDecoderModule.cpp b/dom/media/platforms/agnostic/BlankDecoderModule.cpp index 37a2c059031f..fba07338dcec 100644 --- a/dom/media/platforms/agnostic/BlankDecoderModule.cpp +++ b/dom/media/platforms/agnostic/BlankDecoderModule.cpp @@ -69,6 +69,7 @@ already_AddRefed BlankVideoDataCreator::Create( buffer.mChromaSubsampling = gfx::ChromaSubsampling::HALF_WIDTH_AND_HEIGHT; buffer.mYUVColorSpace = gfx::YUVColorSpace::BT601; + buffer.mColorPrimaries = gfx::ColorSpace2::BT709; return VideoData::CreateAndCopyData(mInfo, mImageContainer, aSample->mOffset, aSample->mTime, aSample->mDuration, diff --git a/dom/media/platforms/agnostic/DAV1DDecoder.cpp b/dom/media/platforms/agnostic/DAV1DDecoder.cpp index 33c89af19060..2db77bf5c12b 100644 --- a/dom/media/platforms/agnostic/DAV1DDecoder.cpp +++ b/dom/media/platforms/agnostic/DAV1DDecoder.cpp @@ -230,9 +230,10 @@ int DAV1DDecoder::GetPicture(DecodedData& aData, MediaResult& aResult) { return 0; } -// When returning Nothing(), the caller chooses the appropriate default -/* static */ Maybe DAV1DDecoder::GetColorSpace( +/* static */ +Maybe DAV1DDecoder::GetColorSpace( const Dav1dPicture& aPicture, LazyLogModule& aLogger) { + // When returning Nothing(), the caller chooses the appropriate default. if (!aPicture.seq_hdr || !aPicture.seq_hdr->color_description_present) { return Nothing(); } @@ -242,6 +243,18 @@ int DAV1DDecoder::GetPicture(DecodedData& aData, MediaResult& aResult) { static_cast(aPicture.seq_hdr->pri), aLogger); } +/* static */ +Maybe DAV1DDecoder::GetColorPrimaries( + const Dav1dPicture& aPicture, LazyLogModule& aLogger) { + // When returning Nothing(), the caller chooses the appropriate default. + if (!aPicture.seq_hdr || !aPicture.seq_hdr->color_description_present) { + return Nothing(); + } + + return gfxUtils::CicpToColorPrimaries( + static_cast(aPicture.seq_hdr->pri), aLogger); +} + already_AddRefed DAV1DDecoder::ConstructImage( const Dav1dPicture& aPicture) { VideoData::YCbCrBuffer b; @@ -256,6 +269,8 @@ already_AddRefed DAV1DDecoder::ConstructImage( b.mYUVColorSpace = DAV1DDecoder::GetColorSpace(aPicture, sPDMLog) .valueOr(DefaultColorSpace({aPicture.p.w, aPicture.p.h})); + b.mColorPrimaries = DAV1DDecoder::GetColorPrimaries(aPicture, sPDMLog) + .valueOr(gfx::ColorSpace2::BT709); b.mColorRange = aPicture.seq_hdr->color_range ? gfx::ColorRange::FULL : gfx::ColorRange::LIMITED; diff --git a/dom/media/platforms/agnostic/DAV1DDecoder.h b/dom/media/platforms/agnostic/DAV1DDecoder.h index 93da31414107..fc59cb6e1b0d 100644 --- a/dom/media/platforms/agnostic/DAV1DDecoder.h +++ b/dom/media/platforms/agnostic/DAV1DDecoder.h @@ -36,6 +36,9 @@ class DAV1DDecoder : public MediaDataDecoder, static Maybe GetColorSpace(const Dav1dPicture& aPicture, LazyLogModule& aLogger); + static Maybe GetColorPrimaries(const Dav1dPicture& aPicture, + LazyLogModule& aLogger); + private: ~DAV1DDecoder() = default; RefPtr InvokeDecode(MediaRawData* aSample); diff --git a/dom/media/platforms/agnostic/VPXDecoder.cpp b/dom/media/platforms/agnostic/VPXDecoder.cpp index 9e343a791357..f691ae20a524 100644 --- a/dom/media/platforms/agnostic/VPXDecoder.cpp +++ b/dom/media/platforms/agnostic/VPXDecoder.cpp @@ -13,6 +13,7 @@ #include "ImageContainer.h" #include "TimeUnits.h" #include "gfx2DGlue.h" +#include "gfxUtils.h" #include "mozilla/PodOperations.h" #include "mozilla/SyncRunnable.h" #include "mozilla/TaskQueue.h" @@ -544,9 +545,9 @@ void VPXDecoder::GetVPCCBox(MediaByteBuffer* aDestBox, writer.WriteBit(aInfo.mFullRange); // full/restricted range // See VPXDecoder::VPXStreamInfo enums - writer.WriteU8(2); // colour primaries: unspecified - writer.WriteU8(2); // transfer characteristics: unspecified - writer.WriteU8(2); // matrix coefficients: unspecified + writer.WriteU8(aInfo.mColorPrimaries); // color primaries + writer.WriteU8(aInfo.mTransferFunction); // transfer characteristics + writer.WriteU8(2); // matrix coefficients: unspecified writer.WriteBits(0, 16); // codecIntializationDataSize (must be 0 for VP8/VP9) @@ -563,6 +564,10 @@ bool VPXDecoder::SetVideoInfo(VideoInfo* aDestInfo, const nsAString& aCodec) { return false; } + aDestInfo->mColorPrimaries = + gfxUtils::CicpToColorPrimaries(colorSpace.mPrimaries, sPDMLog); + aDestInfo->mTransferFunction = + gfxUtils::CicpToTransferFunction(colorSpace.mTransfer); aDestInfo->mColorDepth = gfx::ColorDepthForBitDepth(info.mBitDepth); VPXDecoder::SetChroma(info, chroma); info.mFullRange = colorSpace.mRange == ColorRange::FULL; @@ -604,9 +609,9 @@ void VPXDecoder::ReadVPCCBox(VPXStreamInfo& aDestInfo, MediaByteBuffer* aBox) { SetChroma(aDestInfo, reader.ReadBits(3)); aDestInfo.mFullRange = reader.ReadBit(); - reader.ReadBits(8); // colour primaries - reader.ReadBits(8); // transfer characteristics - reader.ReadBits(8); // matrix coefficients + aDestInfo.mColorPrimaries = reader.ReadBits(8); // color primaries + aDestInfo.mTransferFunction = reader.ReadBits(8); // transfer characteristics + reader.ReadBits(8); // matrix coefficients MOZ_ASSERT(reader.ReadBits(16) == 0); // codecInitializationDataSize (must be 0 for VP8/VP9) diff --git a/dom/media/platforms/agnostic/VPXDecoder.h b/dom/media/platforms/agnostic/VPXDecoder.h index 86048f536aa4..42f691363b9c 100644 --- a/dom/media/platforms/agnostic/VPXDecoder.h +++ b/dom/media/platforms/agnostic/VPXDecoder.h @@ -95,6 +95,37 @@ class VPXDecoder : public MediaDataDecoder, } } + uint8_t mColorPrimaries = gfx::CICP::ColourPrimaries::CP_UNSPECIFIED; + gfx::ColorSpace2 ColorPrimaries() const { + switch (mColorPrimaries) { + case gfx::CICP::ColourPrimaries::CP_BT709: + return gfx::ColorSpace2::BT709; + case gfx::CICP::ColourPrimaries::CP_UNSPECIFIED: + return gfx::ColorSpace2::BT709; + case gfx::CICP::ColourPrimaries::CP_BT2020: + return gfx::ColorSpace2::BT2020; + default: + return gfx::ColorSpace2::BT709; + } + } + + uint8_t mTransferFunction = + gfx::CICP::TransferCharacteristics::TC_UNSPECIFIED; + gfx::TransferFunction TransferFunction() const { + switch (mTransferFunction) { + case gfx::CICP::TransferCharacteristics::TC_BT709: + return gfx::TransferFunction::BT709; + case gfx::CICP::TransferCharacteristics::TC_SRGB: + return gfx::TransferFunction::SRGB; + case gfx::CICP::TransferCharacteristics::TC_SMPTE2084: + return gfx::TransferFunction::PQ; + case gfx::CICP::TransferCharacteristics::TC_HLG: + return gfx::TransferFunction::HLG; + default: + return gfx::TransferFunction::BT709; + } + } + /* mFullRange == false then: For BitDepth equals 8: diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp index b0e83425d6c6..ff32ebfc35f1 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp @@ -1017,6 +1017,23 @@ gfx::YUVColorSpace FFmpegVideoDecoder::GetFrameColorSpace() const { } } +gfx::ColorSpace2 FFmpegVideoDecoder::GetFrameColorPrimaries() const { + AVColorPrimaries colorPrimaries = AVCOL_PRI_UNSPECIFIED; +#if LIBAVCODEC_VERSION_MAJOR > 57 + colorPrimaries = mFrame->color_primaries; +#endif + switch (colorPrimaries) { +#if LIBAVCODEC_VERSION_MAJOR >= 55 + case AVCOL_PRI_BT2020: + return gfx::ColorSpace2::BT2020; +#endif + case AVCOL_PRI_BT709: + return gfx::ColorSpace2::BT709; + default: + return gfx::ColorSpace2::BT709; + } +} + gfx::ColorRange FFmpegVideoDecoder::GetFrameColorRange() const { AVColorRange range = AVCOL_RANGE_UNSPECIFIED; #if LIBAVCODEC_VERSION_MAJOR > 58 diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h index 367aa6bbe1d9..6ae89903fde4 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h @@ -98,6 +98,7 @@ class FFmpegVideoDecoder #endif } gfx::YUVColorSpace GetFrameColorSpace() const; + gfx::ColorSpace2 GetFrameColorPrimaries() const; gfx::ColorRange GetFrameColorRange() const; MediaResult CreateImage(int64_t aOffset, int64_t aPts, int64_t aDuration, diff --git a/dom/media/platforms/omx/OmxDataDecoder.cpp b/dom/media/platforms/omx/OmxDataDecoder.cpp index 18bafa79a597..27e79aefdede 100644 --- a/dom/media/platforms/omx/OmxDataDecoder.cpp +++ b/dom/media/platforms/omx/OmxDataDecoder.cpp @@ -951,6 +951,12 @@ already_AddRefed MediaDataHelper::CreateYUV420VideoData( } b.mYUVColorSpace = *maybeColorSpace; + auto maybeColorPrimaries = info.mColorPrimaries; + if (!maybeColorPrimaries) { + maybeColorPrimaries = Some(gfx::ColorSpace2::BT709); + } + b.mColorPrimaries = *maybeColorPrimaries; + RefPtr data = VideoData::CreateAndCopyData( info, mImageContainer, 0, // Filled later by caller. diff --git a/dom/media/platforms/wrappers/MediaChangeMonitor.cpp b/dom/media/platforms/wrappers/MediaChangeMonitor.cpp index fb41230afca5..17387204ed28 100644 --- a/dom/media/platforms/wrappers/MediaChangeMonitor.cpp +++ b/dom/media/platforms/wrappers/MediaChangeMonitor.cpp @@ -142,6 +142,11 @@ class H264ChangeMonitor : public MediaChangeMonitor::CodecChangeMonitor { mCurrentConfig.mDisplay.height = spsdata.display_height; mCurrentConfig.mColorDepth = spsdata.ColorDepth(); mCurrentConfig.mColorSpace = Some(spsdata.ColorSpace()); + // spsdata.colour_primaries has the same values as + // gfx::CICP::ColourPrimaries. + mCurrentConfig.mColorPrimaries = gfxUtils::CicpToColorPrimaries( + static_cast(spsdata.colour_primaries), + gMediaDecoderLog); // spsdata.transfer_characteristics has the same values as // gfx::CICP::TransferCharacteristics. mCurrentConfig.mTransferFunction = gfxUtils::CicpToTransferFunction( @@ -272,6 +277,7 @@ class VPXChangeMonitor : public MediaChangeMonitor::CodecChangeMonitor { mCurrentConfig.mColorDepth = gfx::ColorDepthForBitDepth(info.mBitDepth); mCurrentConfig.mColorSpace = Some(info.ColorSpace()); + // VPX bitstream doesn't specify color primaries. // We don't update the transfer function here, because VPX bitstream // doesn't specify the transfer function. Instead, we keep the transfer @@ -347,6 +353,8 @@ class AV1ChangeMonitor : public MediaChangeMonitor::CodecChangeMonitor { mCurrentConfig.mColorSpace = gfxUtils::CicpToColorSpace( aInfo.mColorSpace.mMatrix, aInfo.mColorSpace.mPrimaries, gMediaDecoderLog); + mCurrentConfig.mColorPrimaries = gfxUtils::CicpToColorPrimaries( + aInfo.mColorSpace.mPrimaries, gMediaDecoderLog); mCurrentConfig.mTransferFunction = gfxUtils::CicpToTransferFunction(aInfo.mColorSpace.mTransfer); mCurrentConfig.mColorRange = aInfo.mColorSpace.mRange; diff --git a/dom/media/webm/WebMDemuxer.cpp b/dom/media/webm/WebMDemuxer.cpp index 2d3d19682adb..2515a4061d64 100644 --- a/dom/media/webm/WebMDemuxer.cpp +++ b/dom/media/webm/WebMDemuxer.cpp @@ -307,6 +307,10 @@ nsresult WebMDemuxer::ReadMetadata() { return NS_ERROR_FAILURE; } + mInfo.mVideo.mColorPrimaries = gfxUtils::CicpToColorPrimaries( + static_cast(params.primaries), + gMediaDemuxerLog); + // For VPX, this is our only chance to capture the transfer // characteristics, which we can't get from a VPX bitstream later. // We only need this value if the video is using the BT2020 diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h index 4906dc8d97c3..4b3b733caa0b 100644 --- a/gfx/layers/ImageContainer.h +++ b/gfx/layers/ImageContainer.h @@ -669,6 +669,7 @@ struct PlanarYCbCrData { StereoMode mStereoMode = StereoMode::MONO; gfx::ColorDepth mColorDepth = gfx::ColorDepth::COLOR_8; gfx::YUVColorSpace mYUVColorSpace = gfx::YUVColorSpace::Default; + gfx::ColorSpace2 mColorPrimaries = gfx::ColorSpace2::UNKNOWN; gfx::TransferFunction mTransferFunction = gfx::TransferFunction::BT709; gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED; gfx::ChromaSubsampling mChromaSubsampling = gfx::ChromaSubsampling::FULL; diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp index 02f583b075c9..921bb0407eb6 100644 --- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -291,8 +291,8 @@ static already_AddRefed CreateSamplingRestrictedDrawable( DrawTarget* destDrawTarget = aContext->GetDrawTarget(); // We've been not using CreateSamplingRestrictedDrawable in a bunch of places - // for a while. Let's disable it everywhere and confirm that it's ok to get rid - // of. + // for a while. Let's disable it everywhere and confirm that it's ok to get + // rid of. if (destDrawTarget->GetBackendType() == BackendType::DIRECT2D1_1 || (true)) { return nullptr; } @@ -1385,6 +1385,25 @@ const float kIdentityNarrowYCbCrToRGB_RowMajor[16] = { } } +// Translate from CICP values to the color primaries we support, or return +// Nothing() if there is no appropriate match to let the caller choose +// a default or generate an error. +// +// See Rec. ITU-T H.273 (12/2016) for details on CICP +/* static */ Maybe gfxUtils::CicpToColorPrimaries( + const CICP::ColourPrimaries aColourPrimaries, LazyLogModule& aLogger) { + switch (aColourPrimaries) { + case CICP::ColourPrimaries::CP_BT709: + return Some(gfx::ColorSpace2::BT709); + case CICP::ColourPrimaries::CP_BT2020: + return Some(gfx::ColorSpace2::BT2020); + default: + MOZ_LOG(aLogger, LogLevel::Debug, + ("Unsupported color primaries value: %hhu", aColourPrimaries)); + return {}; + } +} + // Translate from CICP values to the transfer functions we support, or return // Nothing() if there is no appropriate match. // diff --git a/gfx/thebes/gfxUtils.h b/gfx/thebes/gfxUtils.h index 6d7f5e2400b6..d4e8e7f9fff8 100644 --- a/gfx/thebes/gfxUtils.h +++ b/gfx/thebes/gfxUtils.h @@ -232,6 +232,10 @@ class gfxUtils { const mozilla::gfx::CICP::ColourPrimaries, mozilla::LazyLogModule& aLogger); + static mozilla::Maybe CicpToColorPrimaries( + const mozilla::gfx::CICP::ColourPrimaries, + mozilla::LazyLogModule& aLogger); + static mozilla::Maybe CicpToTransferFunction( const mozilla::gfx::CICP::TransferCharacteristics); diff --git a/image/decoders/nsAVIFDecoder.cpp b/image/decoders/nsAVIFDecoder.cpp index 4e1fe37a39ff..248ce0a3c8e2 100644 --- a/image/decoders/nsAVIFDecoder.cpp +++ b/image/decoders/nsAVIFDecoder.cpp @@ -1018,6 +1018,12 @@ AVIFDecodedData Dav1dDecoder::Dav1dPictureToDecodedData( seq_hdr.color_range ? gfx::ColorRange::FULL : gfx::ColorRange::LIMITED; data.mColorRange = GetAVIFColorRange(aNclx, av1ColorRange); + auto colorPrimaries = + gfxUtils::CicpToColorPrimaries(data.mColourPrimaries, sAVIFLog); + if (colorPrimaries.isSome()) { + data.mColorPrimaries = *colorPrimaries; + } + if (aAlphaPlane) { MOZ_ASSERT(aAlphaPlane->stride[0] == data.mYStride); data.mAlpha.emplace(); @@ -1100,6 +1106,12 @@ AVIFDecodedData AOMDecoder::AOMImageToToDecodedData( data.SetCicpValues(aNclx, av1ColourPrimaries, av1TransferCharacteristics, av1MatrixCoefficients); + auto colorPrimaries = + gfxUtils::CicpToColorPrimaries(data.mColourPrimaries, sAVIFLog); + if (colorPrimaries.isSome()) { + data.mColorPrimaries = *colorPrimaries; + } + if (aAlphaPlane) { MOZ_ASSERT(aAlphaPlane->stride[AOM_PLANE_Y] == data.mYStride); data.mAlpha.emplace();