Codec2.0: specify buffer format while import output buffer
In ARC++ case, the buffer format is no longer assigned from Chromium side.
Instead, the Android side will allocate the buffer and specify the buffer
format so that we know how to import the buffer in Chromium side.
Bug: None
Test: run native tests on bob (ARC++N) and kevin (ARC++P)
Change-Id: I518c89076f9c0fa825585d7f09be01c1f615d00c
diff --git a/C2VDAAdaptor.cpp b/C2VDAAdaptor.cpp
index 446a6b4..ecfcbef 100644
--- a/C2VDAAdaptor.cpp
+++ b/C2VDAAdaptor.cpp
@@ -13,11 +13,17 @@
#include <v4l2_slice_video_decode_accelerator.h>
#include <videodev2.h>
-#include <system/graphics.h>
#include <utils/Log.h>
namespace android {
+constexpr SupportedPixelFormat kSupportedPixelFormats[] = {
+ // {mCrcb, mSemiplanar, mPixelFormat}
+ {false, true, HalPixelFormat::NV12},
+ {true, false, HalPixelFormat::YV12},
+ // Add more buffer formats when needed
+};
+
C2VDAAdaptor::C2VDAAdaptor() : mNumOutputBuffers(0u) {}
C2VDAAdaptor::~C2VDAAdaptor() {
@@ -71,15 +77,21 @@
mNumOutputBuffers = numOutputBuffers;
}
-void C2VDAAdaptor::importBufferForPicture(int32_t pictureBufferId, int dmabufFd,
+void C2VDAAdaptor::importBufferForPicture(int32_t pictureBufferId, HalPixelFormat format,
+ int dmabufFd,
const std::vector<VideoFramePlane>& planes) {
+ // per change ag/3262504, format should be passed to VDA, however it also matters to VDA API
+ // change.
+ // TODO(johnylin): pass format to VDA after updating VDA codes to latest.
+ (void)format;
+
CHECK(mVDA);
CHECK_LT(pictureBufferId, static_cast<int32_t>(mNumOutputBuffers));
media::NativePixmapHandle handle;
handle.fds.emplace_back(base::FileDescriptor(dmabufFd, true));
for (const auto& plane : planes) {
- handle.planes.emplace_back(plane.stride, plane.offset, 0, 0);
+ handle.planes.emplace_back(plane.mStride, plane.mOffset, 0, 0);
}
mVDA->ImportBufferForPicture(pictureBufferId, handle);
}
@@ -124,30 +136,25 @@
return supportedProfiles;
}
+//static
+HalPixelFormat C2VDAAdaptor::ResolveBufferFormat(bool crcb, bool semiplanar) {
+ auto value = std::find_if(std::begin(kSupportedPixelFormats), std::end(kSupportedPixelFormats),
+ [crcb, semiplanar](const struct SupportedPixelFormat& f) {
+ return f.mCrcb == crcb && f.mSemiplanar == semiplanar;
+ });
+ LOG_ALWAYS_FATAL_IF(value == std::end(kSupportedPixelFormats),
+ "Unsupported pixel format: (crcb=%d, semiplanar=%d)", crcb, semiplanar);
+ return value->mPixelFormat;
+}
+
void C2VDAAdaptor::ProvidePictureBuffers(uint32_t requested_num_of_buffers,
media::VideoPixelFormat output_format,
const media::Size& dimensions) {
- uint32_t pixelFormat;
- switch (output_format) {
- case media::PIXEL_FORMAT_I420:
- case media::PIXEL_FORMAT_YV12:
- case media::PIXEL_FORMAT_NV12:
- case media::PIXEL_FORMAT_NV21:
- // HAL_PIXEL_FORMAT_YCbCr_420_888 is the flexible pixel format in Android
- // which handles all 420 formats, with both orderings of chroma (CbCr and
- // CrCb) as well as planar and semi-planar layouts.
- pixelFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
- break;
- case media::PIXEL_FORMAT_ARGB:
- pixelFormat = HAL_PIXEL_FORMAT_BGRA_8888;
- break;
- default:
- ALOGE("Format not supported: %d", output_format);
- mClient->notifyError(PLATFORM_FAILURE);
- return;
- }
+ // per change ag/3262504, output_format from VDA is no longer used, component side always
+ // allocate graphic buffers for flexible YUV format.
+ (void)output_format;
- mClient->providePictureBuffers(pixelFormat, requested_num_of_buffers, dimensions);
+ mClient->providePictureBuffers(requested_num_of_buffers, dimensions);
mPictureSize = dimensions;
}
diff --git a/C2VDAComponent.cpp b/C2VDAComponent.cpp
index 8228136..0db1d79 100644
--- a/C2VDAComponent.cpp
+++ b/C2VDAComponent.cpp
@@ -451,7 +451,7 @@
}
}
-C2VDAComponent::VideoFormat::VideoFormat(uint32_t pixelFormat, uint32_t minNumBuffers,
+C2VDAComponent::VideoFormat::VideoFormat(HalPixelFormat pixelFormat, uint32_t minNumBuffers,
media::Size codedSize, media::Rect visibleRect)
: mPixelFormat(pixelFormat),
mMinNumBuffers(minNumBuffers),
@@ -860,8 +860,8 @@
EXPECT_RUNNING_OR_RETURN_ON_ERROR();
ALOGV("New output format(pixel_format=0x%x, min_num_buffers=%u, coded_size=%s, crop_rect=%s)",
- format->mPixelFormat, format->mMinNumBuffers, format->mCodedSize.ToString().c_str(),
- format->mVisibleRect.ToString().c_str());
+ static_cast<uint32_t>(format->mPixelFormat), format->mMinNumBuffers,
+ format->mCodedSize.ToString().c_str(), format->mVisibleRect.ToString().c_str());
for (auto& info : mGraphicBlocks) {
if (info.mState == GraphicBlockInfo::State::OWNED_BY_ACCELERATOR)
@@ -880,6 +880,7 @@
// Change the output format only after all output buffers are returned
// from clients.
+ // TODO(johnylin): don't need to wait for new proposed buffer flow.
for (const auto& info : mGraphicBlocks) {
if (info.mState == GraphicBlockInfo::State::OWNED_BY_CLIENT) {
ALOGV("wait buffer: %d for output format change", info.mBlockId);
@@ -887,28 +888,18 @@
}
}
- uint32_t colorFormat;
- int bufferFormat;
- switch (mPendingOutputFormat->mPixelFormat) {
- case HAL_PIXEL_FORMAT_YCbCr_420_888:
- colorFormat = kColorFormatYUV420Flexible;
- bufferFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
- break;
- default:
- ALOGE("pixel format: 0x%x is not supported", mPendingOutputFormat->mPixelFormat);
- reportError(C2_OMITTED);
- return;
- }
+ CHECK_EQ(mPendingOutputFormat->mPixelFormat, HalPixelFormat::YCbCr_420_888);
mOutputFormat.mPixelFormat = mPendingOutputFormat->mPixelFormat;
mOutputFormat.mMinNumBuffers = mPendingOutputFormat->mMinNumBuffers;
mOutputFormat.mCodedSize = mPendingOutputFormat->mCodedSize;
setOutputFormatCrop(mPendingOutputFormat->mVisibleRect);
- mColorFormat = colorFormat;
+ mColorFormat = kColorFormatYUV420Flexible;
- c2_status_t err =
- allocateBuffersFromBlockAllocator(mPendingOutputFormat->mCodedSize, bufferFormat);
+ c2_status_t err = allocateBuffersFromBlockAllocator(
+ mPendingOutputFormat->mCodedSize,
+ static_cast<uint32_t>(mPendingOutputFormat->mPixelFormat));
if (err != C2_OK) {
reportError(err);
return;
@@ -921,7 +912,7 @@
}
c2_status_t C2VDAComponent::allocateBuffersFromBlockAllocator(const media::Size& size,
- int pixelFormat) {
+ uint32_t pixelFormat) {
ALOGV("allocateBuffersFromBlockAllocator(%s, 0x%x)", size.ToString().c_str(), pixelFormat);
size_t bufferCount = mOutputFormat.mMinNumBuffers + kDpbOutputBufferExtraCount;
@@ -983,22 +974,29 @@
offsets[i] = static_cast<uint32_t>(planeAddress - baseAddress);
}
+ bool crcb = false;
if (layout.numPlanes == 3 &&
offsets[C2PlanarLayout::PLANE_U] > offsets[C2PlanarLayout::PLANE_V]) {
// YCrCb format
std::swap(offsets[C2PlanarLayout::PLANE_U], offsets[C2PlanarLayout::PLANE_V]);
+ crcb = true;
}
+ bool semiplanar = false;
uint32_t passedNumPlanes = layout.numPlanes;
if (layout.planes[C2PlanarLayout::PLANE_U].colInc == 2) { // chroma_step
// Semi-planar format
passedNumPlanes--;
+ semiplanar = true;
}
for (uint32_t i = 0; i < passedNumPlanes; ++i) {
ALOGV("plane %u: stride: %d, offset: %u", i, layout.planes[i].rowInc, offsets[i]);
}
+ info.mPixelFormat = C2VDAAdaptor::ResolveBufferFormat(crcb, semiplanar);
+ ALOGV("HAL pixel format: 0x%x", static_cast<uint32_t>(info.mPixelFormat));
+
base::ScopedFD passedHandle(dup(info.mGraphicBlock->handle()->data[0]));
if (!passedHandle.is_valid()) {
ALOGE("Failed to dup(%d), errno=%d", info.mGraphicBlock->handle()->data[0], errno);
@@ -1024,7 +1022,8 @@
// is_valid() is true for the first time the buffer is passed to VDA. In that case, VDA needs to
// import the buffer first.
if (info->mHandle.is_valid()) {
- mVDAAdaptor->importBufferForPicture(info->mBlockId, info->mHandle.release(), info->mPlanes);
+ mVDAAdaptor->importBufferForPicture(info->mBlockId, info->mPixelFormat,
+ info->mHandle.release(), info->mPlanes);
} else {
mVDAAdaptor->reusePictureBuffer(info->mBlockId);
}
@@ -1138,11 +1137,11 @@
return mIntf;
}
-void C2VDAComponent::providePictureBuffers(uint32_t pixelFormat, uint32_t minNumBuffers,
- const media::Size& codedSize) {
+void C2VDAComponent::providePictureBuffers(uint32_t minNumBuffers, const media::Size& codedSize) {
+ // Always use fexible pixel 420 format YCbCr_420_888 in Android.
// Uses coded size for crop rect while it is not available.
- auto format = std::make_unique<VideoFormat>(pixelFormat, minNumBuffers, codedSize,
- media::Rect(codedSize));
+ auto format = std::make_unique<VideoFormat>(HalPixelFormat::YCbCr_420_888, minNumBuffers,
+ codedSize, media::Rect(codedSize));
// Set mRequestedVisibleRect to default.
mRequestedVisibleRect = media::Rect();
diff --git a/include/C2VDAAdaptor.h b/include/C2VDAAdaptor.h
index a59e1be..8f24d10 100644
--- a/include/C2VDAAdaptor.h
+++ b/include/C2VDAAdaptor.h
@@ -26,7 +26,7 @@
VideoDecodeAcceleratorAdaptor::Client* client) override;
void decode(int32_t bitstreamId, int handleFd, off_t offset, uint32_t bytesUsed) override;
void assignPictureBuffers(uint32_t numOutputBuffers) override;
- void importBufferForPicture(int32_t pictureBufferId, int handleFd,
+ void importBufferForPicture(int32_t pictureBufferId, HalPixelFormat format, int handleFd,
const std::vector<VideoFramePlane>& planes) override;
void reusePictureBuffer(int32_t pictureBufferId) override;
void flush() override;
@@ -36,6 +36,8 @@
static media::VideoDecodeAccelerator::SupportedProfiles GetSupportedProfiles(
uint32_t inputFormatFourcc);
+ static HalPixelFormat ResolveBufferFormat(bool crcb, bool semiplanar);
+
// Implementation of the media::VideoDecodeAccelerator::Client interface.
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
media::VideoPixelFormat output_format,
diff --git a/include/C2VDAComponent.h b/include/C2VDAComponent.h
index 6daae45..cfc2720 100644
--- a/include/C2VDAComponent.h
+++ b/include/C2VDAComponent.h
@@ -122,7 +122,7 @@
virtual std::shared_ptr<C2ComponentInterface> intf() override;
// Implementation of VideDecodeAcceleratorAdaptor::Client interface
- virtual void providePictureBuffers(uint32_t pixelFormat, uint32_t minNumBuffers,
+ virtual void providePictureBuffers(uint32_t minNumBuffers,
const media::Size& codedSize) override;
virtual void dismissPictureBuffer(int32_t pictureBufferId) override;
virtual void pictureReady(int32_t pictureBufferId, int32_t bitstreamId,
@@ -181,6 +181,8 @@
State mState = State::OWNED_BY_COMPONENT;
// Graphic block buffer allocated from allocator. This should be reused.
std::shared_ptr<C2GraphicBlock> mGraphicBlock;
+ // HAL pixel format used while importing to VDA.
+ HalPixelFormat mPixelFormat;
// The handle dupped from graphic block for importing to VDA.
base::ScopedFD mHandle;
// VideoFramePlane information for importing to VDA.
@@ -188,13 +190,13 @@
};
struct VideoFormat {
- uint32_t mPixelFormat = 0;
+ HalPixelFormat mPixelFormat = HalPixelFormat::UNKNOWN;
uint32_t mMinNumBuffers = 0;
media::Size mCodedSize;
media::Rect mVisibleRect;
VideoFormat() {}
- VideoFormat(uint32_t pixelFormat, uint32_t minNumBuffers, media::Size codedSize,
+ VideoFormat(HalPixelFormat pixelFormat, uint32_t minNumBuffers, media::Size codedSize,
media::Rect visibleRect);
};
@@ -238,7 +240,7 @@
// Try to apply the output format change.
void tryChangeOutputFormat();
// Allocate output buffers (graphic blocks) from block allocator.
- c2_status_t allocateBuffersFromBlockAllocator(const media::Size& size, int pixelFormat);
+ c2_status_t allocateBuffersFromBlockAllocator(const media::Size& size, uint32_t pixelFormat);
// Append allocated buffer (graphic block) to mGraphicBlocks.
void appendOutputBuffer(std::shared_ptr<C2GraphicBlock> block);
diff --git a/include/VideoDecodeAcceleratorAdaptor.h b/include/VideoDecodeAcceleratorAdaptor.h
index e2e65aa..8f10c3b 100644
--- a/include/VideoDecodeAcceleratorAdaptor.h
+++ b/include/VideoDecodeAcceleratorAdaptor.h
@@ -14,10 +14,25 @@
namespace android {
+enum class HalPixelFormat : uint32_t {
+ UNKNOWN = 0x0,
+ // The pixel formats defined in Android but are used among C2VDAComponent.
+ YCbCr_420_888 = 0x23,
+ YV12 = 0x32315659,
+ NV12 = 0x3231564e,
+};
+
// The offset and stride of a video frame plane.
struct VideoFramePlane {
- uint32_t offset;
- uint32_t stride;
+ uint32_t mOffset;
+ uint32_t mStride;
+};
+
+// The HAL pixel format information supported by Android flexible YUV format.
+struct SupportedPixelFormat {
+ bool mCrcb;
+ bool mSemiplanar;
+ HalPixelFormat mPixelFormat;
};
// Video decoder accelerator adaptor interface.
@@ -42,7 +57,7 @@
virtual ~Client() {}
// Callback to tell client how many and what size of buffers to provide.
- virtual void providePictureBuffers(uint32_t pixelFormat, uint32_t minNumBuffers,
+ virtual void providePictureBuffers(uint32_t minNumBuffers,
const media::Size& codedSize) = 0;
// Callback to dismiss picture buffer that was assigned earlier.
@@ -79,7 +94,8 @@
virtual void assignPictureBuffers(uint32_t numOutputBuffers) = 0;
// Imports planes as backing memory for picture buffer with specified ID.
- virtual void importBufferForPicture(int32_t pictureBufferId, int handleFd,
+ virtual void importBufferForPicture(int32_t pictureBufferId, HalPixelFormat format,
+ int handleFd,
const std::vector<VideoFramePlane>& planes) = 0;
// Sends picture buffer to be reused by the decoder by its piture ID.