From 7fb8d88099a70c470d9322795bcc81cf2277e9a8 Mon Sep 17 00:00:00 2001 From: Andreas Pehrson Date: Mon, 12 Oct 2015 10:33:58 +0800 Subject: [PATCH] Bug 1210286 - Fall back to converting SourceSurfaces (RGB) to NV12 in OMXCodecWrapper. r=jolin --HG-- extra : commitid : HafpaHoj6i extra : rebase_source : a975b625410158b345121f51b1839ac49d4a3883 --- dom/media/omx/OMXCodecWrapper.cpp | 78 +++++++++++++++++++++++++++++-- dom/media/omx/moz.build | 1 + 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/dom/media/omx/OMXCodecWrapper.cpp b/dom/media/omx/OMXCodecWrapper.cpp index 0ea79c928c4a..3afb51a75c74 100644 --- a/dom/media/omx/OMXCodecWrapper.cpp +++ b/dom/media/omx/OMXCodecWrapper.cpp @@ -17,7 +17,10 @@ #include "AudioChannelFormat.h" #include "GrallocImages.h" +#include "LayersLogging.h" +#include "libyuv.h" #include "mozilla/Monitor.h" +#include "mozilla/gfx/2D.h" #include "mozilla/layers/GrallocTextureClient.h" using namespace mozilla; @@ -380,6 +383,67 @@ ConvertGrallocImageToNV12(GrallocImage* aSource, uint8_t* aDestination) graphicBuffer->unlock(); } +static nsresult +ConvertSourceSurfaceToNV12(const nsRefPtr& aSurface, uint8_t* aDestination) +{ + uint32_t width = aSurface->GetSize().width; + uint32_t height = aSurface->GetSize().height; + + uint8_t* y = aDestination; + int yStride = width; + + uint8_t* uv = y + (yStride * height); + int uvStride = width / 2; + + SurfaceFormat format = aSurface->GetFormat(); + + if (!aSurface) { + CODEC_ERROR("Getting surface %s from image failed", Stringify(format).c_str()); + return NS_ERROR_FAILURE; + } + + RefPtr data = aSurface->GetDataSurface(); + if (!data) { + CODEC_ERROR("Getting data surface from %s image with %s (%s) surface failed", + Stringify(format).c_str(), Stringify(aSurface->GetType()).c_str(), + Stringify(aSurface->GetFormat()).c_str()); + return NS_ERROR_FAILURE; + } + + DataSourceSurface::ScopedMap map(data, DataSourceSurface::READ); + if (!map.IsMapped()) { + CODEC_ERROR("Reading DataSourceSurface from %s image with %s (%s) surface failed", + Stringify(format).c_str(), Stringify(aSurface->GetType()).c_str(), + Stringify(aSurface->GetFormat()).c_str()); + return NS_ERROR_FAILURE; + } + + int rv; + switch (aSurface->GetFormat()) { + case SurfaceFormat::B8G8R8A8: + case SurfaceFormat::B8G8R8X8: + rv = libyuv::ARGBToNV12(static_cast(map.GetData()), + map.GetStride(), + y, yStride, + uv, uvStride, + width, height); + break; + default: + CODEC_ERROR("Unsupported SourceSurface format %s", + Stringify(aSurface->GetFormat()).c_str()); + NS_ASSERTION(false, "Unsupported SourceSurface format"); + return NS_ERROR_NOT_IMPLEMENTED; + } + + if (rv != 0) { + CODEC_ERROR("%s to I420 conversion failed", + Stringify(aSurface->GetFormat()).c_str()); + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + nsresult OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight, int64_t aTimestamp, int aInputFlags, bool* aSendEOS) @@ -410,9 +474,10 @@ OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight, halFormat == GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS, NS_ERROR_INVALID_ARG); } else { - // TODO: support RGB to YUV color conversion. - NS_ERROR("Unsupported input image type."); - return NS_ERROR_INVALID_ARG; + nsRefPtr surface = img->GetAsSourceSurface(); + NS_ENSURE_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8A8 || + surface->GetFormat() == SurfaceFormat::B8G8R8X8, + NS_ERROR_INVALID_ARG); } } @@ -450,6 +515,13 @@ OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight, } else if (format == ImageFormat::PLANAR_YCBCR) { ConvertPlanarYCbCrToNV12(static_cast(img)->GetData(), dst); + } else { + nsRefPtr surface = img->GetAsSourceSurface(); + nsresult rv = ConvertSourceSurfaceToNV12(surface, dst); + + if (rv != NS_OK) { + return NS_ERROR_FAILURE; + } } } diff --git a/dom/media/omx/moz.build b/dom/media/omx/moz.build index 9bbfd2607acc..aec361e2071c 100644 --- a/dom/media/omx/moz.build +++ b/dom/media/omx/moz.build @@ -41,6 +41,7 @@ if CONFIG['MOZ_OMX_ENCODER']: 'OMXCodecDescriptorUtil.cpp', 'OMXCodecWrapper.cpp', ] + LOCAL_INCLUDES += ['/media/libyuv/include'] if 'rtsp' in CONFIG['NECKO_PROTOCOLS']: EXPORTS += [