Bug 656185 - Part 2 - Handle odd crop offsets correctly with OpenGl. r=derf

This commit is contained in:
Matt Woodrow 2011-06-27 14:32:16 +12:00
Родитель 467c57b3b0
Коммит 35182074d3
13 изменённых файлов: 230 добавлений и 216 удалений

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

@ -407,6 +407,12 @@ public:
PRUint32 mPicY; PRUint32 mPicY;
gfxIntSize mPicSize; gfxIntSize mPicSize;
StereoMode mStereoMode; StereoMode mStereoMode;
nsIntRect GetPictureRect() const {
return nsIntRect(mPicX, mPicY,
mPicSize.width,
mPicSize.height);
}
}; };
enum { enum {
@ -433,6 +439,20 @@ public:
*/ */
virtual const Data* GetData() { return nsnull; } virtual const Data* GetData() { return nsnull; }
/**
* Make a copy of the YCbCr data.
*
* @param aDest Data object to store the plane data in.
* @param aDestSize Size of the Y plane that was copied.
* @param aDestBufferSize Number of bytes allocated for storage.
* @param aData Input image data.
* @return Raw data pointer for the planes or nsnull on failure.
*/
PRUint8 *CopyData(Data& aDest, gfxIntSize& aDestSize,
PRUint32& aDestBufferSize, const Data& aData);
virtual PRUint8* AllocateBuffer(PRUint32 aSize) { return new (mozilla::fallible_t()) PRUint8[aSize]; };
protected: protected:
PlanarYCbCrImage(void* aImplData) : Image(aImplData, PLANAR_YCBCR) {} PlanarYCbCrImage(void* aImplData) : Image(aImplData, PLANAR_YCBCR) {}
}; };

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

@ -481,6 +481,49 @@ ContainerLayer::DidInsertChild(Layer* aLayer)
} }
} }
PRUint8*
PlanarYCbCrImage::CopyData(Data& aDest, gfxIntSize& aDestSize,
PRUint32& aDestBufferSize, const Data& aData)
{
aDest = aData;
/* We always have a multiple of 16 width so we can force the stride */
aDest.mYStride = aDest.mYSize.width;
aDest.mCbCrStride = aDest.mCbCrSize.width;
// update buffer size
aDestBufferSize = aDest.mCbCrStride * aDest.mCbCrSize.height * 2 +
aDest.mYStride * aDest.mYSize.height;
// get new buffer
PRUint8* buffer = AllocateBuffer(aDestBufferSize);
if (!buffer)
return nsnull;
aDest.mYChannel = buffer;
aDest.mCbChannel = aDest.mYChannel + aDest.mYStride * aDest.mYSize.height;
aDest.mCrChannel = aDest.mCbChannel + aDest.mCbCrStride * aDest.mCbCrSize.height;
for (int i = 0; i < aDest.mYSize.height; i++) {
memcpy(aDest.mYChannel + i * aDest.mYStride,
aData.mYChannel + i * aData.mYStride,
aDest.mYStride);
}
for (int i = 0; i < aDest.mCbCrSize.height; i++) {
memcpy(aDest.mCbChannel + i * aDest.mCbCrStride,
aData.mCbChannel + i * aData.mCbCrStride,
aDest.mCbCrStride);
memcpy(aDest.mCrChannel + i * aDest.mCbCrStride,
aData.mCrChannel + i * aData.mCbCrStride,
aDest.mCbCrStride);
}
aDestSize = aData.mPicSize;
return buffer;
}
#ifdef MOZ_LAYERS_HAVE_LOG #ifdef MOZ_LAYERS_HAVE_LOG
static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer); static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer);

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

@ -149,78 +149,16 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
return; return;
} }
gfx::YUVType type = gfx::YV12;
int width_shift = 0;
int height_shift = 0;
if (aData.mYSize.width == aData.mCbCrSize.width &&
aData.mYSize.height == aData.mCbCrSize.height) {
type = gfx::YV24;
width_shift = 0;
height_shift = 0;
}
else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
aData.mYSize.height == aData.mCbCrSize.height) {
type = gfx::YV16;
width_shift = 1;
height_shift = 0;
}
else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
type = gfx::YV12;
width_shift = 1;
height_shift = 1;
}
else {
NS_ERROR("YCbCr format not supported");
}
if (mDelayedConversion) { if (mDelayedConversion) {
mBuffer = CopyData(mData, mSize, mBufferSize, aData);
mData = aData;
mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
// Round up the values for width and height to make sure we sample enough data
// for the last pixel - See bug 590735
if (width_shift && (aData.mPicSize.width & 1)) {
mData.mCbCrStride++;
mData.mCbCrSize.width++;
}
mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
if (height_shift && (aData.mPicSize.height & 1)) {
mData.mCbCrSize.height++;
}
mData.mYSize = aData.mPicSize;
mData.mYStride = mData.mYSize.width;
mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
mData.mYStride * mData.mYSize.height;
mBuffer = new PRUint8[mBufferSize];
mData.mYChannel = mBuffer;
mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
int cbcr_x = aData.mPicX >> width_shift;
int cbcr_y = aData.mPicY >> height_shift;
for (int i = 0; i < mData.mYSize.height; i++) {
memcpy(mData.mYChannel + i * mData.mYStride,
aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX,
mData.mYStride);
}
for (int i = 0; i < mData.mCbCrSize.height; i++) {
memcpy(mData.mCbChannel + i * mData.mCbCrStride,
aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
mData.mCbCrStride);
}
for (int i = 0; i < mData.mCbCrSize.height; i++) {
memcpy(mData.mCrChannel + i * mData.mCbCrStride,
aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
mData.mCbCrStride);
}
// Fix picture rect to be correct
mData.mPicX = mData.mPicY = 0;
mSize = aData.mPicSize;
return; return;
} }
gfx::YUVType type =
gfx::TypeFromSize(aData.mYSize.width,
aData.mYSize.height,
aData.mCbCrSize.width,
aData.mCbCrSize.height);
gfxASurface::gfxImageFormat format = GetOffscreenFormat(); gfxASurface::gfxImageFormat format = GetOffscreenFormat();

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

@ -2223,7 +2223,8 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext)
YUVImage yuv(tmpYSurface->GetShmem(), YUVImage yuv(tmpYSurface->GetShmem(),
tmpUSurface->GetShmem(), tmpUSurface->GetShmem(),
tmpVSurface->GetShmem()); tmpVSurface->GetShmem(),
data->GetPictureRect());
BasicManager()->CreatedImageBuffer(BasicManager()->Hold(this), BasicManager()->CreatedImageBuffer(BasicManager()->Hold(this),
nsIntSize(mSize.width, mSize.height), nsIntSize(mSize.width, mSize.height),
@ -2231,19 +2232,24 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext)
} }
memcpy(mBackBufferY->Data(), for (int i = 0; i < data->mYSize.height; i++) {
data->mYChannel, memcpy(mBackBufferY->Data() + i * mBackBufferY->Stride(),
data->mYStride * mSize.height); data->mYChannel + i * data->mYStride,
memcpy(mBackBufferU->Data(), data->mYSize.width);
data->mCbChannel, }
data->mCbCrStride * mCbCrSize.height); for (int i = 0; i < data->mCbCrSize.height; i++) {
memcpy(mBackBufferV->Data(), memcpy(mBackBufferU->Data() + i * mBackBufferU->Stride(),
data->mCrChannel, data->mCbChannel + i * data->mCbCrStride,
data->mCbCrStride * mCbCrSize.height); data->mCbCrSize.width);
memcpy(mBackBufferV->Data() + i * mBackBufferV->Stride(),
data->mCrChannel + i * data->mCbCrStride,
data->mCbCrSize.width);
}
YUVImage yuv(mBackBufferY->GetShmem(), YUVImage yuv(mBackBufferY->GetShmem(),
mBackBufferU->GetShmem(), mBackBufferU->GetShmem(),
mBackBufferV->GetShmem()); mBackBufferV->GetShmem(),
data->GetPictureRect());
BasicManager()->PaintedImage(BasicManager()->Hold(this), BasicManager()->PaintedImage(BasicManager()->Hold(this),
yuv); yuv);

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

