Bug 1543359 - P13. Let the video decoder determines the default colorspace if unknown. r=mattwoodrow

When unknown, we rely on the picture height and assume that anything less than 720p is 601 and 709 otherwise. It's not perfect but it's the best we can do.

Differential Revision: https://phabricator.services.mozilla.com/D39275

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jean-Yves Avenard 2019-07-26 04:26:56 +00:00
parent 1d4fe80ec2
commit 84900ae6ff
25 changed files with 91 additions and 25 deletions

View File

@ -308,6 +308,9 @@ bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
return false;
}
MOZ_ASSERT(aBuffer.mYUVColorSpace != gfx::YUVColorSpace::UNKNOWN,
"We must know the colorframe at this point");
PlanarYCbCrData data = ConstructPlanarYCbCrData(aInfo, aBuffer, aPicture);
aVideoImage->SetDelayedConversion(true);
@ -336,6 +339,9 @@ already_AddRefed<VideoData> VideoData::CreateAndCopyData(
return nullptr;
}
MOZ_ASSERT(aBuffer.mYUVColorSpace != gfx::YUVColorSpace::UNKNOWN,
"We must know the colorframe at this point");
RefPtr<VideoData> v(new VideoData(aOffset, aTime, aDuration, aKeyframe,
aTimecode, aInfo.mDisplay, 0));

View File

@ -446,7 +446,7 @@ class VideoData : public MediaData {
};
Plane mPlanes[3];
YUVColorSpace mYUVColorSpace = YUVColorSpace::BT601;
YUVColorSpace mYUVColorSpace = YUVColorSpace::UNKNOWN;
ColorDepth mColorDepth = ColorDepth::COLOR_8;
ColorRange mColorRange = ColorRange::LIMITED;
};

View File

@ -25,6 +25,11 @@ static bool SetImageToBlackPixel(PlanarYCbCrImage* aImage) {
data.mCrChannel = blackPixel + 2;
data.mYStride = data.mCbCrStride = 1;
data.mPicSize = data.mYSize = data.mCbCrSize = gfx::IntSize(1, 1);
data.mYUVColorSpace = gfx::YUVColorSpace::BT601;
// This could be made FULL once bug 1568745 is complete. A black pixel being
// 0x00, 0x80, 0x80
data.mColorRange = gfx::ColorRange::LIMITED;
return aImage->CopyData(data);
}

View File

@ -8,6 +8,7 @@
#include "gfx2DGlue.h"
#include "ImageContainer.h"
#include "Layers.h"
#include "VideoUtils.h"
#include "mozilla/UniquePtr.h"
namespace mozilla {
@ -76,6 +77,10 @@ already_AddRefed<Image> VideoFrame::CreateBlackImage(
data.mPicY = 0;
data.mPicSize = gfx::IntSize(aSize.width, aSize.height);
data.mStereoMode = StereoMode::MONO;
data.mYUVColorSpace = gfx::YUVColorSpace::BT601;
// This could be made FULL once bug 1568745 is complete. A black pixel being
// 0x00, 0x80, 0x80
data.mColorRange = gfx::ColorRange::LIMITED;
// Copies data, so we can free data.
if (!image->CopyData(data)) {

View File

@ -12,6 +12,7 @@
#include "TimeUnits.h"
#include "VideoLimits.h"
#include "mozilla/gfx/Point.h" // for gfx::IntSize
#include "mozilla/gfx/Types.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Attributes.h"
#include "mozilla/CheckedInt.h"
@ -550,6 +551,11 @@ inline void AppendStringIfNotEmpty(nsACString& aDest, nsACString&& aSrc) {
// Main thread only.
bool OnCellularConnection();
inline gfx::YUVColorSpace DefaultColorSpace(const gfx::IntSize& aSize) {
return aSize.height < 720 ? gfx::YUVColorSpace::BT601
: gfx::YUVColorSpace::BT709;
}
} // end namespace mozilla
#endif

View File

@ -769,6 +769,11 @@ already_AddRefed<VideoData> ChromiumCDMParent::CreateVideoFrame(
b.mPlanes[2].mOffset = aFrame.mVPlane().mPlaneOffset();
b.mPlanes[2].mSkip = 0;
// We unfortunately can't know which colorspace the video is using at this
// stage.
b.mYUVColorSpace =
DefaultColorSpace({aFrame.mImageWidth(), aFrame.mImageHeight()});
gfx::IntRect pictureRegion(0, 0, aFrame.mImageWidth(), aFrame.mImageHeight());
RefPtr<VideoData> v = VideoData::CreateAndCopyData(
mVideoInfo, mImageContainer, mLastStreamOffset,

View File

@ -6,6 +6,8 @@
#include "YUVBufferGenerator.h"
#include "VideoUtils.h"
using namespace mozilla::layers;
using namespace mozilla;
@ -74,6 +76,8 @@ Image* YUVBufferGenerator::CreateI420Image() {
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
data.mYUVColorSpace = DefaultColorSpace(data.mYSize);
image->CopyData(data);
return image;
}
@ -146,6 +150,8 @@ Image* YUVBufferGenerator::CreateNV21Image() {
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
data.mYUVColorSpace = DefaultColorSpace(data.mYSize);
image->SetData(data);
return image;
}

View File

@ -85,6 +85,7 @@ static void SetImageToGreenPixel(PlanarYCbCrImage* aImage) {
data.mCrChannel = greenPixel + 2;
data.mYStride = data.mCbCrStride = 1;
data.mPicSize = data.mYSize = data.mCbCrSize = gfx::IntSize(1, 1);
data.mYUVColorSpace = gfx::YUVColorSpace::BT601;
aImage->CopyData(data);
}

View File

@ -200,13 +200,14 @@ RefPtr<MediaDataDecoder::DecodePromise> AOMDecoder::ProcessDecode(
b.mYUVColorSpace = YUVColorSpace::BT2020;
break;
case AOM_CICP_MC_BT_709:
default:
// Set 709 as default, as it's the most sane default.
b.mYUVColorSpace = YUVColorSpace::BT709;
break;
default:
b.mYUVColorSpace = DefaultColorSpace({img->d_w, img->d_h});
break;
}
b.mColorRange = img->range == AOM_CR_FULL_RANGE ? gfx::ColorRange::FULL
: gfx::ColorRange::LIMITED;
b.mColorRange = img->range == AOM_CR_FULL_RANGE ? ColorRange::FULL
: ColorRange::LIMITED;
RefPtr<VideoData> v;
v = VideoData::CreateAndCopyData(mInfo, mImageContainer, aSample->mOffset,

View File

@ -70,6 +70,8 @@ already_AddRefed<MediaData> BlankVideoDataCreator::Create(
buffer.mPlanes[2].mOffset = 0;
buffer.mPlanes[2].mSkip = 0;
buffer.mYUVColorSpace = gfx::YUVColorSpace::BT601;
return VideoData::CreateAndCopyData(
mInfo, mImageContainer, aSample->mOffset, aSample->mTime,
aSample->mDuration, buffer, aSample->mKeyframe, aSample->mTime, mPicture);

View File

@ -194,14 +194,14 @@ already_AddRefed<VideoData> DAV1DDecoder::ConstructImage(
b.mYUVColorSpace = YUVColorSpace::BT601;
break;
case DAV1D_MC_BT709:
default:
// Set 709 as default, as it's the most sane default.
b.mYUVColorSpace = YUVColorSpace::BT709;
break;
default:
break;
}
} else {
// BT709 is the only default that makes sense in a modern video context.
b.mYUVColorSpace = YUVColorSpace::BT709;
}
if (b.mYUVColorSpace == YUVColorSpace::UNKNOWN) {
b.mYUVColorSpace = DefaultColorSpace({aPicture.p.w, aPicture.p.h});
}
b.mColorRange = aPicture.seq_hdr->color_range ? gfx::ColorRange::FULL
: gfx::ColorRange::LIMITED;

View File

@ -166,6 +166,9 @@ RefPtr<MediaDataDecoder::DecodePromise> TheoraDecoder::ProcessDecode(
b.mPlanes[2].mWidth = mTheoraInfo.frame_width >> hdec;
b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
b.mYUVColorSpace =
DefaultColorSpace({mTheoraInfo.frame_width, mTheoraInfo.frame_height});
IntRect pictureArea(mTheoraInfo.pic_x, mTheoraInfo.pic_y,
mTheoraInfo.pic_width, mTheoraInfo.pic_height);

View File

@ -188,7 +188,7 @@ RefPtr<MediaDataDecoder::DecodePromise> VPXDecoder::ProcessDecode(
case VPX_CS_BT_2020:
return gfx::YUVColorSpace::BT2020;
default:
return gfx::YUVColorSpace::UNKNOWN;
return DefaultColorSpace({img->d_w, img->d_h});
}
}();
b.mColorRange = img->range == VPX_CR_FULL_RANGE ? gfx::ColorRange::FULL

View File

@ -56,6 +56,9 @@ void GMPVideoDecoder::Decoded(GMPVideoi420Frame* aDecodedFrame) {
b.mPlanes[i].mSkip = 0;
}
b.mYUVColorSpace =
DefaultColorSpace({decodedFrame->Width(), decodedFrame->Height()});
gfx::IntRect pictureRegion(0, 0, decodedFrame->Width(),
decodedFrame->Height());
RefPtr<VideoData> v = VideoData::CreateAndCopyData(

View File

@ -35,7 +35,9 @@ AppleVTDecoder::AppleVTDecoder(const VideoInfo& aConfig, TaskQueue* aTaskQueue,
mPictureHeight(aConfig.mImage.height),
mDisplayWidth(aConfig.mDisplay.width),
mDisplayHeight(aConfig.mDisplay.height),
mColorSpace(aConfig.mColorSpace),
mColorSpace(aConfig.mColorSpace == gfx::YUVColorSpace::UNKNOWN
? DefaultColorSpace({mPictureWidth, mPictureHeight})
: aConfig.mColorSpace),
mColorRange(aConfig.mColorRange),
mTaskQueue(aTaskQueue),
mMaxRefFrames(aOptions.contains(CreateDecoderParams::Option::LowLatency)

View File

@ -381,16 +381,16 @@ MediaResult FFmpegVideoDecoder<LIBAV_VER>::CreateImage(
b.mYUVColorSpace = gfx::YUVColorSpace::BT601;
break;
case AVCOL_SPC_UNSPECIFIED:
#if LIBAVCODEC_VERSION_MAJOR >= 55
if (mCodecContext->codec_id == AV_CODEC_ID_VP9) {
b.mYUVColorSpace = gfx::YUVColorSpace::BT709;
}
#endif
b.mYUVColorSpace = gfx::YUVColorSpace::UNKNOWN;
break;
default:
break;
}
}
if (b.mYUVColorSpace == gfx::YUVColorSpace::UNKNOWN) {
b.mYUVColorSpace = DefaultColorSpace({mFrame->width, mFrame->height});
}
if (mLib->av_frame_get_color_range) {
auto range = mLib->av_frame_get_color_range(mFrame);
b.mColorRange = range == AVCOL_RANGE_JPEG ? gfx::ColorRange::FULL

View File

@ -35,6 +35,8 @@
namespace mozilla {
using namespace gfx;
static const char* StateTypeToStr(OMX_STATETYPE aType) {
MOZ_ASSERT(aType == OMX_StateLoaded || aType == OMX_StateIdle ||
aType == OMX_StateExecuting || aType == OMX_StatePause ||
@ -936,6 +938,11 @@ already_AddRefed<VideoData> MediaDataHelper::CreateYUV420VideoData(
b.mPlanes[2].mOffset = 0;
b.mPlanes[2].mSkip = 0;
b.mYUVColorSpace =
mTrackInfo->GetAsVideoInfo()->mColorSpace == YUVColorSpace::UNKNOWN
? DefaultColorSpace({width, height})
: mTrackInfo->GetAsVideoInfo()->mColorSpace;
VideoInfo info(*mTrackInfo->GetAsVideoInfo());
RefPtr<VideoData> data = VideoData::CreateAndCopyData(
info, mImageContainer,

View File

@ -626,7 +626,7 @@ class D3D11DXVA2Manager : public DXVA2Manager {
UINT mDeviceManagerToken = 0;
RefPtr<IMFMediaType> mInputType;
GUID mInputSubType;
gfx::YUVColorSpace mYUVColorSpace = gfx::YUVColorSpace::BT601;
gfx::YUVColorSpace mYUVColorSpace = gfx::YUVColorSpace::UNKNOWN;
gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED;
};

View File

@ -68,7 +68,7 @@ GetDefaultStride(IMFMediaType* aType, uint32_t aWidth, uint32_t* aOutStride) {
gfx::YUVColorSpace GetYUVColorSpace(IMFMediaType* aType) {
UINT32 yuvColorMatrix;
HRESULT hr = aType->GetUINT32(MF_MT_YUV_MATRIX, &yuvColorMatrix);
NS_ENSURE_TRUE(SUCCEEDED(hr), gfx::YUVColorSpace::BT601);
NS_ENSURE_TRUE(SUCCEEDED(hr), gfx::YUVColorSpace::UNKNOWN);
switch (yuvColorMatrix) {
case MFVideoTransferMatrix_BT2020_10:
@ -77,8 +77,9 @@ gfx::YUVColorSpace GetYUVColorSpace(IMFMediaType* aType) {
case MFVideoTransferMatrix_BT709:
return gfx::YUVColorSpace::BT709;
case MFVideoTransferMatrix_BT601:
default:
return gfx::YUVColorSpace::BT601;
default:
return gfx::YUVColorSpace::UNKNOWN;
}
}

View File

@ -662,8 +662,11 @@ MediaResult WMFVideoMFTManager::InitInternal() {
if (mUseHwAccel) {
hr = mDXVA2Manager->ConfigureForSize(
outputType, mColorSpace.refOr(gfx::YUVColorSpace::BT601), mColorRange,
mVideoInfo.ImageRect().width, mVideoInfo.ImageRect().height);
outputType,
mColorSpace.refOr(
DefaultColorSpace({mImageSize.width, mImageSize.height})),
mColorRange, mVideoInfo.ImageRect().width,
mVideoInfo.ImageRect().height);
NS_ENSURE_TRUE(SUCCEEDED(hr),
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Fail to configure image size for "
@ -931,7 +934,8 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
}
// YuvColorSpace
b.mYUVColorSpace = mColorSpace.refOr(gfx::YUVColorSpace::BT601);
b.mYUVColorSpace =
mColorSpace.refOr(DefaultColorSpace({videoWidth, videoHeight}));
b.mColorDepth = colorDepth;
b.mColorRange = mColorRange;
@ -1045,7 +1049,9 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset, RefPtr<MediaData>& aOutData) {
if (mUseHwAccel) {
hr = mDXVA2Manager->ConfigureForSize(
outputType, mColorSpace.refOr(gfx::YUVColorSpace::BT601),
outputType,
mColorSpace.refOr(
DefaultColorSpace({mImageSize.width, mImageSize.height})),
mColorRange, mVideoInfo.ImageRect().width,
mVideoInfo.ImageRect().height);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);

View File

@ -230,6 +230,7 @@ static void AllocateSolidColorFrame(layers::PlanarYCbCrData& aData, int aWidth,
aData.mPicY = 0;
aData.mPicSize = IntSize(aWidth, aHeight);
aData.mStereoMode = StereoMode::MONO;
aData.mYUVColorSpace = gfx::YUVColorSpace::BT601;
}
static void ReleaseFrame(layers::PlanarYCbCrData& aData) {

View File

@ -588,6 +588,7 @@ int MediaEngineRemoteVideoSource::DeliverFrame(
data.mPicX = 0;
data.mPicY = 0;
data.mPicSize = IntSize(buffer->width(), buffer->height());
data.mYUVColorSpace = gfx::YUVColorSpace::BT601;
RefPtr<layers::PlanarYCbCrImage> image =
mImageContainer->CreatePlanarYCbCrImage();

View File

@ -733,7 +733,7 @@ struct PlanarYCbCrData {
gfx::IntSize mPicSize = gfx::IntSize(0, 0);
StereoMode mStereoMode = StereoMode::MONO;
gfx::ColorDepth mColorDepth = gfx::ColorDepth::COLOR_8;
gfx::YUVColorSpace mYUVColorSpace = gfx::YUVColorSpace::BT601;
gfx::YUVColorSpace mYUVColorSpace = gfx::YUVColorSpace::UNKNOWN;
gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED;
gfx::IntRect GetPictureRect() const {

View File

@ -150,6 +150,9 @@ CreateSourceSurfaceFromLockedMacIOSurface(MacIOSurface* aSurface) {
data.mCbCrStride = cbCrStride;
data.mCbCrSize = IntSize::Truncate(cbCrWidth, cbCrHeight);
data.mPicSize = data.mYSize;
data.mYUVColorSpace = aSurface->GetYUVColorSpace();
data.mColorRange = aSurface->IsFullRange() ? gfx::ColorRange::FULL
: gfx::ColorRange::LIMITED;
ConvertYCbCrToRGB(data, SurfaceFormat::B8G8R8X8,
IntSize::Truncate(ioWidth, ioHeight),

View File

@ -1505,6 +1505,8 @@ class MediaPipelineReceiveVideo::PipelineListener
yuvData.mPicY = 0;
yuvData.mPicSize = IntSize(i420->width(), i420->height());
yuvData.mStereoMode = StereoMode::MONO;
// This isn't the best default.
yuvData.mYUVColorSpace = gfx::YUVColorSpace::BT601;
if (!yuvImage->CopyData(yuvData)) {
MOZ_ASSERT(false);