diff --git a/tools/replay/SConscript b/tools/replay/SConscript index 4ddeb662e0..3abed43dde 100644 --- a/tools/replay/SConscript +++ b/tools/replay/SConscript @@ -22,4 +22,4 @@ replay_libs = [replay_lib, 'avutil', 'avcodec', 'avformat', 'bz2', 'curl', 'yuv' qt_env.Program("replay", ["main.cc"], LIBS=replay_libs, FRAMEWORKS=base_frameworks) if GetOption('test'): - qt_env.Program('tests/test_replay', ['tests/test_runner.cc', 'tests/test_replay.cc'], LIBS=[replay_libs]) + qt_env.Program('tests/test_replay', ['tests/test_runner.cc', 'tests/test_replay.cc'], LIBS=[replay_libs, qt_libs]) diff --git a/tools/replay/camera.cc b/tools/replay/camera.cc index 66898c9244..2bc8c66aaa 100644 --- a/tools/replay/camera.cc +++ b/tools/replay/camera.cc @@ -1,7 +1,18 @@ #include "tools/replay/camera.h" #include "tools/replay/util.h" +#include "msm_media_info.h" #include +#include + +std::tuple get_nv12_info(int width, int height) { + int nv12_width = VENUS_Y_STRIDE(COLOR_FMT_NV12, width); + int nv12_height = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height); + assert(nv12_width == VENUS_UV_STRIDE(COLOR_FMT_NV12, width)); + assert(nv12_height / 2 == VENUS_UV_SCANLINES(COLOR_FMT_NV12, height)); + size_t nv12_buffer_size = 2346 * nv12_width; // comes from v4l2_format.fmt.pix_mp.plane_fmt[0].sizeimage + return {nv12_width, nv12_height, nv12_buffer_size}; +} CameraServer::CameraServer(std::pair camera_size[MAX_CAMERAS]) { for (int i = 0; i < MAX_CAMERAS; ++i) { @@ -25,7 +36,9 @@ void CameraServer::startVipcServer() { for (auto &cam : cameras_) { if (cam.width > 0 && cam.height > 0) { rInfo("camera[%d] frame size %dx%d", cam.type, cam.width, cam.height); - vipc_server_->create_buffers(cam.stream_type, YUV_BUFFER_COUNT, false, cam.width, cam.height); + auto [nv12_width, nv12_height, nv12_buffer_size] = get_nv12_info(cam.width, cam.height); + vipc_server_->create_buffers_with_sizes(cam.stream_type, YUV_BUFFER_COUNT, false, cam.width, cam.height, + nv12_buffer_size, nv12_width, nv12_width * nv12_height); if (!cam.thread.joinable()) { cam.thread = std::thread(&CameraServer::cameraThread, this, std::ref(cam)); } @@ -38,7 +51,7 @@ void CameraServer::cameraThread(Camera &cam) { auto read_frame = [&](FrameReader *fr, int frame_id) { VisionBuf *yuv_buf = vipc_server_->get_buffer(cam.stream_type); assert(yuv_buf); - bool ret = fr->get(frame_id, (uint8_t *)yuv_buf->addr); + bool ret = fr->get(frame_id, yuv_buf); return ret ? yuv_buf : nullptr; }; diff --git a/tools/replay/camera.h b/tools/replay/camera.h index f2d19ccfb2..9f43c5a362 100644 --- a/tools/replay/camera.h +++ b/tools/replay/camera.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "cereal/visionipc/visionipc_server.h" @@ -10,6 +11,8 @@ #include "tools/replay/framereader.h" #include "tools/replay/logreader.h" +std::tuple get_nv12_info(int width, int height); + class CameraServer { public: CameraServer(std::pair camera_size[MAX_CAMERAS] = nullptr); diff --git a/tools/replay/framereader.cc b/tools/replay/framereader.cc index 3083a0d376..f45996560e 100644 --- a/tools/replay/framereader.cc +++ b/tools/replay/framereader.cc @@ -5,8 +5,6 @@ #include #include "libyuv.h" -#include "cereal/visionipc/visionbuf.h" - #ifdef __APPLE__ #define HW_DEVICE_TYPE AV_HWDEVICE_TYPE_VIDEOTOOLBOX #define HW_PIX_FMT AV_PIX_FMT_VIDEOTOOLBOX @@ -119,7 +117,6 @@ bool FrameReader::load(const std::byte *data, size_t size, bool no_hw_decoder, s width = (decoder_ctx->width + 3) & ~3; height = decoder_ctx->height; - visionbuf_compute_aligned_width_and_height(width, height, &aligned_width, &aligned_height); if (has_hw_decoder && !no_hw_decoder) { if (!initHardwareDecoder(HW_DEVICE_TYPE)) { @@ -178,15 +175,15 @@ bool FrameReader::initHardwareDecoder(AVHWDeviceType hw_device_type) { return true; } -bool FrameReader::get(int idx, uint8_t *yuv) { - assert(yuv != nullptr); +bool FrameReader::get(int idx, VisionBuf *buf) { + assert(buf != nullptr); if (!valid_ || idx < 0 || idx >= packets.size()) { return false; } - return decode(idx, yuv); + return decode(idx, buf); } -bool FrameReader::decode(int idx, uint8_t *yuv) { +bool FrameReader::decode(int idx, VisionBuf *buf) { int from_idx = idx; if (idx != prev_idx + 1 && key_frames_count_ > 1) { // seeking to the nearest key frame @@ -202,7 +199,7 @@ bool FrameReader::decode(int idx, uint8_t *yuv) { for (int i = from_idx; i <= idx; ++i) { AVFrame *f = decodeFrame(packets[i]); if (f && i == idx) { - return copyBuffers(f, yuv); + return copyBuffers(f, buf); } } return false; @@ -234,22 +231,20 @@ AVFrame *FrameReader::decodeFrame(AVPacket *pkt) { } } -bool FrameReader::copyBuffers(AVFrame *f, uint8_t *yuv) { - assert(f != nullptr && yuv != nullptr); - uint8_t *y = yuv; - uint8_t *uv = y + width * height; +bool FrameReader::copyBuffers(AVFrame *f, VisionBuf *buf) { + assert(f != nullptr && buf != nullptr); if (hw_pix_fmt == HW_PIX_FMT) { for (int i = 0; i < height/2; i++) { - memcpy(y + (i*2 + 0)*width, f->data[0] + (i*2 + 0)*f->linesize[0], width); - memcpy(y + (i*2 + 1)*width, f->data[0] + (i*2 + 1)*f->linesize[0], width); - memcpy(uv + i*width, f->data[1] + i*f->linesize[1], width); + memcpy(buf->y + (i*2 + 0)*buf->stride, f->data[0] + (i*2 + 0)*f->linesize[0], width); + memcpy(buf->y + (i*2 + 1)*buf->stride, f->data[0] + (i*2 + 1)*f->linesize[0], width); + memcpy(buf->uv + i*buf->stride, f->data[1] + i*f->linesize[1], width); } } else { libyuv::I420ToNV12(f->data[0], f->linesize[0], f->data[1], f->linesize[1], f->data[2], f->linesize[2], - y, width, - uv, width, + buf->y, buf->stride, + buf->uv, buf->stride, width, height); } return true; diff --git a/tools/replay/framereader.h b/tools/replay/framereader.h index e50b61d7f4..bb72ac8f8d 100644 --- a/tools/replay/framereader.h +++ b/tools/replay/framereader.h @@ -4,6 +4,7 @@ #include #include +#include "cereal/visionipc/visionbuf.h" #include "tools/replay/filereader.h" extern "C" { @@ -22,19 +23,18 @@ public: bool load(const std::string &url, bool no_hw_decoder = false, std::atomic *abort = nullptr, bool local_cache = false, int chunk_size = -1, int retries = 0); bool load(const std::byte *data, size_t size, bool no_hw_decoder = false, std::atomic *abort = nullptr); - bool get(int idx, uint8_t *yuv); + bool get(int idx, VisionBuf *buf); int getYUVSize() const { return width * height * 3 / 2; } size_t getFrameCount() const { return packets.size(); } bool valid() const { return valid_; } int width = 0, height = 0; - int aligned_width = 0, aligned_height = 0; private: bool initHardwareDecoder(AVHWDeviceType hw_device_type); - bool decode(int idx, uint8_t *yuv); + bool decode(int idx, VisionBuf *buf); AVFrame * decodeFrame(AVPacket *pkt); - bool copyBuffers(AVFrame *f, uint8_t *yuv); + bool copyBuffers(AVFrame *f, VisionBuf *buf); std::vector packets; std::unique_ptrav_frame_, hw_frame; diff --git a/tools/replay/tests/test_replay.cc b/tools/replay/tests/test_replay.cc index 441bac0cbd..393a561c0f 100644 --- a/tools/replay/tests/test_replay.cc +++ b/tools/replay/tests/test_replay.cc @@ -95,10 +95,13 @@ void read_segment(int n, const SegmentFile &segment_file, uint32_t flags) { if (cam == RoadCam || cam == WideRoadCam) { REQUIRE(fr->getFrameCount() == 1200); } - std::unique_ptr yuv_buf = std::make_unique(fr->getYUVSize()); + auto [nv12_width, nv12_height, nv12_buffer_size] = get_nv12_info(fr->width, fr->height); + VisionBuf buf; + buf.allocate(nv12_buffer_size); + buf.init_yuv(fr->width, fr->height, nv12_width, nv12_width * nv12_height); // sequence get 100 frames for (int i = 0; i < 100; ++i) { - REQUIRE(fr->get(i, yuv_buf.get())); + REQUIRE(fr->get(i, &buf)); } }