Skip to content

Commit fdab776

Browse files
committed
Better error callbacks
1 parent f52e757 commit fdab776

10 files changed

Lines changed: 113 additions & 22 deletions

File tree

include/ccap_c.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ typedef enum {
7373
CCAP_ERROR_DEVICE_OPEN_FAILED = 0x1003, /**< Camera device open failed */
7474
CCAP_ERROR_DEVICE_START_FAILED = 0x1004, /**< Camera start failed */
7575
CCAP_ERROR_DEVICE_STOP_FAILED = 0x1005, /**< Camera stop failed */
76+
CCAP_ERROR_INITIALIZATION_FAILED = 0x1006, /**< Initialization failed */
7677
CCAP_ERROR_UNSUPPORTED_RESOLUTION = 0x2001, /**< Requested resolution is not supported */
7778
CCAP_ERROR_UNSUPPORTED_PIXEL_FORMAT = 0x2002, /**< Requested pixel format is not supported */
7879
CCAP_ERROR_FRAME_RATE_SET_FAILED = 0x2003, /**< Frame rate setting failed */

include/ccap_def.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ enum class ErrorCode {
242242
/// Camera stop failed
243243
DeviceStopFailed = 0x1005,
244244

245+
/// Initialization failed
246+
InitializationFailed = 0x1006,
247+
245248
/// Requested resolution is not supported
246249
UnsupportedResolution = 0x2001,
247250

src/ccap_c.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,8 @@ static_assert(static_cast<uint32_t>(CCAP_ERROR_DEVICE_START_FAILED) == static_ca
481481
"C and C++ ErrorCode::DeviceStartFailed values must match");
482482
static_assert(static_cast<uint32_t>(CCAP_ERROR_DEVICE_STOP_FAILED) == static_cast<uint32_t>(ccap::ErrorCode::DeviceStopFailed),
483483
"C and C++ ErrorCode::DeviceStopFailed values must match");
484+
static_assert(static_cast<uint32_t>(CCAP_ERROR_INITIALIZATION_FAILED) == static_cast<uint32_t>(ccap::ErrorCode::InitializationFailed),
485+
"C and C++ ErrorCode::InitializationFailed values must match");
484486
static_assert(static_cast<uint32_t>(CCAP_ERROR_UNSUPPORTED_RESOLUTION) == static_cast<uint32_t>(ccap::ErrorCode::UnsupportedResolution),
485487
"C and C++ ErrorCode::UnsupportedResolution values must match");
486488
static_assert(static_cast<uint32_t>(CCAP_ERROR_UNSUPPORTED_PIXEL_FORMAT) == static_cast<uint32_t>(ccap::ErrorCode::UnsupportedPixelFormat),

src/ccap_core.cpp

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ ProviderImp* createProviderV4L2();
3737

3838
// Global error callback storage
3939
namespace {
40-
std::mutex g_errorCallbackMutex;
41-
ErrorCallback g_globalErrorCallback;
42-
}
40+
std::mutex g_errorCallbackMutex;
41+
ErrorCallback g_globalErrorCallback;
42+
} // namespace
4343

4444
void setErrorCallback(ErrorCallback callback) {
4545
std::lock_guard<std::mutex> lock(g_errorCallbackMutex);
@@ -67,6 +67,11 @@ void DefaultAllocator::resize(size_t size) {
6767
// 32字节对齐,满足主流SIMD指令集需求(AVX)
6868
size_t alignedSize = (size + 31) & ~size_t(31);
6969
m_data = static_cast<uint8_t*>(ALIGNED_ALLOC(32, alignedSize));
70+
if (!m_data) {
71+
ccap::reportError(ErrorCode::MemoryAllocationFailed, "Failed to allocate " + std::to_string(alignedSize) + " bytes of aligned memory");
72+
m_size = 0;
73+
return;
74+
}
7075
m_size = alignedSize;
7176
CCAP_LOG_V("ccap: Allocated %zu bytes of memory at %p\n", m_size, m_data);
7277
}
@@ -114,12 +119,17 @@ ProviderImp* createProvider(std::string_view extraInfo) {
114119
if (warningLogEnabled()) {
115120
CCAP_LOG_W("ccap: Unsupported platform!\n");
116121
}
122+
ccap::reportError(ErrorCode::InitializationFailed, "Unsupported platform");
117123
#endif
118124
return nullptr;
119125
}
120126

121127
Provider::Provider() :
122-
m_imp(createProvider("")) {}
128+
m_imp(createProvider("")) {
129+
if (!m_imp) {
130+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::FAILED_TO_CREATE_PROVIDER);
131+
}
132+
}
123133

124134
Provider::~Provider() {
125135
CCAP_LOG_V("ccap: Provider::~Provider() called, this=%p, imp=%p\n", this, m_imp);
@@ -130,24 +140,35 @@ Provider::Provider(std::string_view deviceName, std::string_view extraInfo) :
130140
m_imp(createProvider(extraInfo)) {
131141
if (m_imp) {
132142
open(deviceName);
143+
} else {
144+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::FAILED_TO_CREATE_PROVIDER);
133145
}
134146
}
135147

136148
Provider::Provider(int deviceIndex, std::string_view extraInfo) :
137149
m_imp(createProvider(extraInfo)) {
138150
if (m_imp) {
139151
open(deviceIndex);
152+
} else {
153+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::FAILED_TO_CREATE_PROVIDER);
140154
}
141155
}
142156

143157
std::vector<std::string> Provider::findDeviceNames() { return m_imp ? m_imp->findDeviceNames() : std::vector<std::string>(); }
144158

145159
bool Provider::open(std::string_view deviceName, bool autoStart) {
146-
return m_imp && m_imp->open(deviceName) && (!autoStart || m_imp->start());
160+
if (!m_imp) {
161+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::PROVIDER_IMPLEMENTATION_NULL);
162+
return false;
163+
}
164+
return m_imp->open(deviceName) && (!autoStart || m_imp->start());
147165
}
148166

