meta-imx/meta-imx-sdk/dynamic-layers/chromium-browser-layer/recipes-browser/chromium/chromium-ozone-wayland/0112-V4L2VideoDecoder-Support-tile-to-linear-transform-fo.patch
Neena Busireddy dc179197e2 chromium-ozone-wayland: Refresh VPU patches for chromium 129.0.6668.100 [YOCIMX-8352]
Signed-off-by: Neena Busireddy <neenareddy.busireddy@nxp.com>
2024-10-25 10:18:32 -05:00

329 lines
10 KiB
Diff

From 591913ea8a59426be9902599cec129445804c8d7 Mon Sep 17 00:00:00 2001
From: Hou Qi <qi.hou@nxp.com>
Date: Fri, 13 Sep 2024 23:09:35 +0900
Subject: [PATCH 12/19] V4L2VideoDecoder: Support tile to linear transform for
amphion
Upstream-Status: Inappropriate [NXP specific]
---
media/gpu/v4l2/BUILD.gn | 1 +
media/gpu/v4l2/v4l2_queue.cc | 211 ++++++++++++++++++++++++++++++++++-
media/gpu/v4l2/v4l2_queue.h | 1 +
3 files changed, 209 insertions(+), 4 deletions(-)
diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn
index 0aa466ba9cec5..836ee0bc7504c 100644
--- a/media/gpu/v4l2/BUILD.gn
+++ b/media/gpu/v4l2/BUILD.gn
@@ -92,6 +92,7 @@ source_set("v4l2") {
"EGL",
"GLESv2",
]
+ libs += [ "g2d" ]
configs += [ "//third_party/libyuv:libyuv_config" ]
diff --git a/media/gpu/v4l2/v4l2_queue.cc b/media/gpu/v4l2/v4l2_queue.cc
index de74d0da308c3..945e7a7df9b93 100644
--- a/media/gpu/v4l2/v4l2_queue.cc
+++ b/media/gpu/v4l2/v4l2_queue.cc
@@ -20,6 +20,11 @@
#include "media/gpu/chromeos/platform_video_frame_utils.h"
#include "media/gpu/macros.h"
+#include "g2d.h"
+#include "g2dExt.h"
+#include <linux/dma-buf.h>
+#include <time.h>
+
namespace media {
namespace {
@@ -189,6 +194,11 @@ class V4L2Buffer {
size_t GetMemoryUsage() const;
const struct v4l2_buffer& v4l2_buffer() const { return v4l2_buffer_; }
const scoped_refptr<FrameResource>& GetFrameResource();
+ std::pair<int, int> GetSavedmafd();
+ std::pair<unsigned int, unsigned int> GetSavedphys();
+ std::pair<int, int> Getg2dbufphys();
+ std::pair<void *, void *> Getg2dbufvirs();
+ const struct v4l2_format& GetFmt() const {return format_;}
private:
V4L2Buffer(const IoctlAsCallback& ioctl_cb,
@@ -203,6 +213,13 @@ class V4L2Buffer {
const IoctlAsCallback ioctl_cb_;
const MmapAsCallback mmap_cb_;
std::vector<void*> plane_mappings_;
+ int dmafd0;
+ int dmafd1;
+ unsigned long phys_0;
+ unsigned long phys_1;
+ struct g2d_buf *g2dbuf_p0;
+ struct g2d_buf *g2dbuf_p1;
+ std::vector<base::ScopedFD> g2dbufs_fds;
// V4L2 data as queried by QUERYBUF.
struct v4l2_buffer v4l2_buffer_;
@@ -257,6 +274,90 @@ V4L2Buffer::V4L2Buffer(const IoctlAsCallback& ioctl_cb,
v4l2_buffer_.type = type;
v4l2_buffer_.memory = memory;
plane_mappings_.resize(V4L2_TYPE_IS_MULTIPLANAR(type) ? v4l2_buffer_.length : 1);
+ dmafd0 = dmafd1 = -1;
+ phys_0 = phys_1 = 0;
+ g2dbuf_p0 = g2dbuf_p1 = NULL;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(v4l2_buffer_.type) &&
+ format_.fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12M_8L128) {
+ VLOGF(3) << "Map physical address";
+
+ std::vector<base::ScopedFD> dmabuf_fds = GetDmabufsForV4L2Buffer(
+ ioctl_cb_, v4l2_buffer_.index, V4L2_TYPE_IS_MULTIPLANAR(v4l2_buffer_.type) ? v4l2_buffer_.length : 1,
+ static_cast<enum v4l2_buf_type>(v4l2_buffer_.type));
+ if (dmabuf_fds.empty()) {
+ LOG(ERROR) << "Failed to get DMABUFs of V4L2 buffer";
+ return;
+ }
+
+ // DMA buffer fds should not be invalid
+ for (const auto& dmabuf_fd : dmabuf_fds) {
+ if (!dmabuf_fd.is_valid()) {
+ LOG(ERROR) << "Fail to get DMABUFs of V4L2 buffer - invalid fd";
+ return;
+ }
+ if(dmafd0 == -1)
+ dmafd0 = dmabuf_fd.get();
+ else
+ dmafd1 = dmabuf_fd.get();
+ }
+
+ struct dma_buf_phys{
+ unsigned long phys;
+ };
+ #define DMA_BUF_IOCTL_PHYS _IOW(DMA_BUF_BASE, 10, struct dma_buf_phys)
+ struct dma_buf_phys query0, query1;
+ int ret = ioctl(dmafd0, DMA_BUF_IOCTL_PHYS, &query0);
+ if(ret != 0) {
+ LOG(ERROR)<< "DMA_BUF_IOCTL_PHYS failed at dmafd" << dmafd0;
+ return;
+ }
+ else {
+ phys_0 = query0.phys;
+ }
+
+ ret = ioctl(dmafd1, DMA_BUF_IOCTL_PHYS, &query1);
+ if(ret != 0) {
+ LOG(ERROR)<< "DMA_BUF_IOCTL_PHYS failed at dmafd" << dmafd1;
+ return;
+ }
+ else {
+ phys_1 = query1.phys;
+ }
+
+ if (g2d_alloc) {
+ g2dbuf_p0 = g2d_alloc(format_.fmt.pix_mp.width * format_.fmt.pix_mp.height, 0);
+ g2dbuf_p1 = g2d_alloc(format_.fmt.pix_mp.width * format_.fmt.pix_mp.height / 2, 0);
+ }
+ if((!g2dbuf_p0) || (!g2dbuf_p1)){
+ LOG(ERROR)<<"g2d buf alloc failed";
+ return;
+ }
+
+ int tmpfd = -1;
+ if (g2d_buf_export_fd)
+ tmpfd = g2d_buf_export_fd(g2dbuf_p0);
+ tmpfd = dup(tmpfd);
+ if(tmpfd > 0)
+ g2dbufs_fds.push_back(base::ScopedFD(tmpfd));
+ else if(tmpfd == -1)
+ {
+ LOG(ERROR) << "Failed duplicating g2d fd";
+ return;
+ }
+
+ if (g2d_buf_export_fd)
+ tmpfd = g2d_buf_export_fd(g2dbuf_p1);
+ tmpfd = dup(tmpfd);
+ if(tmpfd>0)
+ g2dbufs_fds.push_back(base::ScopedFD(tmpfd));
+ else if(tmpfd == -1)
+ {
+ LOG(ERROR) << "Failed duplicating g2d fd";
+ return;
+ }
+
+ }
}
V4L2Buffer::~V4L2Buffer() {
@@ -269,6 +370,32 @@ V4L2Buffer::~V4L2Buffer() {
}
}
}
+ if(g2d_free && g2dbuf_p0 && g2dbuf_p1) {
+ g2d_free(g2dbuf_p0);
+ g2d_free(g2dbuf_p1);
+ }
+}
+
+std::pair<int, int> V4L2Buffer::GetSavedmafd() {
+ return std::make_pair(dmafd0, dmafd1);
+}
+
+std::pair<unsigned int, unsigned int> V4L2Buffer::GetSavedphys() {
+ return std::make_pair(phys_0, phys_1);
+}
+
+std::pair<int, int> V4L2Buffer::Getg2dbufphys() {
+ if(g2dbuf_p0 && g2dbuf_p1)
+ return std::make_pair(g2dbuf_p0->buf_paddr, g2dbuf_p1->buf_paddr);
+ else
+ return std::make_pair(-1, -1);
+}
+
+std::pair<void*, void*> V4L2Buffer::Getg2dbufvirs() {
+ if(g2dbuf_p0 && g2dbuf_p1)
+ return std::make_pair(g2dbuf_p0->buf_vaddr, g2dbuf_p1->buf_vaddr);
+ else
+ return std::make_pair(nullptr, nullptr);
}
bool V4L2Buffer::Query() {
@@ -368,13 +495,18 @@ scoped_refptr<FrameResource> V4L2Buffer::CreateFrame() {
dmabuf_fds.emplace_back(duped_fd);
}
- if (V4L2_TYPE_IS_MULTIPLANAR(v4l2_buffer_.type))
+ if (V4L2_TYPE_IS_MULTIPLANAR(v4l2_buffer_.type) &&
+ format_.fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12M_8L128) {
gfx::Size size(format_.fmt.pix_mp.width, format_.fmt.pix_mp.height);
- else
+ return NativePixmapFrameResource::Create(
+ *layout, gfx::Rect(size), size, std::move(g2dbufs_fds), base::TimeDelta());
+ }
+ else {
gfx::Size size(format_.fmt.pix.width, format_.fmt.pix.height);
- return NativePixmapFrameResource::Create(
- *layout, gfx::Rect(size), size, std::move(dmabuf_fds), base::TimeDelta());
+ return NativePixmapFrameResource::Create(
+ *layout, gfx::Rect(size), size, std::move(dmabuf_fds), base::TimeDelta());
+ }
}
const scoped_refptr<FrameResource>& V4L2Buffer::GetFrameResource() {
@@ -1112,6 +1244,10 @@ V4L2Queue::V4L2Queue(const IoctlAsCallback& ioctl_cb,
VPLOG_IF(4, supports_requests_)
<< "This queue does " << (supports_requests_ ? "" : "not")
<< " support requests.";
+
+ g2d_handle = NULL;
+ if(g2d_open && g2d_open(&g2d_handle))
+ VLOGF(1) << "g2d_open fail";
}
V4L2Queue::~V4L2Queue() {
@@ -1127,6 +1263,9 @@ V4L2Queue::~V4L2Queue() {
VQLOGF(1) << "Failed to deallocate queue buffers";
}
+ if(g2d_close && g2d_handle)
+ g2d_close(g2d_handle);
+
std::move(destroy_cb_).Run();
}
@@ -1170,6 +1309,8 @@ std::pair<std::optional<struct v4l2_format>, int> V4L2Queue::GetFormat() {
VPQLOGF(2) << "Failed to get format";
return std::make_pair(std::nullopt, errno);
}
+ if (type_ == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ format.fmt.pix_mp.width = format.fmt.pix_mp.plane_fmt[0].bytesperline;
return std::make_pair(format, 0);
}
@@ -1529,6 +1670,68 @@ std::pair<bool, V4L2ReadableBufferRef> V4L2Queue::DequeueBuffer() {
}
DCHECK(free_buffers_);
+
+ if(type_ == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+ buffers_[v4l2_buffer.index]->GetFmt().fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12M_8L128)
+ {
+ std::pair<unsigned int, unsigned int> v4l_phys = buffers_[v4l2_buffer.index]->GetSavedphys();
+ int width = buffers_[v4l2_buffer.index]->GetFmt().fmt.pix_mp.width;
+ int height = buffers_[v4l2_buffer.index]->GetFmt().fmt.pix_mp.height;
+ int stride = buffers_[v4l2_buffer.index]->GetFmt().fmt.pix_mp.plane_fmt[0].bytesperline;
+ bool interlaced = false;
+ switch (buffers_[v4l2_buffer.index]->GetFmt().fmt.pix_mp.field) {
+ case V4L2_FIELD_INTERLACED:
+ case V4L2_FIELD_INTERLACED_TB:
+ case V4L2_FIELD_INTERLACED_BT:
+ case V4L2_FIELD_SEQ_TB:
+ interlaced = true;
+ break;
+ default:
+ break;
+ };
+ struct g2d_surfaceEx srcEx, dstEx;
+ struct g2d_surface *src = &srcEx.base;
+ struct g2d_surface *dst = &dstEx.base;
+
+ dst->format = G2D_NV12;
+ dst->planes[0] = buffers_[v4l2_buffer.index]->Getg2dbufphys().first;
+ dst->planes[1] = buffers_[v4l2_buffer.index]->Getg2dbufphys().second;
+ dstEx.tiling = G2D_LINEAR;
+ dst->left = 0;
+ dst->top = 0;
+ dst->right = dst->left + width;
+ dst->bottom = dst->top + height;
+ dst->stride= width;
+ dst->width = width;
+ dst->height = height;
+ dst->rot = G2D_ROTATION_0;
+ dst->global_alpha = 0xff;
+ dst->blendfunc = G2D_ONE_MINUS_SRC_ALPHA;
+ dst->clrcolor = 0;
+
+ src->format = G2D_NV12;
+ src->planes[0] = v4l_phys.first;
+ src->planes[1] = v4l_phys.second;
+ srcEx.tiling = G2D_AMPHION_TILED;
+ if (interlaced) {
+ srcEx.tiling = static_cast<g2d_tiling>(0x18); //G2D_AMPHION_TILED | G2D_AMPHION_INTERLACED;
+ DVLOGF(4)<<"interlaced video convert";
+ }
+ src->left = 0;
+ src->top = 0;
+ src->right = src->left + width;
+ src->bottom = src->top + height;
+ src->stride= stride;
+ src->width = width;
+ src->height = height;
+ src->rot = G2D_ROTATION_0;
+ src->global_alpha = 0xff;
+ src->blendfunc = G2D_ONE;
+
+ if (g2d_blitEx)
+ g2d_blitEx(g2d_handle, &srcEx, &dstEx);
+ }
+
return std::make_pair(true, V4L2BufferRefFactory::CreateReadableRef(
v4l2_buffer, weak_this_factory_.GetWeakPtr(),
std::move(queued_frame)));
diff --git a/media/gpu/v4l2/v4l2_queue.h b/media/gpu/v4l2/v4l2_queue.h
index 85c7920417935..1cc22fff58277 100644
--- a/media/gpu/v4l2/v4l2_queue.h
+++ b/media/gpu/v4l2/v4l2_queue.h
@@ -584,6 +584,7 @@ class MEDIA_GPU_EXPORT V4L2Queue
std::optional<struct v4l2_format> current_format_;
std::vector<std::unique_ptr<V4L2Buffer>> buffers_;
+ void* g2d_handle;
// Buffers that are available for client to get and submit.
// Buffers in this list are not referenced by anyone else than ourselves.
--
2.34.1