X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=videoplayer%2Fsrc%2Fmain.rs;h=25ddcabe245f7141ac0dced820b9f9a99e808984;hb=HEAD;hp=3126b19da9614bc87b8d37507d76ce87fdae4157;hpb=034bfb625073790210a9561477c2c8e9765843f0;p=nihav-player.git diff --git a/videoplayer/src/main.rs b/videoplayer/src/main.rs index 3126b19..82fb56f 100644 --- a/videoplayer/src/main.rs +++ b/videoplayer/src/main.rs @@ -27,6 +27,9 @@ use nihav_core::demuxers::*; use nihav_registry::register::*; use nihav_allstuff::*; +#[cfg(feature="hwaccel")] +use hwdec_vaapi::*; + mod audiodec; use audiodec::*; mod videodec; @@ -92,6 +95,41 @@ macro_rules! debug_log { ($log: expr; $blk: block) => {}; } +enum ScaleSize { + Auto, + Times(f32), + Fixed(usize, usize) +} + +impl FromStr for ScaleSize { + type Err = (); + fn from_str(s: &str) -> Result { + if matches!(s, "" | "auto") { + Ok(ScaleSize::Auto) + } else if s.ends_with('x') || s.ends_with('X') { + let factor = s[..s.len() - 1].parse::().map_err(|_| ())?; + if factor > 0.0 { + Ok(ScaleSize::Times(factor)) + } else { + Err(()) + } + } else if s.contains('x') | s.contains('X') { + let mut dims = if s.contains('x') { s.split('x') } else { s.split('X') }; + let w = dims.next().unwrap(); + let h = dims.next().unwrap(); + let width = w.parse::().map_err(|_| ())?; + let height = h.parse::().map_err(|_| ())?; + if width > 0 && height > 0 { + Ok(ScaleSize::Fixed(width, height)) + } else { + Err(()) + } + } else { + Err(()) + } + } +} + pub enum PktSendEvent { Packet(NAPacket), GetFrames, @@ -105,6 +143,8 @@ pub enum DecoderType { Audio(Box), Video(Box, Box), VideoMT(Box, MTFrameReorderer), + #[cfg(feature="hwaccel")] + VideoHW(Box), } pub struct DecoderStuff { @@ -303,9 +343,12 @@ struct Player { has_audio: bool, video_str: u32, audio_str: u32, + sc_size: ScaleSize, vthreads: usize, use_mt: bool, + #[cfg(feature="hwaccel")] + use_hwaccel: bool, paused: bool, mute: bool, @@ -340,9 +383,12 @@ impl Player { has_audio: false, video_str: 0, audio_str: 0, + sc_size: ScaleSize::Auto, vthreads: 3, use_mt: true, + #[cfg(feature="hwaccel")] + use_hwaccel: true, paused: false, mute: false, @@ -489,12 +535,13 @@ impl Player { return Ok(true); }, Keycode::Return | Keycode::KpEnter => return Ok(true), - Keycode::Right => { self.seek(10, true, dmx, disp_queue)?; }, - Keycode::Left => { self.seek(10, false, dmx, disp_queue)?; }, - Keycode::Up => { self.seek(60, true, dmx, disp_queue)?; }, - Keycode::Down => { self.seek(60, false, dmx, disp_queue)?; }, - Keycode::PageUp => { self.seek(600, true, dmx, disp_queue)?; }, - Keycode::PageDown => { self.seek(600, false, dmx, disp_queue)?; }, + Keycode::R => { self.seek(0, true, dmx, disp_queue)?; }, + Keycode::Right | Keycode::Kp6 => { self.seek(10, true, dmx, disp_queue)?; }, + Keycode::Left | Keycode::Kp4 => { self.seek(10, false, dmx, disp_queue)?; }, + Keycode::Up | Keycode::Kp8 => { self.seek(60, true, dmx, disp_queue)?; }, + Keycode::Down | Keycode::Kp2 => { self.seek(60, false, dmx, disp_queue)?; }, + Keycode::PageUp | Keycode::Kp9 => { self.seek(600, true, dmx, disp_queue)?; }, + Keycode::PageDown | Keycode::Kp3 => { self.seek(600, false, dmx, disp_queue)?; }, Keycode::Space => { self.toggle_pause(); }, Keycode::Plus | Keycode::KpPlus => { self.volume = (self.volume + 10).min(MAX_VOLUME); @@ -523,7 +570,11 @@ impl Player { self.vcontrol.try_send_video(PktSendEvent::HurryUp); }, Keycode::O => { - self.osd.toggle(); + if keymod.contains(Mod::RSHIFTMOD) || keymod.contains(Mod::LSHIFTMOD) { + self.osd.toggle_perm(); + } else { + self.osd.toggle(); + } }, _ => {}, }; @@ -541,6 +592,11 @@ impl Player { // prepare data source let path = Path::new(name); let mut file = if let Ok(handle) = File::open(path) { + if let Ok(meta) = handle.metadata() { + if meta.is_dir() { + return window; + } + } handle } else { println!("failed to open {}", name); @@ -614,6 +670,28 @@ impl Player { let str_id = s.get_id(); if info.is_video() { if video_dec.is_none() && self.play_video { + #[cfg(feature="hwaccel")] + if info.get_name() == "h264" && self.use_hwaccel { + let mut dec = new_h264_hwdec(); + let dsupp = Box::new(NADecoderSupport::new()); + let props = info.get_properties().get_video_info().unwrap(); + if props.get_width() != 0 { + width = props.get_width(); + height = props.get_height(); + } + if dec.init(info.clone()).is_err() { + println!("failed to initialise hwaccel video decoder"); + } else { + video_dec = Some(DecoderStuff{ dsupp, dec: DecoderType::VideoHW(dec) }); + self.video_str = str_id; + let (tbn, tbd) = s.get_timebase(); + tb_num = tbn; + tb_den = tbd; + self.has_video = true; + println!(" using hardware-accelerated decoding"); + continue; + } + } if let Some(decfunc) = decfunc_mt { let mut dec = (decfunc)(); let mut dsupp = Box::new(NADecoderSupport::new()); @@ -698,10 +776,26 @@ impl Player { return window; } - while (width <= 384) && (height <= 288) { - width <<= 1; - height <<= 1; - } + match self.sc_size { + ScaleSize::Auto => { + while (width <= 384) && (height <= 288) { + width <<= 1; + height <<= 1; + } + }, + ScaleSize::Times(factor) => { + let nw = ((width as f32) * factor).ceil() as usize; + let nh = ((height as f32) * factor).ceil() as usize; + if nw > 0 && nh > 0 { + width = nw; + height = nh; + } + }, + ScaleSize::Fixed(w, h) => { + width = w; + height = h; + }, + }; // prepare playback structure let mut new_vcontrol = VideoControl::new(video_dec, width, height, tb_num, tb_den); @@ -909,6 +1003,14 @@ fn main() { "-nomt" => { player.use_mt = false; }, + #[cfg(feature="hwaccel")] + "-hwaccel" => { + player.use_hwaccel = true; + }, + #[cfg(feature="hwaccel")] + "-nohwaccel" => { + player.use_hwaccel = false; + }, "-threads" => { if let Some(arg) = aiter.next() { if let Ok(val) = arg.parse::() { @@ -918,6 +1020,15 @@ fn main() { } } }, + "-scale" => { + if let Some(arg) = aiter.next() { + if let Ok(ssize) = arg.parse::() { + player.sc_size = ssize; + } else { + println!("invalid scale size"); + } + } + }, _ => { window = player.play(window, arg, seek_time); if player.end { break; }