@@ -3,10 +3,7 @@ use crate::{
33 output_pipeline,
44 screen_capture:: { ScreenCaptureConfig , ScreenCaptureFormat } ,
55} ;
6- use :: windows:: {
7- Graphics :: Capture :: GraphicsCaptureItem ,
8- Win32 :: Graphics :: Direct3D11 :: { D3D11_BOX , ID3D11Device } ,
9- } ;
6+ use :: windows:: Win32 :: Graphics :: Direct3D11 :: { D3D11_BOX , ID3D11Device } ;
107use anyhow:: anyhow;
118use cap_fail:: fail_err;
129use cap_media_info:: { AudioInfo , VideoInfo } ;
@@ -24,7 +21,7 @@ use std::{
2421 collections:: VecDeque ,
2522 time:: { Duration , Instant } ,
2623} ;
27- use tracing:: { info, trace} ;
24+ use tracing:: { error , info, trace} ;
2825
2926const WINDOW_DURATION : Duration = Duration :: from_secs ( 3 ) ;
3027const LOG_INTERVAL : Duration = Duration :: from_secs ( 5 ) ;
@@ -121,18 +118,12 @@ impl ScreenCaptureConfig<Direct3DCapture> {
121118 Some ( Duration :: from_secs_f64 ( 1.0 / self . config . fps as f64 ) ) ;
122119 }
123120
124- let display = Display :: from_id ( & self . config . display )
125- . ok_or_else ( || SourceError :: NoDisplay ( self . config . display . clone ( ) ) ) ?;
126-
127- let capture_item = display
128- . raw_handle ( )
129- . try_as_capture_item ( )
130- . map_err ( SourceError :: AsCaptureItem ) ?;
131-
121+ // Store the display ID instead of GraphicsCaptureItem to avoid COM threading issues
122+ // The GraphicsCaptureItem will be created on the capture thread
132123 Ok ( (
133124 VideoSourceConfig {
134125 video_info : self . video_info ,
135- capture_item ,
126+ display_id : self . config . display . clone ( ) ,
136127 settings,
137128 d3d_device : self . d3d_device . clone ( ) ,
138129 } ,
@@ -149,7 +140,7 @@ pub enum VideoSourceError {
149140
150141pub struct VideoSourceConfig {
151142 video_info : VideoInfo ,
152- capture_item : GraphicsCaptureItem ,
143+ display_id : DisplayId ,
153144 settings : scap_direct3d:: Settings ,
154145 pub d3d_device : ID3D11Device ,
155146}
@@ -170,9 +161,9 @@ impl output_pipeline::VideoSource for VideoSource {
170161 async fn setup (
171162 VideoSourceConfig {
172163 video_info,
173- capture_item ,
164+ display_id ,
174165 settings,
175- d3d_device,
166+ d3d_device, // Share the D3D device with the encoder to avoid device mismatch
176167 } : Self :: Config ,
177168 mut video_tx : mpsc:: Sender < Self :: Frame > ,
178169 ctx : & mut output_pipeline:: SetupCtx ,
@@ -186,6 +177,28 @@ impl output_pipeline::VideoSource for VideoSource {
186177 ctx. tasks ( ) . spawn_thread ( "d3d-capture-thread" , move || {
187178 cap_mediafoundation_utils:: thread_init ( ) ;
188179
180+ // Look up the display and create the GraphicsCaptureItem on this thread to avoid COM threading issues
181+ let capture_item = match Display :: from_id ( & display_id) {
182+ Some ( display) => {
183+ match display. raw_handle ( ) . try_as_capture_item ( ) {
184+ Ok ( item) => {
185+ trace ! ( "GraphicsCaptureItem created successfully on capture thread" ) ;
186+ item
187+ }
188+ Err ( e) => {
189+ error ! ( "Failed to create GraphicsCaptureItem on capture thread: {}" , e) ;
190+ let _ = error_tx. send ( anyhow ! ( "Failed to create GraphicsCaptureItem: {}" , e) ) ;
191+ return ;
192+ }
193+ }
194+ }
195+ None => {
196+ error ! ( "Display not found for ID: {:?}" , display_id) ;
197+ let _ = error_tx. send ( anyhow ! ( "Display not found for ID: {:?}" , display_id) ) ;
198+ return ;
199+ }
200+ } ;
201+
189202 let res = scap_direct3d:: Capturer :: new (
190203 capture_item,
191204 settings,
@@ -206,26 +219,39 @@ impl output_pipeline::VideoSource for VideoSource {
206219 Ok ( ( ) )
207220 }
208221 } ,
209- Some ( d3d_device) ,
222+ Some ( d3d_device) , // Use the same D3D device as the encoder
210223 ) ;
211224
212225 let mut capturer = match res {
213- Ok ( capturer) => capturer,
226+ Ok ( capturer) => {
227+ trace ! ( "D3D capturer created successfully" ) ;
228+ capturer
229+ }
214230 Err ( e) => {
231+ error ! ( "Failed to create D3D capturer: {}" , e) ;
215232 let _ = error_tx. send ( e. into ( ) ) ;
216233 return ;
217234 }
218235 } ;
219236
220237 let Ok ( VideoControl :: Start ( reply) ) = ctrl_rx. recv ( ) else {
238+ error ! ( "Failed to receive Start control message - channel disconnected" ) ;
239+ let _ = error_tx. send ( anyhow ! ( "Control channel disconnected before Start" ) ) ;
221240 return ;
222241 } ;
223242
224- if reply. send ( capturer. start ( ) . map_err ( Into :: into) ) . is_err ( ) {
243+ trace ! ( "Starting D3D capturer" ) ;
244+ let start_result = capturer. start ( ) . map_err ( Into :: into) ;
245+ if let Err ( ref e) = start_result {
246+ error ! ( "Failed to start D3D capturer: {}" , e) ;
247+ }
248+ if reply. send ( start_result) . is_err ( ) {
249+ error ! ( "Failed to send start result - receiver dropped" ) ;
225250 return ;
226251 }
227252
228253 let Ok ( VideoControl :: Stop ( reply) ) = ctrl_rx. recv ( ) else {
254+ trace ! ( "Failed to receive Stop control message - channel disconnected (expected during shutdown)" ) ;
229255 return ;
230256 } ;
231257
0 commit comments