547 lines
21 KiB
Diff
547 lines
21 KiB
Diff
From 607c1d606efd9f955ad7545dbfdaf38450c5ce20 Mon Sep 17 00:00:00 2001
|
|
From: Wonsik Kim <wonsik@google.com>
|
|
Date: Thu, 3 Dec 2020 11:07:58 -0800
|
|
Subject: [PATCH 29/30] CCodec: fix ByteBuffer mode image
|
|
|
|
- Set offset to (0,0) of Y plane.
|
|
- Fix wrapping criteria.
|
|
|
|
Bug: 169379476
|
|
Test: atest CtsMediaTestCases -- --module-arg CtsMediaTestCases:size:small
|
|
Test: atest ccodec_unit_test
|
|
Change-Id: Ic7e074ddaef277833707363b0b9fecfe210bd57f
|
|
(cherry picked from commit 2eb063152f67e886472ed42c07f3634a5eb63f19)
|
|
---
|
|
media/codec2/sfplugin/CCodecBuffers.cpp | 3 +
|
|
media/codec2/sfplugin/Codec2Buffer.cpp | 14 +-
|
|
.../sfplugin/tests/CCodecBuffers_test.cpp | 450 +++++++++++++++++-
|
|
3 files changed, 456 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
|
|
index 692da584ce..566a18fbee 100644
|
|
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
|
|
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
|
|
@@ -96,6 +96,9 @@ void CCodecBuffers::handleImageData(const sp<Codec2Buffer> &buffer) {
|
|
int32_t vstride = int32_t(offsetDelta / stride);
|
|
newFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
|
|
ALOGD("[%s] updating vstride = %d", mName, vstride);
|
|
+ buffer->setRange(
|
|
+ img->mPlane[0].mOffset,
|
|
+ buffer->size() - img->mPlane[0].mOffset);
|
|
}
|
|
}
|
|
setFormat(newFormat);
|
|
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
|
|
index 25e7da9206..19414a0a0c 100644
|
|
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
|
|
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
|
|
@@ -276,20 +276,22 @@ public:
|
|
int32_t planeSize = 0;
|
|
for (uint32_t i = 0; i < layout.numPlanes; ++i) {
|
|
const C2PlaneInfo &plane = layout.planes[i];
|
|
- ssize_t minOffset = plane.minOffset(mWidth, mHeight);
|
|
- ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
|
|
+ int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
|
|
+ ssize_t minOffset = plane.minOffset(
|
|
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
|
|
+ ssize_t maxOffset = plane.maxOffset(
|
|
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
|
|
if (minPtr > mView.data()[i] + minOffset) {
|
|
minPtr = mView.data()[i] + minOffset;
|
|
}
|
|
if (maxPtr < mView.data()[i] + maxOffset) {
|
|
maxPtr = mView.data()[i] + maxOffset;
|
|
}
|
|
- planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
|
|
- / plane.rowSampling / plane.colSampling
|
|
- * divUp(mAllocatedDepth, 8u);
|
|
+ planeSize += planeStride * divUp(mAllocatedDepth, 8u)
|
|
+ * align(mHeight, 64) / plane.rowSampling;
|
|
}
|
|
|
|
- if ((maxPtr - minPtr + 1) <= planeSize) {
|
|
+ if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
|
|
// FIXME: this is risky as reading/writing data out of bound results
|
|
// in an undefined behavior, but gralloc does assume a
|
|
// contiguous mapping
|
|
diff --git a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
|
|
index 5bee605276..ad8f6e555b 100644
|
|
--- a/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
|
|
+++ b/media/codec2/sfplugin/tests/CCodecBuffers_test.cpp
|
|
@@ -18,22 +18,31 @@
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
+#include <media/stagefright/foundation/AString.h>
|
|
#include <media/stagefright/MediaCodecConstants.h>
|
|
|
|
+#include <C2BlockInternal.h>
|
|
#include <C2PlatformSupport.h>
|
|
|
|
namespace android {
|
|
|
|
+static std::shared_ptr<RawGraphicOutputBuffers> GetRawGraphicOutputBuffers(
|
|
+ int32_t width, int32_t height) {
|
|
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
|
|
+ std::make_shared<RawGraphicOutputBuffers>("test");
|
|
+ sp<AMessage> format{new AMessage};
|
|
+ format->setInt32(KEY_WIDTH, width);
|
|
+ format->setInt32(KEY_HEIGHT, height);
|
|
+ buffers->setFormat(format);
|
|
+ return buffers;
|
|
+}
|
|
+
|
|
TEST(RawGraphicOutputBuffersTest, ChangeNumSlots) {
|
|
constexpr int32_t kWidth = 3840;
|
|
constexpr int32_t kHeight = 2160;
|
|
|
|
std::shared_ptr<RawGraphicOutputBuffers> buffers =
|
|
- std::make_shared<RawGraphicOutputBuffers>("test");
|
|
- sp<AMessage> format{new AMessage};
|
|
- format->setInt32("width", kWidth);
|
|
- format->setInt32("height", kHeight);
|
|
- buffers->setFormat(format);
|
|
+ GetRawGraphicOutputBuffers(kWidth, kHeight);
|
|
|
|
std::shared_ptr<C2BlockPool> pool;
|
|
ASSERT_EQ(OK, GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool));
|
|
@@ -96,4 +105,435 @@ TEST(RawGraphicOutputBuffersTest, ChangeNumSlots) {
|
|
}
|
|
}
|
|
|
|
+class TestGraphicAllocation : public C2GraphicAllocation {
|
|
+public:
|
|
+ TestGraphicAllocation(
|
|
+ uint32_t width,
|
|
+ uint32_t height,
|
|
+ const C2PlanarLayout &layout,
|
|
+ size_t capacity,
|
|
+ std::vector<size_t> offsets)
|
|
+ : C2GraphicAllocation(width, height),
|
|
+ mLayout(layout),
|
|
+ mMemory(capacity, 0xAA),
|
|
+ mOffsets(offsets) {
|
|
+ }
|
|
+
|
|
+ c2_status_t map(
|
|
+ C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
|
|
+ C2PlanarLayout *layout, uint8_t **addr) override {
|
|
+ (void)rect;
|
|
+ (void)usage;
|
|
+ (void)fence;
|
|
+ *layout = mLayout;
|
|
+ for (size_t i = 0; i < mLayout.numPlanes; ++i) {
|
|
+ addr[i] = mMemory.data() + mOffsets[i];
|
|
+ }
|
|
+ return C2_OK;
|
|
+ }
|
|
+
|
|
+ c2_status_t unmap(uint8_t **, C2Rect, C2Fence *) override { return C2_OK; }
|
|
+
|
|
+ C2Allocator::id_t getAllocatorId() const override { return -1; }
|
|
+
|
|
+ const C2Handle *handle() const override { return nullptr; }
|
|
+
|
|
+ bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override {
|
|
+ return other.get() == this;
|
|
+ }
|
|
+
|
|
+private:
|
|
+ C2PlanarLayout mLayout;
|
|
+ std::vector<uint8_t> mMemory;
|
|
+ std::vector<uint8_t *> mAddr;
|
|
+ std::vector<size_t> mOffsets;
|
|
+};
|
|
+
|
|
+class LayoutTest : public ::testing::TestWithParam<std::tuple<bool, std::string, bool, int32_t>> {
|
|
+private:
|
|
+ static C2PlanarLayout YUVPlanarLayout(int32_t stride) {
|
|
+ C2PlanarLayout layout = {
|
|
+ C2PlanarLayout::TYPE_YUV,
|
|
+ 3, /* numPlanes */
|
|
+ 3, /* rootPlanes */
|
|
+ {}, /* planes --- to be filled below */
|
|
+ };
|
|
+ layout.planes[C2PlanarLayout::PLANE_Y] = {
|
|
+ C2PlaneInfo::CHANNEL_Y,
|
|
+ 1, /* colInc */
|
|
+ stride, /* rowInc */
|
|
+ 1, /* colSampling */
|
|
+ 1, /* rowSampling */
|
|
+ 8, /* allocatedDepth */
|
|
+ 8, /* bitDepth */
|
|
+ 0, /* rightShift */
|
|
+ C2PlaneInfo::NATIVE,
|
|
+ C2PlanarLayout::PLANE_Y, /* rootIx */
|
|
+ 0, /* offset */
|
|
+ };
|
|
+ layout.planes[C2PlanarLayout::PLANE_U] = {
|
|
+ C2PlaneInfo::CHANNEL_CB,
|
|
+ 1, /* colInc */
|
|
+ stride / 2, /* rowInc */
|
|
+ 2, /* colSampling */
|
|
+ 2, /* rowSampling */
|
|
+ 8, /* allocatedDepth */
|
|
+ 8, /* bitDepth */
|
|
+ 0, /* rightShift */
|
|
+ C2PlaneInfo::NATIVE,
|
|
+ C2PlanarLayout::PLANE_U, /* rootIx */
|
|
+ 0, /* offset */
|
|
+ };
|
|
+ layout.planes[C2PlanarLayout::PLANE_V] = {
|
|
+ C2PlaneInfo::CHANNEL_CR,
|
|
+ 1, /* colInc */
|
|
+ stride / 2, /* rowInc */
|
|
+ 2, /* colSampling */
|
|
+ 2, /* rowSampling */
|
|
+ 8, /* allocatedDepth */
|
|
+ 8, /* bitDepth */
|
|
+ 0, /* rightShift */
|
|
+ C2PlaneInfo::NATIVE,
|
|
+ C2PlanarLayout::PLANE_V, /* rootIx */
|
|
+ 0, /* offset */
|
|
+ };
|
|
+ return layout;
|
|
+ }
|
|
+
|
|
+ static C2PlanarLayout YUVSemiPlanarLayout(int32_t stride) {
|
|
+ C2PlanarLayout layout = {
|
|
+ C2PlanarLayout::TYPE_YUV,
|
|
+ 3, /* numPlanes */
|
|
+ 2, /* rootPlanes */
|
|
+ {}, /* planes --- to be filled below */
|
|
+ };
|
|
+ layout.planes[C2PlanarLayout::PLANE_Y] = {
|
|
+ C2PlaneInfo::CHANNEL_Y,
|
|
+ 1, /* colInc */
|
|
+ stride, /* rowInc */
|
|
+ 1, /* colSampling */
|
|
+ 1, /* rowSampling */
|
|
+ 8, /* allocatedDepth */
|
|
+ 8, /* bitDepth */
|
|
+ 0, /* rightShift */
|
|
+ C2PlaneInfo::NATIVE,
|
|
+ C2PlanarLayout::PLANE_Y, /* rootIx */
|
|
+ 0, /* offset */
|
|
+ };
|
|
+ layout.planes[C2PlanarLayout::PLANE_U] = {
|
|
+ C2PlaneInfo::CHANNEL_CB,
|
|
+ 2, /* colInc */
|
|
+ stride, /* rowInc */
|
|
+ 2, /* colSampling */
|
|
+ 2, /* rowSampling */
|
|
+ 8, /* allocatedDepth */
|
|
+ 8, /* bitDepth */
|
|
+ 0, /* rightShift */
|
|
+ C2PlaneInfo::NATIVE,
|
|
+ C2PlanarLayout::PLANE_U, /* rootIx */
|
|
+ 0, /* offset */
|
|
+ };
|
|
+ layout.planes[C2PlanarLayout::PLANE_V] = {
|
|
+ C2PlaneInfo::CHANNEL_CR,
|
|
+ 2, /* colInc */
|
|
+ stride, /* rowInc */
|
|
+ 2, /* colSampling */
|
|
+ 2, /* rowSampling */
|
|
+ 8, /* allocatedDepth */
|
|
+ 8, /* bitDepth */
|
|
+ 0, /* rightShift */
|
|
+ C2PlaneInfo::NATIVE,
|
|
+ C2PlanarLayout::PLANE_U, /* rootIx */
|
|
+ 1, /* offset */
|
|
+ };
|
|
+ return layout;
|
|
+ }
|
|
+
|
|
+ static C2PlanarLayout YVUSemiPlanarLayout(int32_t stride) {
|
|
+ C2PlanarLayout layout = {
|
|
+ C2PlanarLayout::TYPE_YUV,
|
|
+ 3, /* numPlanes */
|
|
+ 2, /* rootPlanes */
|
|
+ {}, /* planes --- to be filled below */
|
|
+ };
|
|
+ layout.planes[C2PlanarLayout::PLANE_Y] = {
|
|
+ C2PlaneInfo::CHANNEL_Y,
|
|
+ 1, /* colInc */
|
|
+ stride, /* rowInc */
|
|
+ 1, /* colSampling */
|
|
+ 1, /* rowSampling */
|
|
+ 8, /* allocatedDepth */
|
|
+ 8, /* bitDepth */
|
|
+ 0, /* rightShift */
|
|
+ C2PlaneInfo::NATIVE,
|
|
+ C2PlanarLayout::PLANE_Y, /* rootIx */
|
|
+ 0, /* offset */
|
|
+ };
|
|
+ layout.planes[C2PlanarLayout::PLANE_U] = {
|
|
+ C2PlaneInfo::CHANNEL_CB,
|
|
+ 2, /* colInc */
|
|
+ stride, /* rowInc */
|
|
+ 2, /* colSampling */
|
|
+ 2, /* rowSampling */
|
|
+ 8, /* allocatedDepth */
|
|
+ 8, /* bitDepth */
|
|
+ 0, /* rightShift */
|
|
+ C2PlaneInfo::NATIVE,
|
|
+ C2PlanarLayout::PLANE_V, /* rootIx */
|
|
+ 1, /* offset */
|
|
+ };
|
|
+ layout.planes[C2PlanarLayout::PLANE_V] = {
|
|
+ C2PlaneInfo::CHANNEL_CR,
|
|
+ 2, /* colInc */
|
|
+ stride, /* rowInc */
|
|
+ 2, /* colSampling */
|
|
+ 2, /* rowSampling */
|
|
+ 8, /* allocatedDepth */
|
|
+ 8, /* bitDepth */
|
|
+ 0, /* rightShift */
|
|
+ C2PlaneInfo::NATIVE,
|
|
+ C2PlanarLayout::PLANE_V, /* rootIx */
|
|
+ 0, /* offset */
|
|
+ };
|
|
+ return layout;
|
|
+ }
|
|
+
|
|
+ static std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
|
|
+ uint32_t width,
|
|
+ uint32_t height,
|
|
+ const C2PlanarLayout &layout,
|
|
+ size_t capacity,
|
|
+ std::vector<size_t> offsets) {
|
|
+ std::shared_ptr<C2GraphicAllocation> alloc = std::make_shared<TestGraphicAllocation>(
|
|
+ width,
|
|
+ height,
|
|
+ layout,
|
|
+ capacity,
|
|
+ offsets);
|
|
+
|
|
+ return _C2BlockFactory::CreateGraphicBlock(alloc);
|
|
+ }
|
|
+
|
|
+ static constexpr uint8_t GetPixelValue(uint8_t value, uint32_t row, uint32_t col) {
|
|
+ return (uint32_t(value) * row + col) & 0xFF;
|
|
+ }
|
|
+
|
|
+ static void FillPlane(C2GraphicView &view, size_t index, uint8_t value) {
|
|
+ C2PlanarLayout layout = view.layout();
|
|
+
|
|
+ uint8_t *rowPtr = view.data()[index];
|
|
+ C2PlaneInfo plane = layout.planes[index];
|
|
+ for (uint32_t row = 0; row < view.height() / plane.rowSampling; ++row) {
|
|
+ uint8_t *colPtr = rowPtr;
|
|
+ for (uint32_t col = 0; col < view.width() / plane.colSampling; ++col) {
|
|
+ *colPtr = GetPixelValue(value, row, col);
|
|
+ colPtr += plane.colInc;
|
|
+ }
|
|
+ rowPtr += plane.rowInc;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ static void FillBlock(const std::shared_ptr<C2GraphicBlock> &block) {
|
|
+ C2GraphicView view = block->map().get();
|
|
+
|
|
+ FillPlane(view, C2PlanarLayout::PLANE_Y, 'Y');
|
|
+ FillPlane(view, C2PlanarLayout::PLANE_U, 'U');
|
|
+ FillPlane(view, C2PlanarLayout::PLANE_V, 'V');
|
|
+ }
|
|
+
|
|
+ static bool VerifyPlane(
|
|
+ const MediaImage2 *mediaImage,
|
|
+ const uint8_t *base,
|
|
+ uint32_t index,
|
|
+ uint8_t value,
|
|
+ std::string *errorMsg) {
|
|
+ *errorMsg = "";
|
|
+ MediaImage2::PlaneInfo plane = mediaImage->mPlane[index];
|
|
+ const uint8_t *rowPtr = base + plane.mOffset;
|
|
+ for (uint32_t row = 0; row < mediaImage->mHeight / plane.mVertSubsampling; ++row) {
|
|
+ const uint8_t *colPtr = rowPtr;
|
|
+ for (uint32_t col = 0; col < mediaImage->mWidth / plane.mHorizSubsampling; ++col) {
|
|
+ if (GetPixelValue(value, row, col) != *colPtr) {
|
|
+ *errorMsg = AStringPrintf("row=%u col=%u expected=%02x actual=%02x",
|
|
+ row, col, GetPixelValue(value, row, col), *colPtr).c_str();
|
|
+ return false;
|
|
+ }
|
|
+ colPtr += plane.mColInc;
|
|
+ }
|
|
+ rowPtr += plane.mRowInc;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+public:
|
|
+ static constexpr int32_t kWidth = 320;
|
|
+ static constexpr int32_t kHeight = 240;
|
|
+ static constexpr int32_t kGapLength = kWidth * kHeight * 10;
|
|
+
|
|
+ static std::shared_ptr<C2Buffer> CreateAndFillBufferFromParam(const ParamType ¶m) {
|
|
+ bool contiguous = std::get<0>(param);
|
|
+ std::string planeOrderStr = std::get<1>(param);
|
|
+ bool planar = std::get<2>(param);
|
|
+ int32_t stride = std::get<3>(param);
|
|
+
|
|
+ C2PlanarLayout::plane_index_t planeOrder[3];
|
|
+ C2PlanarLayout layout;
|
|
+
|
|
+ if (planeOrderStr.size() != 3) {
|
|
+ return nullptr;
|
|
+ }
|
|
+ for (size_t i = 0; i < 3; ++i) {
|
|
+ C2PlanarLayout::plane_index_t planeIndex;
|
|
+ switch (planeOrderStr[i]) {
|
|
+ case 'Y': planeIndex = C2PlanarLayout::PLANE_Y; break;
|
|
+ case 'U': planeIndex = C2PlanarLayout::PLANE_U; break;
|
|
+ case 'V': planeIndex = C2PlanarLayout::PLANE_V; break;
|
|
+ default: return nullptr;
|
|
+ }
|
|
+ planeOrder[i] = planeIndex;
|
|
+ }
|
|
+
|
|
+ if (planar) {
|
|
+ layout = YUVPlanarLayout(stride);
|
|
+ } else { // semi-planar
|
|
+ for (size_t i = 0; i < 3; ++i) {
|
|
+ if (planeOrder[i] == C2PlanarLayout::PLANE_U) {
|
|
+ layout = YUVSemiPlanarLayout(stride);
|
|
+ break;
|
|
+ }
|
|
+ if (planeOrder[i] == C2PlanarLayout::PLANE_V) {
|
|
+ layout = YVUSemiPlanarLayout(stride);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ size_t yPlaneSize = stride * kHeight;
|
|
+ size_t uvPlaneSize = stride * kHeight / 4;
|
|
+ size_t capacity = yPlaneSize + uvPlaneSize * 2;
|
|
+ std::vector<size_t> offsets(3);
|
|
+
|
|
+ if (!contiguous) {
|
|
+ if (planar) {
|
|
+ capacity += kGapLength * 2;
|
|
+ } else { // semi-planar
|
|
+ capacity += kGapLength;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ offsets[planeOrder[0]] = 0;
|
|
+ size_t planeSize = (planeOrder[0] == C2PlanarLayout::PLANE_Y) ? yPlaneSize : uvPlaneSize;
|
|
+ for (size_t i = 1; i < 3; ++i) {
|
|
+ offsets[planeOrder[i]] = offsets[planeOrder[i - 1]] + planeSize;
|
|
+ if (!contiguous) {
|
|
+ offsets[planeOrder[i]] += kGapLength;
|
|
+ }
|
|
+ planeSize = (planeOrder[i] == C2PlanarLayout::PLANE_Y) ? yPlaneSize : uvPlaneSize;
|
|
+ if (!planar // semi-planar
|
|
+ && planeOrder[i - 1] != C2PlanarLayout::PLANE_Y
|
|
+ && planeOrder[i] != C2PlanarLayout::PLANE_Y) {
|
|
+ offsets[planeOrder[i]] = offsets[planeOrder[i - 1]] + 1;
|
|
+ planeSize = uvPlaneSize * 2 - 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ std::shared_ptr<C2GraphicBlock> block = CreateGraphicBlock(
|
|
+ kWidth,
|
|
+ kHeight,
|
|
+ layout,
|
|
+ capacity,
|
|
+ offsets);
|
|
+ FillBlock(block);
|
|
+ return C2Buffer::CreateGraphicBuffer(
|
|
+ block->share(block->crop(), C2Fence()));
|
|
+ }
|
|
+
|
|
+ static bool VerifyClientBuffer(
|
|
+ const sp<MediaCodecBuffer> &buffer, std::string *errorMsg) {
|
|
+ *errorMsg = "";
|
|
+ sp<ABuffer> imageData;
|
|
+ if (!buffer->format()->findBuffer("image-data", &imageData)) {
|
|
+ *errorMsg = "Missing image data";
|
|
+ return false;
|
|
+ }
|
|
+ MediaImage2 *mediaImage = (MediaImage2 *)imageData->data();
|
|
+ if (mediaImage->mType != MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
|
|
+ *errorMsg = AStringPrintf("Unexpected type: %d", mediaImage->mType).c_str();
|
|
+ return false;
|
|
+ }
|
|
+ std::string planeErrorMsg;
|
|
+ if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::Y, 'Y', &planeErrorMsg)) {
|
|
+ *errorMsg = "Y plane does not match: " + planeErrorMsg;
|
|
+ return false;
|
|
+ }
|
|
+ if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::U, 'U', &planeErrorMsg)) {
|
|
+ *errorMsg = "U plane does not match: " + planeErrorMsg;
|
|
+ return false;
|
|
+ }
|
|
+ if (!VerifyPlane(mediaImage, buffer->base(), MediaImage2::V, 'V', &planeErrorMsg)) {
|
|
+ *errorMsg = "V plane does not match: " + planeErrorMsg;
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ int32_t width, height, stride;
|
|
+ buffer->format()->findInt32(KEY_WIDTH, &width);
|
|
+ buffer->format()->findInt32(KEY_HEIGHT, &height);
|
|
+ buffer->format()->findInt32(KEY_STRIDE, &stride);
|
|
+
|
|
+ MediaImage2 legacyYLayout = {
|
|
+ MediaImage2::MEDIA_IMAGE_TYPE_Y,
|
|
+ 1, // mNumPlanes
|
|
+ uint32_t(width),
|
|
+ uint32_t(height),
|
|
+ 8,
|
|
+ 8,
|
|
+ {}, // mPlane
|
|
+ };
|
|
+ legacyYLayout.mPlane[MediaImage2::Y] = {
|
|
+ 0, // mOffset
|
|
+ 1, // mColInc
|
|
+ stride, // mRowInc
|
|
+ 1, // mHorizSubsampling
|
|
+ 1, // mVertSubsampling
|
|
+ };
|
|
+ if (!VerifyPlane(&legacyYLayout, buffer->data(), MediaImage2::Y, 'Y', &planeErrorMsg)) {
|
|
+ *errorMsg = "Y plane by legacy layout does not match: " + planeErrorMsg;
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+};
|
|
+
|
|
+TEST_P(LayoutTest, VerifyLayout) {
|
|
+ std::shared_ptr<RawGraphicOutputBuffers> buffers =
|
|
+ GetRawGraphicOutputBuffers(kWidth, kHeight);
|
|
+
|
|
+ std::shared_ptr<C2Buffer> c2Buffer = CreateAndFillBufferFromParam(GetParam());
|
|
+ ASSERT_NE(nullptr, c2Buffer);
|
|
+ sp<MediaCodecBuffer> clientBuffer;
|
|
+ size_t index;
|
|
+ ASSERT_EQ(OK, buffers->registerBuffer(c2Buffer, &index, &clientBuffer));
|
|
+ ASSERT_NE(nullptr, clientBuffer);
|
|
+ std::string errorMsg;
|
|
+ ASSERT_TRUE(VerifyClientBuffer(clientBuffer, &errorMsg)) << errorMsg;
|
|
+}
|
|
+
|
|
+INSTANTIATE_TEST_SUITE_P(
|
|
+ RawGraphicOutputBuffersTest,
|
|
+ LayoutTest,
|
|
+ ::testing::Combine(
|
|
+ ::testing::Bool(), /* contiguous */
|
|
+ ::testing::Values("YUV", "YVU", "UVY", "VUY"),
|
|
+ ::testing::Bool(), /* planar */
|
|
+ ::testing::Values(320, 512)),
|
|
+ [](const ::testing::TestParamInfo<LayoutTest::ParamType> &info) {
|
|
+ std::string contiguous = std::get<0>(info.param) ? "Contiguous" : "Noncontiguous";
|
|
+ std::string planar = std::get<2>(info.param) ? "Planar" : "SemiPlanar";
|
|
+ return contiguous
|
|
+ + std::get<1>(info.param)
|
|
+ + planar
|
|
+ + std::to_string(std::get<3>(info.param));
|
|
+ });
|
|
+
|
|
} // namespace android
|
|
--
|
|
2.25.1
|
|
|