Skip to content

Commit d966f2d

Browse files
committed
fallback to ffmpeg encoder in instant mode too
1 parent c9a8155 commit d966f2d

File tree

7 files changed

+240
-216
lines changed

7 files changed

+240
-216
lines changed

crates/enc-mediafoundation/examples/cli.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod win {
99
use cap_enc_mediafoundation::{
1010
d3d::create_d3d_device,
1111
media::MF_VERSION,
12-
video::{H264Encoder, SampleWriter, VideoEncoderInputSample},
12+
video::{H264Encoder, InputSample, SampleWriter},
1313
};
1414
use clap::Parser;
1515
use scap_targets::Display;
@@ -107,10 +107,7 @@ mod win {
107107
Duration: frame_time.Duration - first_time.Duration,
108108
};
109109

110-
let _ = frame_tx.send(Some(VideoEncoderInputSample::new(
111-
timestamp,
112-
frame.texture().clone(),
113-
)));
110+
let _ = frame_tx.send(Some(frame));
114111

115112
Ok(())
116113
}
@@ -156,7 +153,13 @@ mod win {
156153
break;
157154
};
158155

159-
if video_encoder.handle_needs_input(frame).is_err() {
156+
if video_encoder
157+
.handle_needs_input(
158+
frame.texture(),
159+
frame.inner().SystemRelativeTime().unwrap(),
160+
)
161+
.is_err()
162+
{
160163
break;
161164
}
162165
}

crates/enc-mediafoundation/src/video/h264.rs

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,6 @@ use crate::{
3434
video::{NewVideoProcessorError, VideoProcessor},
3535
};
3636

37-
pub struct VideoEncoderInputSample {
38-
timestamp: TimeSpan,
39-
texture: ID3D11Texture2D,
40-
}
41-
42-
impl VideoEncoderInputSample {
43-
pub fn new(timestamp: TimeSpan, texture: ID3D11Texture2D) -> Self {
44-
Self { timestamp, texture }
45-
}
46-
}
47-
4837
pub struct VideoEncoderOutputSample {
4938
sample: IMFSample,
5039
}
@@ -68,6 +57,8 @@ pub struct H264Encoder {
6857
output_stream_id: u32,
6958
output_type: IMFMediaType,
7059
bitrate: u32,
60+
61+
first_time: Option<TimeSpan>,
7162
}
7263

