fix(camera): read UVC snapshots directly
This commit is contained in:
parent
8c2ed13f80
commit
2c5855a497
@ -5,8 +5,6 @@
|
||||
#ifndef CMVR_ES_UVC_CAMERA_H
|
||||
#define CMVR_ES_UVC_CAMERA_H
|
||||
|
||||
#include <condition_variable>
|
||||
|
||||
#include "common/base/ring_buffer.h"
|
||||
#include "camera/abstract_camera.h"
|
||||
#include "devices/camera/common/include/camera_stream_encoder.h"
|
||||
@ -70,10 +68,7 @@ namespace cmvr::device {
|
||||
std::shared_ptr<std::thread> recording_thread_;
|
||||
|
||||
|
||||
cv::Mat latest_frame_;
|
||||
std::mutex frame_mutex_;
|
||||
std::condition_variable frame_condition_;
|
||||
uint64_t latest_frame_sequence_{0};
|
||||
std::mutex capture_mutex_;
|
||||
|
||||
std::string output_path_;
|
||||
bool is_recording_ = false;
|
||||
|
||||
@ -68,12 +68,6 @@ bool UVCCamera::init() {
|
||||
clear_error_();
|
||||
state_.is_initialized = false;
|
||||
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
latest_frame_.release();
|
||||
latest_frame_sequence_ = 0;
|
||||
}
|
||||
|
||||
stream_frame_buffer_ = std::make_shared<SPMCRingBuffer<StreamFrameData>>(buffer_size_);
|
||||
stream_frame_buffer_->clear();
|
||||
if (cap_.isOpened()) {
|
||||
@ -142,12 +136,6 @@ bool UVCCamera::start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
latest_frame_.release();
|
||||
latest_frame_sequence_ = 0;
|
||||
}
|
||||
|
||||
cap_.open(serial_, cv::CAP_V4L2);
|
||||
this_thread::sleep_for(chrono::milliseconds(100));
|
||||
|
||||
@ -211,11 +199,6 @@ bool UVCCamera::stop() {
|
||||
if (cap_.isOpened()) {
|
||||
cap_.release();
|
||||
}
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
latest_frame_.release();
|
||||
latest_frame_sequence_ = 0;
|
||||
}
|
||||
state_.is_opened = false;
|
||||
return true;
|
||||
}
|
||||
@ -232,15 +215,16 @@ void UVCCamera::getRGBImage(cv::Mat& color, Rs2Intrinsics& intrinsics)
|
||||
std::lock_guard lock(ctrl_mtx_);
|
||||
clear_error_();
|
||||
color.release();
|
||||
if (mode_ == PHOTO_MODE) {
|
||||
if (!state_.is_opened) {
|
||||
state_.is_error = true;
|
||||
state_.error_message = "camera not opened";
|
||||
CMVR_LOG(ERROR) << "[UVCCamera] (getRGBImage): " << state_.error_message;
|
||||
color.release();
|
||||
return;
|
||||
}
|
||||
if (!cap_.read(color)) {
|
||||
if (!state_.is_opened) {
|
||||
state_.is_error = true;
|
||||
state_.error_message = "camera not opened";
|
||||
CMVR_LOG(ERROR) << "[UVCCamera] (getRGBImage): " << state_.error_message;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard capture_lock(capture_mutex_);
|
||||
if (!cap_.read(color) || color.empty()) {
|
||||
state_.is_error = true;
|
||||
state_.error_message = "read color image failed";
|
||||
CMVR_LOG(ERROR) << "[UVCCamera] (getRGBImage): " << state_.error_message;
|
||||
@ -248,60 +232,6 @@ void UVCCamera::getRGBImage(cv::Mat& color, Rs2Intrinsics& intrinsics)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (mode_ == VIDEO_MODE)
|
||||
{
|
||||
if (!state_.is_opened) {
|
||||
state_.is_error = true;
|
||||
state_.error_message = "camera not opened";
|
||||
CMVR_LOG(ERROR) << "[UVCCamera] (getRGBImage): " << state_.error_message;
|
||||
color.release();
|
||||
return;
|
||||
}
|
||||
|
||||
const bool capture_worker_requested = state_.is_streaming || state_.is_recording;
|
||||
bool snapshot_timed_out = false;
|
||||
if (capture_worker_requested) {
|
||||
std::unique_lock frame_lock(frame_mutex_);
|
||||
const uint64_t requested_after_sequence = latest_frame_sequence_;
|
||||
const bool received_new_frame = frame_condition_.wait_for(
|
||||
frame_lock,
|
||||
std::chrono::seconds(2),
|
||||
[this, requested_after_sequence]() {
|
||||
return latest_frame_sequence_ != requested_after_sequence;
|
||||
});
|
||||
|
||||
if (received_new_frame && !latest_frame_.empty()) {
|
||||
latest_frame_.copyTo(color);
|
||||
}
|
||||
snapshot_timed_out = !received_new_frame;
|
||||
}
|
||||
else {
|
||||
if (stream_thread_) {
|
||||
if (stream_thread_->joinable()) {
|
||||
stream_thread_->join();
|
||||
}
|
||||
stream_thread_.reset();
|
||||
is_streaming_running = false;
|
||||
}
|
||||
|
||||
if (!cap_.read(color) || color.empty()) {
|
||||
state_.is_error = true;
|
||||
state_.error_message = "read color image failed";
|
||||
CMVR_LOG(ERROR) << "[UVCCamera] (getRGBImage): " << state_.error_message;
|
||||
color.release();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (color.empty()) {
|
||||
state_.is_error = true;
|
||||
state_.error_message = snapshot_timed_out
|
||||
? "timed out waiting for a new video frame"
|
||||
: "no video frame available";
|
||||
CMVR_LOG(ERROR) << "[UVCCamera] (getRGBImage): " << state_.error_message;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UVCCamera::getDepthImage(cv::Mat& depth, Rs2Intrinsics& intrinsics) {
|
||||
@ -567,7 +497,12 @@ void UVCCamera::streaming_worker_() {
|
||||
while (state_.is_streaming || state_.is_recording) {
|
||||
// 记录当前帧处理开始时间
|
||||
const auto frame_start_time = std::chrono::steady_clock::now();
|
||||
if (!cap_.read(frame) || frame.empty()) {
|
||||
bool frame_read = false;
|
||||
{
|
||||
std::lock_guard capture_lock(capture_mutex_);
|
||||
frame_read = cap_.read(frame);
|
||||
}
|
||||
if (!frame_read || frame.empty()) {
|
||||
state_.is_error = true;
|
||||
state_.error_message = "failed to read frame";
|
||||
CMVR_LOG(ERROR) << "[UVCCamera]streaming_worker_: " << state_.error_message;
|
||||
@ -575,13 +510,6 @@ void UVCCamera::streaming_worker_() {
|
||||
}
|
||||
const auto capture_end_time = std::chrono::steady_clock::now();
|
||||
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
frame.copyTo(latest_frame_);
|
||||
++latest_frame_sequence_;
|
||||
}
|
||||
frame_condition_.notify_all();
|
||||
|
||||
// 以下为编码部分,用于流模式
|
||||
StreamFrameData frame_data;
|
||||
// 保存图像数据
|
||||
@ -694,10 +622,6 @@ void UVCCamera::streaming_worker_() {
|
||||
}
|
||||
|
||||
is_streaming_running = false;
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
latest_frame_.release();
|
||||
}
|
||||
// 线程结束时清空队列
|
||||
stream_frame_buffer_->clear();
|
||||
recordingIndex_ = 0;
|
||||
@ -709,10 +633,6 @@ void UVCCamera::streaming_worker_() {
|
||||
stream_frame_buffer_->clear();
|
||||
// 确保线程状态正确更新
|
||||
is_streaming_running = false;
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
latest_frame_.release();
|
||||
}
|
||||
state_.is_error = true;
|
||||
state_.error_message = e.what();
|
||||
CMVR_LOG(ERROR) << "[UVCCamera]streaming_worker_ error:" << state_.error_message;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user