mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 07:45:30 +00:00
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:
parent
1d4fe80ec2
commit
84900ae6ff
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user