Bug 1306521 - Handle VP9 colorspace BT.709 on BasicCompositor r=nical,jwwang,jya,jrmuizel

This commit is contained in:
Sotaro Ikeda 2016-10-11 19:46:28 -07:00
Родитель c26d9eb6e6
Коммит 1d3ceeff04
24 изменённых файлов: 186 добавлений и 44 удалений

Просмотреть файл

@ -239,6 +239,7 @@ bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
data.mPicY = aPicture.y; data.mPicY = aPicture.y;
data.mPicSize = aPicture.Size(); data.mPicSize = aPicture.Size();
data.mStereoMode = aInfo.mStereoMode; data.mStereoMode = aInfo.mStereoMode;
data.mYUVColorSpace = aBuffer.mYUVColorSpace;
aVideoImage->SetDelayedConversion(true); aVideoImage->SetDelayedConversion(true);
if (aCopyData) { if (aCopyData) {

Просмотреть файл

@ -6,10 +6,11 @@
#if !defined(MediaData_h) #if !defined(MediaData_h)
#define MediaData_h #define MediaData_h
#include "AudioSampleFormat.h"
#include "ImageTypes.h"
#include "nsSize.h" #include "nsSize.h"
#include "mozilla/gfx/Rect.h" #include "mozilla/gfx/Rect.h"
#include "nsRect.h" #include "nsRect.h"
#include "AudioSampleFormat.h"
#include "nsIMemoryReporter.h" #include "nsIMemoryReporter.h"
#include "SharedBuffer.h" #include "SharedBuffer.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
@ -443,6 +444,7 @@ public:
}; };
Plane mPlanes[3]; Plane mPlanes[3];
YUVColorSpace mYUVColorSpace = YUVColorSpace::BT601;
}; };
// Constructs a VideoData object. If aImage is nullptr, creates a new Image // Constructs a VideoData object. If aImage is nullptr, creates a new Image

Просмотреть файл

@ -86,16 +86,22 @@ FFmpegLibWrapper::Link()
return false; return false;
} }
#define AV_FUNC(func, ver) \ #define AV_FUNC_OPTION(func, ver) \
if ((ver) & version) { \ if ((ver) & version) { \
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? mAVUtilLib : mAVCodecLib, #func))) { \ if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? mAVUtilLib : mAVCodecLib, #func))) { \
FFMPEG_LOG("Couldn't load function " # func); \ FFMPEG_LOG("Couldn't load function " # func); \
Unlink(); \
return false; \
} \ } \
} else { \ } else { \
func = (decltype(func))nullptr; \ func = (decltype(func))nullptr; \
} }
#define AV_FUNC(func, ver) \
AV_FUNC_OPTION(func, ver) \
if ((ver) & version && !func) { \
Unlink(); \
return false; \
}
AV_FUNC(av_lockmgr_register, AV_FUNC_AVCODEC_ALL) AV_FUNC(av_lockmgr_register, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_alloc_context3, AV_FUNC_AVCODEC_ALL) AV_FUNC(avcodec_alloc_context3, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_close, AV_FUNC_AVCODEC_ALL) AV_FUNC(avcodec_close, AV_FUNC_AVCODEC_ALL)
@ -118,7 +124,9 @@ FFmpegLibWrapper::Link()
AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57)) AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57)) AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57)) AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
AV_FUNC_OPTION(av_frame_get_colorspace, AV_FUNC_AVUTIL_ALL)
#undef AV_FUNC #undef AV_FUNC
#undef AV_FUNC_OPTION
avcodec_register_all(); avcodec_register_all();
#ifdef DEBUG #ifdef DEBUG

Просмотреть файл

@ -67,6 +67,9 @@ struct FFmpegLibWrapper
void (*av_frame_free)(AVFrame** frame); void (*av_frame_free)(AVFrame** frame);
void (*av_frame_unref)(AVFrame* frame); void (*av_frame_unref)(AVFrame* frame);
// libavutil optional
int (*av_frame_get_colorspace)(const AVFrame *frame);
PRLibrary* mAVCodecLib; PRLibrary* mAVCodecLib;
PRLibrary* mAVUtilLib; PRLibrary* mAVUtilLib;

Просмотреть файл

@ -301,7 +301,19 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample,
b.mPlanes[1].mWidth = b.mPlanes[2].mWidth = (mFrame->width + 1) >> 1; b.mPlanes[1].mWidth = b.mPlanes[2].mWidth = (mFrame->width + 1) >> 1;
b.mPlanes[1].mHeight = b.mPlanes[2].mHeight = (mFrame->height + 1) >> 1; b.mPlanes[1].mHeight = b.mPlanes[2].mHeight = (mFrame->height + 1) >> 1;
} }
if (mLib->av_frame_get_colorspace) {
switch (mLib->av_frame_get_colorspace(mFrame)) {
case AVCOL_SPC_BT709:
b.mYUVColorSpace = YUVColorSpace::BT709;
break;
case AVCOL_SPC_SMPTE170M:
case AVCOL_SPC_BT470BG:
b.mYUVColorSpace = YUVColorSpace::BT601;
break;
default:
NS_WARNING("Unsupported yuv color space.");
}
}
RefPtr<VideoData> v = RefPtr<VideoData> v =
VideoData::CreateAndCopyData(mInfo, VideoData::CreateAndCopyData(mInfo,
mImageContainer, mImageContainer,

Просмотреть файл

@ -942,6 +942,14 @@ struct ParamTraits<mozilla::StereoMode>
mozilla::StereoMode::MAX> mozilla::StereoMode::MAX>
{}; {};
template <>
struct ParamTraits<mozilla::YUVColorSpace>
: public ContiguousEnumSerializer<
mozilla::YUVColorSpace,
mozilla::YUVColorSpace::BT601,
mozilla::YUVColorSpace::UNKNOWN>
{};
template <> template <>
struct ParamTraits<mozilla::layers::ScrollableLayerGuid> struct ParamTraits<mozilla::layers::ScrollableLayerGuid>
{ {

Просмотреть файл

@ -158,6 +158,7 @@ BufferTextureData::CreateInternal(LayersIPCChannel* aAllocator,
BufferTextureData* BufferTextureData*
BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
int32_t aBufferSize, int32_t aBufferSize,
YUVColorSpace aYUVColorSpace,
TextureFlags aTextureFlags) TextureFlags aTextureFlags)
{ {
if (aBufferSize == 0 || !gfx::Factory::CheckBufferSize(aBufferSize)) { if (aBufferSize == 0 || !gfx::Factory::CheckBufferSize(aBufferSize)) {
@ -171,6 +172,7 @@ BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
// afterwards since we don't know the dimensions of the texture at this point. // afterwards since we don't know the dimensions of the texture at this point.
BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), gfx::IntSize(), BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), gfx::IntSize(),
0, 0, 0, StereoMode::MONO, 0, 0, 0, StereoMode::MONO,
aYUVColorSpace,
hasIntermediateBuffer); hasIntermediateBuffer);
return CreateInternal(aAllocator->GetTextureForwarder(), desc, gfx::BackendType::NONE, aBufferSize, return CreateInternal(aAllocator->GetTextureForwarder(), desc, gfx::BackendType::NONE, aBufferSize,
@ -182,6 +184,7 @@ BufferTextureData::CreateForYCbCr(KnowsCompositor* aAllocator,
gfx::IntSize aYSize, gfx::IntSize aYSize,
gfx::IntSize aCbCrSize, gfx::IntSize aCbCrSize,
StereoMode aStereoMode, StereoMode aStereoMode,
YUVColorSpace aYUVColorSpace,
TextureFlags aTextureFlags) TextureFlags aTextureFlags)
{ {
uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(aYSize, aCbCrSize); uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(aYSize, aCbCrSize);
@ -201,7 +204,7 @@ BufferTextureData::CreateForYCbCr(KnowsCompositor* aAllocator,
: true; : true;
YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aCbCrSize, yOffset, cbOffset, YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aCbCrSize, yOffset, cbOffset,
crOffset, aStereoMode, crOffset, aStereoMode, aYUVColorSpace,
hasIntermediateBuffer); hasIntermediateBuffer);
return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder() : nullptr, descriptor, return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder() : nullptr, descriptor,
@ -244,6 +247,12 @@ BufferTextureData::GetCbCrSize() const
return ImageDataSerializer::CbCrSizeFromBufferDescriptor(mDescriptor); return ImageDataSerializer::CbCrSizeFromBufferDescriptor(mDescriptor);
} }
Maybe<YUVColorSpace>
BufferTextureData::GetYUVColorSpace() const
{
return ImageDataSerializer::YUVColorSpaceFromBufferDescriptor(mDescriptor);
}
Maybe<StereoMode> Maybe<StereoMode>
BufferTextureData::GetStereoMode() const BufferTextureData::GetStereoMode() const
{ {

Просмотреть файл

@ -32,6 +32,7 @@ public:
gfx::IntSize aYSize, gfx::IntSize aYSize,
gfx::IntSize aCbCrSize, gfx::IntSize aCbCrSize,
StereoMode aStereoMode, StereoMode aStereoMode,
YUVColorSpace aYUVColorSpace,
TextureFlags aTextureFlags); TextureFlags aTextureFlags);
// It is generally better to use CreateForYCbCr instead. // It is generally better to use CreateForYCbCr instead.
@ -39,6 +40,7 @@ public:
// offsets in the buffer. // offsets in the buffer.
static BufferTextureData* CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, static BufferTextureData* CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
int32_t aSize, int32_t aSize,
YUVColorSpace aYUVColorSpace,
TextureFlags aTextureFlags); TextureFlags aTextureFlags);
virtual bool Lock(OpenMode aMode, FenceHandle*) override { return true; } virtual bool Lock(OpenMode aMode, FenceHandle*) override { return true; }
@ -63,6 +65,8 @@ public:
Maybe<gfx::IntSize> GetCbCrSize() const; Maybe<gfx::IntSize> GetCbCrSize() const;
Maybe<YUVColorSpace> GetYUVColorSpace() const;
Maybe<StereoMode> GetStereoMode() const; Maybe<StereoMode> GetStereoMode() const;
protected: protected:

Просмотреть файл

@ -688,6 +688,7 @@ struct PlanarYCbCrData {
uint32_t mPicY; uint32_t mPicY;
gfx::IntSize mPicSize; gfx::IntSize mPicSize;
StereoMode mStereoMode; StereoMode mStereoMode;
YUVColorSpace mYUVColorSpace;
gfx::IntRect GetPictureRect() const { gfx::IntRect GetPictureRect() const {
return gfx::IntRect(mPicX, mPicY, return gfx::IntRect(mPicX, mPicY,
@ -700,6 +701,7 @@ struct PlanarYCbCrData {
, mCbChannel(nullptr), mCrChannel(nullptr) , mCbChannel(nullptr), mCrChannel(nullptr)
, mCbCrStride(0), mCbCrSize(0, 0) , mCbSkip(0), mCrSkip(0) , mCbCrStride(0), mCbCrSize(0, 0) , mCbSkip(0), mCrSkip(0)
, mPicX(0), mPicY(0), mPicSize(0, 0), mStereoMode(StereoMode::MONO) , mPicX(0), mPicY(0), mPicSize(0, 0), mStereoMode(StereoMode::MONO)
, mYUVColorSpace(YUVColorSpace::BT601)
{} {}
}; };

Просмотреть файл

@ -135,6 +135,20 @@ Maybe<gfx::IntSize> CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescri
} }
} }
Maybe<YUVColorSpace> YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor)
{
{
switch (aDescriptor.type()) {
case BufferDescriptor::TRGBDescriptor:
return Nothing();
case BufferDescriptor::TYCbCrDescriptor:
return Some(aDescriptor.get_YCbCrDescriptor().yUVColorSpace());
default:
MOZ_CRASH("GFX: CbCrSizeFromBufferDescriptor");
}
}
}
Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor) Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor)
{ {
switch (aDescriptor.type()) { switch (aDescriptor.type()) {
@ -202,6 +216,7 @@ DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aD
ycbcrData.mCbCrStride = cbCrStride; ycbcrData.mCbCrStride = cbCrStride;
ycbcrData.mCbCrSize = cbCrSize; ycbcrData.mCbCrSize = cbCrSize;
ycbcrData.mPicSize = ySize; ycbcrData.mPicSize = ySize;
ycbcrData.mYUVColorSpace = aDescriptor.yUVColorSpace();
gfx::ConvertYCbCrToRGB(ycbcrData, gfx::ConvertYCbCrToRGB(ycbcrData,
gfx::SurfaceFormat::B8G8R8X8, gfx::SurfaceFormat::B8G8R8X8,
@ -236,6 +251,7 @@ ConvertAndScaleFromYCbCrDescriptor(uint8_t* aBuffer,
ycbcrData.mCbCrStride = cbCrStride; ycbcrData.mCbCrStride = cbCrStride;
ycbcrData.mCbCrSize = cbCrSize; ycbcrData.mCbCrSize = cbCrSize;
ycbcrData.mPicSize = ySize; ycbcrData.mPicSize = ySize;
ycbcrData.mYUVColorSpace = aDescriptor.yUVColorSpace();
gfx::ConvertYCbCrToRGB(ycbcrData, aDestFormat, aDestSize, aDestBuffer, aStride); gfx::ConvertYCbCrToRGB(ycbcrData, aDestFormat, aDestSize, aDestBuffer, aStride);
} }

Просмотреть файл

@ -60,6 +60,8 @@ gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
Maybe<gfx::IntSize> CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescriptor); Maybe<gfx::IntSize> CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
Maybe<YUVColorSpace> YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor);
Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor); Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor); uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);

Просмотреть файл

@ -115,6 +115,13 @@ enum class StereoMode {
MAX, MAX,
}; };
enum class YUVColorSpace {
BT601,
BT709,
// This represents the unknown format.
UNKNOWN,
};
} // namespace mozilla } // namespace mozilla
#endif #endif

Просмотреть файл

@ -123,6 +123,7 @@ ImageClient::CreateTextureClientForImage(Image* aImage, KnowsCompositor* aForwar
} }
texture = TextureClient::CreateForYCbCr(aForwarder, texture = TextureClient::CreateForYCbCr(aForwarder,
data->mYSize, data->mCbCrSize, data->mStereoMode, data->mYSize, data->mCbCrSize, data->mStereoMode,
data->mYUVColorSpace,
TextureFlags::DEFAULT); TextureFlags::DEFAULT);
if (!texture) { if (!texture) {
return nullptr; return nullptr;
@ -231,7 +232,6 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
RefPtr<GonkNativeHandle::NhObj> nhObj = overlayImage->GetSidebandStream().GetDupNhObj(); RefPtr<GonkNativeHandle::NhObj> nhObj = overlayImage->GetSidebandStream().GetDupNhObj();
GonkNativeHandle handle(nhObj); GonkNativeHandle handle(nhObj);
if (!handle.IsValid()) { if (!handle.IsValid()) {
gfxWarning() << "ImageClientSingle::UpdateImage failed in GetDupNhObj";
return false; return false;
} }
source.handle() = OverlayHandle(handle); source.handle() = OverlayHandle(handle);

Просмотреть файл

@ -1280,6 +1280,7 @@ TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
gfx::IntSize aYSize, gfx::IntSize aYSize,
gfx::IntSize aCbCrSize, gfx::IntSize aCbCrSize,
StereoMode aStereoMode, StereoMode aStereoMode,
YUVColorSpace aYUVColorSpace,
TextureFlags aTextureFlags) TextureFlags aTextureFlags)
{ {
// The only reason we allow aAllocator to be null is for gtests // The only reason we allow aAllocator to be null is for gtests
@ -1293,7 +1294,8 @@ TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
} }
TextureData* data = BufferTextureData::CreateForYCbCr(aAllocator, aYSize, aCbCrSize, TextureData* data = BufferTextureData::CreateForYCbCr(aAllocator, aYSize, aCbCrSize,
aStereoMode, aTextureFlags); aStereoMode, aYUVColorSpace,
aTextureFlags);
if (!data) { if (!data) {
return nullptr; return nullptr;
} }
@ -1306,6 +1308,7 @@ TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
already_AddRefed<TextureClient> already_AddRefed<TextureClient>
TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
size_t aSize, size_t aSize,
YUVColorSpace aYUVColorSpace,
TextureFlags aTextureFlags) TextureFlags aTextureFlags)
{ {
// also test the validity of aAllocator // also test the validity of aAllocator
@ -1315,7 +1318,7 @@ TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
} }
TextureData* data = TextureData* data =
BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aSize, BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aSize, aYUVColorSpace,
aTextureFlags); aTextureFlags);
if (!data) { if (!data) {
return nullptr; return nullptr;

Просмотреть файл

@ -367,6 +367,7 @@ public:
gfx::IntSize aYSize, gfx::IntSize aYSize,
gfx::IntSize aCbCrSize, gfx::IntSize aCbCrSize,
StereoMode aStereoMode, StereoMode aStereoMode,
YUVColorSpace aYUVColorSpace,
TextureFlags aTextureFlags); TextureFlags aTextureFlags);
// Creates and allocates a TextureClient (can be accessed through raw // Creates and allocates a TextureClient (can be accessed through raw
@ -385,6 +386,7 @@ public:
static already_AddRefed<TextureClient> static already_AddRefed<TextureClient>
CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
size_t aSize, size_t aSize,
YUVColorSpace aYUVColorSpace,
TextureFlags aTextureFlags); TextureFlags aTextureFlags);
// Creates and allocates a TextureClient of the same type. // Creates and allocates a TextureClient of the same type.

Просмотреть файл

@ -106,6 +106,8 @@ YCbCrTextureClientAllocationHelper::IsCompatible(TextureClient* aTextureClient)
aTextureClient->GetSize() != mData.mYSize || aTextureClient->GetSize() != mData.mYSize ||
bufferData->GetCbCrSize().isNothing() || bufferData->GetCbCrSize().isNothing() ||
bufferData->GetCbCrSize().ref() != mData.mCbCrSize || bufferData->GetCbCrSize().ref() != mData.mCbCrSize ||
bufferData->GetYUVColorSpace().isNothing() ||
bufferData->GetYUVColorSpace().ref() != mData.mYUVColorSpace ||
bufferData->GetStereoMode().isNothing() || bufferData->GetStereoMode().isNothing() ||
bufferData->GetStereoMode().ref() != mData.mStereoMode) { bufferData->GetStereoMode().ref() != mData.mStereoMode) {
return false; return false;
@ -119,6 +121,7 @@ YCbCrTextureClientAllocationHelper::Allocate(KnowsCompositor* aAllocator)
return TextureClient::CreateForYCbCr(aAllocator, return TextureClient::CreateForYCbCr(aAllocator,
mData.mYSize, mData.mCbCrSize, mData.mYSize, mData.mCbCrSize,
mData.mStereoMode, mData.mStereoMode,
mData.mYUVColorSpace,
mTextureFlags); mTextureFlags);
} }

Просмотреть файл

@ -8,6 +8,7 @@ using struct mozilla::layers::MagicGrallocBufferHandle from "gfxipc/ShadowLayerU
using struct mozilla::layers::GrallocBufferRef from "gfxipc/ShadowLayerUtils.h"; using struct mozilla::layers::GrallocBufferRef from "gfxipc/ShadowLayerUtils.h";
using struct mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h"; using struct mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h";
using mozilla::StereoMode from "ImageTypes.h"; using mozilla::StereoMode from "ImageTypes.h";
using mozilla::YUVColorSpace from "ImageTypes.h";
using struct mozilla::null_t from "ipc/IPCMessageUtils.h"; using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h"; using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h"; using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
@ -115,6 +116,7 @@ struct YCbCrDescriptor {
uint32_t cbOffset; uint32_t cbOffset;
uint32_t crOffset; uint32_t crOffset;
StereoMode stereoMode; StereoMode stereoMode;
YUVColorSpace yUVColorSpace;
bool hasIntermediateBuffer; bool hasIntermediateBuffer;
}; };

Просмотреть файл

@ -116,8 +116,10 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
return nullptr; return nullptr;
} }
// XXX Add YUVColorSpace handling. Use YUVColorSpace::BT601 for now.
mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(mCompositable->GetForwarder(), mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(mCompositable->GetForwarder(),
size, size,
YUVColorSpace::BT601,
mCompositable->GetTextureFlags()); mCompositable->GetTextureFlags());
// get new buffer _without_ setting mBuffer. // get new buffer _without_ setting mBuffer.
@ -163,7 +165,7 @@ SharedPlanarYCbCrImage::AdoptData(const Data &aData)
static_cast<BufferTextureData*>(mTextureClient->GetInternalData())->SetDesciptor( static_cast<BufferTextureData*>(mTextureClient->GetInternalData())->SetDesciptor(
YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset, YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset,
aData.mStereoMode, hasIntermediateBuffer) aData.mStereoMode, aData.mYUVColorSpace, hasIntermediateBuffer)
); );
return true; return true;
@ -219,6 +221,7 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
mData.mPicY = aData.mPicY; mData.mPicY = aData.mPicY;
mData.mPicSize = aData.mPicSize; mData.mPicSize = aData.mPicSize;
mData.mStereoMode = aData.mStereoMode; mData.mStereoMode = aData.mStereoMode;
mData.mYUVColorSpace = aData.mYUVColorSpace;
// those members are not always equal to aData's, due to potentially different // those members are not always equal to aData's, due to potentially different
// packing. // packing.
mData.mYSkip = 0; mData.mYSkip = 0;

