v4l2_codec2 encoder: Clean up format convertor.
This CL reworks the format convertor to improve readability:
- Move allocating of buffers to a separate function
- Group logic to determine the input pixel format
- Improve documentation
No changes have been made that affect functionality.
Bug: 205203831
Test: arc.VideoEncodeAccel.h264_192p_i420_vm
arc.PowerCameraRecordingPerf.vm
Change-Id: I2d5b909988c1bc35edac537c5c7f895ff13bba80
(cherry picked from commit cf13f59125992191c6b14d350785f1033528fee3)
diff --git a/common/FormatConverter.cpp b/common/FormatConverter.cpp
index 17b33c2..4f4a3d0 100644
--- a/common/FormatConverter.cpp
+++ b/common/FormatConverter.cpp
@@ -115,78 +115,105 @@
videoPixelFormatToString(outFormat).c_str(), visibleSize.width, visibleSize.height,
inputCount, codedSize.width, codedSize.height);
- std::shared_ptr<C2BlockPool> pool;
- c2_status_t status = GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool);
- if (status != C2_OK) {
- ALOGE("Failed to get basic graphic block pool (err=%d)", status);
- return status;
- }
-
- HalPixelFormat halFormat;
- if (outFormat == VideoPixelFormat::I420) {
- // Android HAL format doesn't have I420, we use YV12 instead and swap U and V data while
- // conversion to perform I420.
- halFormat = HalPixelFormat::YV12;
- } else {
- halFormat = HalPixelFormat::YCBCR_420_888; // will allocate NV12 by minigbm.
- }
-
- uint32_t bufferCount = std::max(inputCount, 1u);
- for (uint32_t i = 0; i < bufferCount; i++) {
- std::shared_ptr<C2GraphicBlock> block;
- status = pool->fetchGraphicBlock(codedSize.width, codedSize.height,
- static_cast<uint32_t>(halFormat),
- {(C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE),
- static_cast<uint64_t>(BufferUsage::VIDEO_ENCODER)},
- &block);
- if (status != C2_OK) {
- ALOGE("Failed to fetch graphic block (err=%d)", status);
- return status;
- }
- mGraphicBlocks.emplace_back(new BlockEntry(std::move(block)));
- mAvailableQueue.push(mGraphicBlocks.back().get());
- }
-
mOutFormat = outFormat;
mVisibleSize = visibleSize;
+ mCodedSize = codedSize;
mTempPlaneU =
std::unique_ptr<uint8_t[]>(new uint8_t[mVisibleSize.width * mVisibleSize.height / 4]);
mTempPlaneV =
std::unique_ptr<uint8_t[]>(new uint8_t[mVisibleSize.width * mVisibleSize.height / 4]);
+ // Allocate graphic blocks for format conversion.
+ uint32_t requested_buffer_count = std::max(1u, inputCount);
+ c2_status_t status = allocateBuffers(requested_buffer_count);
+ if (status != C2_OK) {
+ ALOGE("Failed to allocate buffers (error: %d)", status);
+ return status;
+ }
+
return C2_OK;
}
-C2ConstGraphicBlock FormatConverter::convertBlock(uint64_t frameIndex,
- const C2ConstGraphicBlock& inputBlock,
- c2_status_t* status) {
+c2_status_t FormatConverter::allocateBuffers(uint32_t count) {
+ ALOGV("Allocating %u buffers (format: %s, visible size: %dx%d, coded size: %dx%d)", count,
+ videoPixelFormatToString(mOutFormat).c_str(), mVisibleSize.width, mVisibleSize.height,
+ mCodedSize.width, mCodedSize.height);
+
+ HalPixelFormat halFormat;
+ if (mOutFormat == VideoPixelFormat::I420) {
+ // Android HAL format doesn't have I420, we use YV12 instead and swap U/V while converting.
+ halFormat = HalPixelFormat::YV12;
+ } else {
+ halFormat = HalPixelFormat::YCBCR_420_888; // Will allocate NV12 in minigbm.
+ }
+
+ std::shared_ptr<C2BlockPool> pool;
+ c2_status_t status = GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, nullptr, &pool);
+ if (status != C2_OK) {
+ ALOGE("Failed to get basic graphic block pool (error: %d)", status);
+ return C2_NO_MEMORY;
+ }
+
+ for (uint32_t i = 0; i < count; i++) {
+ std::shared_ptr<C2GraphicBlock> block;
+ status = pool->fetchGraphicBlock(mCodedSize.width, mCodedSize.height,
+ static_cast<uint32_t>(halFormat),
+ {(C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE),
+ static_cast<uint64_t>(BufferUsage::VIDEO_ENCODER)},
+ &block);
+ if (status != C2_OK) {
+ ALOGE("Failed to fetch graphic block (error: %d)", status);
+ return C2_NO_MEMORY;
+ }
+ mGraphicBlocks.emplace_back(new BlockEntry(std::move(block)));
+ mAvailableQueue.push(mGraphicBlocks.back().get());
+ }
+
+ return C2_OK;
+}
+
+c2_status_t FormatConverter::convertBlock(uint64_t frameIndex,
+ const C2ConstGraphicBlock& inputBlock,
+ C2ConstGraphicBlock* convertedBlock) {
+ const C2GraphicView& inputView = inputBlock.map().get();
+ C2PlanarLayout inputLayout = inputView.layout();
+
+ // Determine the input buffer pixel format.
+ VideoPixelFormat inputFormat = VideoPixelFormat::UNKNOWN;
+ std::unique_ptr<ImplDefinedToRGBXMap> idMap;
+ if (inputLayout.type == C2PlanarLayout::TYPE_YUV) {
+ if (inputLayout.rootPlanes == 3) {
+ inputFormat = VideoPixelFormat::YV12;
+ } else if (inputLayout.rootPlanes == 2) {
+ const uint8_t* const* data = inputView.data();
+ inputFormat = (data[C2PlanarLayout::PLANE_V] > data[C2PlanarLayout::PLANE_U])
+ ? VideoPixelFormat::NV12
+ : VideoPixelFormat::NV21;
+ }
+ } else if (static_cast<uint32_t>(inputLayout.type) == 0u) {
+ // The above layout() cannot fill layout information and sets it to 0 instead if the input
+ // format is IMPLEMENTATION_DEFINED and its backed format is RGB. We fill the layout by
+ // using ImplDefinedToRGBXMap in this case.
+ idMap = ImplDefinedToRGBXMap::Create(inputBlock);
+ if (!idMap) {
+ ALOGE("Unable to parse RGBX_8888 from IMPLEMENTATION_DEFINED");
+ return C2_CORRUPTED;
+ }
+ // There is only RGBA_8888 specified in C2AllocationGralloc::map(), no BGRA_8888. Maybe
+ // BGRA_8888 is not used now?
+ inputFormat = VideoPixelFormat::ABGR;
+ inputLayout.type = C2PlanarLayout::TYPE_RGB;
+ }
+
if (!isReady()) {
ALOGV("There is no available block for conversion");
- *status = C2_NO_MEMORY;
- return inputBlock; // This is actually redundant and should not be used.
+ return C2_NO_MEMORY;
}
BlockEntry* entry = mAvailableQueue.front();
std::shared_ptr<C2GraphicBlock> outputBlock = entry->mBlock;
- const C2GraphicView& inputView = inputBlock.map().get();
- C2PlanarLayout inputLayout = inputView.layout();
-
- // The above layout() cannot fill layout information and memset 0 instead if the input format is
- // IMPLEMENTATION_DEFINED and its backed format is RGB. We fill the layout by using
- // ImplDefinedToRGBXMap in the case.
- std::unique_ptr<ImplDefinedToRGBXMap> idMap;
- if (static_cast<uint32_t>(inputLayout.type) == 0u) {
- idMap = ImplDefinedToRGBXMap::Create(inputBlock);
- if (idMap == nullptr) {
- ALOGE("Unable to parse RGBX_8888 from IMPLEMENTATION_DEFINED");
- *status = C2_CORRUPTED;
- return inputBlock; // This is actually redundant and should not be used.
- }
- inputLayout.type = C2PlanarLayout::TYPE_RGB;
- }
-
C2GraphicView outputView = outputBlock->map().get();
C2PlanarLayout outputLayout = outputView.layout();
uint8_t* dstY = outputView.data()[C2PlanarLayout::PLANE_Y];
@@ -198,8 +225,6 @@
const int dstStrideV = outputLayout.planes[C2PlanarLayout::PLANE_U].rowInc; // only for I420
const int dstStrideUV = outputLayout.planes[C2PlanarLayout::PLANE_U].rowInc; // only for NV12
- VideoPixelFormat inputFormat = VideoPixelFormat::UNKNOWN;
- *status = C2_OK;
if (inputLayout.type == C2PlanarLayout::TYPE_YUV) {
const uint8_t* srcY = inputView.data()[C2PlanarLayout::PLANE_Y];
const uint8_t* srcU = inputView.data()[C2PlanarLayout::PLANE_U];
@@ -207,16 +232,12 @@
const int srcStrideY = inputLayout.planes[C2PlanarLayout::PLANE_Y].rowInc;
const int srcStrideU = inputLayout.planes[C2PlanarLayout::PLANE_U].rowInc;
const int srcStrideV = inputLayout.planes[C2PlanarLayout::PLANE_V].rowInc;
- if (inputLayout.rootPlanes == 3) {
- inputFormat = VideoPixelFormat::YV12;
- } else if (inputLayout.rootPlanes == 2) {
- inputFormat = (srcV > srcU) ? VideoPixelFormat::NV12 : VideoPixelFormat::NV21;
- }
if (inputFormat == mOutFormat) {
ALOGV("Zero-Copy is applied");
mGraphicBlocks.emplace_back(new BlockEntry(frameIndex));
- return inputBlock;
+ *convertedBlock = inputBlock;
+ return C2_OK;
}
switch (convertMap(inputFormat, mOutFormat)) {
@@ -253,14 +274,9 @@
ALOGE("Unsupported pixel format conversion from %s to %s",
videoPixelFormatToString(inputFormat).c_str(),
videoPixelFormatToString(mOutFormat).c_str());
- *status = C2_CORRUPTED;
- return inputBlock; // This is actually redundant and should not be used.
+ return C2_CORRUPTED;
}
} else if (inputLayout.type == C2PlanarLayout::TYPE_RGB) {
- // There is only RGBA_8888 specified in C2AllocationGralloc::map(), no BGRA_8888. Maybe
- // BGRA_8888 is not used now?
- inputFormat = VideoPixelFormat::ABGR;
-
const uint8_t* srcRGB = (idMap) ? idMap->addr() : inputView.data()[C2PlanarLayout::PLANE_R];
const int srcStrideRGB =
(idMap) ? idMap->rowInc() : inputLayout.planes[C2PlanarLayout::PLANE_R].rowInc;
@@ -287,20 +303,21 @@
ALOGE("Unsupported pixel format conversion from %s to %s",
videoPixelFormatToString(inputFormat).c_str(),
videoPixelFormatToString(mOutFormat).c_str());
- *status = C2_CORRUPTED;
- return inputBlock; // This is actually redundant and should not be used.
+ return C2_CORRUPTED;
}
} else {
ALOGE("Unsupported input layout type");
- *status = C2_CORRUPTED;
- return inputBlock; // This is actually redundant and should not be used.
+ return C2_CORRUPTED;
}
ALOGV("convertBlock(frame_index=%" PRIu64 ", format=%s)", frameIndex,
videoPixelFormatToString(inputFormat).c_str());
entry->mAssociatedFrameIndex = frameIndex;
mAvailableQueue.pop();
- return outputBlock->share(C2Rect(mVisibleSize.width, mVisibleSize.height), C2Fence());
+
+ *convertedBlock =
+ outputBlock->share(C2Rect(mVisibleSize.width, mVisibleSize.height), C2Fence());
+ return C2_OK;
}
c2_status_t FormatConverter::returnBlock(uint64_t frameIndex) {