From 35182074d321ce19f15df623b111268fe3ee6d88 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 27 Jun 2011 14:32:16 +1200 Subject: [PATCH] Bug 656185 - Part 2 - Handle odd crop offsets correctly with OpenGl. r=derf --- gfx/layers/ImageLayers.h | 20 +++ gfx/layers/Layers.cpp | 43 +++++++ gfx/layers/basic/BasicImages.cpp | 76 ++---------- gfx/layers/basic/BasicLayers.cpp | 28 +++-- gfx/layers/ipc/PLayers.ipdl | 1 + gfx/layers/opengl/ImageLayerOGL.cpp | 184 ++++++++-------------------- gfx/layers/opengl/ImageLayerOGL.h | 6 +- gfx/thebes/GLContext.cpp | 9 +- gfx/ycbcr/README | 2 + gfx/ycbcr/TypeFromSize.patch | 58 +++++++++ gfx/ycbcr/update.sh | 1 + gfx/ycbcr/yuv_convert.cpp | 16 +++ gfx/ycbcr/yuv_convert.h | 2 + 13 files changed, 230 insertions(+), 216 deletions(-) create mode 100644 gfx/ycbcr/TypeFromSize.patch diff --git a/gfx/layers/ImageLayers.h b/gfx/layers/ImageLayers.h index 4f2a01f7c0d..6edcf471481 100644 --- a/gfx/layers/ImageLayers.h +++ b/gfx/layers/ImageLayers.h @@ -407,6 +407,12 @@ public: PRUint32 mPicY; gfxIntSize mPicSize; StereoMode mStereoMode; + + nsIntRect GetPictureRect() const { + return nsIntRect(mPicX, mPicY, + mPicSize.width, + mPicSize.height); + } }; enum { @@ -433,6 +439,20 @@ public: */ 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: PlanarYCbCrImage(void* aImplData) : Image(aImplData, PLANAR_YCBCR) {} }; diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 5e3f49546f6..01e9f477b18 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -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 static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer); diff --git a/gfx/layers/basic/BasicImages.cpp b/gfx/layers/basic/BasicImages.cpp index 37fd33f4b7b..7b2c5e370c2 100644 --- a/gfx/layers/basic/BasicImages.cpp +++ b/gfx/layers/basic/BasicImages.cpp @@ -149,78 +149,16 @@ BasicPlanarYCbCrImage::SetData(const Data& aData) 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) { - - 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; + mBuffer = CopyData(mData, mSize, mBufferSize, aData); return; } + + gfx::YUVType type = + gfx::TypeFromSize(aData.mYSize.width, + aData.mYSize.height, + aData.mCbCrSize.width, + aData.mCbCrSize.height); gfxASurface::gfxImageFormat format = GetOffscreenFormat(); diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 8876aee2ebc..7cff68da073 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -2223,7 +2223,8 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext) YUVImage yuv(tmpYSurface->GetShmem(), tmpUSurface->GetShmem(), - tmpVSurface->GetShmem()); + tmpVSurface->GetShmem(), + data->GetPictureRect()); BasicManager()->CreatedImageBuffer(BasicManager()->Hold(this), nsIntSize(mSize.width, mSize.height), @@ -2231,19 +2232,24 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext) } - memcpy(mBackBufferY->Data(), - data->mYChannel, - data->mYStride * mSize.height); - memcpy(mBackBufferU->Data(), - data->mCbChannel, - data->mCbCrStride * mCbCrSize.height); - memcpy(mBackBufferV->Data(), - data->mCrChannel, - data->mCbCrStride * mCbCrSize.height); + for (int i = 0; i < data->mYSize.height; i++) { + memcpy(mBackBufferY->Data() + i * mBackBufferY->Stride(), + data->mYChannel + i * data->mYStride, + data->mYSize.width); + } + for (int i = 0; i < data->mCbCrSize.height; i++) { + memcpy(mBackBufferU->Data() + i * mBackBufferU->Stride(), + data->mCbChannel + i * data->mCbCrStride, + data->mCbCrSize.width); + memcpy(mBackBufferV->Data() + i * mBackBufferV->Stride(), + data->mCrChannel + i * data->mCbCrStride, + data->mCbCrSize.width); + } YUVImage yuv(mBackBufferY->GetShmem(), mBackBufferU->GetShmem(), - mBackBufferV->GetShmem()); + mBackBufferV->GetShmem(), + data->GetPictureRect()); BasicManager()->PaintedImage(BasicManager()->Hold(this), yuv); diff --git a/gfx/layers/ipc/PLayers.ipdl b/gfx/layers/ipc/PLayers.ipdl index fecaf456836..b1e8562c06f 100644 --- a/gfx/layers/ipc/PLayers.ipdl +++ b/gfx/layers/ipc/PLayers.ipdl @@ -87,6 +87,7 @@ struct YUVImage { Shmem Ydata; Shmem Udata; Shmem Vdata; + nsIntRect picture; }; union SharedImage { diff --git a/gfx/layers/opengl/ImageLayerOGL.cpp b/gfx/layers/opengl/ImageLayerOGL.cpp index 694eb1903fe..f041d940fac 100644 --- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -276,23 +276,29 @@ ImageContainerOGL::GetCurrentAsSurface(gfxIntSize *aSize) return nsnull; } - size = yuvImage->mSize; + size = yuvImage->mData.mPicSize; nsRefPtr imageSurface = 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, yuvImage->mData.mCbChannel, yuvImage->mData.mCrChannel, imageSurface->Data(), - 0, - 0, + yuvImage->mData.mPicX, + yuvImage->mData.mPicY, size.width, size.height, yuvImage->mData.mYStride, yuvImage->mData.mCbCrStride, imageSurface->Stride(), - yuvImage->mType); + type); *aSize = size; return imageSurface.forget().get(); @@ -432,7 +438,10 @@ ImageLayerOGL::RenderLayer(int, program->SetRenderOffset(aOffset); 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 // someone else forgets. @@ -662,84 +671,11 @@ PlanarYCbCrImageOGL::~PlanarYCbCrImageOGL() void 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 if (mBuffer) mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize); - - // update buffer size - 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; + + mBuffer = CopyData(mData, mSize, mBufferSize, aData); mHasData = PR_TRUE; } @@ -765,60 +701,28 @@ UploadYUVToTexture(GLContext* gl, const PlanarYCbCrImage::Data& aData, GLTexture* aUTexture, GLTexture* aVTexture) { - GLint alignment; - - if (!((ptrdiff_t)aData.mYStride & 0x7) && !((ptrdiff_t)aData.mYChannel & 0x7)) { - alignment = 8; - } else if (!((ptrdiff_t)aData.mYStride & 0x3)) { - alignment = 4; - } else if (!((ptrdiff_t)aData.mYStride & 0x1)) { - 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; - } + nsIntRect size(0, 0, aData.mYSize.width, aData.mYSize.height); + GLuint texture = aYTexture->GetTextureID(); + nsRefPtr surf = new gfxImageSurface(aData.mYChannel, + aData.mYSize, + aData.mYStride, + gfxASurface::ImageFormatA8); + gl->UploadSurfaceToTexture(surf, size, texture, true); - // Set texture alignment for Cb/Cr plane - gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment); + size = nsIntRect(0, 0, aData.mCbCrSize.width, aData.mCbCrSize.height); + 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()); - gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0, - 0, 0, aData.mCbCrSize.width, aData.mCbCrSize.height, - LOCAL_GL_LUMINANCE, - LOCAL_GL_UNSIGNED_BYTE, - aData.mCbChannel); - - 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); + texture = aVTexture->GetTextureID(); + surf = new gfxImageSurface(aData.mCrChannel, + aData.mCbCrSize, + aData.mCbCrStride, + gfxASurface::ImageFormatA8); + gl->UploadSurfaceToTexture(surf, size, texture, true); } void @@ -977,6 +881,9 @@ ShadowImageLayerOGL::Swap(const SharedImage& aNewFront, SharedImage* aNewBack) gfxSharedImageSurface::Open(yuv.Udata()); nsRefPtr surfV = gfxSharedImageSurface::Open(yuv.Vdata()); + + mPictureRect = yuv.picture(); + mSize = surfY->GetSize(); PlanarYCbCrImage::Data data; data.mYChannel = surfY->Data(); @@ -1056,11 +963,20 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer, yuvProgram->Activate(); yuvProgram->SetLayerQuadRect(nsIntRect(0, 0, - mSize.width, - mSize.height)); + mPictureRect.width, + mPictureRect.height)); yuvProgram->SetYCbCrTextureUnits(0, 1, 2); program = yuvProgram; + program->SetLayerTransform(GetEffectiveTransform()); + program->SetLayerOpacity(GetEffectiveOpacity()); + program->SetRenderOffset(aOffset); + + mOGLManager->BindAndDrawQuadWithTextureRect(program, + mPictureRect, + nsIntSize(mSize.width, mSize.height)); + + return; } program->SetLayerTransform(GetEffectiveTransform()); diff --git a/gfx/layers/opengl/ImageLayerOGL.h b/gfx/layers/opengl/ImageLayerOGL.h index 8a3f996b479..1f32798f30c 100644 --- a/gfx/layers/opengl/ImageLayerOGL.h +++ b/gfx/layers/opengl/ImageLayerOGL.h @@ -207,6 +207,10 @@ public: mTextures[2].IsAllocated(); } + PRUint8* AllocateBuffer(PRUint32 aSize) { + return mRecycleBin->GetBuffer(aSize); + } + nsAutoArrayPtr mBuffer; PRUint32 mBufferSize; nsRefPtr mRecycleBin; @@ -214,7 +218,6 @@ public: Data mData; gfxIntSize mSize; PRPackedBool mHasData; - gfx::YUVType mType; }; @@ -268,6 +271,7 @@ private: nsRefPtr mTexImage; GLTexture mYUVTexture[3]; gfxIntSize mSize; + nsIntRect mPictureRect; }; } /* layers */ diff --git a/gfx/thebes/GLContext.cpp b/gfx/thebes/GLContext.cpp index e648ce587af..6b85d1ab60a 100644 --- a/gfx/thebes/GLContext.cpp +++ b/gfx/thebes/GLContext.cpp @@ -1382,7 +1382,8 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface, if (!imageSurface || (imageSurface->Format() != gfxASurface::ImageFormatARGB32 && 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 nsIntRect bounds = aDstRegion.GetBounds(); imageSurface = @@ -1430,6 +1431,12 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface, type = LOCAL_GL_UNSIGNED_SHORT_5_6_5; shader = RGBALayerProgramType; 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: NS_ASSERTION(false, "Unhandled image surface format!"); format = 0; diff --git a/gfx/ycbcr/README b/gfx/ycbcr/README index 4bbcd0c88ea..95ea0fdb270 100644 --- a/gfx/ycbcr/README +++ b/gfx/ycbcr/README @@ -23,3 +23,5 @@ convert.patch contains the following changes: be properly guarded with cpuid() calls. win64.patch: SSE2 optimization for Microsoft Visual C++ x64 version + +TypeFromSize.patch: Bug 656185 - Add a method to detect YUVType from plane sizes. diff --git a/gfx/ycbcr/TypeFromSize.patch b/gfx/ycbcr/TypeFromSize.patch new file mode 100644 index 00000000000..e523cf71dc5 --- /dev/null +++ b/gfx/ycbcr/TypeFromSize.patch @@ -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, diff --git a/gfx/ycbcr/update.sh b/gfx/ycbcr/update.sh index 54f223683df..9b0c07ab54f 100644 --- a/gfx/ycbcr/update.sh +++ b/gfx/ycbcr/update.sh @@ -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 patch -p3