diff options
Diffstat (limited to 'dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp')
-rw-r--r-- | dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp new file mode 100644 index 0000000000..3f136c4ac8 --- /dev/null +++ b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 2; 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/. */ + +#include "WidevineVideoFrame.h" +#include "GMPLog.h" +#include "WidevineUtils.h" +#include "mozilla/CheckedInt.h" +#include "mozilla/IntegerPrintfMacros.h" + +namespace mozilla { + +WidevineVideoFrame::WidevineVideoFrame() + : mFormat(cdm::VideoFormat::kUnknownVideoFormat), + mSize{0, 0}, + mBuffer(nullptr), + mTimestamp(0) { + MOZ_ASSERT(mSize.height == 0 && mSize.width == 0, "Size should be zeroed"); + GMP_LOG_DEBUG("WidevineVideoFrame::WidevineVideoFrame() this=%p", this); + memset(mPlaneOffsets, 0, sizeof(mPlaneOffsets)); + memset(mPlaneStrides, 0, sizeof(mPlaneStrides)); +} + +WidevineVideoFrame::WidevineVideoFrame(WidevineVideoFrame&& aOther) + : mFormat(aOther.mFormat), + mSize(aOther.mSize), + mBuffer(aOther.mBuffer), + mTimestamp(aOther.mTimestamp) { + GMP_LOG_DEBUG( + "WidevineVideoFrame::WidevineVideoFrame(WidevineVideoFrame&&) " + "this=%p, other=%p", + this, &aOther); + memcpy(mPlaneOffsets, aOther.mPlaneOffsets, sizeof(mPlaneOffsets)); + memcpy(mPlaneStrides, aOther.mPlaneStrides, sizeof(mPlaneStrides)); + aOther.mBuffer = nullptr; +} + +WidevineVideoFrame::~WidevineVideoFrame() { + if (mBuffer) { + mBuffer->Destroy(); + mBuffer = nullptr; + } +} + +void WidevineVideoFrame::SetFormat(cdm::VideoFormat aFormat) { + GMP_LOG_DEBUG("WidevineVideoFrame::SetFormat(%d) this=%p", aFormat, this); + mFormat = aFormat; +} + +cdm::VideoFormat WidevineVideoFrame::Format() const { return mFormat; } + +void WidevineVideoFrame::SetSize(cdm::Size aSize) { + GMP_LOG_DEBUG("WidevineVideoFrame::SetSize(%d,%d) this=%p", aSize.width, + aSize.height, this); + mSize.width = aSize.width; + mSize.height = aSize.height; +} + +cdm::Size WidevineVideoFrame::Size() const { return mSize; } + +void WidevineVideoFrame::SetFrameBuffer(cdm::Buffer* aFrameBuffer) { + GMP_LOG_DEBUG("WidevineVideoFrame::SetFrameBuffer(%p) this=%p", aFrameBuffer, + this); + MOZ_ASSERT(!mBuffer); + mBuffer = aFrameBuffer; +} + +cdm::Buffer* WidevineVideoFrame::FrameBuffer() { return mBuffer; } + +void WidevineVideoFrame::SetPlaneOffset(cdm::VideoPlane aPlane, + uint32_t aOffset) { + GMP_LOG_DEBUG("WidevineVideoFrame::SetPlaneOffset(%d, %" PRIu32 ") this=%p", + aPlane, aOffset, this); + mPlaneOffsets[aPlane] = aOffset; +} + +uint32_t WidevineVideoFrame::PlaneOffset(cdm::VideoPlane aPlane) { + return mPlaneOffsets[aPlane]; +} + +void WidevineVideoFrame::SetStride(cdm::VideoPlane aPlane, uint32_t aStride) { + GMP_LOG_DEBUG("WidevineVideoFrame::SetStride(%d, %" PRIu32 ") this=%p", + aPlane, aStride, this); + mPlaneStrides[aPlane] = aStride; +} + +uint32_t WidevineVideoFrame::Stride(cdm::VideoPlane aPlane) { + return mPlaneStrides[aPlane]; +} + +void WidevineVideoFrame::SetTimestamp(int64_t timestamp) { + GMP_LOG_DEBUG("WidevineVideoFrame::SetTimestamp(%" PRId64 ") this=%p", + timestamp, this); + mTimestamp = timestamp; +} + +int64_t WidevineVideoFrame::Timestamp() const { return mTimestamp; } + +bool WidevineVideoFrame::InitToBlack(int32_t aWidth, int32_t aHeight, + int64_t aTimeStamp) { + if (NS_WARN_IF(aWidth < 0 || aHeight < 0)) { + MOZ_ASSERT_UNREACHABLE("Frame dimensions should be positive"); + return false; + } + + const uint32_t halfWidth = (uint32_t(aWidth) + 1) / 2; + CheckedInt<size_t> ySizeChk = aWidth; + ySizeChk *= aHeight; + CheckedInt<size_t> uSizeChk = halfWidth; + uSizeChk *= (uint32_t(aHeight) + 1) / 2; + CheckedInt<size_t> yuSizeChk = ySizeChk + uSizeChk; + if (NS_WARN_IF(!yuSizeChk.isValid())) { + return false; + } + + WidevineBuffer* buffer = new WidevineBuffer(yuSizeChk.value()); + const size_t ySize = ySizeChk.value(); + const size_t uSize = uSizeChk.value(); + // Black in YCbCr is (0,128,128). + memset(buffer->Data(), 0, ySize); + memset(buffer->Data() + ySize, 128, uSize); + if (mBuffer) { + mBuffer->Destroy(); + mBuffer = nullptr; + } + SetFormat(cdm::VideoFormat::kI420); + SetSize(cdm::Size{aWidth, aHeight}); + SetFrameBuffer(buffer); + SetPlaneOffset(cdm::VideoPlane::kYPlane, 0); + SetStride(cdm::VideoPlane::kYPlane, aWidth); + // Note: U and V planes are stored at the same place in order to + // save memory since their contents are the same. + SetPlaneOffset(cdm::VideoPlane::kUPlane, ySize); + SetStride(cdm::VideoPlane::kUPlane, halfWidth); + SetPlaneOffset(cdm::VideoPlane::kVPlane, ySize); + SetStride(cdm::VideoPlane::kVPlane, halfWidth); + SetTimestamp(aTimeStamp); + return true; +} + +} // namespace mozilla |