149167
bool Provider::open(int deviceIndex, bool autoStart) {
150-
if (!m_imp) return false;
168+
if (!m_imp) {
169+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::PROVIDER_IMPLEMENTATION_NULL);
170+
return false;
171+
}
151172

152173
std::string deviceName;
153174
if (deviceIndex >= 0) {
@@ -167,32 +188,74 @@ bool Provider::isOpened() const { return m_imp && m_imp->isOpened(); }
167188

168189
std::optional<DeviceInfo> Provider::getDeviceInfo() const { return m_imp ? m_imp->getDeviceInfo() : std::nullopt; }
169190

170-
void Provider::close() { m_imp->close(); }
191+
void Provider::close() {
192+
if (m_imp) {
193+
m_imp->close();
194+
}
195+
}
171196

172-
bool Provider::start() { return m_imp && m_imp->start(); }
197+
bool Provider::start() {
198+
if (!m_imp) {
199+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::PROVIDER_IMPLEMENTATION_NULL);
200+
return false;
201+
}
202+
return m_imp->start();
203+
}
173204

174205
void Provider::stop() {
175206
if (m_imp) m_imp->stop();
176207
}
177208

178209
bool Provider::isStarted() const { return m_imp && m_imp->isStarted(); }
179210

180-
bool Provider::set(PropertyName prop, double value) { return m_imp->set(prop, value); }
211+
bool Provider::set(PropertyName prop, double value) {
212+
if (!m_imp) {
213+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::PROVIDER_IMPLEMENTATION_NULL);
214+
return false;
215+
}
216+
return m_imp->set(prop, value);
217+
}
181218

182219
double Provider::get(PropertyName prop) { return m_imp ? m_imp->get(prop) : NAN; }
183220

184-
std::shared_ptr<VideoFrame> Provider::grab(uint32_t timeoutInMs) { return m_imp->grab(timeoutInMs); }
221+
std::shared_ptr<VideoFrame> Provider::grab(uint32_t timeoutInMs) {
222+
if (!m_imp) {
223+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::PROVIDER_IMPLEMENTATION_NULL);
224+
return nullptr;
225+
}
226+
return m_imp->grab(timeoutInMs);
227+
}
185228

186229
void Provider::setNewFrameCallback(std::function<bool(const std::shared_ptr<VideoFrame>&)> callback) {
230+
if (!m_imp) {
231+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::PROVIDER_IMPLEMENTATION_NULL);
232+
return;
233+
}
187234
m_imp->setNewFrameCallback(std::move(callback));
188235
}
189236

190237
void Provider::setFrameAllocator(std::function<std::shared_ptr<Allocator>()> allocatorFactory) {
238+
if (!m_imp) {
239+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::PROVIDER_IMPLEMENTATION_NULL);
240+
return;
241+
}
191242
m_imp->setFrameAllocator(std::move(allocatorFactory));
192243
}
193244

194-
void Provider::setMaxAvailableFrameSize(uint32_t size) { m_imp->setMaxAvailableFrameSize(size); }
245+
void Provider::setMaxAvailableFrameSize(uint32_t size) {
246+
if (!m_imp) {
247+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::PROVIDER_IMPLEMENTATION_NULL);
248+
return;
249+
}
250+
m_imp->setMaxAvailableFrameSize(size);
251+
}
195252

196-
void Provider::setMaxCacheFrameSize(uint32_t size) { m_imp->setMaxCacheFrameSize(size); }
253+
void Provider::setMaxCacheFrameSize(uint32_t size) {
254+
if (!m_imp) {
255+
ccap::reportError(ErrorCode::InitializationFailed, ErrorMessages::PROVIDER_IMPLEMENTATION_NULL);
256+
return;
257+
}
258+
m_imp->setMaxCacheFrameSize(size);
259+
}
197260

198-
} // namespace ccap
261+
} // namespace ccap

src/ccap_imp.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ std::shared_ptr<VideoFrame> ProviderImp::grab(uint32_t timeoutInMs) {
111111
if (m_availableFrames.empty() && timeoutInMs > 0) {
112112
if (!isStarted()) {
113113
CCAP_LOG_W("ccap: Grab called when camera is not started!");
114+
ccap::reportError(ErrorCode::DeviceStartFailed, "Grab called when camera is not started");
114115
return nullptr;
115116
}
116117

@@ -127,6 +128,7 @@ std::shared_ptr<VideoFrame> ProviderImp::grab(uint32_t timeoutInMs) {
127128
m_grabFrameWaiting = false;
128129
if (!waitSuccess) {
129130
CCAP_LOG_V("ccap: Grab timed out after %u ms\n", timeoutInMs);
131+
ccap::reportError(ErrorCode::FrameCaptureTimeout, "Grab timed out after " + std::to_string(timeoutInMs) + " ms");
130132
return nullptr;
131133
}
132134
}
@@ -198,4 +200,4 @@ void reportError(ErrorCode errorCode, std::string_view description) {
198200
}
199201
}
200202

201-
} // namespace ccap
203+
} // namespace ccap

src/ccap_imp.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#endif
3333

