Add H.264 inference session recording and replay

This commit is contained in:
zmv
2026-09-24 15:05:44 +08:00
parent 0192fccbf0
commit daab1db58f
17 changed files with 532 additions and 10 deletions
+10 -3
View File
@@ -4,6 +4,7 @@
#include "detector.hpp"
#include "door_risk.hpp"
#include "records.hpp"
#include "inference_session.hpp"
#include "result_conversion.hpp"
#include <opencv2/core.hpp>
#include <atomic>
@@ -51,6 +52,8 @@ struct CameraPipeline::Impl {
BoundedQueue<Detected> detections;
LatestResult results;
std::unique_ptr<OutputWriter> outputWriter;
std::unique_ptr<SessionWriter> sessionWriter;
std::unique_ptr<SessionReader> sessionReader;
fangjia::TrtLogger logger;
std::unique_ptr<Detector> detector;
std::unique_ptr<fangjia::RtmwEngine> pose;
@@ -66,6 +69,7 @@ struct CameraPipeline::Impl {
double totalLatency{};
explicit Impl(PipelineConfig c):config(std::move(c)),captures(config.queue_capacity),detections(config.queue_capacity) {
if(!config.replay_session.empty())sessionReader=std::make_unique<SessionReader>(config);
if(config.queue_capacity>8)throw std::invalid_argument("Queue capacity must be between 1 and 8");
if(config.max_people<1||config.max_people>16||!std::isfinite(config.detector_confidence)||config.detector_confidence<=0||config.detector_confidence>=1)
throw std::invalid_argument("Invalid detector configuration");
@@ -95,6 +99,7 @@ struct CameraPipeline::Impl {
{std::lock_guard<std::mutex> lock(stateMutex);if(started||stopped)throw std::logic_error("CameraPipeline can only be started once");started=true;}
try {
outputWriter=std::make_unique<OutputWriter>(config.output);
sessionWriter=std::make_unique<SessionWriter>(config);
detector=std::make_unique<Detector>(config.engines/"yolo11s.engine",logger,config.detector_confidence,config.max_people);
pose=std::make_unique<fangjia::RtmwEngine>(config.engines/"rtmw_l_384.engine",logger,config.camera.width,config.camera.height,config.max_people);
DoorOptions options;options.constant=config.door_mask;options.warning=config.warning_relative;options.release=config.release_relative;
@@ -107,7 +112,7 @@ struct CameraPipeline::Impl {
Stream warmup;
pose->warmup(warmup.value);
detector->infer(cv::Mat(config.camera.height,config.camera.width,CV_8UC3,cv::Scalar()),warmup.value);
{std::lock_guard<std::mutex> lock(stateMutex);camera=std::make_unique<Camera>(config.camera);if(stopped)camera->requestStop();}
{std::lock_guard<std::mutex> lock(stateMutex);if(!sessionReader)camera=std::make_unique<Camera>(config.camera);if(stopped&&camera)camera->requestStop();}
active=!stopped.load();
captureThread=std::thread([this]{try{captureLoop();}catch(...){fail();}});
detectorThread=std::thread([this]{try{detectorLoop();}catch(...){fail();}});
@@ -116,7 +121,7 @@ struct CameraPipeline::Impl {
}
void captureLoop() {
while(!stopped) {
auto frame=camera->read();if(!frame)break;
auto frame=sessionReader?sessionReader->read():camera->read();if(!frame)break;
gaps+=frame->metadata.skipped_driver_frames;
errorFrames+=frame->metadata.discarded_error_frames;
if(!captures.push(std::move(*frame)))break;
@@ -152,7 +157,7 @@ struct CameraPipeline::Impl {
}
auto poseElapsed=elapsedMs(poseStart);auto fusionStart=monotonicNs();
auto fused=fusion.update(raw,isolated,index);
auto record=makeRecord(index,raw,isolated,fused,false,false);
auto record=makeRecord(index,raw,isolated,fused,!config.record_session.empty(),false);
auto riskData=risk->evaluate(index,record);
auto result=std::make_shared<FrameResult>(makeFrameResult(record,riskData,detected->frame.metadata));
attachPoses(*result,fused);
@@ -162,8 +167,10 @@ struct CameraPipeline::Impl {
FrameResultPtr immutable=result;
results.publish(std::move(immutable));
{std::lock_guard<std::mutex> lock(stateMutex);totalLatency+=result->timing.capture_to_result_ms;++published;}
if(!config.record_session.empty())sessionWriter->write(*result,record,detected->frame.replay_record.get());
outputWriter->write(*result);
}
sessionWriter->finish();
active=false;
}
};