зеркало из https://github.com/mozilla/gecko-dev.git
Bug 767480 - Gralloc backed video buffer. r=roc
This commit is contained in:
Родитель
a55761dc81
Коммит
967b36e8ae
|
@ -63,6 +63,20 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
|
|||
aPlane.mStride > 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsYV12Format(const VideoData::YCbCrBuffer::Plane& aYPlane,
|
||||
const VideoData::YCbCrBuffer::Plane& aCbPlane,
|
||||
const VideoData::YCbCrBuffer::Plane& aCrPlane)
|
||||
{
|
||||
return
|
||||
aYPlane.mWidth % 2 == 0 &&
|
||||
aYPlane.mHeight % 2 == 0 &&
|
||||
aYPlane.mWidth / 2 == aCbPlane.mWidth &&
|
||||
aYPlane.mHeight / 2 == aCbPlane.mHeight &&
|
||||
aCbPlane.mWidth == aCrPlane.mWidth &&
|
||||
aCbPlane.mHeight == aCrPlane.mHeight;
|
||||
}
|
||||
|
||||
bool
|
||||
nsVideoInfo::ValidateVideoRegion(const nsIntSize& aFrame,
|
||||
const nsIntRect& aPicture,
|
||||
|
@ -183,22 +197,27 @@ VideoData* VideoData::Create(nsVideoInfo& aInfo,
|
|||
aKeyframe,
|
||||
aTimecode,
|
||||
aInfo.mDisplay));
|
||||
// Currently our decoder only knows how to output to PLANAR_YCBCR
|
||||
// format.
|
||||
ImageFormat format = PLANAR_YCBCR;
|
||||
v->mImage = aContainer->CreateImage(&format, 1);
|
||||
if (!v->mImage) {
|
||||
return nullptr;
|
||||
}
|
||||
NS_ASSERTION(v->mImage->GetFormat() == PLANAR_YCBCR,
|
||||
"Wrong format?");
|
||||
PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
|
||||
|
||||
PlanarYCbCrImage::Data data;
|
||||
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
|
||||
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
|
||||
const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
|
||||
|
||||
// Currently our decoder only knows how to output to PLANAR_YCBCR
|
||||
// format.
|
||||
ImageFormat format[2] = {PLANAR_YCBCR, GRALLOC_PLANAR_YCBCR};
|
||||
if (IsYV12Format(Y, Cb, Cr)) {
|
||||
v->mImage = aContainer->CreateImage(format, 2);
|
||||
} else {
|
||||
v->mImage = aContainer->CreateImage(format, 1);
|
||||
}
|
||||
if (!v->mImage) {
|
||||
return nullptr;
|
||||
}
|
||||
NS_ASSERTION(v->mImage->GetFormat() == PLANAR_YCBCR ||
|
||||
v->mImage->GetFormat() == GRALLOC_PLANAR_YCBCR,
|
||||
"Wrong format?");
|
||||
PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
|
||||
|
||||
PlanarYCbCrImage::Data data;
|
||||
data.mYChannel = Y.mData;
|
||||
data.mYSize = gfxIntSize(Y.mWidth, Y.mHeight);
|
||||
data.mYStride = Y.mStride;
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "GrallocImages.h"
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
using namespace android;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
GrallocPlanarYCbCrImage::GrallocPlanarYCbCrImage()
|
||||
: PlanarYCbCrImage(nullptr)
|
||||
{
|
||||
mFormat = GRALLOC_PLANAR_YCBCR;
|
||||
}
|
||||
|
||||
GrallocPlanarYCbCrImage::~GrallocPlanarYCbCrImage()
|
||||
{
|
||||
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
|
||||
ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
|
||||
}
|
||||
|
||||
void
|
||||
GrallocPlanarYCbCrImage::SetData(const Data& aData)
|
||||
{
|
||||
NS_PRECONDITION(aData.mYSize.width % 2 == 0, "Image should have even width");
|
||||
NS_PRECONDITION(aData.mYSize.height % 2 == 0, "Image should have even height");
|
||||
NS_PRECONDITION(aData.mYStride % 16 == 0, "Image should have stride of multiple of 16 pixels");
|
||||
|
||||
mData = aData;
|
||||
mSize = aData.mPicSize;
|
||||
|
||||
if (mSurfaceDescriptor.type() == SurfaceDescriptor::T__None) {
|
||||
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
|
||||
ibc->AllocSurfaceDescriptorGralloc(aData.mYSize,
|
||||
HAL_PIXEL_FORMAT_YV12,
|
||||
GraphicBuffer::USAGE_SW_READ_OFTEN |
|
||||
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
|
||||
GraphicBuffer::USAGE_HW_TEXTURE,
|
||||
&mSurfaceDescriptor);
|
||||
}
|
||||
sp<GraphicBuffer> graphicBuffer =
|
||||
GrallocBufferActor::GetFrom(mSurfaceDescriptor.get_SurfaceDescriptorGralloc());
|
||||
if (!graphicBuffer.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (graphicBuffer->initCheck() != NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
void* vaddr;
|
||||
if (graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
|
||||
&vaddr) != OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
PRUint8* yChannel = static_cast<PRUint8*>(vaddr);
|
||||
gfxIntSize ySize = gfxIntSize(aData.mYSize.width,
|
||||
aData.mYSize.height);
|
||||
PRInt32 yStride = graphicBuffer->getStride();
|
||||
|
||||
PRUint8* vChannel = yChannel + (yStride * ySize.height);
|
||||
gfxIntSize uvSize = gfxIntSize(ySize.width / 2,
|
||||
ySize.height / 2);
|
||||
// Align to 16 bytes boundary
|
||||
PRInt32 uvStride = ((yStride / 2) + 15) & ~0x0F;
|
||||
PRUint8* uChannel = vChannel + (uvStride * uvSize.height);
|
||||
|
||||
// Memory outside of the image width may not writable. If the stride
|
||||
// equals to the image width then we can use only one copy.
|
||||
if (yStride == mData.mYStride &&
|
||||
yStride == ySize.width) {
|
||||
memcpy(yChannel, mData.mYChannel, yStride * ySize.width);
|
||||
} else {
|
||||
for (int i = 0; i < ySize.height; i++) {
|
||||
memcpy(yChannel + i * yStride,
|
||||
mData.mYChannel + i * mData.mYStride,
|
||||
ySize.width);
|
||||
}
|
||||
}
|
||||
if (uvStride == mData.mCbCrStride &&
|
||||
uvStride == uvSize.width) {
|
||||
memcpy(uChannel, mData.mCbChannel, uvStride * uvSize.width);
|
||||
memcpy(vChannel, mData.mCrChannel, uvStride * uvSize.width);
|
||||
} else {
|
||||
for (int i = 0; i < uvSize.height; i++) {
|
||||
memcpy(uChannel + i * uvStride,
|
||||
mData.mCbChannel + i * mData.mCbCrStride,
|
||||
uvSize.width);
|
||||
memcpy(vChannel + i * uvStride,
|
||||
mData.mCrChannel + i * mData.mCbCrStride,
|
||||
uvSize.width);
|
||||
}
|
||||
}
|
||||
graphicBuffer->unlock();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,70 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GRALLOCIMAGES_H
|
||||
#define GRALLOCIMAGES_H
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
|
||||
#include "mozilla/layers/LayersSurfaces.h"
|
||||
#include "ImageLayers.h"
|
||||
|
||||
#include <ui/GraphicBuffer.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* The YUV format supported by Android HAL
|
||||
*
|
||||
* 4:2:0 - CbCr width and height is half that of Y.
|
||||
*
|
||||
* This format assumes
|
||||
* - an even width
|
||||
* - an even height
|
||||
* - a horizontal stride multiple of 16 pixels
|
||||
* - a vertical stride equal to the height
|
||||
*
|
||||
* y_size = stride * height
|
||||
* c_size = ALIGN(stride/2, 16) * height/2
|
||||
* size = y_size + c_size * 2
|
||||
* cr_offset = y_size
|
||||
* cb_offset = y_size + c_size
|
||||
*
|
||||
* The Image that is rendered is the picture region defined by
|
||||
* mPicX, mPicY and mPicSize. The size of the rendered image is
|
||||
* mPicSize, not mYSize or mCbCrSize.
|
||||
*/
|
||||
class THEBES_API GrallocPlanarYCbCrImage : public PlanarYCbCrImage {
|
||||
typedef PlanarYCbCrImage::Data Data;
|
||||
|
||||
public:
|
||||
GrallocPlanarYCbCrImage();
|
||||
|
||||
virtual ~GrallocPlanarYCbCrImage();
|
||||
|
||||
/**
|
||||
* This makes a copy of the data buffers, in order to support functioning
|
||||
* in all different layer managers.
|
||||
*/
|
||||
virtual void SetData(const Data& aData);
|
||||
|
||||
virtual PRUint32 GetDataSize() { return 0; }
|
||||
|
||||
virtual bool IsValid() { return mSurfaceDescriptor.type() != SurfaceDescriptor::T__None; }
|
||||
|
||||
SurfaceDescriptor GetSurfaceDescriptor() {
|
||||
return mSurfaceDescriptor;
|
||||
}
|
||||
|
||||
private:
|
||||
SurfaceDescriptor mSurfaceDescriptor;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
#endif
|
||||
|
||||
#endif /* GRALLOCIMAGES_H */
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "ImageContainer.h"
|
||||
#include "GonkIOSurfaceImage.h"
|
||||
#include "GrallocImages.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "mozilla/ipc/CrossProcessMutex.h"
|
||||
#include "SharedTextureImage.h"
|
||||
|
@ -30,6 +31,7 @@
|
|||
#endif
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
using namespace android;
|
||||
using mozilla::gfx::DataSourceSurface;
|
||||
using mozilla::gfx::SourceSurface;
|
||||
|
||||
|
@ -47,22 +49,37 @@ ImageFactory::CreateImage(const ImageFormat *aFormats,
|
|||
return nullptr;
|
||||
}
|
||||
nsRefPtr<Image> img;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (FormatInList(aFormats, aNumFormats, GRALLOC_PLANAR_YCBCR)) {
|
||||
img = new GrallocPlanarYCbCrImage();
|
||||
return img.forget();
|
||||
}
|
||||
#endif
|
||||
if (FormatInList(aFormats, aNumFormats, PLANAR_YCBCR)) {
|
||||
img = new PlanarYCbCrImage(aRecycleBin);
|
||||
} else if (FormatInList(aFormats, aNumFormats, CAIRO_SURFACE)) {
|
||||
return img.forget();
|
||||
}
|
||||
if (FormatInList(aFormats, aNumFormats, CAIRO_SURFACE)) {
|
||||
img = new CairoImage();
|
||||
} else if (FormatInList(aFormats, aNumFormats, SHARED_TEXTURE)) {
|
||||
return img.forget();
|
||||
}
|
||||
if (FormatInList(aFormats, aNumFormats, SHARED_TEXTURE)) {
|
||||
img = new SharedTextureImage();
|
||||
return img.forget();
|
||||
}
|
||||
#ifdef XP_MACOSX
|
||||
} else if (FormatInList(aFormats, aNumFormats, MAC_IO_SURFACE)) {
|
||||
if (FormatInList(aFormats, aNumFormats, MAC_IO_SURFACE)) {
|
||||
img = new MacIOSurfaceImage();
|
||||
return img.forget();
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
} else if (FormatInList(aFormats, aNumFormats, GONK_IO_SURFACE)) {
|
||||
if (FormatInList(aFormats, aNumFormats, GONK_IO_SURFACE)) {
|
||||
img = new GonkIOSurfaceImage();
|
||||
#endif
|
||||
return img.forget();
|
||||
}
|
||||
return img.forget();
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BufferRecycleBin::BufferRecycleBin()
|
||||
|
|
|
@ -644,7 +644,7 @@ public:
|
|||
MAX_DIMENSION = 16384
|
||||
};
|
||||
|
||||
~PlanarYCbCrImage();
|
||||
virtual ~PlanarYCbCrImage();
|
||||
|
||||
/**
|
||||
* This makes a copy of the data buffers, in order to support functioning
|
||||
|
|
|
@ -16,6 +16,13 @@ enum ImageFormat {
|
|||
*/
|
||||
PLANAR_YCBCR,
|
||||
|
||||
/**
|
||||
* The GRALLOC_PLANAR_YCBCR format creates a GrallocPlanarYCbCrImage, a
|
||||
* subtype of PlanarYCbCrImage. It takes a PlanarYCbCrImage data and can be
|
||||
* used as a texture by Gonk backend directly.
|
||||
*/
|
||||
GRALLOC_PLANAR_YCBCR,
|
||||
|
||||
/**
|
||||
* The CAIRO_SURFACE format creates a CairoImage. All backends should
|
||||
* support this format, because video rendering sometimes requires it.
|
||||
|
@ -73,4 +80,4 @@ enum StereoMode {
|
|||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -172,7 +172,10 @@ endif
|
|||
# has full system permissions there.
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
|
||||
EXPORTS_mozilla/layers += ShadowLayerUtilsGralloc.h
|
||||
CPPSRCS += ShadowLayerUtilsGralloc.cpp
|
||||
CPPSRCS += \
|
||||
ShadowLayerUtilsGralloc.cpp \
|
||||
GrallocImages.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/layers/SharedImageUtils.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "GonkIOSurfaceImage.h"
|
||||
#include "GrallocImages.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -206,6 +207,10 @@ SharedImage* ImageContainerChild::CreateSharedImageFromData(Image* image)
|
|||
GonkIOSurfaceImage* gonkImage = static_cast<GonkIOSurfaceImage*>(image);
|
||||
SharedImage* result = new SharedImage(gonkImage->GetSurfaceDescriptor());
|
||||
return result;
|
||||
} else if (image->GetFormat() == GRALLOC_PLANAR_YCBCR) {
|
||||
GrallocPlanarYCbCrImage* GrallocImage = static_cast<GrallocPlanarYCbCrImage*>(image);
|
||||
SharedImage* result = new SharedImage(GrallocImage->GetSurfaceDescriptor());
|
||||
return result;
|
||||
#endif
|
||||
} else {
|
||||
NS_RUNTIMEABORT("TODO: Only YUVImage is supported here right now.");
|
||||
|
|
Загрузка…
Ссылка в новой задаче