3434
namespace ccap {
35+
3536
struct FrameProperty {
3637
double fps{ 0.0 }; ///< 0 means device default.
3738

@@ -131,6 +132,12 @@ inline bool operator&(PixelFormat lhs, PixelFormatConstants rhs) { return (stati
131132

132133
void reportError(ErrorCode errorCode, std::string_view description);
133134

135+
// Common error messages
136+
namespace ErrorMessages {
137+
constexpr const char* PROVIDER_IMPLEMENTATION_NULL = "Provider implementation is null";
138+
constexpr const char* FAILED_TO_CREATE_PROVIDER = "Failed to create provider implementation";
139+
} // namespace ErrorMessages
140+
134141
} // namespace ccap
135142

136-
#endif
143+
#endif

src/ccap_imp_apple.mm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ - (BOOL)open {
298298

299299
if (![_session canSetSessionPreset:preset]) {
300300
CCAP_NSLOG_E(@"ccap: CameraCaptureObjc init - session preset not supported, using AVCaptureSessionPresetHigh");
301+
ccap::reportError(ErrorCode::UnsupportedResolution, "Session preset not supported");
301302
preset = AVCaptureSessionPresetHigh;
302303
}
303304

@@ -644,6 +645,7 @@ - (void)setFrameRate:(double)fps {
644645
}
645646
} else {
646647
CCAP_NSLOG_E(@"ccap: Desired fps (%g) not supported, skipping", fps);
648+
ccap::reportError(ErrorCode::FrameRateSetFailed, "Desired fps not supported");
647649
}
648650
}
649651
} else {
@@ -1037,6 +1039,7 @@ - (void)captureOutput:(AVCaptureOutput*)output
10371039
bool ProviderApple::start() {
10381040
if (!isOpened()) {
10391041
CCAP_NSLOG_W(@"ccap: camera start called with no device opened");
1042+
ccap::reportError(ErrorCode::DeviceStartFailed, "Camera start called with no device opened");
10401043
return false;
10411044
}
10421045

@@ -1059,4 +1062,4 @@ - (void)captureOutput:(AVCaptureOutput*)output
10591062

10601063
} // namespace ccap
10611064

1062-
#endif
1065+
#endif

src/ccap_imp_linux.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ bool ProviderV4L2::open(std::string_view deviceName) {
126126
if (!setupDevice()) {
127127
::close(m_fd);
128128
m_fd = -1;
129-
reportError(ErrorCode::DeviceOpenFailed, "Failed to setup device " + m_devicePath);
129+
ccap::reportError(ErrorCode::DeviceOpenFailed, "Failed to setup device " + m_devicePath);
130130
return false;
131131
}
132132

@@ -187,7 +187,7 @@ bool ProviderV4L2::start() {
187187
}
188188

189189
if (!negotiateFormat() || !allocateBuffers() || !startStreaming()) {
190-
reportError(ErrorCode::DeviceStartFailed, "Failed to start streaming");
190+
ccap::reportError(ErrorCode::DeviceStartFailed, "Failed to start streaming");
191191
return false;
192192
}
193193

@@ -451,6 +451,7 @@ void ProviderV4L2::stopStreaming() {
451451
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
452452
if (ioctl(m_fd, VIDIOC_STREAMOFF, &type) < 0) {
453453
CCAP_LOG_E("ccap: VIDIOC_STREAMOFF failed: %s\n", strerror(errno));
454+
ccap::reportError(ErrorCode::DeviceStopFailed, "VIDIOC_STREAMOFF failed: " + std::string(strerror(errno)));
454455
}
455456
}
456457

@@ -636,6 +637,7 @@ bool ProviderV4L2::readFrame() {
636637

637638
if (ioctl(m_fd, VIDIOC_QBUF, &requeueBuf) < 0) {
638639
CCAP_LOG_E("ccap: VIDIOC_QBUF failed in destructor: %s\n", strerror(errno));
640+
ccap::reportError(ErrorCode::FrameCaptureFailed, "VIDIOC_QBUF failed in destructor: " + std::string(strerror(errno)));
639641
}
640642
}
641643
frame = nullptr;
@@ -651,6 +653,7 @@ bool ProviderV4L2::readFrame() {
651653
// Requeue buffer immediately after copying data
652654
if (ioctl(m_fd, VIDIOC_QBUF, &buf) < 0) {
653655
CCAP_LOG_E("ccap: VIDIOC_QBUF failed: %s\n", strerror(errno));
656+
ccap::reportError(ErrorCode::FrameCaptureFailed, "VIDIOC_QBUF failed: " + std::string(strerror(errno)));
654657
return false;
655658
}
656659
}

src/ccap_imp_windows.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ bool ProviderDirectShow::createStream() {
589589
}
590590
} else {
591591
CCAP_LOG_E("ccap: SetFormat failed, result=0x%lx\n", setFormatResult);
592+
ccap::reportError(ErrorCode::UnsupportedPixelFormat, "SetFormat failed");
592593
}
593594
}
594595
}
@@ -623,6 +624,7 @@ bool ProviderDirectShow::createStream() {
623624
hr = m_graph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter);
624625
if (FAILED(hr)) {
625626
CCAP_LOG_E("ccap: QueryInterface IMediaFilter failed, result=0x%lx\n", hr);
627+
ccap::reportError(ErrorCode::DeviceOpenFailed, "QueryInterface IMediaFilter failed");
626628
} else {
627629
pMediaFilter->SetSyncSource(NULL);
628630
pMediaFilter->Release();
@@ -686,11 +688,12 @@ bool ProviderDirectShow::open(std::string_view deviceName) {
686688
CCAP_LOG_I("ccap: Found video capture device: %s\n", m_deviceName.c_str());
687689

688690
if (!buildGraph()) {
689-
reportError(ErrorCode::DeviceOpenFailed, "Failed to build DirectShow graph");
691+
ccap::reportError(ErrorCode::DeviceOpenFailed, "Failed to build DirectShow graph");
690692
return false;
691693
}
692694

693695
if (!createStream()) {
696+
ccap::reportError(ErrorCode::DeviceOpenFailed, "Failed to create DirectShow stream");
694697
return false;
695698
}
696699

@@ -706,7 +709,8 @@ bool ProviderDirectShow::open(std::string_view deviceName) {
706709
hr = m_graph->QueryInterface(IID_IVideoWindow, (LPVOID*)&videoWindow);
707710
if (FAILED(hr)) {
708711
CCAP_LOG_E("ccap: QueryInterface IVideoWindow failed, result=0x%lx\n", hr);
709-
return hr;
712+
ccap::reportError(ErrorCode::DeviceOpenFailed, "QueryInterface IVideoWindow failed");
713+
return false;
710714
}
711715
videoWindow->put_AutoShow(false);
712716
}
@@ -732,6 +736,7 @@ HRESULT STDMETHODCALLTYPE ProviderDirectShow::SampleCB(double sampleTime, IMedia
732736
BYTE* sampleData = nullptr;
733737
if (auto hr = mediaSample->GetPointer(&sampleData); FAILED(hr)) {
734738
CCAP_LOG_E("ccap: GetPointer failed, hr=0x%lx\n", hr);
739+
ccap::reportError(ErrorCode::FrameCaptureFailed, "GetPointer failed");
735740
return S_OK;
736741
}
737742

@@ -1069,4 +1074,4 @@ bool ProviderDirectShow::isStarted() const { return m_isRunning && m_mediaContro
10691074
ProviderImp* createProviderDirectShow() { return new ProviderDirectShow(); }
10701075

10711076
} // namespace ccap
1072-
#endif
1077+
#endif

src/ccap_utils.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ std::string_view errorCodeToString(ErrorCode errorCode) {
261261
return "Camera start failed";
262262
case ErrorCode::DeviceStopFailed:
263263
return "Camera stop failed";
264+
case ErrorCode::InitializationFailed:
265+
return "Initialization failed";
264266
case ErrorCode::UnsupportedResolution:
265267
return "Requested resolution is not supported";
266268
case ErrorCode::UnsupportedPixelFormat:
@@ -282,4 +284,4 @@ std::string_view errorCodeToString(ErrorCode errorCode) {
282284
}
283285
}
284286

285-
} // namespace ccap
287+
} // namespace ccap

0 commit comments

Comments
 (0)