mirror of
https://github.com/nxp-imx/meta-imx.git
synced 2025-07-19 18:39:09 +02:00
329 lines
10 KiB
Diff
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
|
|
|