Просмотреть файл

@ -258,6 +258,7 @@ TEST(Layers, TextureYCbCrSerialization) {
clientData.mYStride = ySurface->Stride(); clientData.mYStride = ySurface->Stride();
clientData.mCbCrStride = cbSurface->Stride(); clientData.mCbCrStride = cbSurface->Stride();
clientData.mStereoMode = StereoMode::MONO; clientData.mStereoMode = StereoMode::MONO;
clientData.mYUVColorSpace = YUVColorSpace::BT601;
clientData.mYSkip = 0; clientData.mYSkip = 0;
clientData.mCbSkip = 0; clientData.mCbSkip = 0;
clientData.mCrSkip = 0; clientData.mCrSkip = 0;
@ -266,7 +267,8 @@ TEST(Layers, TextureYCbCrSerialization) {
clientData.mPicX = 0; clientData.mPicX = 0;
RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(nullptr, clientData.mYSize, clientData.mCbCrSize, RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(nullptr, clientData.mYSize, clientData.mCbCrSize,
StereoMode::MONO, TextureFlags::DEALLOCATE_CLIENT); StereoMode::MONO, YUVColorSpace::BT601,
TextureFlags::DEALLOCATE_CLIENT);
TestTextureClientYCbCr(client, clientData); TestTextureClientYCbCr(client, clientData);

Просмотреть файл

@ -118,6 +118,7 @@ ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData,
aData.mCbCrStride, aData.mCbCrStride,
aStride, aStride,
yuvtype, yuvtype,
aData.mYUVColorSpace,
FILTER_BILINEAR); FILTER_BILINEAR);
} else { // no prescale } else { // no prescale
#if defined(HAVE_YCBCR_TO_RGB565) #if defined(HAVE_YCBCR_TO_RGB565)
@ -147,7 +148,8 @@ ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData,
aData.mYStride, aData.mYStride,
aData.mCbCrStride, aData.mCbCrStride,
aStride, aStride,
yuvtype); yuvtype,
aData.mYUVColorSpace);
} }
} }

Просмотреть файл

@ -71,6 +71,7 @@ struct YUVBuferIter {
const uint8* src_v; const uint8* src_v;
uint32 src_fourcc; uint32 src_fourcc;
const struct YuvConstants* yuvconstants;
int y_index; int y_index;
const uint8* src_row_y; const uint8* src_row_y;
const uint8* src_row_u; const uint8* src_row_u;
@ -200,15 +201,20 @@ static void YUVBuferIter_MoveToNextRowForI420(YUVBuferIter& iter) {
} }
static __inline void YUVBuferIter_ConvertToARGBRow(YUVBuferIter& iter, uint8* argb_row) { static __inline void YUVBuferIter_ConvertToARGBRow(YUVBuferIter& iter, uint8* argb_row) {
iter.YUVToARGBRow(iter.src_row_y, iter.src_row_u, iter.src_row_v, argb_row, &kYuvI601Constants, iter.src_width); iter.YUVToARGBRow(iter.src_row_y, iter.src_row_u, iter.src_row_v, argb_row, iter.yuvconstants, iter.src_width);
} }
void YUVBuferIter_Init(YUVBuferIter& iter, uint32 src_fourcc) { void YUVBuferIter_Init(YUVBuferIter& iter, uint32 src_fourcc, mozilla::YUVColorSpace yuv_color_space) {
iter.src_fourcc = src_fourcc; iter.src_fourcc = src_fourcc;
iter.y_index = 0; iter.y_index = 0;
iter.src_row_y = iter.src_y; iter.src_row_y = iter.src_y;
iter.src_row_u = iter.src_u; iter.src_row_u = iter.src_u;
iter.src_row_v = iter.src_v; iter.src_row_v = iter.src_v;
if (yuv_color_space == mozilla::YUVColorSpace::BT709) {
iter.yuvconstants = &kYuvH709Constants;
} else {
iter.yuvconstants = &kYuvI601Constants;
}
if (src_fourcc == FOURCC_I444) { if (src_fourcc == FOURCC_I444) {
YUVBuferIter_InitI444(iter); YUVBuferIter_InitI444(iter);
@ -241,7 +247,8 @@ static void ScaleYUVToARGBDown2(int src_width, int src_height,
uint8* dst_argb, uint8* dst_argb,
int x, int dx, int y, int dy, int x, int dx, int y, int dy,
enum FilterMode filtering, enum FilterMode filtering,
uint32 src_fourcc) { uint32 src_fourcc,
mozilla::YUVColorSpace yuv_color_space) {
int j; int j;
// Allocate 2 rows of ARGB for source conversion. // Allocate 2 rows of ARGB for source conversion.
@ -259,7 +266,7 @@ static void ScaleYUVToARGBDown2(int src_width, int src_height,
iter.src_y = src_y; iter.src_y = src_y;
iter.src_u = src_u; iter.src_u = src_u;
iter.src_v = src_v; iter.src_v = src_v;
YUVBuferIter_Init(iter, src_fourcc); YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
void (*ScaleARGBRowDown2)(const uint8* src_argb, ptrdiff_t src_stride, void (*ScaleARGBRowDown2)(const uint8* src_argb, ptrdiff_t src_stride,
uint8* dst_argb, int dst_width) = uint8* dst_argb, int dst_width) =
@ -377,7 +384,8 @@ static void ScaleYUVToARGBDownEven(int src_width, int src_height,
uint8* dst_argb, uint8* dst_argb,
int x, int dx, int y, int dy, int x, int dx, int y, int dy,
enum FilterMode filtering, enum FilterMode filtering,
uint32 src_fourcc) { uint32 src_fourcc,
mozilla::YUVColorSpace yuv_color_space) {
int j; int j;
// Allocate 2 rows of ARGB for source conversion. // Allocate 2 rows of ARGB for source conversion.
const int kRowSize = (src_width * 4 + 15) & ~15; const int kRowSize = (src_width * 4 + 15) & ~15;
@ -424,7 +432,7 @@ static void ScaleYUVToARGBDownEven(int src_width, int src_height,
iter.src_y = src_y; iter.src_y = src_y;
iter.src_u = src_u; iter.src_u = src_u;
iter.src_v = src_v; iter.src_v = src_v;
YUVBuferIter_Init(iter, src_fourcc); YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
const int dyi = dy >> 16; const int dyi = dy >> 16;
int lastyi = yi; int lastyi = yi;
@ -497,7 +505,8 @@ static void ScaleYUVToARGBBilinearDown(int src_width, int src_height,
uint8* dst_argb, uint8* dst_argb,
int x, int dx, int y, int dy, int x, int dx, int y, int dy,
enum FilterMode filtering, enum FilterMode filtering,
uint32 src_fourcc) { uint32 src_fourcc,
mozilla::YUVColorSpace yuv_color_space) {
int j; int j;
void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb, void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
ptrdiff_t src_stride, int dst_width, int source_y_fraction) = ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
@ -583,7 +592,7 @@ static void ScaleYUVToARGBBilinearDown(int src_width, int src_height,
iter.src_y = src_y; iter.src_y = src_y;
iter.src_u = src_u; iter.src_u = src_u;
iter.src_v = src_v; iter.src_v = src_v;
YUVBuferIter_Init(iter, src_fourcc); YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
iter.MoveTo(iter, yi); iter.MoveTo(iter, yi);
// TODO(fbarchard): Consider not allocating row buffer for kFilterLinear. // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
@ -665,7 +674,8 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height,
uint8* dst_argb, uint8* dst_argb,
int x, int dx, int y, int dy, int x, int dx, int y, int dy,
enum FilterMode filtering, enum FilterMode filtering,
uint32 src_fourcc) { uint32 src_fourcc,
mozilla::YUVColorSpace yuv_color_space) {
int j; int j;
void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb, void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
ptrdiff_t src_stride, int dst_width, int source_y_fraction) = ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
@ -762,7 +772,7 @@ static void ScaleYUVToARGBBilinearUp(int src_width, int src_height,
iter.src_y = src_y; iter.src_y = src_y;
iter.src_u = src_u; iter.src_u = src_u;
iter.src_v = src_v; iter.src_v = src_v;
YUVBuferIter_Init(iter, src_fourcc); YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
iter.MoveTo(iter, yi); iter.MoveTo(iter, yi);
// Allocate 2 rows of ARGB. // Allocate 2 rows of ARGB.
@ -848,7 +858,8 @@ static void ScaleYUVToARGBSimple(int src_width, int src_height,
const uint8* src_v, const uint8* src_v,
uint8* dst_argb, uint8* dst_argb,
int x, int dx, int y, int dy, int x, int dx, int y, int dy,
uint32 src_fourcc) { uint32 src_fourcc,
mozilla::YUVColorSpace yuv_color_space) {
int j; int j;
void (*ScaleARGBCols)(uint8* dst_argb, const uint8* src_argb, void (*ScaleARGBCols)(uint8* dst_argb, const uint8* src_argb,
int dst_width, int x, int dx) = int dst_width, int x, int dx) =
@ -890,7 +901,7 @@ static void ScaleYUVToARGBSimple(int src_width, int src_height,
iter.src_y = src_y; iter.src_y = src_y;
iter.src_u = src_u; iter.src_u = src_u;
iter.src_v = src_v; iter.src_v = src_v;
YUVBuferIter_Init(iter, src_fourcc); YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
iter.MoveTo(iter, yi); iter.MoveTo(iter, yi);
int lasty = yi; int lasty = yi;
@ -916,7 +927,8 @@ static void YUVToARGBCopy(const uint8* src_y, int src_stride_y,
int src_width, int src_height, int src_width, int src_height,
uint8* dst_argb, int dst_stride_argb, uint8* dst_argb, int dst_stride_argb,
int dst_width, int dst_height, int dst_width, int dst_height,
uint32 src_fourcc) uint32 src_fourcc,
mozilla::YUVColorSpace yuv_color_space)
{ {
YUVBuferIter iter; YUVBuferIter iter;
iter.src_width = src_width; iter.src_width = src_width;
@ -927,7 +939,7 @@ static void YUVToARGBCopy(const uint8* src_y, int src_stride_y,
iter.src_y = src_y; iter.src_y = src_y;
iter.src_u = src_u; iter.src_u = src_u;
iter.src_v = src_v; iter.src_v = src_v;
YUVBuferIter_Init(iter, src_fourcc); YUVBuferIter_Init(iter, src_fourcc, yuv_color_space);
for (int j = 0; j < dst_height; ++j) { for (int j = 0; j < dst_height; ++j) {
YUVBuferIter_ConvertToARGBRow(iter, dst_argb); YUVBuferIter_ConvertToARGBRow(iter, dst_argb);
@ -943,7 +955,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
uint8* dst_argb, int dst_stride_argb, uint8* dst_argb, int dst_stride_argb,
int dst_width, int dst_height, int dst_width, int dst_height,
enum FilterMode filtering, enum FilterMode filtering,
uint32 src_fourcc) uint32 src_fourcc,
mozilla::YUVColorSpace yuv_color_space)
{ {
// Initial source x/y coordinate and step values as 16.16 fixed point. // Initial source x/y coordinate and step values as 16.16 fixed point.
int x = 0; int x = 0;
@ -979,7 +992,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
dst_argb, dst_argb,
x, dx, y, dy, x, dx, y, dy,
filtering, filtering,
src_fourcc); src_fourcc,
yuv_color_space);
return; return;
} }
ScaleYUVToARGBDownEven(src_width, src_height, ScaleYUVToARGBDownEven(src_width, src_height,
@ -994,7 +1008,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
dst_argb, dst_argb,
x, dx, y, dy, x, dx, y, dy,
filtering, filtering,
src_fourcc); src_fourcc,
yuv_color_space);
return; return;
} }
// Optimized odd scale down. ie 3, 5, 7, 9x. // Optimized odd scale down. ie 3, 5, 7, 9x.
@ -1008,7 +1023,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
src_width, src_height, src_width, src_height,
dst_argb, dst_stride_argb, dst_argb, dst_stride_argb,
dst_width, dst_height, dst_width, dst_height,
src_fourcc); src_fourcc,
yuv_color_space);
return; return;
} }
} }
@ -1027,7 +1043,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
dst_argb, dst_argb,
x, dx, y, dy, x, dx, y, dy,
filtering, filtering,
src_fourcc); src_fourcc,
yuv_color_space);
return; return;
} }
if (filtering) { if (filtering) {
@ -1043,7 +1060,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
dst_argb, dst_argb,
x, dx, y, dy, x, dx, y, dy,
filtering, filtering,
src_fourcc); src_fourcc,
yuv_color_space);
return; return;
} }
ScaleYUVToARGBSimple(src_width, src_height, ScaleYUVToARGBSimple(src_width, src_height,
@ -1057,7 +1075,8 @@ static void ScaleYUVToARGB(const uint8* src_y, int src_stride_y,
src_v, src_v,
dst_argb, dst_argb,
x, dx, y, dy, x, dx, y, dy,
src_fourcc); src_fourcc,
yuv_color_space);
} }
bool IsConvertSupported(uint32 src_fourcc) bool IsConvertSupported(uint32 src_fourcc)
@ -1075,6 +1094,7 @@ int YUVToARGBScale(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u, const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v, const uint8* src_v, int src_stride_v,
uint32 src_fourcc, uint32 src_fourcc,
mozilla::YUVColorSpace yuv_color_space,
int src_width, int src_height, int src_width, int src_height,
uint8* dst_argb, int dst_stride_argb, uint8* dst_argb, int dst_stride_argb,
int dst_width, int dst_height, int dst_width, int dst_height,
@ -1095,7 +1115,8 @@ int YUVToARGBScale(const uint8* src_y, int src_stride_y,
dst_argb, dst_stride_argb, dst_argb, dst_stride_argb,
dst_width, dst_height, dst_width, dst_height,
filtering, filtering,
src_fourcc); src_fourcc,
yuv_color_space);
return 0; return 0;
} }

