зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1141979 - part4 - Add NVImage; r=jrmuizel
MozReview-Commit-ID: 9kacGnqHVRH --HG-- extra : transplant_source : %D2%95%C2%5E%F40%0D%86.%CD%F7%236%E8%D3%D8%7Frv%99
This commit is contained in:
Родитель
089b22220f
Коммит
802fc0f1d8
|
@ -10,6 +10,7 @@
|
|||
#include "gfx2DGlue.h"
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "gfxUtils.h" // for gfxUtils
|
||||
#include "libyuv.h"
|
||||
#include "mozilla/RefPtr.h" // for already_AddRefed
|
||||
#include "mozilla/ipc/CrossProcessMutex.h" // for CrossProcessMutex, etc
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
|
@ -598,6 +599,163 @@ PlanarYCbCrImage::GetAsSourceSurface()
|
|||
return surface.forget();
|
||||
}
|
||||
|
||||
NVImage::NVImage()
|
||||
: Image(nullptr, ImageFormat::NV_IMAGE)
|
||||
, mBufferSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
NVImage::~NVImage()
|
||||
{
|
||||
}
|
||||
|
||||
IntSize
|
||||
NVImage::GetSize()
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
IntRect
|
||||
NVImage::GetPictureRect()
|
||||
{
|
||||
return mData.GetPictureRect();
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface>
|
||||
NVImage::GetAsSourceSurface()
|
||||
{
|
||||
if (mSourceSurface) {
|
||||
RefPtr<gfx::SourceSurface> surface(mSourceSurface);
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
// Convert the current NV12 or NV21 data to YUV420P so that we can follow the
|
||||
// logics in PlanarYCbCrImage::GetAsSourceSurface().
|
||||
const int bufferLength = mData.mYSize.height * mData.mYStride +
|
||||
mData.mCbCrSize.height * mData.mCbCrSize.width * 2;
|
||||
uint8_t* buffer = new uint8_t[bufferLength];
|
||||
|
||||
Data aData = mData;
|
||||
aData.mCbCrStride = aData.mCbCrSize.width;
|
||||
aData.mCbSkip = 0;
|
||||
aData.mCrSkip = 0;
|
||||
aData.mYChannel = buffer;
|
||||
aData.mCbChannel = aData.mYChannel + aData.mYSize.height * aData.mYStride;
|
||||
aData.mCrChannel = aData.mCbChannel + aData.mCbCrSize.height * aData.mCbCrStride;
|
||||
|
||||
if (mData.mCbChannel < mData.mCrChannel) { // NV12
|
||||
libyuv::NV12ToI420(mData.mYChannel, mData.mYStride,
|
||||
mData.mCbChannel, mData.mCbCrStride,
|
||||
aData.mYChannel, aData.mYStride,
|
||||
aData.mCbChannel, aData.mCbCrStride,
|
||||
aData.mCrChannel, aData.mCbCrStride,
|
||||
aData.mYSize.width, aData.mYSize.height);
|
||||
} else { // NV21
|
||||
libyuv::NV21ToI420(mData.mYChannel, mData.mYStride,
|
||||
mData.mCrChannel, mData.mCbCrStride,
|
||||
aData.mYChannel, aData.mYStride,
|
||||
aData.mCbChannel, aData.mCbCrStride,
|
||||
aData.mCrChannel, aData.mCbCrStride,
|
||||
aData.mYSize.width, aData.mYSize.height);
|
||||
}
|
||||
|
||||
// The logics in PlanarYCbCrImage::GetAsSourceSurface().
|
||||
gfx::IntSize size(mSize);
|
||||
gfx::SurfaceFormat format =
|
||||
gfx::ImageFormatToSurfaceFormat(gfxPlatform::GetPlatform()->GetOffscreenFormat());
|
||||
gfx::GetYCbCrToRGBDestFormatAndSize(aData, format, size);
|
||||
if (mSize.width > PlanarYCbCrImage::MAX_DIMENSION ||
|
||||
mSize.height > PlanarYCbCrImage::MAX_DIMENSION) {
|
||||
NS_ERROR("Illegal image dest width or height");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> surface = gfx::Factory::CreateDataSourceSurface(size, format);
|
||||
if (NS_WARN_IF(!surface)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DataSourceSurface::ScopedMap mapping(surface, DataSourceSurface::WRITE);
|
||||
if (NS_WARN_IF(!mapping.IsMapped())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfx::ConvertYCbCrToRGB(aData, format, size, mapping.GetData(), mapping.GetStride());
|
||||
|
||||
mSourceSurface = surface;
|
||||
|
||||
// Release the temporary buffer.
|
||||
delete[] buffer;
|
||||
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
NVImage::IsValid()
|
||||
{
|
||||
return !!mBufferSize;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NVImage::GetBufferSize() const
|
||||
{
|
||||
return mBufferSize;
|
||||
}
|
||||
|
||||
NVImage*
|
||||
NVImage::AsNVImage()
|
||||
{
|
||||
return this;
|
||||
};
|
||||
|
||||
bool
|
||||
NVImage::SetData(const Data& aData)
|
||||
{
|
||||
MOZ_ASSERT(aData.mCbSkip == 1 && aData.mCrSkip == 1);
|
||||
MOZ_ASSERT((int)std::abs(aData.mCbChannel - aData.mCrChannel) == 1);
|
||||
|
||||
// Calculate buffer size
|
||||
const uint32_t size = aData.mYSize.height * aData.mYStride +
|
||||
aData.mCbCrSize.height * aData.mCbCrStride;
|
||||
|
||||
// Allocate a new buffer.
|
||||
mBuffer = AllocateBuffer(size);
|
||||
if (!mBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update mBufferSize.
|
||||
mBufferSize = size;
|
||||
|
||||
// Update mData.
|
||||
mData = aData;
|
||||
mData.mYChannel = mBuffer.get();
|
||||
mData.mCbChannel = mData.mYChannel + (aData.mCbChannel - aData.mYChannel);
|
||||
mData.mCrChannel = mData.mYChannel + (aData.mCrChannel - aData.mYChannel);
|
||||
|
||||
// Update mSize.
|
||||
mSize = aData.mPicSize;
|
||||
|
||||
// Copy the input data into mBuffer.
|
||||
// This copies the y-channel and the interleaving CbCr-channel.
|
||||
memcpy(mData.mYChannel, aData.mYChannel, mBufferSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const NVImage::Data*
|
||||
NVImage::GetData() const
|
||||
{
|
||||
return &mData;
|
||||
}
|
||||
|
||||
UniquePtr<uint8_t>
|
||||
NVImage::AllocateBuffer(uint32_t aSize)
|
||||
{
|
||||
UniquePtr<uint8_t> buffer(new uint8_t[aSize]);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
SourceSurfaceImage::SourceSurfaceImage(const gfx::IntSize& aSize, gfx::SourceSurface* aSourceSurface)
|
||||
: Image(nullptr, ImageFormat::CAIRO_SURFACE),
|
||||
mSize(aSize),
|
||||
|
|
|
@ -152,6 +152,7 @@ class PlanarYCbCrImage;
|
|||
class TextureClient;
|
||||
class CompositableClient;
|
||||
class GrallocImage;
|
||||
class NVImage;
|
||||
|
||||
struct ImageBackendData
|
||||
{
|
||||
|
@ -237,6 +238,8 @@ public:
|
|||
#endif
|
||||
virtual PlanarYCbCrImage* AsPlanarYCbCrImage() { return nullptr; }
|
||||
|
||||
virtual NVImage* AsNVImage() { return nullptr; }
|
||||
|
||||
protected:
|
||||
Image(void* aImplData, ImageFormat aFormat) :
|
||||
mImplData(aImplData),
|
||||
|
@ -814,6 +817,48 @@ protected:
|
|||
mozilla::UniquePtr<uint8_t[]> mBuffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* NVImage is used to store YUV420SP_NV12 and YUV420SP_NV21 data natively, which
|
||||
* are not supported by PlanarYCbCrImage. (PlanarYCbCrImage only stores YUV444P,
|
||||
* YUV422P and YUV420P, it converts YUV420SP_NV12 and YUV420SP_NV21 data into
|
||||
* YUV420P in its PlanarYCbCrImage::SetData() method.)
|
||||
*
|
||||
* PlanarYCbCrData is able to express all the YUV family and so we keep use it
|
||||
* in NVImage.
|
||||
*/
|
||||
class NVImage: public Image {
|
||||
typedef PlanarYCbCrData Data;
|
||||
|
||||
public:
|
||||
explicit NVImage();
|
||||
virtual ~NVImage() override;
|
||||
|
||||
// Methods inherited from layers::Image.
|
||||
virtual gfx::IntSize GetSize() override;
|
||||
virtual gfx::IntRect GetPictureRect() override;
|
||||
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||
virtual bool IsValid() override;
|
||||
virtual NVImage* AsNVImage() override;
|
||||
|
||||
// Methods mimic layers::PlanarYCbCrImage.
|
||||
virtual bool SetData(const Data& aData);
|
||||
virtual const Data* GetData() const;
|
||||
virtual uint32_t GetBufferSize() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Return a buffer to store image data in.
|
||||
*/
|
||||
mozilla::UniquePtr<uint8_t> AllocateBuffer(uint32_t aSize);
|
||||
|
||||
mozilla::UniquePtr<uint8_t> mBuffer;
|
||||
uint32_t mBufferSize;
|
||||
gfx::IntSize mSize;
|
||||
Data mData;
|
||||
nsCountedRef<nsMainThreadSourceSurfaceRef> mSourceSurface;
|
||||
};
|
||||
|
||||
/**
|
||||
* Currently, the data in a SourceSurfaceImage surface is treated as being in the
|
||||
* device output color space. This class is very simple as all backends
|
||||
|
|
|
@ -16,6 +16,12 @@ enum class ImageFormat {
|
|||
*/
|
||||
PLANAR_YCBCR,
|
||||
|
||||
/**
|
||||
* The NV_IMAGE format creates a NVImage. The PLANAR_YCBCR together with this
|
||||
* complete the YUV format family.
|
||||
*/
|
||||
NV_IMAGE,
|
||||
|
||||
/**
|
||||
* The GRALLOC_PLANAR_YCBCR format creates a GrallocImage, a subtype of
|
||||
* PlanarYCbCrImage. It takes a PlanarYCbCrImage data or the raw gralloc
|
||||
|
|
|
@ -428,6 +428,7 @@ LOCAL_INCLUDES += [
|
|||
'/docshell/base', # for nsDocShell.h
|
||||
'/layout/base', # for TouchManager.h
|
||||
'/layout/generic', # for nsTextFrame.h
|
||||
'/media/libyuv/include', # for libyuv.h
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
Загрузка…
Ссылка в новой задаче