Skip to content
Snippets Groups Projects
Commit 311121a4 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Use dma-buf inode number as buffer unique id" am: c9cd11bc am:...

Merge "Use dma-buf inode number as buffer unique id" am: c9cd11bc am: 89261386 am: e11c60dd am: 89c63ddd

Original change: https://android-review.googlesource.com/c/platform/external/v4l2_codec2/+/1878495

Change-Id: Ic86f6ccf96a422b04177e21bfe8e8778685899a7
parents bb65bd6b 89c63ddd
No related branches found
No related tags found
No related merge requests found
......@@ -18,7 +18,7 @@ request to the driver via the V4L2 API.
* Gralloc support for graphic buffer allocation
* ION or Gralloc support for linear buffer allocation
* DRM for buffer identification
* Kernel v5.3+ or [this patch][1] backported for buffer identification
* [V4L2 stateful decoding API](https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-decoder.html)
* [V4L2 encoding API](https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-encoder.html)
* Widevine DRM for secure playback
......@@ -47,12 +47,9 @@ PRODUCT_COPY_FILES += \
<path_to_file>:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_c2.xml
# Set the customized property of v4l2_codec2, including:
# - The DRM device name and path pattern.
# - The maximum concurrent instances for decoder/encoder.
# It should be the same as "concurrent-instances" at media_codec_c2.xml.
PRODUCT_PROPERTY_OVERRIDES += \
ro.vendor.v4l2_codec2.drm_device_name=virtio_gpu \
ro.vendor.v4l2_codec2.drm_device_path=/dev/dri/renderD* \
ro.vendor.v4l2_codec2.decode_concurrent_instances=8 \
ro.vendor.v4l2_codec2.encode_concurrent_instances=8
......@@ -364,3 +361,5 @@ PPS NAL units are prepended to IDR frames by enabling the
*V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR* control. If the V4L2 driver does not
support this control the encoder will manually cache and prepend SPS and PPS NAL
units.
[1]: https://android.googlesource.com/kernel/common/+/ed63bb1d1f8469586006a9ca63c42344401aa2ab
......@@ -18,7 +18,6 @@ cc_library_shared {
srcs: [
"C2VdaBqBlockPool.cpp",
"C2VdaPooledBlockPool.cpp",
"DrmGrallocHelpers.cpp",
"H2BGraphicBufferProducer.cpp",
"V4L2PluginStore.cpp",
"VendorAllocatorLoader.cpp",
......@@ -34,7 +33,6 @@ cc_library_shared {
"android.hardware.graphics.bufferqueue@2.0",
"libchrome",
"libcutils",
"libdrm",
"libhardware",
"libhidlbase",
"libnativewindow",
......
......@@ -9,6 +9,9 @@
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <chrono>
#include <mutex>
......@@ -24,7 +27,6 @@
#include <log/log.h>
#include <ui/BufferQueueDefs.h>
#include <v4l2_codec2/plugin_store/DrmGrallocHelpers.h>
#include <v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h>
#include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
......@@ -44,8 +46,6 @@ constexpr int kMaxDequeuedBufferCount = 32u;
using namespace std::chrono_literals;
// We use the value of DRM handle as the unique ID of the graphic buffers.
using unique_id_t = uint32_t;
// Type for IGBP slot index.
using slot_t = int32_t;
......@@ -54,6 +54,20 @@ using ::android::BufferQueueDefs::NUM_BUFFER_SLOTS;
using ::android::hardware::Return;
using HProducerListener = ::android::hardware::graphics::bufferqueue::V2_0::IProducerListener;
std::optional<unique_id_t> getDmabufId(int dmabufFd) {
struct stat sb {};
if (fstat(dmabufFd, &sb) != 0) {
return std::nullopt;
}
if (sb.st_size == 0) {
ALOGE("Dma-buf size is 0. Please check your kernel is v5.3+");
return std::nullopt;
}
return static_cast<unique_id_t>(sb.st_ino);
}
static c2_status_t asC2Error(status_t err) {
switch (err) {
case OK:
......@@ -408,47 +422,6 @@ private:
uint64_t mUsageToBeMigrated = 0;
};
class DrmHandleManager {
public:
DrmHandleManager() { mRenderFd = openRenderFd(); }
~DrmHandleManager() {
closeAllHandles();
if (mRenderFd) {
close(*mRenderFd);
}
}
std::optional<unique_id_t> getHandle(int primeFd) {
if (!mRenderFd) {
return std::nullopt;
}
std::optional<unique_id_t> handle = getDrmHandle(*mRenderFd, primeFd);
// Defer closing the handle until we don't need the buffer to keep the returned DRM handle
// the same.
if (handle) {
mHandles.insert(*handle);
}
return handle;
}
void closeAllHandles() {
if (!mRenderFd) {
return;
}
for (const unique_id_t& handle : mHandles) {
closeDrmHandle(*mRenderFd, handle);
}
mHandles.clear();
}
private:
std::optional<int> mRenderFd;
std::set<unique_id_t> mHandles;
};
class C2VdaBqBlockPool::Impl : public std::enable_shared_from_this<C2VdaBqBlockPool::Impl>,
public EventNotifier::Listener {
public:
......@@ -514,9 +487,6 @@ private:
TrackedGraphicBuffers mTrackedGraphicBuffers;
// We treat DRM handle as uniqueId of GraphicBuffer.
DrmHandleManager mDrmHandleManager;
// Number of buffers requested on requestNewBufferSet() call.
size_t mBuffersRequested = 0u;
// Currently requested buffer formats.
......@@ -673,7 +643,7 @@ status_t C2VdaBqBlockPool::Impl::getFreeSlotLocked(uint32_t width, uint32_t heig
return requestStatus;
}
const auto uniqueId = mDrmHandleManager.getHandle(slotBuffer->handle->data[0]);
const auto uniqueId = getDmabufId(slotBuffer->handle->data[0]);
if (!uniqueId) {
ALOGE("%s(): failed to get uniqueId of GraphicBuffer from slot=%d", __func__, *slot);
return UNKNOWN_ERROR;
......@@ -802,7 +772,6 @@ c2_status_t C2VdaBqBlockPool::Impl::requestNewBufferSet(int32_t bufferCount, uin
// Release all remained slot buffer references here. CCodec should either cancel or queue its
// owned buffers from this set before the next resolution change.
mTrackedGraphicBuffers.reset();
mDrmHandleManager.closeAllHandles();
mBuffersRequested = static_cast<size_t>(bufferCount);
......@@ -822,7 +791,6 @@ void C2VdaBqBlockPool::Impl::configureProducer(const sp<HGraphicBufferProducer>&
mProducer = nullptr;
mProducerId = 0;
mTrackedGraphicBuffers.reset();
mDrmHandleManager.closeAllHandles();
return;
}
......@@ -931,7 +899,7 @@ bool C2VdaBqBlockPool::Impl::setNotifyBlockAvailableCb(::base::OnceClosure cb) {
std::optional<unique_id_t> C2VdaBqBlockPool::Impl::getBufferIdFromGraphicBlock(
const C2Block2D& block) {
return mDrmHandleManager.getHandle(block.handle()->data[0]);
return getDmabufId(block.handle()->data[0]);
}
status_t C2VdaBqBlockPool::Impl::allowAllocation(bool allow) {
......
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//#define LOG_NDEBUG 0
#define LOG_TAG "DrmGrallocHelper"
#include <v4l2_codec2/plugin_store/DrmGrallocHelpers.h>
#include <fcntl.h>
#include <glob.h>
#include <string>
#include <vector>
#include <cutils/properties.h>
#include <drm/drm.h>
#include <log/log.h>
namespace android {
namespace {
// Return a list of paths that matches |pattern|, the unix style pathname pattern.
std::vector<std::string> glob(const std::string& pattern) {
glob_t glob_result;
memset(&glob_result, 0, sizeof(glob_result));
std::vector<std::string> paths;
if (glob(pattern.c_str(), GLOB_ERR | GLOB_NOESCAPE, NULL, &glob_result) == 0) {
for (size_t i = 0; i < glob_result.gl_pathc; ++i) {
paths.emplace_back(glob_result.gl_pathv[i]);
}
}
globfree(&glob_result);
return paths;
}
std::optional<std::string> propertyGetString(const char* key) {
char buf[PROPERTY_VALUE_MAX];
int len = property_get(key, buf, nullptr);
if (len == 0) {
return std::nullopt;
}
return std::string(buf, len);
}
} // namespace
std::optional<int> openRenderFd() {
constexpr char kDevNamePropertyKey[] = "ro.vendor.v4l2_codec2.drm_device_name";
constexpr char kDevPathPropertyKey[] = "ro.vendor.v4l2_codec2.drm_device_path";
const auto devName = propertyGetString(kDevNamePropertyKey);
if (!devName) {
ALOGE("Failed to get DRM device name from Android property");
return std::nullopt;
}
const auto devPath = propertyGetString(kDevPathPropertyKey).value_or("/dev/dri/renderD*");
for (const auto filePath : glob(devPath)) {
int fd = open(filePath.c_str(), O_RDWR | O_CLOEXEC);
if (fd < 0) {
continue;
}
char name[32];
struct drm_version v;
memset(&v, 0, sizeof(v));
v.name = name;
v.name_len = sizeof(name);
if (ioctl(fd, static_cast<int>(DRM_IOCTL_VERSION), &v)) {
close(fd);
continue;
}
if (devName->size() != v.name_len || *devName != name) {
close(fd);
continue;
}
return fd;
}
return std::nullopt;
}
std::optional<uint32_t> getDrmHandle(int renderFd, int primeFd) {
ALOGV("%s(renderFd=%d, primeFd=%u)", __func__, renderFd, primeFd);
struct drm_prime_handle prime;
memset(&prime, 0, sizeof(prime));
prime.fd = primeFd;
if (ioctl(renderFd, static_cast<int>(DRM_IOCTL_PRIME_FD_TO_HANDLE), &prime)) {
ALOGE("Can't translate prime fd %d to handle", prime.fd);
return std::nullopt;
}
return prime.handle;
}
void closeDrmHandle(int renderFd, uint32_t handle) {
ALOGV("%s(renderFd=%d, handle=%u)", __func__, renderFd, handle);
struct drm_gem_close gem;
memset(&gem, 0, sizeof(gem));
gem.handle = handle;
ioctl(renderFd, DRM_IOCTL_GEM_CLOSE, &gem);
}
} // namespace android
......@@ -16,6 +16,10 @@
namespace android {
// We use the value of dma-buf inode as the unique ID of the graphic buffers.
using unique_id_t = uint32_t;
std::optional<unique_id_t> getDmabufId(int dmabufFd);
/**
* The BufferQueue-backed block pool design which supports to request arbitrary count of graphic
* buffers from IGBP, and use this buffer set among codec component and client.
......
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_V4L2_CODEC2_PLUGIN_STORE_STORE_DRM_GRALLOC_HELPERS_H
#define ANDROID_V4L2_CODEC2_PLUGIN_STORE_STORE_DRM_GRALLOC_HELPERS_H
#include <stdint.h>
#include <optional>
namespace android {
std::optional<int> openRenderFd();
std::optional<uint32_t> getDrmHandle(int renderFd, int primeFd);
void closeDrmHandle(int renderFd, uint32_t handle);
} // namespace android
#endif // ANDROID_V4L2_CODEC2_PLUGIN_STORE_STORE_DRM_GRALLOC_HELPERS_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment