X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=videoplayer%2Fsrc%2Fvideodec.rs;h=ac60466be8fa4827f78b964bcf40f14cb5d1a814;hb=37f130a74415deaf920b04209e1c334a8876c381;hp=0a1dcd59220737411ef82e68a5c58f6f46a6327c;hpb=b5053bfc25fb327776886269e615c2e5dd63fa08;p=nihav-player.git diff --git a/videoplayer/src/videodec.rs b/videoplayer/src/videodec.rs index 0a1dcd5..ac60466 100644 --- a/videoplayer/src/videodec.rs +++ b/videoplayer/src/videodec.rs @@ -10,10 +10,11 @@ use nihav_core::formats::*; use nihav_core::codecs::*; use nihav_core::scale::*; -use super::{DecoderStuff, DispQueue, FrameRecord, PktSendEvent, FRAME_QUEUE_LEN}; +use super::{DecoderStuff, DecoderType, 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); pub const FRAME_QUEUE_SIZE: usize = 25; @@ -91,29 +92,134 @@ impl VideoDecoder { Some((opic, time)) } pub fn next_frame(&mut self, pkt: &NAPacket) -> Option { - if let Ok(frm) = self.dec.dec.decode(&mut self.dec.dsupp, pkt) { - self.dec.reord.add_frame(frm); - while let Some(frm) = self.dec.reord.get_frame() { - let bt = frm.get_buffer(); - if let NABufferType::None = bt { continue; } - let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0)); - return self.convert_buf(bt, ts); - } - } + match self.dec.dec { + DecoderType::Video(ref mut vdec, ref mut reord) => { + if let Ok(frm) = vdec.decode(&mut self.dec.dsupp, pkt) { + reord.add_frame(frm); + while let Some(frm) = reord.get_frame() { + let bt = frm.get_buffer(); + if let NABufferType::None = bt { continue; } + let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0)); + return self.convert_buf(bt, ts); + } + } + }, + DecoderType::VideoMT(ref mut vdec, ref mut reord) => { + let queue_id = reord.register_frame(); + match vdec.queue_pkt(&mut self.dec.dsupp, &pkt, queue_id) { + Ok(true) => {}, + Ok(false) => { + while !vdec.can_take_input() || vdec.has_output() { + match vdec.get_frame() { + (Ok(frm), id) => { + reord.add_frame(frm, id); + }, + (Err(err), id) => { + reord.drop_frame(id); + panic!("frame {} decoding error {:?}", id, err); + }, + }; + } + match vdec.queue_pkt(&mut self.dec.dsupp, &pkt, queue_id) { + Ok(true) => {}, + Ok(false) => panic!("still can't queue frame!"), + Err(err) => panic!("queueing error {:?}", err), + }; + }, + Err(err) => panic!("queueing error {:?}", err), + }; + while let Some(frm) = reord.get_frame() { + let bt = frm.get_buffer(); + if let NABufferType::None = bt { continue; } + let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0)); + return self.convert_buf(bt, ts); + } + }, + _ => panic!("not a video decoder!"), + }; + None + } + pub fn more_frames(&mut self, do_not_wait: bool) -> Option { + match self.dec.dec { + DecoderType::Video(ref mut _dec, ref mut reord) => { + while let Some(frm) = reord.get_frame() { + let bt = frm.get_buffer(); + if let NABufferType::None = bt { continue; } + let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0)); + return self.convert_buf(bt, ts); + } + }, + DecoderType::VideoMT(ref mut vdec, ref mut reord) => { + let mut got_some = false; + while vdec.has_output() { + match vdec.get_frame() { + (Ok(frm), id) => { + reord.add_frame(frm, id); + got_some = true; + }, + (Err(err), id) => { + reord.drop_frame(id); + panic!("frame {} decoding error {:?}", id, err); + }, + }; + } + if !got_some && !do_not_wait { + match vdec.get_frame() { + (Ok(frm), id) => { + reord.add_frame(frm, id); + }, + (Err(DecoderError::NoFrame), _) => {}, + (Err(err), id) => { + reord.drop_frame(id); + panic!("frame {} decoding error {:?}", id, err); + }, + }; + } + while let Some(frm) = reord.get_frame() { + let bt = frm.get_buffer(); + if let NABufferType::None = bt { continue; } + let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0)); + return self.convert_buf(bt, ts); + } + }, + _ => {}, + }; None } pub fn last_frame(&mut self) -> Option { - while let Some(frm) = self.dec.reord.get_last_frames() { - let bt = frm.get_buffer(); - if let NABufferType::None = bt { continue; } - let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0)); - return self.convert_buf(bt, ts); - } + match self.dec.dec { + DecoderType::Video(ref mut _dec, ref mut reord) => { + while let Some(frm) = reord.get_last_frames() { + let bt = frm.get_buffer(); + if let NABufferType::None = bt { continue; } + let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0)); + return self.convert_buf(bt, ts); + } + }, + DecoderType::VideoMT(ref mut _dec, ref mut reord) => { + while let Some(frm) = reord.get_last_frames() { + let bt = frm.get_buffer(); + if let NABufferType::None = bt { continue; } + let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0)); + return self.convert_buf(bt, ts); + } + }, + _ => {}, + }; None } pub fn flush(&mut self) { - self.dec.dec.flush(); - self.dec.reord.flush(); + match self.dec.dec { + DecoderType::Video(ref mut dec, ref mut reord) => { + dec.flush(); + reord.flush(); + }, + DecoderType::VideoMT(ref mut dec, ref mut reord) => { + dec.flush(); + reord.flush(); + }, + _ => {}, + }; } } @@ -129,7 +235,16 @@ fn start_video_decoding(width: usize, height: usize, tb_num: u32, tb_den: u32, v if let Some((buf, time)) = vdec.next_frame(&pkt) { vfsend.send((buf, time)).unwrap(); } + while let Some((buf, time)) = vdec.more_frames(true) { + vfsend.send((buf, time)).unwrap(); + } + } + }, + Ok(PktSendEvent::GetFrames) => { + while let Some((buf, time)) = vdec.more_frames(false) { + vfsend.send((buf, time)).unwrap(); } + GET_FRAMES_END.store(true, Ordering::Relaxed); }, Ok(PktSendEvent::Flush) => { vdec.flush(); @@ -152,10 +267,12 @@ fn start_video_decoding(width: usize, height: usize, tb_num: u32, tb_den: u32, v }, Ok(PktSendEvent::HurryUp) => { skip_mode = skip_mode.advance(); - vdec.dec.dec.set_options(&[NAOption{ + if let DecoderType::Video(ref mut dec, ref mut _reord) = vdec.dec.dec { + dec.set_options(&[NAOption{ name: FRAME_SKIP_OPTION, value: NAValue::String(skip_mode.to_string()), }]); + } }, Err(_) => { break; @@ -286,6 +403,15 @@ impl VideoControl { pub fn is_video_end(&self) -> bool { VIDEO_END.load(Ordering::Relaxed) } + pub fn wait_for_frames(&mut self) { + GET_FRAMES_END.store(false, Ordering::Relaxed); + self.try_send_event(PktSendEvent::GetFrames); + while !self.try_send_queued() { + } + while !GET_FRAMES_END.load(Ordering::Relaxed) { + thread::yield_now(); + } + } pub fn is_yuv(&self) -> bool { self.do_yuv }