Skip to content

Commit 506b3ef

Browse files
authored
Hold camera and mic locks while recording is active (#1162)
* hold camera and mic locks while recording is active * hold locks inside sources * hold camera feed on instant mode
1 parent 10a7f5a commit 506b3ef

File tree

4 files changed

+38
-36
lines changed

4 files changed

+38
-36
lines changed

apps/desktop/src-tauri/src/recording.rs

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use cap_project::{
88
cursor::CursorEvents,
99
};
1010
use cap_recording::PipelineDoneError;
11+
use cap_recording::feeds::camera::CameraFeedLock;
12+
use cap_recording::feeds::microphone::MicrophoneFeedLock;
1113
use cap_recording::{
1214
RecordingError, RecordingMode,
1315
feeds::{camera, microphone},
@@ -53,20 +55,24 @@ use crate::{
5355
windows::{CapWindowId, ShowCapWindow},
5456
};
5557

58+
pub struct InProgressRecordingCommon {
59+
pub target_name: String,
60+
pub inputs: StartRecordingInputs,
61+
pub recording_dir: PathBuf,
62+
}
63+
5664
pub enum InProgressRecording {
5765
Instant {
58-
target_name: String,
5966
handle: instant_recording::ActorHandle,
6067
progressive_upload: InstantMultipartUpload,
6168
video_upload_info: VideoUploadInfo,
62-
inputs: StartRecordingInputs,
63-
recording_dir: PathBuf,
69+
common: InProgressRecordingCommon,
70+
// camera isn't used as part of recording pipeline so we hold lock here
71+
camera_feed: Option<Arc<CameraFeedLock>>,
6472
},
6573
Studio {
66-
target_name: String,
6774
handle: studio_recording::ActorHandle,
68-
inputs: StartRecordingInputs,
69-
recording_dir: PathBuf,
75+
common: InProgressRecordingCommon,
7076
},
7177
}
7278

@@ -80,8 +86,8 @@ impl InProgressRecording {
8086

8187
pub fn inputs(&self) -> &StartRecordingInputs {
8288
match self {
83-
Self::Instant { inputs, .. } => inputs,
84-
Self::Studio { inputs, .. } => inputs,
89+
Self::Instant { common, .. } => &common.inputs,
90+
Self::Studio { common, .. } => &common.inputs,
8591
}
8692
}
8793

@@ -101,8 +107,8 @@ impl InProgressRecording {
101107

102108
pub fn recording_dir(&self) -> &PathBuf {
103109
match self {
104-
Self::Instant { recording_dir, .. } => recording_dir,
105-
Self::Studio { recording_dir, .. } => recording_dir,
110+
Self::Instant { common, .. } => &common.recording_dir,
111+
Self::Studio { common, .. } => &common.recording_dir,
106112
}
107113
}
108114

@@ -112,21 +118,17 @@ impl InProgressRecording {
112118
handle,
113119
progressive_upload,
114120
video_upload_info,
115-
target_name,
121+
common,
116122
..
117123
} => CompletedRecording::Instant {
118124
recording: handle.stop().await?,
119125
progressive_upload,
120126
video_upload_info,
121-
target_name,
127+
target_name: common.target_name,
122128
},
123-
Self::Studio {
124-
handle,
125-
target_name,
126-
..
127-
} => CompletedRecording::Studio {
129+
Self::Studio { handle, common, .. } => CompletedRecording::Studio {
128130
recording: handle.stop().await?,
129-
target_name,
131+
target_name: common.target_name,
130132
},
131133
})
132134
}
@@ -449,6 +451,12 @@ pub async fn start_recording(
449451
.map_err(|e| format!("GetShareableContent: {e}"))?
450452
.ok_or_else(|| format!("GetShareableContent/NotAvailable"))?;
451453

454+
let common = InProgressRecordingCommon {
455+
target_name,
456+
inputs: inputs.clone(),
457+
recording_dir: recording_dir.clone(),
458+
};
459+
452460
let actor = match inputs.mode {
453461
RecordingMode::Studio => {
454462
let mut builder = studio_recording::Actor::builder(
@@ -481,12 +489,7 @@ pub async fn start_recording(
481489
e.to_string()
482490
})?;
483491

484-
InProgressRecording::Studio {
485-
handle,
486-
target_name,
487-
inputs,
488-
recording_dir: recording_dir.clone(),
489-
}
492+
InProgressRecording::Studio { handle, common }
490493
}
491494
RecordingMode::Instant => {
492495
let Some(video_upload_info) = video_upload_info.clone() else {
@@ -526,9 +529,8 @@ pub async fn start_recording(
526529
handle,
527530
progressive_upload,
528531
video_upload_info,
529-
target_name,
530-
inputs,
531-
recording_dir: recording_dir.clone(),
532+
common,
533+
camera_feed,
532534
}
533535
}
534536
};

crates/recording/src/instant_recording.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
RecordingBaseInputs,
33
capture_pipeline::{MakeCapturePipeline, ScreenCaptureMethod, Stop, create_screen_capture},
4-
feeds::microphone::MicrophoneFeedLock,
4+
feeds::{camera::CameraFeedLock, microphone::MicrophoneFeedLock},
55
output_pipeline::{self, OutputPipeline},
66
sources::screen_capture::{ScreenCaptureConfig, ScreenCaptureTarget},
77
};

crates/recording/src/sources/camera.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl VideoSource for Camera {
1515
type Frame = FFmpegVideoFrame;
1616

1717
async fn setup(
18-
config: Self::Config,
18+
feed_lock: Self::Config,
1919
mut video_tx: mpsc::Sender<Self::Frame>,
2020
_: &mut SetupCtx,
2121
) -> anyhow::Result<Self>
@@ -24,7 +24,7 @@ impl VideoSource for Camera {
2424
{
2525
let (tx, rx) = flume::bounded(8);
2626

27-
config
27+
feed_lock
2828
.ask(camera::AddSender(tx))
2929
.await
3030
.map_err(|e| anyhow!("Failed to add camera sender: {e}"))?;
@@ -35,7 +35,7 @@ impl VideoSource for Camera {
3535
}
3636
});
3737

38-
Ok(Self(config))
38+
Ok(Self(feed_lock))
3939
}
4040

4141
fn video_info(&self) -> VideoInfo {

crates/recording/src/sources/microphone.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@ use cap_media_info::AudioInfo;
77
use futures::{SinkExt, channel::mpsc};
88
use std::sync::Arc;
99

10-
pub struct Microphone(AudioInfo);
10+
pub struct Microphone(AudioInfo, Arc<MicrophoneFeedLock>);
1111

1212
impl AudioSource for Microphone {
1313
type Config = Arc<MicrophoneFeedLock>;
1414

1515
fn setup(
16-
config: Self::Config,
16+
feed_lock: Self::Config,
1717
mut audio_tx: mpsc::Sender<AudioFrame>,
1818
_: &mut crate::SetupCtx,
1919
) -> impl Future<Output = anyhow::Result<Self>> + 'static
2020
where
2121
Self: Sized,
2222
{
2323
async move {
24-
let audio_info = config.audio_info();
24+
let audio_info = feed_lock.audio_info();
2525
let (tx, rx) = flume::bounded(8);
2626

27-
config
27+
feed_lock
2828
.ask(microphone::AddSender(tx))
2929
.await
3030
.map_err(|e| anyhow!("Failed to add camera sender: {e}"))?;
@@ -40,7 +40,7 @@ impl AudioSource for Microphone {
4040
}
4141
});
4242

43-
Ok(Self(audio_info))
43+
Ok(Self(audio_info, feed_lock))
4444
}
4545
}
4646

0 commit comments

Comments
 (0)