Calculate video drift all the way in application update
This commit is contained in:
parent
56e3939861
commit
b3689dd693
2 changed files with 32 additions and 24 deletions
26
src/main.rs
26
src/main.rs
|
|
@ -20,7 +20,7 @@ use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process,
|
process,
|
||||||
sync::{mpsc, Arc, Mutex},
|
sync::{mpsc, Arc, Mutex},
|
||||||
time::Instant,
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use config::{AppTheme, Config, CONFIG_VERSION};
|
use config::{AppTheme, Config, CONFIG_VERSION};
|
||||||
|
|
@ -295,7 +295,7 @@ impl Application for App {
|
||||||
Message::SystemThemeModeChange(_theme_mode) => {
|
Message::SystemThemeModeChange(_theme_mode) => {
|
||||||
return self.update_config();
|
return self.update_config();
|
||||||
}
|
}
|
||||||
Message::Tick(_time) => {
|
Message::Tick(frame_time) => {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
let video_frame_opt = {
|
let video_frame_opt = {
|
||||||
|
|
@ -303,8 +303,11 @@ impl Application for App {
|
||||||
//TODO: show frames at desired presentation time instead of clearing
|
//TODO: show frames at desired presentation time instead of clearing
|
||||||
let mut video_frame_opt = video_frames.pop_front();
|
let mut video_frame_opt = video_frames.pop_front();
|
||||||
while video_frames.len() >= 4 {
|
while video_frames.len() >= 4 {
|
||||||
if let Some(video_frame) = video_frames.pop_front() {
|
if let Some(extra_frame) = video_frames.pop_front() {
|
||||||
video_frame_opt = Some(video_frame);
|
if let Some(old_frame) = video_frame_opt {
|
||||||
|
log::warn!("skipping video frame {:?}", old_frame.0.pts());
|
||||||
|
}
|
||||||
|
video_frame_opt = Some(extra_frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
video_frame_opt
|
video_frame_opt
|
||||||
|
|
@ -312,6 +315,7 @@ impl Application for App {
|
||||||
match video_frame_opt {
|
match video_frame_opt {
|
||||||
Some(video_frame) => {
|
Some(video_frame) => {
|
||||||
let pts = video_frame.0.pts();
|
let pts = video_frame.0.pts();
|
||||||
|
let present_time_opt = video_frame.1;
|
||||||
self.handle_opt = Some(video_frame.into_handle());
|
self.handle_opt = Some(video_frame.into_handle());
|
||||||
|
|
||||||
let duration = start.elapsed();
|
let duration = start.elapsed();
|
||||||
|
|
@ -320,6 +324,20 @@ impl Application for App {
|
||||||
pts,
|
pts,
|
||||||
duration
|
duration
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if let Some(present_time) = present_time_opt {
|
||||||
|
if present_time > frame_time {
|
||||||
|
let ahead = present_time - frame_time;
|
||||||
|
if ahead > Duration::from_millis(1) {
|
||||||
|
log::debug!("video ahead {:?}", ahead);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let behind = frame_time - present_time;
|
||||||
|
if behind > Duration::from_millis(1) {
|
||||||
|
log::debug!("video behind {:?}", behind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ pub enum PlayerMessage {
|
||||||
SeekRelative(f64),
|
SeekRelative(f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VideoFrame(pub Video);
|
pub struct VideoFrame(pub Video, pub Option<Instant>);
|
||||||
|
|
||||||
impl VideoFrame {
|
impl VideoFrame {
|
||||||
pub fn into_handle(self) -> widget::image::Handle {
|
pub fn into_handle(self) -> widget::image::Handle {
|
||||||
|
|
@ -170,8 +170,6 @@ fn ffmpeg_thread<P: AsRef<Path>>(
|
||||||
let video_width = video_decoder.width();
|
let video_width = video_decoder.width();
|
||||||
let video_height = video_decoder.height();
|
let video_height = video_decoder.height();
|
||||||
let (cpu_frame_tx, cpu_frame_rx) = mpsc::channel::<(Video, Option<Instant>)>();
|
let (cpu_frame_tx, cpu_frame_rx) = mpsc::channel::<(Video, Option<Instant>)>();
|
||||||
let min_sleep = Duration::from_millis(1);
|
|
||||||
let min_skip = Duration::from_millis(1);
|
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name("video_scale".to_string())
|
.name("video_scale".to_string())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
|
|
@ -212,27 +210,19 @@ fn ffmpeg_thread<P: AsRef<Path>>(
|
||||||
video_scaler.run(&cpu_frame, &mut scaled_frame).unwrap();
|
video_scaler.run(&cpu_frame, &mut scaled_frame).unwrap();
|
||||||
scaled_frame.set_pts(pts_opt);
|
scaled_frame.set_pts(pts_opt);
|
||||||
|
|
||||||
if let Some(pts) = pts_opt {
|
let present_time_opt = if let Some(pts) = pts_opt {
|
||||||
let expected_float = pts as f64 * video_time_base;
|
let expected_float = pts as f64 * video_time_base;
|
||||||
let expected = Duration::from_secs_f64(expected_float);
|
let expected = Duration::from_secs_f64(expected_float);
|
||||||
if let Some(sync_time) = &sync_time_opt {
|
if let Some(sync_time) = sync_time_opt {
|
||||||
// Sync with audio
|
Some(sync_time + expected)
|
||||||
let actual = sync_time.elapsed();
|
} else {
|
||||||
if expected > actual {
|
None
|
||||||
let sleep = expected - actual;
|
|
||||||
if sleep > min_sleep {
|
|
||||||
log::debug!("video ahead {:?}", sleep);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let skip = actual - expected;
|
|
||||||
if skip > min_skip {
|
|
||||||
log::debug!("video behind {:?}", skip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let video_frame = VideoFrame(scaled_frame);
|
let video_frame = VideoFrame(scaled_frame, present_time_opt);
|
||||||
{
|
{
|
||||||
let mut video_frames = video_frames_lock.lock().unwrap();
|
let mut video_frames = video_frames_lock.lock().unwrap();
|
||||||
video_frames.push_back(video_frame);
|
video_frames.push_back(video_frame);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue