only pull preroll on pause
This commit is contained in:
parent
b4fceafe1f
commit
82dea04f5b
2 changed files with 17 additions and 21 deletions
36
src/video.rs
36
src/video.rs
|
@ -58,7 +58,7 @@ pub(crate) struct Internal {
|
||||||
pub(crate) frame: Arc<Mutex<Vec<u8>>>,
|
pub(crate) frame: Arc<Mutex<Vec<u8>>>,
|
||||||
pub(crate) upload_frame: Arc<AtomicBool>,
|
pub(crate) upload_frame: Arc<AtomicBool>,
|
||||||
pub(crate) last_frame_time: Arc<Mutex<Instant>>,
|
pub(crate) last_frame_time: Arc<Mutex<Instant>>,
|
||||||
pub(crate) paused: bool,
|
pub(crate) paused: Arc<AtomicBool>,
|
||||||
pub(crate) looping: bool,
|
pub(crate) looping: bool,
|
||||||
pub(crate) is_eos: bool,
|
pub(crate) is_eos: bool,
|
||||||
pub(crate) restart_stream: bool,
|
pub(crate) restart_stream: bool,
|
||||||
|
@ -132,7 +132,7 @@ impl Internal {
|
||||||
gst::State::Playing
|
gst::State::Playing
|
||||||
})
|
})
|
||||||
.unwrap(/* state was changed in ctor; state errors caught there */);
|
.unwrap(/* state was changed in ctor; state errors caught there */);
|
||||||
self.paused = paused;
|
self.paused.store(paused, Ordering::SeqCst);
|
||||||
|
|
||||||
// Set restart_stream flag to make the stream restart on the next Message::NextFrame
|
// Set restart_stream flag to make the stream restart on the next Message::NextFrame
|
||||||
if self.is_eos && !paused {
|
if self.is_eos && !paused {
|
||||||
|
@ -174,7 +174,7 @@ impl Video {
|
||||||
pub fn new(uri: &url::Url) -> Result<Self, Error> {
|
pub fn new(uri: &url::Url) -> Result<Self, Error> {
|
||||||
gst::init()?;
|
gst::init()?;
|
||||||
|
|
||||||
let pipeline = format!("playbin uri=\"{}\" video-sink=\"videoscale ! videoconvert ! appsink name=iced_video caps=video/x-raw,format=NV12,pixel-aspect-ratio=1/1\"", uri.as_str());
|
let pipeline = format!("playbin uri=\"{}\" video-sink=\"videoscale ! videoconvert ! appsink name=iced_video drop=true caps=video/x-raw,format=NV12,pixel-aspect-ratio=1/1\"", uri.as_str());
|
||||||
let pipeline = gst::parse::launch(pipeline.as_ref())?
|
let pipeline = gst::parse::launch(pipeline.as_ref())?
|
||||||
.downcast::<gst::Pipeline>()
|
.downcast::<gst::Pipeline>()
|
||||||
.map_err(|_| Error::Cast)?;
|
.map_err(|_| Error::Cast)?;
|
||||||
|
@ -249,30 +249,26 @@ impl Video {
|
||||||
let upload_frame = Arc::new(AtomicBool::new(false));
|
let upload_frame = Arc::new(AtomicBool::new(false));
|
||||||
let alive = Arc::new(AtomicBool::new(true));
|
let alive = Arc::new(AtomicBool::new(true));
|
||||||
let last_frame_time = Arc::new(Mutex::new(Instant::now()));
|
let last_frame_time = Arc::new(Mutex::new(Instant::now()));
|
||||||
|
let paused = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
let pipeline_ref = pipeline.clone();
|
|
||||||
let frame_ref = Arc::clone(&frame);
|
let frame_ref = Arc::clone(&frame);
|
||||||
let upload_frame_ref = Arc::clone(&upload_frame);
|
let upload_frame_ref = Arc::clone(&upload_frame);
|
||||||
let alive_ref = Arc::clone(&alive);
|
let alive_ref = Arc::clone(&alive);
|
||||||
let last_frame_time_ref = Arc::clone(&last_frame_time);
|
let last_frame_time_ref = Arc::clone(&last_frame_time);
|
||||||
|
let paused_ref = Arc::clone(&paused);
|
||||||
|
|
||||||
let worker = std::thread::spawn(move || {
|
let worker = std::thread::spawn(move || {
|
||||||
while alive_ref.load(Ordering::Acquire) {
|
while alive_ref.load(Ordering::Acquire) {
|
||||||
let frame_interval = std::time::Duration::from_secs_f64(1.0 / framerate);
|
|
||||||
|
|
||||||
let state = pipeline_ref.state(None).1;
|
|
||||||
if state != gst::State::Playing {
|
|
||||||
// otherwise thread will busy loop pulling preroll
|
|
||||||
std::thread::sleep(2 * frame_interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(gst::FlowError::Error) = (|| -> Result<(), gst::FlowError> {
|
if let Err(gst::FlowError::Error) = (|| -> Result<(), gst::FlowError> {
|
||||||
let timeout =
|
let sample = if paused_ref.load(Ordering::SeqCst) {
|
||||||
gst::ClockTime::from_nseconds(2 * frame_interval.as_nanos() as u64);
|
app_sink
|
||||||
let sample = app_sink
|
.try_pull_preroll(gst::ClockTime::from_mseconds(16))
|
||||||
.try_pull_sample(timeout)
|
.ok_or(gst::FlowError::Eos)?
|
||||||
.or_else(|| app_sink.try_pull_preroll(timeout))
|
} else {
|
||||||
.ok_or(gst::FlowError::Eos)?;
|
app_sink
|
||||||
|
.try_pull_sample(gst::ClockTime::from_mseconds(16))
|
||||||
|
.ok_or(gst::FlowError::Eos)?
|
||||||
|
};
|
||||||
|
|
||||||
let buffer = sample.buffer().ok_or(gst::FlowError::Error)?;
|
let buffer = sample.buffer().ok_or(gst::FlowError::Error)?;
|
||||||
let map = buffer.map_readable().map_err(|_| gst::FlowError::Error)?;
|
let map = buffer.map_readable().map_err(|_| gst::FlowError::Error)?;
|
||||||
|
@ -311,7 +307,7 @@ impl Video {
|
||||||
frame,
|
frame,
|
||||||
upload_frame,
|
upload_frame,
|
||||||
last_frame_time,
|
last_frame_time,
|
||||||
paused: false,
|
paused,
|
||||||
looping: false,
|
looping: false,
|
||||||
is_eos: false,
|
is_eos: false,
|
||||||
restart_stream: false,
|
restart_stream: false,
|
||||||
|
@ -375,7 +371,7 @@ impl Video {
|
||||||
|
|
||||||
/// Get if the media is paused or not.
|
/// Get if the media is paused or not.
|
||||||
pub fn paused(&self) -> bool {
|
pub fn paused(&self) -> bool {
|
||||||
self.0.borrow().paused
|
self.0.borrow().paused.load(Ordering::SeqCst)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Jumps to a specific position in the media.
|
/// Jumps to a specific position in the media.
|
||||||
|
|
|
@ -204,7 +204,7 @@ where
|
||||||
let mut inner = self.video.0.borrow_mut();
|
let mut inner = self.video.0.borrow_mut();
|
||||||
|
|
||||||
if let iced::Event::Window(iced::window::Event::RedrawRequested(_)) = event {
|
if let iced::Event::Window(iced::window::Event::RedrawRequested(_)) = event {
|
||||||
if inner.restart_stream || (!inner.is_eos && !inner.paused) {
|
if inner.restart_stream || (!inner.is_eos && !inner.paused.load(Ordering::SeqCst)) {
|
||||||
let mut restart_stream = false;
|
let mut restart_stream = false;
|
||||||
if inner.restart_stream {
|
if inner.restart_stream {
|
||||||
restart_stream = true;
|
restart_stream = true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue