@@ -44,28 +44,45 @@ std::optional<cv::Mat> FramePoolScreencap::screencap()
4444
4545 winrt::Windows::Graphics::Capture::Direct3D11CaptureFrame frame = nullptr ;
4646
47- // 先清空 FramePool 中可能残留的旧帧
48- while (auto old_frame = cap_frame_pool_.TryGetNextFrame ()) {
49- old_frame.Close ();
50- }
51-
52- // 等待新帧到来
53- using namespace std ::chrono_literals;
54- auto start_time = std::chrono::steady_clock::now ();
55- while (duration_since (start_time) < 2000ms) {
56- std::this_thread::sleep_for (2ms);
57- frame = cap_frame_pool_.TryGetNextFrame ();
58- if (frame) {
59- break ;
47+ try {
48+ // 先清空 FramePool 中可能残留的旧帧
49+ while (auto old_frame = cap_frame_pool_.TryGetNextFrame ()) {
50+ old_frame.Close ();
6051 }
52+
53+ // 等待新帧到来
54+ using namespace std ::chrono_literals;
55+ auto start_time = std::chrono::steady_clock::now ();
56+ while (duration_since (start_time) < 2000ms) {
57+ std::this_thread::sleep_for (2ms);
58+ frame = cap_frame_pool_.TryGetNextFrame ();
59+ if (frame) {
60+ break ;
61+ }
62+ }
63+ }
64+ catch (const winrt::hresult_error& e) {
65+ LogError << " Failed to get frame" << VAR (e.code ()) << VAR (winrt::to_string (e.message ()));
66+ uninit ();
67+ return std::nullopt ;
6168 }
6269
6370 if (!frame) {
6471 LogError << " Failed to get frame after timeout" ;
6572 return std::nullopt ;
6673 }
6774
68- auto access = frame.Surface ().as <Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess>();
75+ auto surface = frame.Surface ();
76+ if (!surface) {
77+ LogError << " frame.Surface() is null" ;
78+ return std::nullopt ;
79+ }
80+
81+ auto access = surface.try_as <Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess>();
82+ if (!access) {
83+ LogError << " Failed to get IDirect3DDxgiInterfaceAccess" ;
84+ return std::nullopt ;
85+ }
6986
7087 winrt::com_ptr<ID3D11Texture2D> texture = nullptr ;
7188 HRESULT ret = access->GetInterface (winrt::guid_of<ID3D11Texture2D>(), texture.put_void ());
@@ -197,12 +214,22 @@ bool FramePoolScreencap::init()
197214 return false ;
198215 }
199216
200- auto activation_factory = winrt::get_activation_factory<winrt::Windows::Graphics::Capture::GraphicsCaptureItem>();
201- auto interop_factory = activation_factory.as <IGraphicsCaptureItemInterop>();
202- ret = interop_factory->CreateForWindow (
203- hwnd_,
204- winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
205- winrt::put_abi (cap_item_));
217+ try {
218+ auto activation_factory = winrt::get_activation_factory<winrt::Windows::Graphics::Capture::GraphicsCaptureItem>();
219+ auto interop_factory = activation_factory.try_as <IGraphicsCaptureItemInterop>();
220+ if (!interop_factory) {
221+ LogError << " Failed to get IGraphicsCaptureItemInterop" ;
222+ return false ;
223+ }
224+ ret = interop_factory->CreateForWindow (
225+ hwnd_,
226+ winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
227+ winrt::put_abi (cap_item_));
228+ }
229+ catch (const winrt::hresult_error& e) {
230+ LogError << " Failed to create GraphicsCaptureItem" << VAR (e.code ()) << VAR (winrt::to_string (e.message ()));
231+ return false ;
232+ }
206233 if (FAILED (ret)) {
207234 LogError << " CreateForWindow GraphicsCaptureItem failed" << VAR (ret);
208235 return false ;
@@ -224,7 +251,11 @@ bool FramePoolScreencap::init()
224251 return false ;
225252 }
226253
227- winrt::com_ptr<IDXGIDevice> dxgi_device = d3d_device_.as <IDXGIDevice>();
254+ auto dxgi_device = d3d_device_.try_as <IDXGIDevice>();
255+ if (!dxgi_device) {
256+ LogError << " Failed to get IDXGIDevice" ;
257+ return false ;
258+ }
228259
229260 winrt::com_ptr<IInspectable> inspectable = nullptr ;
230261 ret = CreateDirect3D11DeviceFromDXGIDevice (dxgi_device.get (), inspectable.put ());
@@ -233,27 +264,51 @@ bool FramePoolScreencap::init()
233264 return false ;
234265 }
235266
236- cap_frame_pool_ = winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool::Create (
237- inspectable.as <winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice>(),
238- winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
239- 1 ,
240- cap_item_.Size ());
267+ auto d3d_device_interop = inspectable.try_as <winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice>();
268+ if (!d3d_device_interop) {
269+ LogError << " Failed to get IDirect3DDevice" ;
270+ return false ;
271+ }
272+
273+ try {
274+ cap_frame_pool_ = winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool::Create (
275+ d3d_device_interop,
276+ winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
277+ 1 ,
278+ cap_item_.Size ());
279+ }
280+ catch (const winrt::hresult_error& e) {
281+ LogError << " Direct3D11CaptureFramePool::Create failed" << VAR (e.code ()) << VAR (winrt::to_string (e.message ()));
282+ return false ;
283+ }
241284
242285 if (!cap_frame_pool_) {
243- LogError << " Direct3D11CaptureFramePool::Create failed " ;
286+ LogError << " Direct3D11CaptureFramePool::Create returned null " ;
244287 return false ;
245288 }
246289
247- cap_session_ = cap_frame_pool_.CreateCaptureSession (cap_item_);
290+ try {
291+ cap_session_ = cap_frame_pool_.CreateCaptureSession (cap_item_);
292+ }
293+ catch (const winrt::hresult_error& e) {
294+ LogError << " CreateCaptureSession failed" << VAR (e.code ()) << VAR (winrt::to_string (e.message ()));
295+ return false ;
296+ }
248297 if (!cap_session_) {
249- LogError << " CreateCaptureSession failed " ;
298+ LogError << " CreateCaptureSession returned null " ;
250299 return false ;
251300 }
252301
253302 // 尝试关闭截图时的黄色边框(Windows 11 及部分 Win10 版本支持)
254303 try_disable_border ();
255304
256- cap_session_.StartCapture ();
305+ try {
306+ cap_session_.StartCapture ();
307+ }
308+ catch (const winrt::hresult_error& e) {
309+ LogError << " StartCapture failed" << VAR (e.code ()) << VAR (winrt::to_string (e.message ()));
310+ return false ;
311+ }
257312
258313 // 记录初始窗口大小
259314 if (cap_item_) {
@@ -268,13 +323,27 @@ bool FramePoolScreencap::init()
268323void FramePoolScreencap::uninit ()
269324{
270325 if (cap_session_) {
271- cap_session_.Close ();
326+ try {
327+ cap_session_.Close ();
328+ }
329+ catch (const winrt::hresult_error& e) {
330+ LogWarn << " cap_session_.Close() failed" << VAR (e.code ()) << VAR (winrt::to_string (e.message ()));
331+ }
272332 cap_session_ = nullptr ;
273333 }
274334
335+ if (cap_frame_pool_) {
336+ try {
337+ cap_frame_pool_.Close ();
338+ }
339+ catch (const winrt::hresult_error& e) {
340+ LogWarn << " cap_frame_pool_.Close() failed" << VAR (e.code ()) << VAR (winrt::to_string (e.message ()));
341+ }
342+ cap_frame_pool_ = nullptr ;
343+ }
344+
275345 readable_texture_ = nullptr ;
276- cap_frame_pool_ = nullptr ;
277- cap_session_ = nullptr ;
346+ cap_item_ = nullptr ;
278347 texture_desc_ = { 0 };
279348 last_capture_size_ = {};
280349}
@@ -285,7 +354,20 @@ bool FramePoolScreencap::check_and_handle_size_changed()
285354 return true ;
286355 }
287356
288- auto current_size = cap_item_.Size ();
357+ if (!IsWindow (hwnd_)) {
358+ LogError << " Window is no longer valid" ;
359+ return false ;
360+ }
361+
362+ winrt::Windows::Graphics::SizeInt32 current_size {};
363+ try {
364+ current_size = cap_item_.Size ();
365+ }
366+ catch (const winrt::hresult_error& e) {
367+ LogError << " Failed to get capture item size" << VAR (e.code ()) << VAR (winrt::to_string (e.message ()));
368+ uninit ();
369+ return false ;
370+ }
289371 // 如果窗口大小没有变化,直接返回
290372 if (current_size.Width == last_capture_size_.first && current_size.Height == last_capture_size_.second ) {
291373 return true ;
@@ -352,21 +434,27 @@ void FramePoolScreencap::try_disable_border()
352434 return ;
353435 }
354436
355- auto op = GraphicsCaptureAccess::RequestAccessAsync (GraphicsCaptureAccessKind::Borderless);
356- auto status = op.wait_for (std::chrono::seconds (5 ));
357- if (status != winrt::Windows::Foundation::AsyncStatus::Completed) {
358- LogWarn << " RequestAccessAsync did not complete in time" ;
359- return ;
360- }
437+ try {
438+ auto op = GraphicsCaptureAccess::RequestAccessAsync (GraphicsCaptureAccessKind::Borderless);
439+ auto status = op.wait_for (std::chrono::seconds (5 ));
440+ if (status != winrt::Windows::Foundation::AsyncStatus::Completed) {
441+ LogWarn << " RequestAccessAsync did not complete in time" ;
442+ return ;
443+ }
361444
362- auto access_result = op.GetResults ();
363- if (access_result != winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus::Allowed) {
364- LogWarn << " Borderless capture access not granted:" << static_cast <int >(access_result);
365- return ;
366- }
445+ auto access_result = op.GetResults ();
446+ if (access_result
447+ != winrt::Windows::Security::Authorization::AppCapabilityAccess::AppCapabilityAccessStatus::Allowed) {
448+ LogWarn << " Borderless capture access not granted:" << static_cast <int >(access_result);
449+ return ;
450+ }
367451
368- cap_session_.IsBorderRequired (false );
369- LogInfo << " Capture border disabled successfully" ;
452+ cap_session_.IsBorderRequired (false );
453+ LogInfo << " Capture border disabled successfully" ;
454+ }
455+ catch (const winrt::hresult_error& e) {
456+ LogWarn << " Failed to disable capture border" << VAR (e.code ()) << VAR (winrt::to_string (e.message ()));
457+ }
370458}
371459
372460MAA_CTRL_UNIT_NS_END
0 commit comments