Skip to content

Commit 17169d1

Browse files
committed
more fixes
1 parent a4b8bdd commit 17169d1

File tree

7 files changed

+73
-49
lines changed

7 files changed

+73
-49
lines changed

crates/enc-ffmpeg/src/audio/aac.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ impl AACEncoder {
9191
encoder.set_rate(rate);
9292
encoder.set_format(output_config.sample_format);
9393
encoder.set_channel_layout(output_config.channel_layout());
94-
encoder.set_time_base(output_config.time_base);
94+
encoder.set_time_base(FFRational(1, output_config.rate()));
9595

9696
let encoder = encoder.open()?;
9797

crates/enc-ffmpeg/src/audio/buffered_resampler.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub struct BufferedResampler {
1111
resampler: ffmpeg::software::resampling::Context,
1212
buffer: VecDeque<(ffmpeg::frame::Audio, i64)>,
1313
sample_index: usize,
14+
// used to account for cases where pts is rounded down instead of up
15+
min_next_pts: Option<i64>,
1416
}
1517

1618
impl BufferedResampler {
@@ -19,6 +21,7 @@ impl BufferedResampler {
1921
resampler,
2022
buffer: VecDeque::new(),
2123
sample_index: 0,
24+
min_next_pts: None,
2225
}
2326
}
2427

@@ -46,7 +49,13 @@ impl BufferedResampler {
4649
*self.resampler.output()
4750
}
4851

49-
pub fn add_frame(&mut self, frame: ffmpeg::frame::Audio) {
52+
pub fn add_frame(&mut self, mut frame: ffmpeg::frame::Audio) {
53+
if let Some(min_next_pts) = self.min_next_pts {
54+
if let Some(pts) = frame.pts() {
55+
frame.set_pts(Some(pts.max(min_next_pts)));
56+
}
57+
}
58+
5059
let pts = frame.pts().unwrap();
5160

5261
let mut resampled_frame = ffmpeg::frame::Audio::empty();
@@ -76,6 +85,8 @@ impl BufferedResampler {
7685

7786
next_pts = next_pts + samples as i64;
7887
}
88+
89+
self.min_next_pts = Some(pts + frame.samples() as i64);
7990
}
8091

8192
fn get_frame_inner(&mut self, samples: usize) -> Option<ffmpeg::frame::Audio> {

crates/recording/examples/recording-cli.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@ pub async fn main() {
3636
// .await
3737
// .unwrap();
3838

39-
let (error_tx, _) = flume::bounded(1);
40-
let mic_feed = MicrophoneFeed::spawn(MicrophoneFeed::new(error_tx));
41-
42-
mic_feed
43-
.ask(microphone::SetInput {
44-
label: MicrophoneFeed::default().map(|v| v.0).unwrap(),
45-
})
46-
.await
47-
.unwrap()
48-
.await
49-
.unwrap();
39+
// let (error_tx, _) = flume::bounded(1);
40+
// let mic_feed = MicrophoneFeed::spawn(MicrophoneFeed::new(error_tx));
41+
42+
// mic_feed
43+
// .ask(microphone::SetInput {
44+
// label: MicrophoneFeed::default().map(|v| v.0).unwrap(),
45+
// })
46+
// .await
47+
// .unwrap()
48+
// .await
49+
// .unwrap();
5050

5151
// tokio::time::sleep(Duration::from_millis(10)).await;
5252

crates/recording/src/capture_pipeline.rs

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::{
1515
future::Future,
1616
path::PathBuf,
1717
sync::{Arc, atomic::AtomicBool},
18-
time::{Duration, SystemTime},
18+
time::SystemTime,
1919
};
2020

2121
pub trait MakeCapturePipeline: ScreenCaptureFormat + std::fmt::Debug + 'static {
@@ -395,8 +395,6 @@ impl MakeCapturePipeline for screen_capture::Direct3DCapture {
395395
where
396396
Self: Sized,
397397
{
398-
use std::sync::mpsc;
399-
400398
use cap_enc_ffmpeg::{AACEncoder, AudioEncoder};
401399
use windows::Graphics::SizeInt32;
402400

@@ -490,41 +488,35 @@ impl MakeCapturePipeline for screen_capture::Direct3DCapture {
490488

491489
let output = Arc::new(std::sync::Mutex::new(output));
492490

493-
let (screen_first_tx, screen_first_rx) = mpsc::sync_channel(1);
491+
let (first_frame_tx, first_frame_rx) = tokio::sync::oneshot::channel::<Timestamp>();
494492

495493
if let Some(mut audio_encoder) = audio_encoder {
496494
builder.spawn_source("audio_mixer", audio_mixer);
497495

498-
// let is_done = is_done.clone();
499496
let output = output.clone();
500497
builder.spawn_task("audio_encoding", move |ready| {
501-
let screen_first_offset = loop {
502-
match screen_first_rx.recv_timeout(Duration::from_millis(5)) {
503-
Ok(offset) => {
504-
audio_rx.drain().count();
505-
break offset;
506-
}
507-
Err(mpsc::RecvTimeoutError::Timeout) => continue,
508-
Err(mpsc::RecvTimeoutError::Disconnected) => return Ok(()),
509-
}
510-
};
511-
512498
let _ = ready.send(Ok(()));
513499

500+
let time = first_frame_rx.blocking_recv().unwrap();
501+
let screen_first_offset = time.duration_since(start_time);
502+
514503
while let Ok((mut frame, timestamp)) = audio_rx.recv() {
515504
let ts_offset = timestamp.duration_since(start_time);
505+
dbg!(ts_offset);
516506

517507
let Some(ts_offset) = ts_offset.checked_sub(screen_first_offset) else {
518508
continue;
519509
};
520510

521511
let pts = (ts_offset.as_secs_f64() * frame.rate() as f64) as i64;
522512
frame.set_pts(Some(pts));
513+
dbg!(pts);
523514

524515
if let Ok(mut output) = output.lock() {
525-
audio_encoder.queue_frame(frame, &mut *output);
516+
audio_encoder.queue_frame(frame, &mut output)
526517
}
527518
}
519+
528520
Ok(())
529521
});
530522
}
@@ -540,7 +532,7 @@ impl MakeCapturePipeline for screen_capture::Direct3DCapture {
540532

541533
let _ = ready.send(Ok(()));
542534

543-
let mut screen_first_tx = Some(screen_first_tx);
535+
let mut first_frame_tx = Some(first_frame_tx);
544536

545537
while let Ok(e) = encoder.get_event() {
546538
match e {
@@ -560,9 +552,8 @@ impl MakeCapturePipeline for screen_capture::Direct3DCapture {
560552
PerformanceCounterTimestamp::new(frame_time.Duration),
561553
);
562554

563-
if let Some(screen_first_tx) = screen_first_tx.take() {
564-
let _ = screen_first_tx
565-
.try_send(timestamp.duration_since(start_time));
555+
if let Some(first_frame_tx) = first_frame_tx.take() {
556+
let _ = first_frame_tx.send(timestamp);
566557
}
567558

568559
encoder

crates/recording/src/sources/audio_mixer.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ impl AudioMixerBuilder {
116116
_filter_graph: filter_graph,
117117
_amix: amix,
118118
_aformat: aformat,
119+
start_timestamp: None,
120+
timestamps: Timestamps::now(),
119121
})
120122
}
121123
}
@@ -131,6 +133,8 @@ pub struct AudioMixer {
131133
_filter_graph: ffmpeg::filter::Graph,
132134
_amix: ffmpeg::filter::Context,
133135
_aformat: ffmpeg::filter::Context,
136+
timestamps: Timestamps,
137+
start_timestamp: Option<Timestamp>,
134138
}
135139

136140
impl AudioMixer {
@@ -141,15 +145,15 @@ impl AudioMixer {
141145
);
142146
pub const BUFFER_TIMEOUT: Duration = Duration::from_millis(10);
143147

144-
fn buffer_sources(&mut self, start: Timestamps) {
148+
fn buffer_sources(&mut self) {
145149
for source in &mut self.sources {
146150
let rate = source.info.rate();
147151

148152
while let Ok((frame, timestamp)) = source.rx.try_recv() {
149153
// if gap between incoming and last, insert silence
150154
if let Some((buffer_last_timestamp, buffer_last_duration)) = source.buffer_last {
151-
let timestamp_elapsed = timestamp.duration_since(start);
152-
let buffer_last_elapsed = buffer_last_timestamp.duration_since(start);
155+
let timestamp_elapsed = timestamp.duration_since(self.timestamps);
156+
let buffer_last_elapsed = buffer_last_timestamp.duration_since(self.timestamps);
153157

154158
if timestamp_elapsed > buffer_last_elapsed {
155159
let elapsed_since_last_frame = timestamp_elapsed - buffer_last_elapsed;
@@ -158,9 +162,9 @@ impl AudioMixer {
158162
&& buffer_last_duration - elapsed_since_last_frame
159163
>= Duration::from_millis(1)
160164
{
161-
let gap = (buffer_last_timestamp.duration_since(start)
165+
let gap = (buffer_last_timestamp.duration_since(self.timestamps)
162166
+ buffer_last_duration)
163-
- timestamp.duration_since(start);
167+
- timestamp.duration_since(self.timestamps);
164168

165169
debug!("Gap between last buffer frame, inserting {gap:?} of silence");
166170

@@ -183,7 +187,7 @@ impl AudioMixer {
183187
}
184188
}
185189
} else {
186-
let gap = timestamp.duration_since(start);
190+
let gap = timestamp.duration_since(self.timestamps);
187191

188192
if !gap.is_zero() {
189193
debug!("Gap from beginning of stream, inserting {gap:?} of silence");
@@ -210,8 +214,9 @@ impl AudioMixer {
210214

211215
frame.set_rate(rate as u32);
212216

213-
let timestamp =
214-
Timestamp::Instant(start.instant() + chunk_duration * i as u32);
217+
let timestamp = Timestamp::Instant(
218+
self.timestamps.instant() + chunk_duration * i as u32,
219+
);
215220
source.buffer_last = Some((timestamp, chunk_duration));
216221
source.buffer.push_back((frame, timestamp));
217222
}
@@ -233,14 +238,15 @@ impl AudioMixer {
233238
let duration =
234239
Duration::from_secs_f64(leftover_chunk_size as f64 / rate as f64);
235240
let timestamp = Timestamp::Instant(
236-
start.instant() + chunk_duration * chunks.floor() as u32 + duration,
241+
self.timestamps.instant()
242+
+ chunk_duration * chunks.floor() as u32
243+
+ duration,
237244
);
238245
source.buffer_last = Some((timestamp, duration));
239246
source.buffer.push_back((frame, timestamp));
240247
}
241248
}
242249

243-
// dbg!(frame.samples());
244250
source.buffer_last = Some((
245251
timestamp,
246252
Duration::from_secs_f64(frame.samples() as f64 / frame.rate() as f64),
@@ -251,7 +257,23 @@ impl AudioMixer {
251257
}
252258

253259
fn tick(&mut self, start: Timestamps, now: Instant) -> Result<(), ()> {
254-
self.buffer_sources(start);
260+
self.buffer_sources();
261+
262+
if self.start_timestamp.is_none() {
263+
self.start_timestamp = self
264+
.sources
265+
.iter()
266+
.filter_map(|s| s.buffer.get(0))
267+
.min_by(|a, b| {
268+
a.1.duration_since(self.timestamps)
269+
.cmp(&b.1.duration_since(self.timestamps))
270+
})
271+
.map(|v| v.1);
272+
}
273+
274+
let Some(start_timestamp) = self.start_timestamp else {
275+
return Ok(());
276+
};
255277

256278
for (i, source) in self.sources.iter_mut().enumerate() {
257279
for buffer in source.buffer.drain(..) {
@@ -262,12 +284,10 @@ impl AudioMixer {
262284
let mut filtered = ffmpeg::frame::Audio::empty();
263285
while self.abuffersink.sink().frame(&mut filtered).is_ok() {
264286
let elapsed = Duration::from_secs_f64(self.samples_out as f64 / filtered.rate() as f64);
265-
let timestamp = start.instant() + elapsed;
287+
let timestamp = start.instant() + start_timestamp.duration_since(start) + elapsed;
266288

267289
self.samples_out += filtered.samples();
268290

269-
// dbg!(filtered.samples(), timestamp);
270-
271291
if self
272292
.output
273293
.send((filtered, Timestamp::Instant(timestamp)))

crates/recording/src/sources/screen_capture/windows.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,8 @@ pub mod audio {
487487

488488
let timestamp = Timestamp::from_cpal(info.timestamp().capture);
489489

490+
dbg!(timestamp);
491+
490492
let _ = audio_tx.send((data.as_ffmpeg(config), timestamp));
491493
},
492494
move |e| {

crates/recording/src/studio_recording.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ async fn create_segment_pipeline(
861861

862862
let elapsed = timestamp.duration_since(start_time)
863863
- first_timestamp.duration_since(start_time);
864-
frame.set_pts(Some((elapsed.as_secs_f64() * rate) as i64));
864+
frame.set_pts(Some(dbg!(elapsed.as_secs_f64() * rate).round() as i64));
865865

866866
output.queue_frame(frame);
867867
}

0 commit comments

Comments
 (0)