Skip to content

Commit 82361aa

Browse files
committed
Add Windows-specific fragmented muxer support
1 parent 5960feb commit 82361aa

3 files changed

Lines changed: 36 additions & 17 deletions

File tree

crates/enc-ffmpeg/src/mux/segmented_stream.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,19 @@ impl SegmentedVideoEncoder {
148148

149149
let mut output = format::output_as(&manifest_path, "dash")?;
150150

151+
let init_seg_path = base_path.join(INIT_SEGMENT_NAME);
152+
let media_seg_pattern = base_path.join("segment_$Number%03d$.m4s");
153+
154+
#[cfg(windows)]
155+
let init_seg_str = init_seg_path.to_string_lossy().replace('\\', "/");
156+
#[cfg(windows)]
157+
let media_seg_str = media_seg_pattern.to_string_lossy().replace('\\', "/");
158+
159+
#[cfg(not(windows))]
160+
let init_seg_str = init_seg_path.to_string_lossy().to_string();
161+
#[cfg(not(windows))]
162+
let media_seg_str = media_seg_pattern.to_string_lossy().to_string();
163+
151164
unsafe {
152165
let opts = output.as_mut_ptr();
153166

@@ -157,8 +170,8 @@ impl SegmentedVideoEncoder {
157170
ffmpeg::ffi::av_opt_set((*opts).priv_data, k.as_ptr(), v.as_ptr(), 0);
158171
};
159172

160-
set_opt("init_seg_name", INIT_SEGMENT_NAME);
161-
set_opt("media_seg_name", "segment_$Number%03d$.m4s");
173+
set_opt("init_seg_name", &init_seg_str);
174+
set_opt("media_seg_name", &media_seg_str);
162175
set_opt(
163176
"seg_duration",
164177
&config.segment_duration.as_secs_f64().to_string(),

crates/recording/src/capture_pipeline.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ use crate::{
88

99
#[cfg(target_os = "macos")]
1010
use crate::output_pipeline::{MacOSFragmentedM4SMuxer, MacOSFragmentedM4SMuxerConfig};
11+
#[cfg(windows)]
12+
use crate::output_pipeline::{WindowsFragmentedM4SMuxer, WindowsFragmentedM4SMuxerConfig};
13+
#[cfg(windows)]
14+
use cap_enc_ffmpeg::h264::H264Preset;
1115
use anyhow::anyhow;
1216
use cap_timestamp::Timestamps;
1317
use std::{path::PathBuf, sync::Arc};
@@ -136,11 +140,9 @@ impl MakeCapturePipeline for screen_capture::Direct3DCapture {
136140
output_path: PathBuf,
137141
start_time: Timestamps,
138142
fragmented: bool,
139-
_shared_pause_state: Option<SharedPauseState>,
143+
shared_pause_state: Option<SharedPauseState>,
140144
encoder_preferences: EncoderPreferences,
141145
) -> anyhow::Result<OutputPipeline> {
142-
let d3d_device = screen_capture.d3d_device.clone();
143-
144146
if fragmented {
145147
let fragments_dir = output_path
146148
.parent()
@@ -150,17 +152,15 @@ impl MakeCapturePipeline for screen_capture::Direct3DCapture {
150152
OutputPipeline::builder(fragments_dir)
151153
.with_video::<screen_capture::VideoSource>(screen_capture)
152154
.with_timestamps(start_time)
153-
.build::<WindowsSegmentedMuxer>(WindowsSegmentedMuxerConfig {
154-
pixel_format: screen_capture::Direct3DCapture::PIXEL_FORMAT.as_dxgi(),
155-
d3d_device,
156-
bitrate_multiplier: 0.15f32,
157-
frame_rate: 30u32,
158-
output_size: None,
159-
encoder_preferences,
155+
.build::<WindowsFragmentedM4SMuxer>(WindowsFragmentedM4SMuxerConfig {
160156
segment_duration: std::time::Duration::from_secs(3),
157+
preset: H264Preset::Ultrafast,
158+
output_size: None,
159+
shared_pause_state,
161160
})
162161
.await
163162
} else {
163+
let d3d_device = screen_capture.d3d_device.clone();
164164
OutputPipeline::builder(output_path.clone())
165165
.with_video::<screen_capture::VideoSource>(screen_capture)
166166
.with_timestamps(start_time)

crates/recording/src/studio_recording.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ use crate::output_pipeline::{
1919

2020
#[cfg(windows)]
2121
use crate::output_pipeline::{
22-
WindowsCameraMuxer, WindowsCameraMuxerConfig, WindowsSegmentedCameraMuxer,
23-
WindowsSegmentedCameraMuxerConfig,
22+
WindowsCameraMuxer, WindowsCameraMuxerConfig, WindowsFragmentedM4SCameraMuxer,
23+
WindowsFragmentedM4SCameraMuxerConfig,
2424
};
2525
use anyhow::{Context as _, anyhow, bail};
2626
use cap_media_info::VideoInfo;
@@ -877,7 +877,13 @@ async fn create_segment_pipeline(
877877
};
878878

879879
#[cfg(windows)]
880-
let shared_pause_state: Option<SharedPauseState> = None;
880+
let shared_pause_state = if fragmented {
881+
Some(SharedPauseState::new(Arc::new(
882+
std::sync::atomic::AtomicBool::new(false),
883+
)))
884+
} else {
885+
None
886+
};
881887

882888
let screen = ScreenCaptureMethod::make_studio_mode_pipeline(
883889
capture_source,
@@ -925,8 +931,8 @@ async fn create_segment_pipeline(
925931
OutputPipeline::builder(fragments_dir)
926932
.with_video::<sources::NativeCamera>(camera_feed)
927933
.with_timestamps(start_time)
928-
.build::<WindowsSegmentedCameraMuxer>(WindowsSegmentedCameraMuxerConfig {
929-
encoder_preferences: encoder_preferences.clone(),
934+
.build::<WindowsFragmentedM4SCameraMuxer>(WindowsFragmentedM4SCameraMuxerConfig {
935+
shared_pause_state: shared_pause_state.clone(),
930936
..Default::default()
931937
})
932938
.instrument(error_span!("camera-out"))

0 commit comments

Comments
 (0)