Просмотреть файл

@ -14,6 +14,8 @@
#include "libyuv/basic_types.h" #include "libyuv/basic_types.h"
#include "libyuv/scale.h" // For FilterMode #include "libyuv/scale.h" // For FilterMode
#include "ImageTypes.h" // For YUVColorSpace
#ifdef __cplusplus #ifdef __cplusplus
namespace libyuv { namespace libyuv {
extern "C" { extern "C" {
@ -23,6 +25,7 @@ int YUVToARGBScale(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u, const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v, const uint8* src_v, int src_stride_v,
uint32 src_fourcc, uint32 src_fourcc,
mozilla::YUVColorSpace yuv_color_space,
int src_width, int src_height, int src_width, int src_height,
uint8* dst_argb, int dst_stride_argb, uint8* dst_argb, int dst_stride_argb,
int dst_width, int dst_height, int dst_width, int dst_height,

Просмотреть файл

@ -75,7 +75,8 @@ void ConvertYCbCrToRGB32(const uint8* y_buf,
int y_pitch, int y_pitch,
int uv_pitch, int uv_pitch,
int rgb_pitch, int rgb_pitch,
YUVType yuv_type) { YUVType yuv_type,
YUVColorSpace yuv_color_space) {
// Deprecated function's conversion is accurate. // Deprecated function's conversion is accurate.
@ -87,7 +88,13 @@ void ConvertYCbCrToRGB32(const uint8* y_buf,
// The function is still fast on some old intel chips. // The function is still fast on some old intel chips.
// See Bug 1256475. // See Bug 1256475.
bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() || bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() ||
(supports_mmx() && supports_sse() && !supports_sse3()); (supports_mmx() && supports_sse() && !supports_sse3() &&
yuv_color_space == YUVColorSpace::BT601);
// The deprecated function only support BT601.
// See Bug 1210357.
if (yuv_color_space != YUVColorSpace::BT601) {
use_deprecated = false;
}
if (use_deprecated) { if (use_deprecated) {
ConvertYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf, rgb_buf, ConvertYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf, rgb_buf,
pic_x, pic_y, pic_width, pic_height, pic_x, pic_y, pic_width, pic_height,
@ -120,12 +127,22 @@ void ConvertYCbCrToRGB32(const uint8* y_buf,
const uint8* src_y = y_buf + y_pitch * pic_y + pic_x; const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
const uint8* src_u = u_buf + (uv_pitch * pic_y + pic_x) / 2; const uint8* src_u = u_buf + (uv_pitch * pic_y + pic_x) / 2;
const uint8* src_v = v_buf + (uv_pitch * pic_y + pic_x) / 2; const uint8* src_v = v_buf + (uv_pitch * pic_y + pic_x) / 2;
DebugOnly<int> err = libyuv::I420ToARGB(src_y, y_pitch, if (yuv_color_space == YUVColorSpace::BT709) {
src_u, uv_pitch, DebugOnly<int> err = libyuv::H420ToARGB(src_y, y_pitch,
src_v, uv_pitch, src_u, uv_pitch,
rgb_buf, rgb_pitch, src_v, uv_pitch,
pic_width, pic_height); rgb_buf, rgb_pitch,
MOZ_ASSERT(!err); pic_width, pic_height);
MOZ_ASSERT(!err);
} else {
MOZ_ASSERT(yuv_color_space == YUVColorSpace::BT601);
DebugOnly<int> err = libyuv::I420ToARGB(src_y, y_pitch,
src_u, uv_pitch,
src_v, uv_pitch,
rgb_buf, rgb_pitch,
pic_width, pic_height);
MOZ_ASSERT(!err);
}
} }
} }
@ -257,6 +274,7 @@ void ScaleYCbCrToRGB32(const uint8* y_buf,
int uv_pitch, int uv_pitch,
int rgb_pitch, int rgb_pitch,
YUVType yuv_type, YUVType yuv_type,
YUVColorSpace yuv_color_space,
ScaleFilter filter) { ScaleFilter filter) {
bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() || bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() ||
@ -265,6 +283,11 @@ void ScaleYCbCrToRGB32(const uint8* y_buf,
supports_sse3() || supports_sse3() ||
#endif #endif
(supports_mmx() && supports_sse() && !supports_sse3()); (supports_mmx() && supports_sse() && !supports_sse3());
// The deprecated function only support BT601.
// See Bug 1210357.
if (yuv_color_space != YUVColorSpace::BT601) {
use_deprecated = false;
}
if (use_deprecated) { if (use_deprecated) {
ScaleYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf, ScaleYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf,
rgb_buf, rgb_buf,
@ -283,6 +306,7 @@ void ScaleYCbCrToRGB32(const uint8* y_buf,
u_buf, uv_pitch, u_buf, uv_pitch,
v_buf, uv_pitch, v_buf, uv_pitch,
FourCCFromYUVType(yuv_type), FourCCFromYUVType(yuv_type),
yuv_color_space,
source_width, source_height, source_width, source_height,
rgb_buf, rgb_pitch, rgb_buf, rgb_pitch,
width, height, width, height,

Просмотреть файл

@ -6,6 +6,7 @@
#define MEDIA_BASE_YUV_CONVERT_H_ #define MEDIA_BASE_YUV_CONVERT_H_
#include "chromium_types.h" #include "chromium_types.h"
#include "ImageTypes.h"
namespace mozilla { namespace mozilla {
@ -55,7 +56,8 @@ void ConvertYCbCrToRGB32(const uint8* yplane,
int ystride, int ystride,
int uvstride, int uvstride,
int rgbstride, int rgbstride,
YUVType yuv_type); YUVType yuv_type,
YUVColorSpace yuv_color_space);
void ConvertYCbCrToRGB32_deprecated(const uint8* yplane, void ConvertYCbCrToRGB32_deprecated(const uint8* yplane,
const uint8* uplane, const uint8* uplane,
@ -84,6 +86,7 @@ void ScaleYCbCrToRGB32(const uint8* yplane,
int uvstride, int uvstride,
int rgbstride, int rgbstride,
YUVType yuv_type, YUVType yuv_type,
YUVColorSpace yuv_color_space,
ScaleFilter filter); ScaleFilter filter);
void ScaleYCbCrToRGB32_deprecated(const uint8* yplane, void ScaleYCbCrToRGB32_deprecated(const uint8* yplane,