Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions crates/reco-autocam/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ pub fn setup_autocam(
let detection_interval = config.detection_interval;
let tracking_mode = config.tracking_mode;
let field_roi = config.field_roi.as_ref();
// Only read by the tensorrt-native path and the Linux ORT-GPU path
// below - an ort-only Windows build has neither compiled in.
#[cfg(any(feature = "tensorrt-native", all(feature = "ort", target_os = "linux")))]
let is_10bit = config.is_10bit;

let mut detection_active = false;
Expand Down
8 changes: 7 additions & 1 deletion crates/reco-core/src/interop/d3d11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,13 @@ impl D3d11StagingPool {
///
/// Performs `CopySubresourceRegion` (GPU-to-GPU, ~0.2ms) then waits
/// for completion via an event query before returning.
pub fn stage_frame(
///
/// # Safety
///
/// `src_texture`, if non-null, must be a valid `ID3D11Texture2D*` COM
/// pointer (as produced by FFmpeg's D3D11VA decode path via
/// `AVFrame::data[0]`) that stays alive for the duration of this call.
pub unsafe fn stage_frame(
&mut self,
src_texture: *mut c_void,
array_slice: usize,
Expand Down
10 changes: 8 additions & 2 deletions crates/reco-core/src/session/detection_dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ fn cpu_frames<'a>(
}

/// Per-camera CUDA NV12 frames from the shared-texture slot pointers.
#[cfg(any(target_os = "linux", target_os = "windows"))]
///
/// Linux only - the only caller (the `GpuResident` zero-copy match arm)
/// is `#[cfg(target_os = "linux")]`.
#[cfg(target_os = "linux")]
pub(super) fn cuda_nv12_frames(
left_buf: &crate::interop::zero_copy::GpuBufInfo,
right_buf: &crate::interop::zero_copy::GpuBufInfo,
Expand Down Expand Up @@ -506,7 +509,10 @@ impl StitchSession {
}

/// Run GPU-resident detection from CUDA NV12 shared textures.
#[cfg(any(target_os = "linux", target_os = "windows"))]
///
/// Linux only - the only caller (the `GpuResident` zero-copy match
/// arm) is `#[cfg(target_os = "linux")]`.
#[cfg(target_os = "linux")]
pub(crate) fn detect_and_update_director_gpu(
&mut self,
left_buf: &crate::interop::zero_copy::GpuBufInfo,
Expand Down
16 changes: 12 additions & 4 deletions crates/reco-core/src/session/frame_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,12 @@ impl StitchSession {
let right_pool_slot = left_pool_slot + 2;

let pool = self.d3d11_staging_pool.as_mut().unwrap();
pool.stage_frame(left_texture, left_slice, left_pool_slot)?;
pool.stage_frame(right_texture, right_slice, right_pool_slot)?;
// SAFETY: left_texture/right_texture are FFmpeg D3D11VA decode
// textures (AVFrame::data[0]) valid for this call's duration.
unsafe {
pool.stage_frame(left_texture, left_slice, left_pool_slot)?;
pool.stage_frame(right_texture, right_slice, right_pool_slot)?;
}
Ok(first_frame)
}

Expand Down Expand Up @@ -904,8 +908,12 @@ impl StitchSession {
let pool = self.d3d11_staging_pool.as_mut().unwrap();
let left_slot = (produce_index as usize * 2) % pool.n_slots();
let right_slot = (produce_index as usize * 2 + 1) % pool.n_slots();
pool.stage_frame(*left_texture, *left_slice, left_slot)?;
pool.stage_frame(*right_texture, *right_slice, right_slot)?;
// SAFETY: left_texture/right_texture are FFmpeg D3D11VA decode
// textures (AVFrame::data[0]) valid for this call's duration.
unsafe {
pool.stage_frame(*left_texture, *left_slice, left_slot)?;
pool.stage_frame(*right_texture, *right_slice, right_slot)?;
}
return Ok(Some(left_slot));
}
Ok(None)
Expand Down
7 changes: 4 additions & 3 deletions crates/reco-core/src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,9 @@ pub struct StitchSession {
std::sync::mpsc::SyncSender<u8>,
std::sync::mpsc::SyncSender<u8>,
)>,
/// CUDA buffer info for GPU detection (GPU zero-copy).
#[cfg(any(target_os = "linux", target_os = "windows"))]
/// CUDA buffer info for GPU detection (Linux GPU zero-copy path only -
/// the only reader, `FrameLoopContext::gpu_buf_info`, is Linux-only).
#[cfg(target_os = "linux")]
pub(crate) gpu_buf_info: Option<(
crate::interop::zero_copy::GpuBufInfo,
crate::interop::zero_copy::GpuBufInfo,
Expand Down Expand Up @@ -263,7 +264,7 @@ impl StitchSession {
gpu_bind_groups: None,
#[cfg(target_os = "linux")]
gpu_slot_free_tx: None,
#[cfg(any(target_os = "linux", target_os = "windows"))]
#[cfg(target_os = "linux")]
gpu_buf_info: None,
#[cfg(target_os = "linux")]
gpu_shared_views: None,
Expand Down
28 changes: 13 additions & 15 deletions crates/reco-io/src/smart_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ enum WindowsDecodeState {
right: crate::stitch_job::InputPath,
sync_offset: i64,
},
// No join_handles/shutdown flag here, unlike the Linux CUDA path
// (LinuxZeroCopyState): the D3D11VA decode threads exit via channel
// drop, with no ordering hazard on shutdown that a flag needs to
// coordinate.
Running {
pair_rx: std::sync::mpsc::Receiver<(
crate::ffmpeg::decoder::D3d11Frame,
crate::ffmpeg::decoder::D3d11Frame,
)>,
join_handles: Vec<std::thread::JoinHandle<()>>,
shutdown: std::sync::Arc<std::sync::atomic::AtomicBool>,
},
}

Expand Down Expand Up @@ -107,11 +109,7 @@ impl WindowsZeroCopyState {
let right = right.clone();
let sync_offset = *sync_offset;
let pair_rx = crate::zero_copy::spawn_d3d11_decode_pair(&left, &right, sync_offset);
self.decode = WindowsDecodeState::Running {
pair_rx,
join_handles: Vec::new(),
shutdown: std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)),
};
self.decode = WindowsDecodeState::Running { pair_rx };
}
}
}
Expand Down Expand Up @@ -775,14 +773,14 @@ impl Drop for SmartFileSource {
// channel, causing decode threads to exit when send() fails.
// Without this, orphaned decode threads keep the process alive.
#[cfg(target_os = "windows")]
if let SourceMode::D3d11ZeroCopy(state) = &mut self.mode {
if let WindowsDecodeState::Running { pair_rx, .. } = &mut state.decode {
drop(std::mem::replace(
pair_rx,
std::sync::mpsc::sync_channel(0).1,
));
log::debug!("D3D11VA source dropped, decode threads signalled to exit");
}
if let SourceMode::D3d11ZeroCopy(state) = &mut self.mode
&& let WindowsDecodeState::Running { pair_rx } = &mut state.decode
{
drop(std::mem::replace(
pair_rx,
std::sync::mpsc::sync_channel(0).1,
));
log::debug!("D3D11VA source dropped, decode threads signalled to exit");
}
// MetalZeroCopy: the Receiver is owned directly by the enum
// variant and drops naturally when the mode is replaced.
Expand Down
Loading