decode directly to NV12 with the correct stride without using the hw rotator

sync
pencilpusher 2 weeks ago committed by GitHub
parent 7455dde790
commit 276bc77d4a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 53
      tools/replay/qcom/decoder.cc
  2. 9
      tools/replay/qcom/decoder.h

@ -8,6 +8,14 @@
#include "common/swaglog.h" #include "common/swaglog.h"
#include "common/util.h" #include "common/util.h"
// echo "0xFFFF" > /sys/kernel/debug/msm_vidc/debug_level
static void copyBuffer(VisionBuf *src_buf, VisionBuf *dst_buf) {
// Copy Y plane
memcpy(dst_buf->y, src_buf->y, src_buf->height * src_buf->stride);
// Copy UV plane
memcpy(dst_buf->uv, src_buf->uv, src_buf->height / 2 * src_buf->stride);
}
static void request_buffers(int fd, v4l2_buf_type buf_type, unsigned int count) { static void request_buffers(int fd, v4l2_buf_type buf_type, unsigned int count) {
struct v4l2_requestbuffers reqbuf = { struct v4l2_requestbuffers reqbuf = {
@ -44,8 +52,7 @@ bool MsmVidc::init(const char* dev, size_t width, size_t height, uint64_t codec)
util::safe_ioctl(fd, VIDIOC_STREAMON, &out_type, "VIDIOC_STREAMON OUTPUT failed"); util::safe_ioctl(fd, VIDIOC_STREAMON, &out_type, "VIDIOC_STREAMON OUTPUT failed");
restartCapture(); restartCapture();
setupPolling(); setupPolling();
rotator.init();
rotator.configUBWCtoNV12(width, height);
this->initialized = true; this->initialized = true;
return true; return true;
} }
@ -117,26 +124,14 @@ VisionBuf* MsmVidc::handleCapture() {
buf.length = 1; buf.length = 1;
util::safe_ioctl(this->fd, VIDIOC_DQBUF, &buf, "VIDIOC_DQBUF CAPTURE failed"); util::safe_ioctl(this->fd, VIDIOC_DQBUF, &buf, "VIDIOC_DQBUF CAPTURE failed");
if (buf.m.planes[0].bytesused) { if (this->reconfigure_pending || buf.m.planes[0].bytesused == 0) {
static size_t cap_cnt = 0; return nullptr;
cap_cnt++;
if (cap_cnt % 240 == 0) {
LOGD("Dequeued %zu capture buffers", cap_cnt);
} }
if (!this->reconfigure_pending) {
rotator.putFrame(&cap_bufs[buf.index]); copyBuffer(&cap_bufs[buf.index], this->current_output_buf);
VisionBuf *rotated = rotator.getFrame(100);
queueCaptureBuffer(buf.index); queueCaptureBuffer(buf.index);
if (rotated) {
rotator.convertStride(rotated, this->current_output_buf);
return this->current_output_buf; return this->current_output_buf;
} }
}
} else {
LOGE("Dequeued empty capture buffer %d", buf.index);
}
return nullptr;
}
bool MsmVidc::subscribeEvents() { bool MsmVidc::subscribeEvents() {
for (uint32_t event : subscriptions) { for (uint32_t event : subscriptions) {
@ -149,12 +144,16 @@ bool MsmVidc::subscribeEvents() {
bool MsmVidc::setPlaneFormat(enum v4l2_buf_type type, uint32_t fourcc) { bool MsmVidc::setPlaneFormat(enum v4l2_buf_type type, uint32_t fourcc) {
struct v4l2_format fmt = {.type = type}; struct v4l2_format fmt = {.type = type};
struct v4l2_pix_format_mplane *pix = &fmt.fmt.pix_mp; struct v4l2_pix_format_mplane *pix = &fmt.fmt.pix_mp;
*pix = { .width = (__u32)this->w, .height = (__u32)this->h, .pixelformat = fourcc }; *pix = {
.width = (__u32)this->w,
.height = (__u32)this->h,
.pixelformat = fourcc
};
util::safe_ioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT failed"); util::safe_ioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT failed");
if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
this->out_buf_size = pix->plane_fmt[0].sizeimage; this->out_buf_size = pix->plane_fmt[0].sizeimage;
int ion_size = this->out_buf_size * OUTPUT_BUFFER_COUNT; // Output (input) buffers are ION buffer. int ion_size = this->out_buf_size * OUTPUT_BUFFER_COUNT; // Output (input) buffers are ION buffer.
this->out_buf.allocate_no_cache(ion_size); // mmap rw this->out_buf.allocate(ion_size); // mmap rw
for (int i = 0; i < OUTPUT_BUFFER_COUNT; i++) { for (int i = 0; i < OUTPUT_BUFFER_COUNT; i++) {
this->out_buf_off[i] = i * this->out_buf_size; this->out_buf_off[i] = i * this->out_buf_size;
this->out_buf_addr[i] = (char *)this->out_buf.addr + this->out_buf_off[i]; this->out_buf_addr[i] = (char *)this->out_buf.addr + this->out_buf_off[i];
@ -164,11 +163,15 @@ bool MsmVidc::setPlaneFormat(enum v4l2_buf_type type, uint32_t fourcc) {
} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
request_buffers(this->fd, type, CAPTURE_BUFFER_COUNT); request_buffers(this->fd, type, CAPTURE_BUFFER_COUNT);
util::safe_ioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT failed"); util::safe_ioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT failed");
const __u32 y_size = pix->plane_fmt[0].sizeimage;
const __u32 y_stride = pix->plane_fmt[0].bytesperline;
for (int i = 0; i < CAPTURE_BUFFER_COUNT; i++) { for (int i = 0; i < CAPTURE_BUFFER_COUNT; i++) {
this->cap_bufs[i].allocate_no_cache(pix->plane_fmt[0].sizeimage); size_t uv_offset = (size_t)y_stride * pix->height;
this->cap_bufs[i].init_yuv(pix->width, pix->height, pix->plane_fmt[0].bytesperline, 0); size_t required = uv_offset + (y_stride * pix->height / 2); // enough for Y + UV. For linear NV12, UV plane starts at y_stride * height.
size_t alloc_size = std::max<size_t>(y_size, required);
this->cap_bufs[i].allocate(alloc_size);
this->cap_bufs[i].init_yuv(pix->width, pix->height, y_stride, uv_offset);
} }
this->cap_buf_format = pix->pixelformat;
LOGD("Set capture buffer size to %d, count %d, addr %p, extradata size %d", LOGD("Set capture buffer size to %d, count %d, addr %p, extradata size %d",
pix->plane_fmt[0].sizeimage, CAPTURE_BUFFER_COUNT, this->cap_bufs[0].addr, pix->plane_fmt[1].sizeimage); pix->plane_fmt[0].sizeimage, CAPTURE_BUFFER_COUNT, this->cap_bufs[0].addr, pix->plane_fmt[1].sizeimage);
} }
@ -201,7 +204,7 @@ bool MsmVidc::restartCapture() {
} }
// setup, start and queue capture buffers // setup, start and queue capture buffers
setDBP(); setDBP();
setPlaneFormat(type, V4L2_PIX_FMT_NV12_UBWC); setPlaneFormat(type, V4L2_PIX_FMT_NV12);
util::safe_ioctl(this->fd, VIDIOC_STREAMON, &type, "VIDIOC_STREAMON CAPTURE failed"); util::safe_ioctl(this->fd, VIDIOC_STREAMON, &type, "VIDIOC_STREAMON CAPTURE failed");
for (size_t i = 0; i < CAPTURE_BUFFER_COUNT; ++i) { for (size_t i = 0; i < CAPTURE_BUFFER_COUNT; ++i) {
queueCaptureBuffer(i); queueCaptureBuffer(i);
@ -259,7 +262,7 @@ bool MsmVidc::setDBP() {
struct v4l2_ext_control control[2] = {0}; struct v4l2_ext_control control[2] = {0};
struct v4l2_ext_controls controls = {0}; struct v4l2_ext_controls controls = {0};
control[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE; control[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
control[0].value = 0; // V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY control[0].value = 1; // V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY
control[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT; control[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
control[1].value = 0; // V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE control[1].value = 0; // V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE
controls.count = 2; controls.count = 2;

@ -1,6 +1,9 @@
#pragma once #pragma once
#include "sde_rotator.h" #include <linux/videodev2.h>
#include <poll.h>
#include "msgq/visionipc/visionbuf.h"
#include "third_party/linux/include/media/msm_vidc.h" #include "third_party/linux/include/media/msm_vidc.h"
extern "C" { extern "C" {
@ -59,8 +62,6 @@ private:
bool out_buf_flag[OUTPUT_BUFFER_COUNT] = {false}; bool out_buf_flag[OUTPUT_BUFFER_COUNT] = {false};
const int out_buf_cnt = OUTPUT_BUFFER_COUNT; const int out_buf_cnt = OUTPUT_BUFFER_COUNT;
uint32_t cap_buf_format = 0;
const int subscriptions[2] = { const int subscriptions[2] = {
V4L2_EVENT_MSM_VIDC_FLUSH_DONE, V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT
@ -87,6 +88,4 @@ private:
int handleSignal(); int handleSignal();
bool handleOutput(); bool handleOutput();
bool handleEvent(); bool handleEvent();
SdeRotator rotator;
}; };

Loading…
Cancel
Save