7364
#[derive(Clone, Debug, thiserror::Error)]
@@ -93,17 +84,17 @@ pub enum NewVideoEncoderError {
9384
unsafe impl Send for H264Encoder {}
9485

9586
impl H264Encoder {
96-
/// Recommended bitrate multipler: 0.05-0.1
97-
pub fn new(
87+
pub fn new_with_scaled_output(
9888
d3d_device: &ID3D11Device,
9989
format: DXGI_FORMAT,
100-
resolution: SizeInt32,
90+
input_resolution: SizeInt32,
91+
output_resolution: SizeInt32,
10192
frame_rate: u32,
10293
bitrate_multipler: f32,
10394
) -> Result<Self, NewVideoEncoderError> {
10495
let bitrate = calculate_bitrate(
105-
resolution.Width as u32,
106-
resolution.Height as u32,
96+
output_resolution.Width as u32,
97+
output_resolution.Height as u32,
10798
frame_rate,
10899
bitrate_multipler,
109100
);
@@ -119,9 +110,9 @@ impl H264Encoder {
119110
let video_processor = VideoProcessor::new(
120111
d3d_device.clone(),
121112
format,
122-
resolution,
113+
input_resolution,
123114
DXGI_FORMAT_NV12,
124-
resolution,
115+
output_resolution,
125116
frame_rate,
126117
)
127118
.map_err(NewVideoEncoderError::VideoProcessor)?;
@@ -219,10 +210,10 @@ impl H264Encoder {
219210
MFSetAttributeSize(
220211
&attributes,
221212
&MF_MT_FRAME_SIZE,
222-
resolution.Width as u32,
223-
resolution.Height as u32,
213+
output_resolution.Width as u32,
214+
output_resolution.Height as u32,
224215
)?;
225-
MFSetAttributeRatio(&attributes, &MF_MT_FRAME_RATE, 60, 1)?;
216+
MFSetAttributeRatio(&attributes, &MF_MT_FRAME_RATE, frame_rate, 1)?;
226217
MFSetAttributeRatio(&attributes, &MF_MT_PIXEL_ASPECT_RATIO, 1, 1)?;
227218
output_type.SetUINT32(&MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive.0 as u32)?;
228219
output_type.SetUINT32(&MF_MT_ALL_SAMPLES_INDEPENDENT, 1)?;
@@ -248,10 +239,10 @@ impl H264Encoder {
248239
MFSetAttributeSize(
249240
&attributes,
250241
&MF_MT_FRAME_SIZE,
251-
resolution.Width as u32,
252-
resolution.Height as u32,
242+
output_resolution.Width as u32,
243+
output_resolution.Height as u32,
253244
)?;
254-
MFSetAttributeRatio(&attributes, &MF_MT_FRAME_RATE, 60, 1)?;
245+
MFSetAttributeRatio(&attributes, &MF_MT_FRAME_RATE, frame_rate, 1)?;
255246
let result = transform.SetInputType(
256247
input_stream_id,
257248
&input_type,
@@ -292,9 +283,27 @@ impl H264Encoder {
292283
bitrate,
293284

294285
output_type,
286+
first_time: None,
295287
})
296288
}
297289

290+
pub fn new(
291+
d3d_device: &ID3D11Device,
292+
format: DXGI_FORMAT,
293+
resolution: SizeInt32,
294+
frame_rate: u32,
295+
bitrate_multipler: f32,
296+
) -> Result<Self, NewVideoEncoderError> {
297+
Self::new_with_scaled_output(
298+
d3d_device,
299+
format,
300+
resolution,
301+
resolution,
302+
frame_rate,
303+
bitrate_multipler,
304+
)
305+
}
306+
298307
pub fn bitrate(&self) -> u32 {
299308
self.bitrate
300309
}
@@ -370,9 +379,12 @@ impl H264Encoder {
370379

371380
pub fn handle_needs_input(
372381
&mut self,
373-
sample: VideoEncoderInputSample,
382+
texture: &ID3D11Texture2D,
383+
timestamp: TimeSpan,
374384
) -> windows::core::Result<()> {
375-
self.video_processor.process_texture(&sample.texture)?;
385+
self.video_processor.process_texture(texture)?;
386+
387+
let first_time = self.first_time.get_or_insert(timestamp);
376388

377389
let input_buffer = unsafe {
378390
MFCreateDXGISurfaceBuffer(
@@ -385,7 +397,7 @@ impl H264Encoder {
385397
let mf_sample = unsafe { MFCreateSample()? };
386398
unsafe {
387399
mf_sample.AddBuffer(&input_buffer)?;
388-
mf_sample.SetSampleTime(sample.timestamp.Duration)?;
400+
mf_sample.SetSampleTime(timestamp.Duration - first_time.Duration)?;
389401
self.transform
390402
.ProcessInput(self.input_stream_id, &mf_sample, 0)?;
391403
};

crates/mediafoundation-ffmpeg/src/h264.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ impl H264StreamMuxer {
8080
}
8181

8282
/// Write an H264 sample from MediaFoundation to the output
83-
#[cfg(windows)]
8483
pub fn write_sample(
8584
&mut self,
8685
sample: &IMFSample,

crates/recording/examples/recording-cli.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub async fn main() {
2222

2323
info!("Recording to directory '{}'", dir.path().display());
2424

25-
let (handle, _ready_rx) = cap_recording::instant_recording::spawn_instant_recording_actor(
25+
let (handle, _ready_rx) = cap_recording::spawn_studio_recording_actor(
2626
"test".to_string(),
2727
dir.path().into(),
2828
RecordingBaseInputs {
@@ -33,6 +33,7 @@ pub async fn main() {
3333
camera_feed: None,
3434
mic_feed: None,
3535
},
36+
false,
3637
// true,
3738
)
3839
.await

0 commit comments

Comments
 (0)