fix(camera): capture a fresh UVC snapshot
This commit is contained in:
parent
b0efc341a9
commit
8c2ed13f80
@ -5,6 +5,8 @@
|
||||
#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"
|
||||
@ -68,8 +70,10 @@ namespace cmvr::device {
|
||||
std::shared_ptr<std::thread> recording_thread_;
|
||||
|
||||
|
||||
cv::Mat latest_frame_; // 存储最新帧
|
||||
std::mutex frame_mutex_; // 保护最新帧的访问
|
||||
cv::Mat latest_frame_;
|
||||
std::mutex frame_mutex_;
|
||||
std::condition_variable frame_condition_;
|
||||
uint64_t latest_frame_sequence_{0};
|
||||
|
||||
std::string output_path_;
|
||||
bool is_recording_ = false;
|
||||
|
||||
@ -71,6 +71,7 @@ bool UVCCamera::init() {
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
latest_frame_.release();
|
||||
latest_frame_sequence_ = 0;
|
||||
}
|
||||
|
||||
stream_frame_buffer_ = std::make_shared<SPMCRingBuffer<StreamFrameData>>(buffer_size_);
|
||||
@ -144,6 +145,7 @@ bool UVCCamera::start() {
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
latest_frame_.release();
|
||||
latest_frame_sequence_ = 0;
|
||||
}
|
||||
|
||||
cap_.open(serial_, cv::CAP_V4L2);
|
||||
@ -212,6 +214,7 @@ bool UVCCamera::stop() {
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
latest_frame_.release();
|
||||
latest_frame_sequence_ = 0;
|
||||
}
|
||||
state_.is_opened = false;
|
||||
return true;
|
||||
@ -228,6 +231,7 @@ 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;
|
||||
@ -254,15 +258,24 @@ void UVCCamera::getRGBImage(cv::Mat& color, Rs2Intrinsics& intrinsics)
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
if (!latest_frame_.empty()) {
|
||||
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;
|
||||
}
|
||||
|
||||
const bool capture_worker_requested = state_.is_streaming || state_.is_recording;
|
||||
if (color.empty() && !capture_worker_requested) {
|
||||
else {
|
||||
if (stream_thread_) {
|
||||
if (stream_thread_->joinable()) {
|
||||
stream_thread_->join();
|
||||
@ -282,7 +295,9 @@ void UVCCamera::getRGBImage(cv::Mat& color, Rs2Intrinsics& intrinsics)
|
||||
|
||||
if (color.empty()) {
|
||||
state_.is_error = true;
|
||||
state_.error_message = "no video frame available";
|
||||
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;
|
||||
}
|
||||
@ -563,7 +578,9 @@ void UVCCamera::streaming_worker_() {
|
||||
{
|
||||
std::lock_guard frame_lock(frame_mutex_);
|
||||
frame.copyTo(latest_frame_);
|
||||
++latest_frame_sequence_;
|
||||
}
|
||||
frame_condition_.notify_all();
|
||||
|
||||
// 以下为编码部分,用于流模式
|
||||
StreamFrameData frame_data;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user