safesight/edge/tests/test_codec_backend.cpp
tian 29d9ef5d0d refactor: 项目结构梳理 - 设备端/管理端对称布局
仓库结构:
  edge/     设备端(原根目录设备端代码整体移入)
  control/  管理端(清理后)
  docs/     文档(PRD 移入 design/)
  README.md 根导航(新增)

清理:
- control/.brainstorm 临时草稿删除
- control 根级重复文档(API表/PRD_04)并入 docs/design/
- control/plan.md -> docs/implementation/control-plan.md
- control/safesightd-linux-arm64 二进制取消版本控制(.gitignore)
- edge/transform 模型转换产物归入 models/,onnx/pt 大源文件取消跟踪(.gitignore)
- Readme.md(PRD) -> docs/design/PRD_Product_v1.2.md(避开 README 大小写冲突)

更新:
- 根 README.md 导航、docs/README.md 文档索引
- deployment.md/检查表路径加 edge/ 前缀
- .gitignore 重写(edge/control 分区规则)
2026-08-02 11:39:54 +08:00

145 lines
4.5 KiB
C++

#include <gtest/gtest.h>
#include <memory>
#include <vector>
#include "hw/hw_factory.h"
namespace rk3588 {
namespace {
static SimpleJson MakeDecoderConfig(const std::string& backend, const std::string& codec,
const std::vector<uint8_t>& extradata = {}) {
SimpleJson::Object obj;
obj["backend"] = SimpleJson(backend);
obj["codec"] = SimpleJson(codec);
if (!extradata.empty()) {
SimpleJson::Array arr;
arr.reserve(extradata.size());
for (auto b : extradata) {
arr.emplace_back(static_cast<double>(b));
}
obj["extradata"] = SimpleJson(std::move(arr));
}
return SimpleJson(std::move(obj));
}
static SimpleJson MakeEncoderConfig(const std::string& backend, const std::string& codec) {
SimpleJson::Object obj;
obj["backend"] = SimpleJson(backend);
obj["codec"] = SimpleJson(codec);
obj["fps"] = SimpleJson(25.0);
obj["gop"] = SimpleJson(50.0);
obj["bitrate_kbps"] = SimpleJson(1000.0);
obj["width"] = SimpleJson(64.0);
obj["height"] = SimpleJson(64.0);
obj["pixel_format"] = SimpleJson(std::string("nv12"));
return SimpleJson(std::move(obj));
}
static std::shared_ptr<Frame> MakeTestFrame() {
auto frame = std::make_shared<Frame>();
frame->width = 64;
frame->height = 64;
frame->format = PixelFormat::NV12;
frame->plane_count = 2;
frame->stride = 64;
const size_t y_size = static_cast<size_t>(frame->width * frame->height);
const size_t total = y_size * 3 / 2;
auto buffer = std::make_shared<std::vector<uint8_t>>(total, 0);
frame->data = buffer->data();
frame->data_size = buffer->size();
frame->SetOwner(buffer);
frame->planes[0] = {frame->data, frame->width, static_cast<int>(y_size), 0};
frame->planes[1] = {frame->data + y_size, frame->width, static_cast<int>(y_size / 2), static_cast<int>(y_size)};
frame->pts = 1000;
frame->SyncBufferFromFrame();
return frame;
}
TEST(CodecBackendTest, DecoderOpenCloseSmoke) {
#if !defined(RK3588_ENABLE_MPP) && !defined(RK3588_ENABLE_FFMPEG)
GTEST_SKIP() << "Codec backends not enabled";
#endif
std::string backend = "mpp";
#if !defined(RK3588_ENABLE_MPP)
backend = "ffmpeg";
#endif
auto cfg = MakeDecoderConfig(backend, "h264");
auto decoder = HwFactory::CreateDecoder(cfg);
ASSERT_NE(decoder, nullptr);
if (decoder->Open(cfg).Failed()) {
GTEST_SKIP() << "Decoder backend not available";
}
decoder->Close();
}
TEST(CodecBackendTest, EncoderOpenCloseSmoke) {
#if !defined(RK3588_ENABLE_MPP) && !defined(RK3588_ENABLE_FFMPEG)
GTEST_SKIP() << "Codec backends not enabled";
#endif
std::string backend = "mpp";
#if !defined(RK3588_ENABLE_MPP)
backend = "ffmpeg";
#endif
auto cfg = MakeEncoderConfig(backend, "h264");
auto encoder = HwFactory::CreateEncoder(cfg);
ASSERT_NE(encoder, nullptr);
if (encoder->Open(cfg).Failed()) {
GTEST_SKIP() << "Encoder backend not available";
}
encoder->Close();
}
TEST(CodecBackendTest, CodecPipelineEncodeDecodeOneFrame) {
#if !defined(RK3588_ENABLE_MPP)
GTEST_SKIP() << "MPP backend not enabled";
#endif
auto encoder_cfg = MakeEncoderConfig("mpp", "h264");
auto encoder = HwFactory::CreateEncoder(encoder_cfg);
ASSERT_NE(encoder, nullptr);
if (encoder->Open(encoder_cfg).Failed()) {
GTEST_SKIP() << "Encoder not available";
}
auto frame = MakeTestFrame();
ASSERT_TRUE(encoder->Send(frame).Ok());
auto pkt_res = encoder->Receive();
if (!pkt_res.Ok() || pkt_res.Value().data.empty()) {
GTEST_SKIP() << "Encoder did not produce packet";
}
auto pkt = std::move(pkt_res.Value());
auto extradata = encoder->ExtraData();
auto decoder_cfg = MakeDecoderConfig("mpp", "h264", extradata);
auto decoder = HwFactory::CreateDecoder(decoder_cfg);
ASSERT_NE(decoder, nullptr);
if (decoder->Open(decoder_cfg).Failed()) {
GTEST_SKIP() << "Decoder not available";
}
DecodePacket dp;
dp.data = pkt.data.data();
dp.size = pkt.data.size();
dp.pts = pkt.pts;
dp.keyframe = pkt.keyframe;
ASSERT_TRUE(decoder->Send(dp).Ok());
bool got_frame = false;
for (int i = 0; i < 10; ++i) {
auto out = decoder->Receive();
if (out.Ok() && out.Value()) {
got_frame = true;
break;
}
if (out.ErrMessage() != "no_frame") break;
}
EXPECT_TRUE(got_frame);
decoder->Close();
encoder->Close();
}
} // namespace
} // namespace rk3588