@ -87,6 +87,7 @@ struct YUVImage {
Shmem Ydata; Shmem Ydata;
Shmem Udata; Shmem Udata;
Shmem Vdata; Shmem Vdata;
nsIntRect picture;
}; };
union SharedImage { union SharedImage {

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

@ -276,23 +276,29 @@ ImageContainerOGL::GetCurrentAsSurface(gfxIntSize *aSize)
return nsnull; return nsnull;
} }
size = yuvImage->mSize; size = yuvImage->mData.mPicSize;
nsRefPtr<gfxImageSurface> imageSurface = nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(size, gfxASurface::ImageFormatRGB24); new gfxImageSurface(size, gfxASurface::ImageFormatRGB24);
gfx::YUVType type =
gfx::TypeFromSize(yuvImage->mData.mYSize.width,
yuvImage->mData.mYSize.height,
yuvImage->mData.mCbCrSize.width,
yuvImage->mData.mCbCrSize.height);
gfx::ConvertYCbCrToRGB32(yuvImage->mData.mYChannel, gfx::ConvertYCbCrToRGB32(yuvImage->mData.mYChannel,
yuvImage->mData.mCbChannel, yuvImage->mData.mCbChannel,
yuvImage->mData.mCrChannel, yuvImage->mData.mCrChannel,
imageSurface->Data(), imageSurface->Data(),
0, yuvImage->mData.mPicX,
0, yuvImage->mData.mPicY,
size.width, size.width,
size.height, size.height,
yuvImage->mData.mYStride, yuvImage->mData.mYStride,
yuvImage->mData.mCbCrStride, yuvImage->mData.mCbCrStride,
imageSurface->Stride(), imageSurface->Stride(),
yuvImage->mType); type);
*aSize = size; *aSize = size;
return imageSurface.forget().get(); return imageSurface.forget().get();
@ -432,7 +438,10 @@ ImageLayerOGL::RenderLayer(int,
program->SetRenderOffset(aOffset); program->SetRenderOffset(aOffset);
program->SetYCbCrTextureUnits(0, 1, 2); program->SetYCbCrTextureUnits(0, 1, 2);
mOGLManager->BindAndDrawQuad(program); mOGLManager->BindAndDrawQuadWithTextureRect(program,
yuvImage->mData.GetPictureRect(),
nsIntSize(yuvImage->mData.mYSize.width,
yuvImage->mData.mYSize.height));
// We shouldn't need to do this, but do it anyway just in case // We shouldn't need to do this, but do it anyway just in case
// someone else forgets. // someone else forgets.
@ -662,84 +671,11 @@ PlanarYCbCrImageOGL::~PlanarYCbCrImageOGL()
void void
PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData) PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData)
{ {
// For now, we copy the data
int width_shift = 0;
int height_shift = 0;
if (aData.mYSize.width == aData.mCbCrSize.width &&
aData.mYSize.height == aData.mCbCrSize.height) {
// YV24 format
width_shift = 0;
height_shift = 0;
mType = gfx::YV24;
} else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
aData.mYSize.height == aData.mCbCrSize.height) {
// YV16 format
width_shift = 1;
height_shift = 0;
mType = gfx::YV16;
} else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
// YV12 format
width_shift = 1;
height_shift = 1;
mType = gfx::YV12;
} else {
NS_ERROR("YCbCr format not supported");
}
mData = aData;
mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
// Round up the values for width and height to make sure we sample enough data
// for the last pixel - See bug 590735
if (width_shift && (aData.mPicSize.width & 1)) {
mData.mCbCrStride++;
mData.mCbCrSize.width++;
}
mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
if (height_shift && (aData.mPicSize.height & 1)) {
mData.mCbCrSize.height++;
}
mData.mYSize = aData.mPicSize;
mData.mYStride = mData.mYSize.width;
// Recycle the previous image main-memory buffer now that we're about to get a new buffer // Recycle the previous image main-memory buffer now that we're about to get a new buffer
if (mBuffer) if (mBuffer)
mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize); mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
// update buffer size mBuffer = CopyData(mData, mSize, mBufferSize, aData);
mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
mData.mYStride * mData.mYSize.height;
// get new buffer
mBuffer = mRecycleBin->GetBuffer(mBufferSize);
if (!mBuffer)
return;
mData.mYChannel = mBuffer;
mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
int cbcr_x = aData.mPicX >> width_shift;
int cbcr_y = aData.mPicY >> height_shift;
for (int i = 0; i < mData.mYSize.height; i++) {
memcpy(mData.mYChannel + i * mData.mYStride,
aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX,
mData.mYStride);
}
for (int i = 0; i < mData.mCbCrSize.height; i++) {
memcpy(mData.mCbChannel + i * mData.mCbCrStride,
aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
mData.mCbCrStride);
}
for (int i = 0; i < mData.mCbCrSize.height; i++) {
memcpy(mData.mCrChannel + i * mData.mCbCrStride,
aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
mData.mCbCrStride);
}
// Fix picture rect to be correct
mData.mPicX = mData.mPicY = 0;
mSize = aData.mPicSize;
mHasData = PR_TRUE; mHasData = PR_TRUE;
} }
@ -765,60 +701,28 @@ UploadYUVToTexture(GLContext* gl, const PlanarYCbCrImage::Data& aData,
GLTexture* aUTexture, GLTexture* aUTexture,
GLTexture* aVTexture) GLTexture* aVTexture)
{ {
GLint alignment; nsIntRect size(0, 0, aData.mYSize.width, aData.mYSize.height);
GLuint texture = aYTexture->GetTextureID();
if (!((ptrdiff_t)aData.mYStride & 0x7) && !((ptrdiff_t)aData.mYChannel & 0x7)) { nsRefPtr<gfxASurface> surf = new gfxImageSurface(aData.mYChannel,
alignment = 8; aData.mYSize,
} else if (!((ptrdiff_t)aData.mYStride & 0x3)) { aData.mYStride,
alignment = 4; gfxASurface::ImageFormatA8);
} else if (!((ptrdiff_t)aData.mYStride & 0x1)) { gl->UploadSurfaceToTexture(surf, size, texture, true);
alignment = 2;
} else {
alignment = 1;
}
// Set texture alignment for Y plane.
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment);
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aYTexture->GetTextureID());
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
0, 0, aData.mYSize.width, aData.mYSize.height,
LOCAL_GL_LUMINANCE,
LOCAL_GL_UNSIGNED_BYTE,
aData.mYChannel);
if (!((ptrdiff_t)aData.mCbCrStride & 0x7) &&
!((ptrdiff_t)aData.mCbChannel & 0x7) &&
!((ptrdiff_t)aData.mCrChannel & 0x7))
{
alignment = 8;
} else if (!((ptrdiff_t)aData.mCbCrStride & 0x3)) {
alignment = 4;
} else if (!((ptrdiff_t)aData.mCbCrStride & 0x1)) {
alignment = 2;
} else {
alignment = 1;
}
// Set texture alignment for Cb/Cr plane size = nsIntRect(0, 0, aData.mCbCrSize.width, aData.mCbCrSize.height);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment); texture = aUTexture->GetTextureID();
surf = new gfxImageSurface(aData.mCbChannel,
aData.mCbCrSize,
aData.mCbCrStride,
gfxASurface::ImageFormatA8);
gl->UploadSurfaceToTexture(surf, size, texture, true);
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aUTexture->GetTextureID()); texture = aVTexture->GetTextureID();
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0, surf = new gfxImageSurface(aData.mCrChannel,
0, 0, aData.mCbCrSize.width, aData.mCbCrSize.height, aData.mCbCrSize,
LOCAL_GL_LUMINANCE, aData.mCbCrStride,
LOCAL_GL_UNSIGNED_BYTE, gfxASurface::ImageFormatA8);
aData.mCbChannel); gl->UploadSurfaceToTexture(surf, size, texture, true);
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aVTexture->GetTextureID());
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
0, 0, aData.mCbCrSize.width, aData.mCbCrSize.height,
LOCAL_GL_LUMINANCE,
LOCAL_GL_UNSIGNED_BYTE,
aData.mCrChannel);
// Reset alignment to default
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
} }
void void
@ -977,6 +881,9 @@ ShadowImageLayerOGL::Swap(const SharedImage& aNewFront, SharedImage* aNewBack)
gfxSharedImageSurface::Open(yuv.Udata()); gfxSharedImageSurface::Open(yuv.Udata());
nsRefPtr<gfxSharedImageSurface> surfV = nsRefPtr<gfxSharedImageSurface> surfV =
gfxSharedImageSurface::Open(yuv.Vdata()); gfxSharedImageSurface::Open(yuv.Vdata());
mPictureRect = yuv.picture();
mSize = surfY->GetSize();
PlanarYCbCrImage::Data data; PlanarYCbCrImage::Data data;
data.mYChannel = surfY->Data(); data.mYChannel = surfY->Data();
@ -1056,11 +963,20 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
yuvProgram->Activate(); yuvProgram->Activate();
yuvProgram->SetLayerQuadRect(nsIntRect(0, 0, yuvProgram->SetLayerQuadRect(nsIntRect(0, 0,
mSize.width, mPictureRect.width,
mSize.height)); mPictureRect.height));
yuvProgram->SetYCbCrTextureUnits(0, 1, 2); yuvProgram->SetYCbCrTextureUnits(0, 1, 2);
program = yuvProgram; program = yuvProgram;
program->SetLayerTransform(GetEffectiveTransform());
program->SetLayerOpacity(GetEffectiveOpacity());
program->SetRenderOffset(aOffset);
mOGLManager->BindAndDrawQuadWithTextureRect(program,
mPictureRect,
nsIntSize(mSize.width, mSize.height));
return;
} }
program->SetLayerTransform(GetEffectiveTransform()); program->SetLayerTransform(GetEffectiveTransform());

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

@ -207,6 +207,10 @@ public:
mTextures[2].IsAllocated(); mTextures[2].IsAllocated();
} }
PRUint8* AllocateBuffer(PRUint32 aSize) {
return mRecycleBin->GetBuffer(aSize);
}
nsAutoArrayPtr<PRUint8> mBuffer; nsAutoArrayPtr<PRUint8> mBuffer;
PRUint32 mBufferSize; PRUint32 mBufferSize;
nsRefPtr<RecycleBin> mRecycleBin; nsRefPtr<RecycleBin> mRecycleBin;
@ -214,7 +218,6 @@ public:
Data mData; Data mData;
gfxIntSize mSize; gfxIntSize mSize;
PRPackedBool mHasData; PRPackedBool mHasData;
gfx::YUVType mType;
}; };
@ -268,6 +271,7 @@ private:
nsRefPtr<TextureImage> mTexImage; nsRefPtr<TextureImage> mTexImage;
GLTexture mYUVTexture[3]; GLTexture mYUVTexture[3];
gfxIntSize mSize; gfxIntSize mSize;
nsIntRect mPictureRect;
}; };
} /* layers */ } /* layers */

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

@ -1382,7 +1382,8 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
if (!imageSurface || if (!imageSurface ||
(imageSurface->Format() != gfxASurface::ImageFormatARGB32 && (imageSurface->Format() != gfxASurface::ImageFormatARGB32 &&
imageSurface->Format() != gfxASurface::ImageFormatRGB24 && imageSurface->Format() != gfxASurface::ImageFormatRGB24 &&
imageSurface->Format() != gfxASurface::ImageFormatRGB16_565)) { imageSurface->Format() != gfxASurface::ImageFormatRGB16_565 &&
imageSurface->Format() != gfxASurface::ImageFormatA8)) {
// We can't get suitable pixel data for the surface, make a copy // We can't get suitable pixel data for the surface, make a copy
nsIntRect bounds = aDstRegion.GetBounds(); nsIntRect bounds = aDstRegion.GetBounds();
imageSurface = imageSurface =
@ -1430,6 +1431,12 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
type = LOCAL_GL_UNSIGNED_SHORT_5_6_5; type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
shader = RGBALayerProgramType; shader = RGBALayerProgramType;
break; break;
case gfxASurface::ImageFormatA8:
format = LOCAL_GL_LUMINANCE;
type = LOCAL_GL_UNSIGNED_BYTE;
// We don't have a specific luminance shader
shader = ShaderProgramType(0);
break;
default: default:
NS_ASSERTION(false, "Unhandled image surface format!"); NS_ASSERTION(false, "Unhandled image surface format!");
format = 0; format = 0;

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

@ -23,3 +23,5 @@ convert.patch contains the following changes:
be properly guarded with cpuid() calls. be properly guarded with cpuid() calls.
win64.patch: SSE2 optimization for Microsoft Visual C++ x64 version win64.patch: SSE2 optimization for Microsoft Visual C++ x64 version
TypeFromSize.patch: Bug 656185 - Add a method to detect YUVType from plane sizes.

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

@ -0,0 +1,58 @@
diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
--- a/gfx/ycbcr/yuv_convert.cpp
+++ b/gfx/ycbcr/yuv_convert.cpp
@@ -26,16 +26,32 @@ namespace mozilla {
namespace gfx {
// 16.16 fixed point arithmetic
const int kFractionBits = 16;
const int kFractionMax = 1 << kFractionBits;
const int kFractionMask = ((1 << kFractionBits) - 1);
+NS_GFX_(YUVType) TypeFromSize(int ywidth,
+ int yheight,
+ int cbcrwidth,
+ int cbcrheight)
+{
+ if (ywidth == cbcrwidth && yheight == cbcrheight) {
+ return YV24;
+ }
+ else if (ywidth / 2 == cbcrwidth && yheight == cbcrheight) {
+ return YV16;
+ }
+ else {
+ return YV12;
+ }
+}
+
// Convert a frame of YUV to 32 bit ARGB.
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int pic_x,
int pic_y,
int pic_width,
diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
--- a/gfx/ycbcr/yuv_convert.h
+++ b/gfx/ycbcr/yuv_convert.h
@@ -36,16 +36,18 @@ enum Rotate {
// Filter affects how scaling looks.
enum ScaleFilter {
FILTER_NONE = 0, // No filter (point sampled).
FILTER_BILINEAR_H = 1, // Bilinear horizontal filter.
FILTER_BILINEAR_V = 2, // Bilinear vertical filter.
FILTER_BILINEAR = 3 // Bilinear filter.
};
+NS_GFX_(YUVType) TypeFromSize(int ywidth, int yheight, int cbcrwidth, int cbcrheight);
+
// Convert a frame of YUV to 32 bit ARGB.
// Pass in YV16/YV12 depending on source format
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane,
const uint8* uplane,
const uint8* vplane,
uint8* rgbframe,
int pic_x,
int pic_y,

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

@ -8,3 +8,4 @@ cp $1/media/base/yuv_row_win.cc yuv_row_win.cpp
cp $1/media/base/yuv_row_posix.cc yuv_row_c.cpp cp $1/media/base/yuv_row_posix.cc yuv_row_c.cpp
patch -p3 <convert.patch patch -p3 <convert.patch
patch -p3 <win64.patch patch -p3 <win64.patch
patch -p3 <TypeFromSize.patch

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

@ -31,6 +31,22 @@ const int kFractionBits = 16;
const int kFractionMax = 1 << kFractionBits; const int kFractionMax = 1 << kFractionBits;
const int kFractionMask = ((1 << kFractionBits) - 1); const int kFractionMask = ((1 << kFractionBits) - 1);
NS_GFX_(YUVType) TypeFromSize(int ywidth,
int yheight,
int cbcrwidth,
int cbcrheight)
{
if (ywidth == cbcrwidth && yheight == cbcrheight) {
return YV24;
}
else if (ywidth / 2 == cbcrwidth && yheight == cbcrheight) {
return YV16;
}
else {
return YV12;
}
}
// Convert a frame of YUV to 32 bit ARGB. // Convert a frame of YUV to 32 bit ARGB.
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf, NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf,
const uint8* u_buf, const uint8* u_buf,

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

@ -41,6 +41,8 @@ enum ScaleFilter {
FILTER_BILINEAR = 3 // Bilinear filter. FILTER_BILINEAR = 3 // Bilinear filter.
}; };
NS_GFX_(YUVType) TypeFromSize(int ywidth, int yheight, int cbcrwidth, int cbcrheight);
// Convert a frame of YUV to 32 bit ARGB. // Convert a frame of YUV to 32 bit ARGB.
// Pass in YV16/YV12 depending on source format // Pass in YV16/YV12 depending on source format
NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane, NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane,