sync
Adeeb Shihadeh 1 month ago
parent 95a5ddde27
commit d39c6a20b8
  1. 2
      tools/replay/SConscript
  2. 2
      tools/replay/framereader.h
  3. 158
      tools/replay/qcom/sde_rotator.cc
  4. 31
      tools/replay/qcom/sde_rotator.h
  5. 2
      tools/replay/qcom_decoder.cc
  6. 0
      tools/replay/qcom_decoder.h

@ -12,7 +12,7 @@ else:
base_libs.append('OpenCL') base_libs.append('OpenCL')
replay_lib_src = ["replay.cc", "consoleui.cc", "camera.cc", "filereader.cc", "logreader.cc", "framereader.cc", replay_lib_src = ["replay.cc", "consoleui.cc", "camera.cc", "filereader.cc", "logreader.cc", "framereader.cc",
"route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "api.cc", "qcom/decoder.cc"] "route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "api.cc", "qcom_decoder.cc"]
replay_lib = replay_env.Library("replay", replay_lib_src, LIBS=base_libs, FRAMEWORKS=base_frameworks) replay_lib = replay_env.Library("replay", replay_lib_src, LIBS=base_libs, FRAMEWORKS=base_frameworks)
Export('replay_lib') Export('replay_lib')
replay_libs = [replay_lib, 'avutil', 'avcodec', 'avformat', 'bz2', 'zstd', 'curl', 'yuv', 'ncurses'] + base_libs replay_libs = [replay_lib, 'avutil', 'avcodec', 'avformat', 'bz2', 'zstd', 'curl', 'yuv', 'ncurses'] + base_libs

@ -6,7 +6,7 @@
#include "msgq/visionipc/visionbuf.h" #include "msgq/visionipc/visionbuf.h"
#include "tools/replay/filereader.h" #include "tools/replay/filereader.h"
#include "tools/replay/util.h" #include "tools/replay/util.h"
#include "tools/replay/qcom/decoder.h" #include "tools/replay/qcom_decoder.h"
extern "C" { extern "C" {
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>

@ -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…
Cancel
Save