summaryrefslogtreecommitdiffstats
path: root/videoplayer/src/videodec.rs
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2023-06-18 15:28:45 +0200
committerKostya Shishkov <kostya.shishkov@gmail.com>2023-06-18 15:28:45 +0200
commit4e72c04a50ab02f6be479799d5b48161f043ebd2 (patch)
treeb9d489214299145514c7fedead4f57e41ae86f26 /videoplayer/src/videodec.rs
parent0b064d417951df4685eba8cc70a3d1df66334662 (diff)
downloadnihav-player-4e72c04a50ab02f6be479799d5b48161f043ebd2.tar.gz
try to improve state handling in decoding threads
Diffstat (limited to 'videoplayer/src/videodec.rs')
-rw-r--r--videoplayer/src/videodec.rs47
1 files changed, 26 insertions, 21 deletions
diff --git a/videoplayer/src/videodec.rs b/videoplayer/src/videodec.rs
index ac60466..1a34aad 100644
--- a/videoplayer/src/videodec.rs
+++ b/videoplayer/src/videodec.rs
@@ -1,5 +1,4 @@
use std::thread::JoinHandle;
-use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Receiver, SyncSender, TrySendError};
use std::thread;
@@ -10,11 +9,9 @@ use nihav_core::formats::*;
use nihav_core::codecs::*;
use nihav_core::scale::*;
-use super::{DecoderStuff, DecoderType, DispQueue, FrameRecord, PktSendEvent, FRAME_QUEUE_LEN};
+use super::{DecoderStuff, DecoderType, DecoderState, DecodingState, DispQueue, FrameRecord, PktSendEvent, FRAME_QUEUE_LEN};
-static SKIP_VDECODING: AtomicBool = AtomicBool::new(false);
-static VIDEO_END: AtomicBool = AtomicBool::new(false);
-static GET_FRAMES_END: AtomicBool = AtomicBool::new(false);
+static VDEC_STATE: DecoderState = DecoderState::new();
pub const FRAME_QUEUE_SIZE: usize = 25;
@@ -69,7 +66,7 @@ impl VideoDecoder {
let mut opic = if let ColorModel::YUV(_) = self.ifmt.get_format().get_model() {
self.yuv_pool.prealloc_video(self.oinfo_yuv, 2).unwrap();
while self.yuv_pool.get_free().is_none() {
- if SKIP_VDECODING.load(Ordering::Relaxed) {
+ if VDEC_STATE.is_flushing() {
return None;
}
std::thread::yield_now();
@@ -78,7 +75,7 @@ impl VideoDecoder {
} else {
self.rgb_pool.prealloc_video(self.oinfo_rgb, 0).unwrap();
while self.rgb_pool.get_free().is_none() {
- if SKIP_VDECODING.load(Ordering::Relaxed) {
+ if VDEC_STATE.is_flushing() {
return None;
}
std::thread::yield_now();
@@ -225,13 +222,13 @@ impl VideoDecoder {
fn start_video_decoding(width: usize, height: usize, tb_num: u32, tb_den: u32, video_dec: DecoderStuff, vprecv: Receiver<PktSendEvent>, vfsend: SyncSender<(NABufferType, u64)>) -> JoinHandle<()> {
std::thread::Builder::new().name("vdecoder".to_string()).spawn(move ||{
- SKIP_VDECODING.store(false, Ordering::Relaxed);
+ VDEC_STATE.set_state(DecodingState::Waiting);
let mut vdec = VideoDecoder::new(width, height, tb_num, tb_den, video_dec);
let mut skip_mode = FrameSkipMode::None;
loop {
match vprecv.recv() {
Ok(PktSendEvent::Packet(pkt)) => {
- if !SKIP_VDECODING.load(Ordering::Relaxed) {
+ if !VDEC_STATE.is_flushing() {
if let Some((buf, time)) = vdec.next_frame(&pkt) {
vfsend.send((buf, time)).unwrap();
}
@@ -244,11 +241,11 @@ fn start_video_decoding(width: usize, height: usize, tb_num: u32, tb_den: u32, v
while let Some((buf, time)) = vdec.more_frames(false) {
vfsend.send((buf, time)).unwrap();
}
- GET_FRAMES_END.store(true, Ordering::Relaxed);
+ VDEC_STATE.set_state(DecodingState::Waiting);
},
Ok(PktSendEvent::Flush) => {
vdec.flush();
- SKIP_VDECODING.store(false, Ordering::Relaxed);
+ VDEC_STATE.set_state(DecodingState::Waiting);
},
Ok(PktSendEvent::End) => {
while vdec.yuv_pool.get_free().is_some() && vdec.rgb_pool.get_free().is_some() {
@@ -258,11 +255,11 @@ fn start_video_decoding(width: usize, height: usize, tb_num: u32, tb_den: u32, v
}
vfsend.send(ret.unwrap()).unwrap();
}
- VIDEO_END.store(true, Ordering::Relaxed);
+ VDEC_STATE.set_state(DecodingState::End);
break;
},
Ok(PktSendEvent::ImmediateEnd) => {
- VIDEO_END.store(true, Ordering::Relaxed);
+ VDEC_STATE.set_state(DecodingState::End);
break;
},
Ok(PktSendEvent::HurryUp) => {
@@ -335,7 +332,7 @@ impl VideoControl {
let (vpsend, vprecv) = std::sync::mpsc::sync_channel::<PktSendEvent>(0);
let (vfsend, vfrecv) = std::sync::mpsc::sync_channel::<FrameRecord>(FRAME_QUEUE_SIZE - 1);
- VIDEO_END.store(false, Ordering::Relaxed);
+ VDEC_STATE.set_state(DecodingState::Normal);
let vthread = if let Some(video_dec) = video_dec {
start_video_decoding(width, height, tb_num, tb_den, video_dec, vprecv, vfsend)
@@ -351,6 +348,7 @@ impl VideoControl {
_ => {},
};
}
+ VDEC_STATE.set_state(DecodingState::End);
}).unwrap()
};
@@ -364,7 +362,7 @@ impl VideoControl {
}
pub fn flush(&mut self) {
self.vqueue.clear();
- SKIP_VDECODING.store(true, Ordering::Release);
+ VDEC_STATE.set_state(DecodingState::Flush);
for _ in 0..8 {
let _ = self.vfrecv.try_recv();
}
@@ -401,15 +399,22 @@ impl VideoControl {
true
}
pub fn is_video_end(&self) -> bool {
- VIDEO_END.load(Ordering::Relaxed)
+ matches!(VDEC_STATE.get_state(), DecodingState::End | DecodingState::Error)
}
- pub fn wait_for_frames(&mut self) {
- GET_FRAMES_END.store(false, Ordering::Relaxed);
+ pub fn wait_for_frames(&mut self) -> Result<(), ()> {
+ VDEC_STATE.set_state(DecodingState::Prefetch);
self.try_send_event(PktSendEvent::GetFrames);
while !self.try_send_queued() {
}
- while !GET_FRAMES_END.load(Ordering::Relaxed) {
- thread::yield_now();
+ loop {
+ match VDEC_STATE.get_state() {
+ DecodingState::Waiting => {
+ VDEC_STATE.set_state(DecodingState::Normal);
+ return Ok(());
+ },
+ DecodingState::Prefetch => thread::yield_now(),
+ _ => return Err(()),
+ };
}
}
@@ -451,7 +456,7 @@ impl VideoControl {
}
pub fn finish(self) {
- SKIP_VDECODING.store(true, Ordering::Release);
+ VDEC_STATE.set_state(DecodingState::Flush);
for _ in 0..8 {
let _ = self.vfrecv.try_recv();
}