Bug 1219330 - Handle PlanaYCbCrImage::SetData failure. r=jya, jesup

This commit is contained in:
Nicolas Silva 2015-11-03 12:24:26 +01:00
parent c1d1624064
commit 1ebb1e2bb7
13 changed files with 72 additions and 47 deletions

View File

@ -198,14 +198,14 @@ VideoData::ShallowCopyUpdateTimestampAndDuration(const VideoData* aOther,
} }
/* static */ /* static */
void VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage, bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
const VideoInfo& aInfo, const VideoInfo& aInfo,
const YCbCrBuffer &aBuffer, const YCbCrBuffer &aBuffer,
const IntRect& aPicture, const IntRect& aPicture,
bool aCopyData) bool aCopyData)
{ {
if (!aVideoImage) { if (!aVideoImage) {
return; return false;
} }
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0]; const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1]; const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
@ -229,9 +229,9 @@ void VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
aVideoImage->SetDelayedConversion(true); aVideoImage->SetDelayedConversion(true);
if (aCopyData) { if (aCopyData) {
aVideoImage->SetData(data); return aVideoImage->SetData(data);
} else { } else {
aVideoImage->SetDataNoCopy(data); return aVideoImage->SetDataNoCopy(data);
} }
} }
@ -330,12 +330,10 @@ VideoData::Create(const VideoInfo& aInfo,
"Wrong format?"); "Wrong format?");
PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get()); PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
if (!aImage) { bool shouldCopyData = (aImage == nullptr);
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture, if (!VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
true /* aCopyData */); shouldCopyData)) {
} else { return nullptr;
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
false /* aCopyData */);
} }
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
@ -346,8 +344,10 @@ VideoData::Create(const VideoInfo& aInfo,
return nullptr; return nullptr;
} }
videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get()); videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture, if(!VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
true /* aCopyData */); true /* aCopyData */)) {
return nullptr;
}
} }
#endif #endif
return v.forget(); return v.forget();
@ -473,7 +473,9 @@ VideoData::Create(const VideoInfo& aInfo,
data.mPicSize = aPicture.Size(); data.mPicSize = aPicture.Size();
data.mGraphicBuffer = aBuffer; data.mGraphicBuffer = aBuffer;
videoImage->SetData(data); if (!videoImage->SetData(data)) {
return nullptr;
}
return v.forget(); return v.forget();
} }

View File

@ -283,7 +283,7 @@ public:
// Initialize PlanarYCbCrImage. Only When aCopyData is true, // Initialize PlanarYCbCrImage. Only When aCopyData is true,
// video data is copied to PlanarYCbCrImage. // video data is copied to PlanarYCbCrImage.
static void SetVideoDataToImage(PlanarYCbCrImage* aVideoImage, static bool SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
const VideoInfo& aInfo, const VideoInfo& aInfo,
const YCbCrBuffer &aBuffer, const YCbCrBuffer &aBuffer,
const IntRect& aPicture, const IntRect& aPicture,

View File

@ -80,7 +80,10 @@ VideoFrame::CreateBlackImage(const gfx::IntSize& aSize)
data.mStereoMode = StereoMode::MONO; data.mStereoMode = StereoMode::MONO;
// SetData copies data, so we can free data. // SetData copies data, so we can free data.
planar->SetData(data); if (!planar->SetData(data)) {
MOZ_ASSERT(false);
return nullptr;
}
return image.forget(); return image.forget();
} }

View File

@ -250,10 +250,16 @@ MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
0, 0); 0, 0);
#endif #endif
ycbcr_image->SetData(data); bool setData = ycbcr_image->SetData(data);
MOZ_ASSERT(setData);
// SetData copies data, so we can free the frame // SetData copies data, so we can free the frame
ReleaseFrame(data); ReleaseFrame(data);
if (!setData) {
return NS_ERROR_FAILURE;
}
MonitorAutoLock lock(mMonitor); MonitorAutoLock lock(mMonitor);
// implicitly releases last image // implicitly releases last image

View File

@ -315,7 +315,10 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
data.mPicSize = IntSize(mWidth, mHeight); data.mPicSize = IntSize(mWidth, mHeight);
data.mStereoMode = StereoMode::MONO; data.mStereoMode = StereoMode::MONO;
videoImage->SetData(data); if (!videoImage->SetData(data)) {
MOZ_ASSERT(false);
return 0;
}
#ifdef DEBUG #ifdef DEBUG
static uint32_t frame_num = 0; static uint32_t frame_num = 0;

View File

@ -57,7 +57,7 @@ GrallocImage::~GrallocImage()
{ {
} }
void bool
GrallocImage::SetData(const Data& aData) GrallocImage::SetData(const Data& aData)
{ {
MOZ_ASSERT(!mTextureClient, "TextureClient is already set"); MOZ_ASSERT(!mTextureClient, "TextureClient is already set");
@ -70,7 +70,7 @@ GrallocImage::SetData(const Data& aData)
if (gfxPlatform::GetPlatform()->IsInGonkEmulator()) { if (gfxPlatform::GetPlatform()->IsInGonkEmulator()) {
// Emulator does not support HAL_PIXEL_FORMAT_YV12. // Emulator does not support HAL_PIXEL_FORMAT_YV12.
return; return false;
} }
RefPtr<GrallocTextureClientOGL> textureClient = RefPtr<GrallocTextureClientOGL> textureClient =
@ -88,7 +88,7 @@ GrallocImage::SetData(const Data& aData)
sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer(); sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
if (!result || !graphicBuffer.get()) { if (!result || !graphicBuffer.get()) {
mTextureClient = nullptr; mTextureClient = nullptr;
return; return false;
} }
mTextureClient = textureClient; mTextureClient = textureClient;
@ -96,7 +96,7 @@ GrallocImage::SetData(const Data& aData)
void* vaddr; void* vaddr;
if (graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, if (graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
&vaddr) != OK) { &vaddr) != OK) {
return; return false;
} }
uint8_t* yChannel = static_cast<uint8_t*>(vaddr); uint8_t* yChannel = static_cast<uint8_t*>(vaddr);
@ -144,12 +144,14 @@ GrallocImage::SetData(const Data& aData)
mData.mYChannel = nullptr; mData.mYChannel = nullptr;
mData.mCrChannel = nullptr; mData.mCrChannel = nullptr;
mData.mCbChannel = nullptr; mData.mCbChannel = nullptr;
return true;
} }
void GrallocImage::SetData(const GrallocData& aData) bool GrallocImage::SetData(const GrallocData& aData)
{ {
mTextureClient = static_cast<GrallocTextureClientOGL*>(aData.mGraphicBuffer.get()); mTextureClient = static_cast<GrallocTextureClientOGL*>(aData.mGraphicBuffer.get());
mSize = aData.mPicSize; mSize = aData.mPicSize;
return true;
} }
/** /**

View File

@ -66,13 +66,13 @@ public:
* This makes a copy of the data buffers, in order to support functioning * This makes a copy of the data buffers, in order to support functioning
* in all different layer managers. * in all different layer managers.
*/ */
virtual void SetData(const Data& aData); virtual bool SetData(const Data& aData);
/** /**
* Share the SurfaceDescriptor without making the copy, in order * Share the SurfaceDescriptor without making the copy, in order
* to support functioning in all different layer managers. * to support functioning in all different layer managers.
*/ */
virtual void SetData(const GrallocData& aData); virtual bool SetData(const GrallocData& aData);
// From [android 4.0.4]/hardware/msm7k/libgralloc-qsd8k/gralloc_priv.h // From [android 4.0.4]/hardware/msm7k/libgralloc-qsd8k/gralloc_priv.h
enum { enum {

View File

@ -484,7 +484,7 @@ CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
} }
} }
void bool
PlanarYCbCrImage::CopyData(const Data& aData) PlanarYCbCrImage::CopyData(const Data& aData)
{ {
mData = aData; mData = aData;
@ -496,7 +496,7 @@ PlanarYCbCrImage::CopyData(const Data& aData)
// get new buffer // get new buffer
mBuffer = AllocateBuffer(size); mBuffer = AllocateBuffer(size);
if (!mBuffer) if (!mBuffer)
return; return false;
// update buffer size // update buffer size
mBufferSize = size; mBufferSize = size;
@ -513,12 +513,13 @@ PlanarYCbCrImage::CopyData(const Data& aData)
mData.mCbCrSize, mData.mCbCrStride, mData.mCrSkip); mData.mCbCrSize, mData.mCbCrStride, mData.mCrSkip);
mSize = aData.mPicSize; mSize = aData.mPicSize;
return true;
} }
void bool
PlanarYCbCrImage::SetData(const Data &aData) PlanarYCbCrImage::SetData(const Data &aData)
{ {
CopyData(aData); return CopyData(aData);
} }
gfxImageFormat gfxImageFormat
@ -529,11 +530,12 @@ PlanarYCbCrImage::GetOffscreenFormat()
mOffscreenFormat; mOffscreenFormat;
} }
void bool
PlanarYCbCrImage::SetDataNoCopy(const Data &aData) PlanarYCbCrImage::SetDataNoCopy(const Data &aData)
{ {
mData = aData; mData = aData;
mSize = aData.mPicSize; mSize = aData.mPicSize;
return true;
} }
uint8_t* uint8_t*

View File

@ -656,7 +656,7 @@ public:
* This makes a copy of the data buffers, in order to support functioning * This makes a copy of the data buffers, in order to support functioning
* in all different layer managers. * in all different layer managers.
*/ */
virtual void SetData(const Data& aData); virtual bool SetData(const Data& aData);
/** /**
* This doesn't make a copy of the data buffers. Can be used when mBuffer is * This doesn't make a copy of the data buffers. Can be used when mBuffer is
@ -665,7 +665,7 @@ public:
* The GStreamer media backend uses this to decode into PlanarYCbCrImage(s) * The GStreamer media backend uses this to decode into PlanarYCbCrImage(s)
* directly. * directly.
*/ */
virtual void SetDataNoCopy(const Data &aData); virtual bool SetDataNoCopy(const Data &aData);
/** /**
* This allocates and returns a new buffer * This allocates and returns a new buffer
@ -709,7 +709,7 @@ protected:
* *
* @param aData Input image data. * @param aData Input image data.
*/ */
void CopyData(const Data& aData); bool CopyData(const Data& aData);
/** /**
* Return a buffer to store image data in. * Return a buffer to store image data in.

View File

@ -48,7 +48,7 @@ public:
} }
} }
virtual void SetData(const Data& aData) override; virtual bool SetData(const Data& aData) override;
virtual void SetDelayedConversion(bool aDelayed) override { mDelayedConversion = aDelayed; } virtual void SetDelayedConversion(bool aDelayed) override { mDelayedConversion = aDelayed; }
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override; already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
@ -91,20 +91,20 @@ public:
} }
}; };
void bool
BasicPlanarYCbCrImage::SetData(const Data& aData) BasicPlanarYCbCrImage::SetData(const Data& aData)
{ {
PlanarYCbCrImage::SetData(aData); PlanarYCbCrImage::SetData(aData);
if (mDelayedConversion) { if (mDelayedConversion) {
return; return false;
} }
// Do some sanity checks to prevent integer overflow // Do some sanity checks to prevent integer overflow
if (aData.mYSize.width > PlanarYCbCrImage::MAX_DIMENSION || if (aData.mYSize.width > PlanarYCbCrImage::MAX_DIMENSION ||
aData.mYSize.height > PlanarYCbCrImage::MAX_DIMENSION) { aData.mYSize.height > PlanarYCbCrImage::MAX_DIMENSION) {
NS_ERROR("Illegal image source width or height"); NS_ERROR("Illegal image source width or height");
return; return false;
} }
gfx::SurfaceFormat format = gfx::ImageFormatToSurfaceFormat(GetOffscreenFormat()); gfx::SurfaceFormat format = gfx::ImageFormatToSurfaceFormat(GetOffscreenFormat());
@ -114,7 +114,7 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
if (size.width > PlanarYCbCrImage::MAX_DIMENSION || if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
size.height > PlanarYCbCrImage::MAX_DIMENSION) { size.height > PlanarYCbCrImage::MAX_DIMENSION) {
NS_ERROR("Illegal image dest width or height"); NS_ERROR("Illegal image dest width or height");
return; return false;
} }
gfxImageFormat iFormat = gfx::SurfaceFormatToImageFormat(format); gfxImageFormat iFormat = gfx::SurfaceFormatToImageFormat(format);
@ -122,12 +122,14 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
mDecodedBuffer = AllocateBuffer(size.height * mStride); mDecodedBuffer = AllocateBuffer(size.height * mStride);
if (!mDecodedBuffer) { if (!mDecodedBuffer) {
// out of memory // out of memory
return; return false;
} }
gfx::ConvertYCbCrToRGB(aData, format, size, mDecodedBuffer, mStride); gfx::ConvertYCbCrToRGB(aData, format, size, mDecodedBuffer, mStride);
SetOffscreenFormat(iFormat); SetOffscreenFormat(iFormat);
mSize = size; mSize = size;
return true;
} }
already_AddRefed<gfx::SourceSurface> already_AddRefed<gfx::SourceSurface>

View File

@ -80,7 +80,7 @@ SharedPlanarYCbCrImage::GetAsSourceSurface()
return PlanarYCbCrImage::GetAsSourceSurface(); return PlanarYCbCrImage::GetAsSourceSurface();
} }
void bool
SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData) SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData)
{ {
// If mTextureClient has not already been allocated (through Allocate(aData)) // If mTextureClient has not already been allocated (through Allocate(aData))
@ -88,20 +88,21 @@ SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData)
// been called since it will trigger a full copy. // been called since it will trigger a full copy.
PlanarYCbCrData data = aData; PlanarYCbCrData data = aData;
if (!mTextureClient && !Allocate(data)) { if (!mTextureClient && !Allocate(data)) {
return; return false;
} }
MOZ_ASSERT(mTextureClient->AsTextureClientYCbCr()); MOZ_ASSERT(mTextureClient->AsTextureClientYCbCr());
if (!mTextureClient->Lock(OpenMode::OPEN_WRITE_ONLY)) { if (!mTextureClient->Lock(OpenMode::OPEN_WRITE_ONLY)) {
MOZ_ASSERT(false, "Failed to lock the texture."); MOZ_ASSERT(false, "Failed to lock the texture.");
return; return false;
} }
TextureClientAutoUnlock unlock(mTextureClient); TextureClientAutoUnlock unlock(mTextureClient);
if (!mTextureClient->AsTextureClientYCbCr()->UpdateYCbCr(aData)) { if (!mTextureClient->AsTextureClientYCbCr()->UpdateYCbCr(aData)) {
MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient"); MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
return; return false;
} }
mTextureClient->MarkImmutable(); mTextureClient->MarkImmutable();
return true;
} }
// needs to be overriden because the parent class sets mBuffer which we // needs to be overriden because the parent class sets mBuffer which we
@ -131,12 +132,12 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
return serializer.GetData(); return serializer.GetData();
} }
void bool
SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData) SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
{ {
MOZ_ASSERT(mTextureClient, "This Image should have already allocated data"); MOZ_ASSERT(mTextureClient, "This Image should have already allocated data");
if (!mTextureClient) { if (!mTextureClient) {
return; return false;
} }
mData = aData; mData = aData;
mSize = aData.mPicSize; mSize = aData.mPicSize;
@ -159,6 +160,7 @@ SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
aData.mYSize, aData.mYSize,
aData.mCbCrSize, aData.mCbCrSize,
aData.mStereoMode); aData.mStereoMode);
return true;
} }
uint8_t* uint8_t*

View File

@ -35,8 +35,8 @@ public:
virtual uint8_t* GetBuffer() override; virtual uint8_t* GetBuffer() override;
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override; virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
virtual void SetData(const PlanarYCbCrData& aData) override; virtual bool SetData(const PlanarYCbCrData& aData) override;
virtual void SetDataNoCopy(const Data &aData) override; virtual bool SetDataNoCopy(const Data &aData) override;
virtual bool Allocate(PlanarYCbCrData& aData); virtual bool Allocate(PlanarYCbCrData& aData);
virtual uint8_t* AllocateBuffer(uint32_t aSize) override; virtual uint8_t* AllocateBuffer(uint32_t aSize) override;

View File

@ -1501,7 +1501,10 @@ void MediaPipelineReceiveVideo::PipelineListener::RenderVideoFrame(
yuvData.mPicSize = IntSize(width_, height_); yuvData.mPicSize = IntSize(width_, height_);
yuvData.mStereoMode = StereoMode::MONO; yuvData.mStereoMode = StereoMode::MONO;
yuvImage->SetData(yuvData); if (!yuvImage->SetData(yuvData)) {
MOZ_ASSERT(false);
return;
}
image_ = image.forget(); image_ = image.forget();
} }