114 lines
3.8 KiB
C++
114 lines
3.8 KiB
C++
/* 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 "ImageContainer.h"
|
|
#include "gtest/gtest.h"
|
|
#include "mozilla/RefPtr.h"
|
|
#include "mozilla/gfx/Types.h"
|
|
|
|
using mozilla::MakeRefPtr;
|
|
using mozilla::gfx::ChromaSubsampling;
|
|
using mozilla::gfx::ColorDepth;
|
|
using mozilla::gfx::ColorRange;
|
|
using mozilla::gfx::IntRect;
|
|
using mozilla::layers::BufferRecycleBin;
|
|
using mozilla::layers::PlanarYCbCrData;
|
|
using mozilla::layers::RecyclingPlanarYCbCrImage;
|
|
|
|
static const uint32_t kWidth = 4;
|
|
static const uint32_t kHeight = 2;
|
|
static const uint32_t kHalfHeight = (kHeight + 1) / 2;
|
|
static const int32_t kStride = static_cast<int32_t>(kWidth) * 2; // 8
|
|
|
|
static const uint8_t kUVRow[8] = {
|
|
0x10, 0x12, // U0
|
|
0xAA, 0xBB, // V0
|
|
0x20, 0x22, // U1
|
|
0xCC, 0xDD, // V1
|
|
};
|
|
|
|
static PlanarYCbCrData MakeP010Data(uint8_t* aYPlane, uint8_t* aUVPlane) {
|
|
PlanarYCbCrData d;
|
|
d.mYChannel = aYPlane;
|
|
d.mYStride = kStride;
|
|
d.mYSkip = 0;
|
|
d.mCbChannel = aUVPlane;
|
|
d.mCrChannel = aUVPlane + sizeof(uint16_t);
|
|
d.mCbCrStride = kStride;
|
|
d.mCbSkip = 1;
|
|
d.mCrSkip = 1;
|
|
d.mPictureRect = IntRect(0, 0, kWidth, kHeight);
|
|
d.mChromaSubsampling = ChromaSubsampling::HALF_WIDTH_AND_HEIGHT;
|
|
d.mColorDepth = ColorDepth::COLOR_10;
|
|
d.mColorRange = ColorRange::LIMITED;
|
|
return d;
|
|
}
|
|
|
|
// Verifies correct 16-bit chroma de-interleaving from a P010 UV plane.
|
|
TEST(CopyPlane, P010ChromaDeinterleave)
|
|
{
|
|
uint8_t yPlane[kStride * kHeight] = {};
|
|
uint8_t uvPlane[kStride * kHalfHeight];
|
|
memcpy(uvPlane, kUVRow, sizeof(kUVRow));
|
|
|
|
auto recycleBin = MakeRefPtr<BufferRecycleBin>();
|
|
auto image = MakeRefPtr<RecyclingPlanarYCbCrImage>(recycleBin.get());
|
|
ASSERT_EQ(NS_OK, image->CopyData(MakeP010Data(yPlane, uvPlane)));
|
|
|
|
const PlanarYCbCrData* r = image->GetData();
|
|
ASSERT_TRUE(r);
|
|
|
|
EXPECT_EQ(r->mCbChannel[0], 0x10); // U0lo
|
|
EXPECT_EQ(r->mCbChannel[1], 0x12); // U0hi
|
|
EXPECT_EQ(r->mCbChannel[2], 0x20); // U1lo
|
|
EXPECT_EQ(r->mCbChannel[3], 0x22); // U1hi
|
|
EXPECT_EQ(r->mCbChannel[4], 0x00); // gap
|
|
EXPECT_EQ(r->mCbChannel[5], 0x00);
|
|
EXPECT_EQ(r->mCbChannel[6], 0x00);
|
|
EXPECT_EQ(r->mCbChannel[7], 0x00);
|
|
|
|
EXPECT_EQ(r->mCrChannel[0], 0xAA); // V0lo
|
|
EXPECT_EQ(r->mCrChannel[1], 0xBB); // V0hi
|
|
EXPECT_EQ(r->mCrChannel[2], 0xCC); // V1lo
|
|
EXPECT_EQ(r->mCrChannel[3], 0xDD); // V1hi
|
|
EXPECT_EQ(r->mCrChannel[4], 0x00); // gap
|
|
EXPECT_EQ(r->mCrChannel[5], 0x00);
|
|
EXPECT_EQ(r->mCrChannel[6], 0x00);
|
|
EXPECT_EQ(r->mCrChannel[7], 0x00);
|
|
}
|
|
|
|
// Verifies gap bytes are zero even when the recycled buffer was pre-dirtied
|
|
// with 0xFF, simulating stale frame data exposed via VideoFrame.copyTo().
|
|
TEST(CopyPlane, P010GapBytesZeroFilledOnRecycledBuffer)
|
|
{
|
|
uint8_t yPlane[kStride * kHeight] = {};
|
|
uint8_t uvPlane[kStride * kHalfHeight];
|
|
memcpy(uvPlane, kUVRow, sizeof(kUVRow));
|
|
|
|
auto recycleBin = MakeRefPtr<BufferRecycleBin>();
|
|
|
|
{
|
|
const uint32_t bufSize = static_cast<uint32_t>(kStride) * kHalfHeight * 2 +
|
|
static_cast<uint32_t>(kStride) * kHeight;
|
|
auto dirtyBuf = recycleBin->GetBuffer(bufSize);
|
|
memset(dirtyBuf.get(), 0xFF, bufSize);
|
|
recycleBin->RecycleBuffer(std::move(dirtyBuf), bufSize);
|
|
}
|
|
|
|
auto image = MakeRefPtr<RecyclingPlanarYCbCrImage>(recycleBin.get());
|
|
ASSERT_EQ(NS_OK, image->CopyData(MakeP010Data(yPlane, uvPlane)));
|
|
|
|
const PlanarYCbCrData* r = image->GetData();
|
|
ASSERT_TRUE(r);
|
|
|
|
EXPECT_EQ(r->mCbChannel[4], 0x00);
|
|
EXPECT_EQ(r->mCbChannel[5], 0x00);
|
|
EXPECT_EQ(r->mCbChannel[6], 0x00);
|
|
EXPECT_EQ(r->mCbChannel[7], 0x00);
|
|
EXPECT_EQ(r->mCrChannel[4], 0x00);
|
|
EXPECT_EQ(r->mCrChannel[5], 0x00);
|
|
EXPECT_EQ(r->mCrChannel[6], 0x00);
|
|
EXPECT_EQ(r->mCrChannel[7], 0x00);
|
|
}
|