зеркало из https://github.com/mozilla/gecko-dev.git
Bug 983039 - [Media encoder] Support YV12 GrallocImage in OMXVideoEncoder on B2G. r=roc
This commit is contained in:
Родитель
0d2a3367a0
Коммит
d6ff6e6958
|
@ -230,6 +230,72 @@ ConvertPlanarYCbCrToNV12(const PlanarYCbCrData* aSource, uint8_t* aDestination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert pixels in graphic buffer to NV12 format. aSource is the layer image
|
||||||
|
// containing source graphic buffer, and aDestination is the destination of
|
||||||
|
// conversion. Currently only 2 source format are supported:
|
||||||
|
// - NV21/HAL_PIXEL_FORMAT_YCrCb_420_SP (from camera preview window).
|
||||||
|
// - YV12/HAL_PIXEL_FORMAT_YV12 (from video decoder).
|
||||||
|
static
|
||||||
|
void
|
||||||
|
ConvertGrallocImageToNV12(GrallocImage* aSource, uint8_t* aDestination)
|
||||||
|
{
|
||||||
|
// Get graphic buffer.
|
||||||
|
SurfaceDescriptor handle = aSource->GetSurfaceDescriptor();
|
||||||
|
SurfaceDescriptorGralloc gralloc = handle.get_SurfaceDescriptorGralloc();
|
||||||
|
sp<GraphicBuffer> graphicBuffer = GrallocBufferActor::GetFrom(gralloc);
|
||||||
|
|
||||||
|
int pixelFormat = graphicBuffer->getPixelFormat();
|
||||||
|
// Only support NV21 (from camera) or YV12 (from HW decoder output) for now.
|
||||||
|
NS_ENSURE_TRUE_VOID(pixelFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
|
||||||
|
pixelFormat == HAL_PIXEL_FORMAT_YV12);
|
||||||
|
|
||||||
|
void* imgPtr = nullptr;
|
||||||
|
graphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_MASK, &imgPtr);
|
||||||
|
// Build PlanarYCbCrData for NV21 or YV12 buffer.
|
||||||
|
PlanarYCbCrData yuv;
|
||||||
|
switch (pixelFormat) {
|
||||||
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP: // From camera.
|
||||||
|
yuv.mYChannel = static_cast<uint8_t*>(imgPtr);
|
||||||
|
yuv.mYSkip = 0;
|
||||||
|
yuv.mYSize.width = graphicBuffer->getWidth();
|
||||||
|
yuv.mYSize.height = graphicBuffer->getHeight();
|
||||||
|
yuv.mYStride = graphicBuffer->getStride();
|
||||||
|
// 4:2:0.
|
||||||
|
yuv.mCbCrSize.width = yuv.mYSize.width / 2;
|
||||||
|
yuv.mCbCrSize.height = yuv.mYSize.height / 2;
|
||||||
|
// Interleaved VU plane.
|
||||||
|
yuv.mCrChannel = yuv.mYChannel + (yuv.mYStride * yuv.mYSize.height);
|
||||||
|
yuv.mCrSkip = 1;
|
||||||
|
yuv.mCbChannel = yuv.mCrChannel + 1;
|
||||||
|
yuv.mCbSkip = 1;
|
||||||
|
yuv.mCbCrStride = yuv.mYStride;
|
||||||
|
ConvertPlanarYCbCrToNV12(&yuv, aDestination);
|
||||||
|
break;
|
||||||
|
case HAL_PIXEL_FORMAT_YV12: // From video decoder.
|
||||||
|
// Android YV12 format is defined in system/core/include/system/graphics.h
|
||||||
|
yuv.mYChannel = static_cast<uint8_t*>(imgPtr);
|
||||||
|
yuv.mYSkip = 0;
|
||||||
|
yuv.mYSize.width = graphicBuffer->getWidth();
|
||||||
|
yuv.mYSize.height = graphicBuffer->getHeight();
|
||||||
|
yuv.mYStride = graphicBuffer->getStride();
|
||||||
|
// 4:2:0.
|
||||||
|
yuv.mCbCrSize.width = yuv.mYSize.width / 2;
|
||||||
|
yuv.mCbCrSize.height = yuv.mYSize.height / 2;
|
||||||
|
yuv.mCrChannel = yuv.mYChannel + (yuv.mYStride * yuv.mYSize.height);
|
||||||
|
// Aligned to 16 bytes boundary.
|
||||||
|
yuv.mCbCrStride = (yuv.mYStride / 2 + 15) & ~0x0F;
|
||||||
|
yuv.mCrSkip = 0;
|
||||||
|
yuv.mCbChannel = yuv.mCrChannel + (yuv.mCbCrStride * yuv.mCbCrSize.height);
|
||||||
|
yuv.mCbSkip = 0;
|
||||||
|
ConvertPlanarYCbCrToNV12(&yuv, aDestination);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NS_ERROR("Unsupported input gralloc image type. Should never be here.");
|
||||||
|
}
|
||||||
|
|
||||||
|
graphicBuffer->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
|
OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
|
||||||
int64_t aTimestamp, int aInputFlags)
|
int64_t aTimestamp, int aInputFlags)
|
||||||
|
@ -252,7 +318,6 @@ OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
|
||||||
|
|
||||||
size_t yLen = aWidth * aHeight;
|
size_t yLen = aWidth * aHeight;
|
||||||
size_t uvLen = yLen / 2;
|
size_t uvLen = yLen / 2;
|
||||||
|
|
||||||
// Buffer should be large enough to hold input image data.
|
// Buffer should be large enough to hold input image data.
|
||||||
MOZ_ASSERT(dstSize >= yLen + uvLen);
|
MOZ_ASSERT(dstSize >= yLen + uvLen);
|
||||||
|
|
||||||
|
@ -273,40 +338,7 @@ OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
|
||||||
aHeight == img->GetSize().height);
|
aHeight == img->GetSize().height);
|
||||||
|
|
||||||
if (format == ImageFormat::GRALLOC_PLANAR_YCBCR) {
|
if (format == ImageFormat::GRALLOC_PLANAR_YCBCR) {
|
||||||
// Get graphic buffer pointer.
|
ConvertGrallocImageToNV12(static_cast<GrallocImage*>(img), dst);
|
||||||
void* imgPtr = nullptr;
|
|
||||||
GrallocImage* nativeImage = static_cast<GrallocImage*>(img);
|
|
||||||
SurfaceDescriptor handle = nativeImage->GetSurfaceDescriptor();
|
|
||||||
SurfaceDescriptorGralloc gralloc = handle.get_SurfaceDescriptorGralloc();
|
|
||||||
sp<GraphicBuffer> graphicBuffer = GrallocBufferActor::GetFrom(gralloc);
|
|
||||||
graphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_MASK, &imgPtr);
|
|
||||||
uint8_t* src = static_cast<uint8_t*>(imgPtr);
|
|
||||||
|
|
||||||
// Only support NV21 for now.
|
|
||||||
MOZ_ASSERT(graphicBuffer->getPixelFormat() ==
|
|
||||||
HAL_PIXEL_FORMAT_YCrCb_420_SP);
|
|
||||||
|
|
||||||
// Build PlanarYCbCrData for NV21 buffer.
|
|
||||||
PlanarYCbCrData nv21;
|
|
||||||
// Y plane.
|
|
||||||
nv21.mYChannel = src;
|
|
||||||
nv21.mYSize.width = aWidth;
|
|
||||||
nv21.mYSize.height = aHeight;
|
|
||||||
nv21.mYStride = aWidth;
|
|
||||||
nv21.mYSkip = 0;
|
|
||||||
// Interleaved VU plane.
|
|
||||||
nv21.mCrChannel = src + yLen;
|
|
||||||
nv21.mCrSkip = 1;
|
|
||||||
nv21.mCbChannel = nv21.mCrChannel + 1;
|
|
||||||
nv21.mCbSkip = 1;
|
|
||||||
nv21.mCbCrStride = aWidth;
|
|
||||||
// 4:2:0.
|
|
||||||
nv21.mCbCrSize.width = aWidth / 2;
|
|
||||||
nv21.mCbCrSize.height = aHeight / 2;
|
|
||||||
|
|
||||||
ConvertPlanarYCbCrToNV12(&nv21, dst);
|
|
||||||
|
|
||||||
graphicBuffer->unlock();
|
|
||||||
} else if (format == ImageFormat::PLANAR_YCBCR) {
|
} else if (format == ImageFormat::PLANAR_YCBCR) {
|
||||||
ConvertPlanarYCbCrToNV12(static_cast<PlanarYCbCrImage*>(img)->GetData(),
|
ConvertPlanarYCbCrToNV12(static_cast<PlanarYCbCrImage*>(img)->GetData(),
|
||||||
dst);
|
dst);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче