parent
95a5ddde27
commit
d39c6a20b8
6 changed files with 3 additions and 192 deletions
@ -1,158 +0,0 @@ |
|||||||
#include "sde_rotator.h" |
|
||||||
|
|
||||||
#include <assert.h> |
|
||||||
#include <cstdio> |
|
||||||
#include <errno.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <linux/ion.h> |
|
||||||
#include <msm_ion.h> |
|
||||||
#include <string.h> |
|
||||||
#include <sys/ioctl.h> |
|
||||||
#include <sys/mman.h> |
|
||||||
|
|
||||||
#include "common/util.h" |
|
||||||
#include "common/swaglog.h" |
|
||||||
#include "third_party/linux/include/msm_media_info.h" |
|
||||||
|
|
||||||
|
|
||||||
static void request_buffers(int fd, v4l2_buf_type buf_type, unsigned int count) { |
|
||||||
struct v4l2_requestbuffers reqbuf = { |
|
||||||
.count = count, |
|
||||||
.type = buf_type, |
|
||||||
.memory = V4L2_MEMORY_USERPTR |
|
||||||
}; |
|
||||||
util::safe_ioctl(fd, VIDIOC_REQBUFS, &reqbuf, "VIDIOC_REQBUFS failed"); |
|
||||||
} |
|
||||||
|
|
||||||
bool SdeRotator::init(const char *dev) { |
|
||||||
LOGD("Initializing sde_rot device %s", dev); |
|
||||||
fd = open(dev, O_RDWR, 0); |
|
||||||
if (fd < 0) { |
|
||||||
LOGE("failed to open rotator device"); |
|
||||||
return false; |
|
||||||
} |
|
||||||
fmt_cap = {}, fmt_out = {}, cap_desc = {}; |
|
||||||
pfd = { .fd = fd, .events = POLLIN | POLLRDNORM, .revents = 0 }; |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
SdeRotator::~SdeRotator() { |
|
||||||
if (fd >= 0) { |
|
||||||
close(fd); |
|
||||||
fd = -1; |
|
||||||
} |
|
||||||
cap_buf.free(); |
|
||||||
cap_buf.~VisionBuf(); |
|
||||||
new (&cap_buf) VisionBuf(); |
|
||||||
queued = false; |
|
||||||
} |
|
||||||
|
|
||||||
int SdeRotator::configUBWCtoNV12(int width, int height) { |
|
||||||
// stop streaming if already started
|
|
||||||
enum v4l2_buf_type t; |
|
||||||
t = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
|
||||||
util::safe_ioctl(fd, VIDIOC_STREAMOFF, &t, "VIDIOC_STREAMOFF OUTPUT failed"); |
|
||||||
t = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|
||||||
util::safe_ioctl(fd, VIDIOC_STREAMOFF, &t, "VIDIOC_STREAMOFF CAPTURE failed"); |
|
||||||
LOGD("Configuring rotator for width=%d height=%d", width, height); |
|
||||||
queued = false; |
|
||||||
fmt_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
|
||||||
fmt_out.fmt.pix.width = width; |
|
||||||
fmt_out.fmt.pix.height = height; |
|
||||||
fmt_out.fmt.pix.pixelformat = V4L2_PIX_FMT_NV12_UBWC; |
|
||||||
fmt_out.fmt.pix.field = V4L2_FIELD_NONE; |
|
||||||
util::safe_ioctl(fd, VIDIOC_S_FMT, &fmt_out, "VIDIOC_S_FMT OUTPUT failed"); |
|
||||||
|
|
||||||
fmt_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|
||||||
fmt_cap.fmt.pix.width = width; |
|
||||||
fmt_cap.fmt.pix.height = height; |
|
||||||
fmt_cap.fmt.pix.pixelformat = V4L2_PIX_FMT_NV12; |
|
||||||
fmt_cap.fmt.pix.field = V4L2_FIELD_NONE; |
|
||||||
util::safe_ioctl(fd, VIDIOC_S_FMT, &fmt_cap, "VIDIOC_S_FMT CAPTURE failed"); |
|
||||||
|
|
||||||
request_buffers(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, 1); |
|
||||||
if (cap_buf.fd >= 0) { |
|
||||||
munmap(cap_buf.addr, cap_buf.len); |
|
||||||
cap_buf.free(); |
|
||||||
} |
|
||||||
cap_buf = VisionBuf(); |
|
||||||
cap_buf.allocate(fmt_cap.fmt.pix.sizeimage); |
|
||||||
cap_buf.addr = mmap(nullptr, |
|
||||||
fmt_cap.fmt.pix.sizeimage, |
|
||||||
PROT_READ | PROT_WRITE, |
|
||||||
MAP_SHARED, |
|
||||||
cap_buf.fd, |
|
||||||
0); |
|
||||||
assert(cap_buf.addr != MAP_FAILED); |
|
||||||
cap_buf.init_yuv(fmt_cap.fmt.pix.width, fmt_cap.fmt.pix.height, |
|
||||||
fmt_cap.fmt.pix.bytesperline, fmt_cap.fmt.pix.bytesperline * fmt_cap.fmt.pix.height); |
|
||||||
|
|
||||||
request_buffers(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, 1); |
|
||||||
memset(&cap_desc, 0, sizeof(cap_desc)); |
|
||||||
cap_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|
||||||
cap_desc.memory = V4L2_MEMORY_USERPTR; |
|
||||||
cap_desc.index = 0; |
|
||||||
util::safe_ioctl(fd, VIDIOC_QUERYBUF, &cap_desc, "VIDIOC_QUERYBUF CAPTURE failed"); |
|
||||||
|
|
||||||
t = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
|
||||||
util::safe_ioctl(fd, VIDIOC_STREAMON, &t, "VIDIOC_STREAMON OUTPUT failed"); |
|
||||||
t = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|
||||||
util::safe_ioctl(fd, VIDIOC_STREAMON, &t, "VIDIOC_STREAMON CAPTURE failed"); |
|
||||||
|
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
int SdeRotator::putFrame(VisionBuf *ubwc) |
|
||||||
{ |
|
||||||
if (ubwc->width != cap_buf.width || ubwc->height != cap_buf.height) |
|
||||||
configUBWCtoNV12(ubwc->width, ubwc->height); |
|
||||||
/* OUTPUT (UBWC) */ |
|
||||||
struct v4l2_buffer out = {}; |
|
||||||
out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
|
||||||
out.memory = V4L2_MEMORY_USERPTR; |
|
||||||
out.index = 0; |
|
||||||
out.m.userptr = static_cast<unsigned long>(ubwc->fd); |
|
||||||
out.length = fmt_out.fmt.pix.sizeimage; |
|
||||||
util::safe_ioctl(fd, VIDIOC_QBUF, &out, "VIDIOC_QBUF OUTPUT failed"); |
|
||||||
/* CAPTURE (linear NV12) – use previously cached cap_desc */ |
|
||||||
struct v4l2_buffer cap = cap_desc; |
|
||||||
cap.m.userptr = static_cast<unsigned long>(cap_buf.fd); |
|
||||||
util::safe_ioctl(fd, VIDIOC_QBUF, &cap, "VIDIOC_QBUF CAPTURE failed"); |
|
||||||
|
|
||||||
queued = true; |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
VisionBuf* SdeRotator::getFrame(int timeout_ms) { |
|
||||||
if (poll(&pfd, 1, timeout_ms) <= 0 || !queued) { // timeout or in flight
|
|
||||||
return nullptr; |
|
||||||
} |
|
||||||
/* dequeue CAPTURE */ |
|
||||||
struct v4l2_buffer cap = {}; |
|
||||||
cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|
||||||
cap.memory = V4L2_MEMORY_USERPTR; |
|
||||||
util::safe_ioctl(fd, VIDIOC_DQBUF, &cap, "VIDIOC_DQBUF CAPTURE failed"); |
|
||||||
/* dequeue OUTPUT (frees the slot) */ |
|
||||||
struct v4l2_buffer out = {}; |
|
||||||
out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; |
|
||||||
out.memory = V4L2_MEMORY_USERPTR; |
|
||||||
util::safe_ioctl(fd, VIDIOC_DQBUF, &out, "VIDIOC_DQBUF OUTPUT failed"); |
|
||||||
|
|
||||||
queued = false; |
|
||||||
return &cap_buf; |
|
||||||
} |
|
||||||
|
|
||||||
void SdeRotator::convertStride(VisionBuf *rotated_buf, VisionBuf *user_buf) { |
|
||||||
// Copy Y plane row by row
|
|
||||||
for (int y = 0; y < user_buf->height; y++) { |
|
||||||
uint8_t *src_row = (uint8_t*)rotated_buf->y + y * rotated_buf->stride; |
|
||||||
uint8_t *dst_row = (uint8_t*)user_buf->y + y * user_buf->stride; |
|
||||||
memcpy(dst_row, src_row, user_buf->width); |
|
||||||
} |
|
||||||
// Copy UV plane row by row (NV12: height/2)
|
|
||||||
for (int y = 0; y < user_buf->height / 2; y++) { |
|
||||||
uint8_t *src_row = (uint8_t*)rotated_buf->uv + y * rotated_buf->stride; |
|
||||||
uint8_t *dst_row = (uint8_t*)user_buf->uv + y * user_buf->stride; |
|
||||||
memcpy(dst_row, src_row, user_buf->width); |
|
||||||
} |
|
||||||
} |
|
@ -1,31 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <linux/videodev2.h> |
|
||||||
#include <poll.h> |
|
||||||
|
|
||||||
#include "msgq/visionipc/visionbuf.h" |
|
||||||
|
|
||||||
#ifndef V4L2_PIX_FMT_NV12_UBWC |
|
||||||
#define V4L2_PIX_FMT_NV12_UBWC v4l2_fourcc('Q', '1', '2', '8') |
|
||||||
#endif |
|
||||||
|
|
||||||
#define ROTATOR_DEVICE "/dev/video2" |
|
||||||
|
|
||||||
class SdeRotator { |
|
||||||
public: |
|
||||||
SdeRotator() = default; |
|
||||||
~SdeRotator(); |
|
||||||
bool init(const char *dev = ROTATOR_DEVICE); |
|
||||||
int configUBWCtoNV12(int width, int height); |
|
||||||
int putFrame(VisionBuf *ubwc); |
|
||||||
VisionBuf* getFrame(int timeout_ms); |
|
||||||
void convertStride(VisionBuf *rotated_buf, VisionBuf *user_buf); |
|
||||||
bool queued = false; |
|
||||||
|
|
||||||
private: |
|
||||||
int fd; |
|
||||||
struct v4l2_format fmt_cap = {0}, fmt_out = {0}; |
|
||||||
VisionBuf cap_buf; |
|
||||||
struct pollfd pfd; |
|
||||||
struct v4l2_buffer cap_desc{}; // cached QUERYBUF result
|
|
||||||
}; |
|
@ -1,4 +1,4 @@ |
|||||||
#include "decoder.h" |
#include "qcom_decoder.h" |
||||||
|
|
||||||
#include <assert.h> |
#include <assert.h> |
||||||
#include "third_party/linux/include/v4l2-controls.h" |
#include "third_party/linux/include/v4l2-controls.h" |
Loading…
Reference in new issue