videoplayer: add hardware-accelerated H.264 video decoding support
authorKostya Shishkov <kostya.shishkov@gmail.com>
Fri, 20 Oct 2023 16:40:20 +0000 (18:40 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Fri, 20 Oct 2023 16:40:20 +0000 (18:40 +0200)
videoplayer/Cargo.toml
videoplayer/src/main.rs
videoplayer/src/videodec.rs

index f145029d15bcce3e7c9be085bc9f9f675e75634e..8cdc4a2bb96312807f13b82ff47b4bb0dd34c8eb 100644 (file)
@@ -8,9 +8,11 @@ edition = "2018"
 nihav_core = { path="../../nihav-core" }
 nihav_registry = { path="../../nihav-registry" }
 nihav_allstuff = { path="../../nihav-allstuff" }
+hwdec_vaapi = { path="../hwdec-vaapi", optional = true }
 
 sdl2 = "^0.33"
 
 [features]
-default = []
-debug = []
\ No newline at end of file
+default = ["hwaccel"]
+debug = []
+hwaccel = ["hwdec_vaapi"]
\ No newline at end of file
index cd35eb5e8d2e6d8cb9aff0d314c2041e34abaf1e..cabb925fb5e0ecd1dbcd6d7ecfcf8a7cc72b8d58 100644 (file)
@@ -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;
@@ -140,6 +143,8 @@ pub enum DecoderType {
     Audio(Box<dyn NADecoder + Send>),
     Video(Box<dyn NADecoder + Send>, Box<dyn FrameReorderer + Send>),
     VideoMT(Box<dyn NADecoderMT + Send>, MTFrameReorderer),
+    #[cfg(feature="hwaccel")]
+    VideoHW(Box<dyn HWDecoder + Send>),
 }
 
 pub struct DecoderStuff {
@@ -342,6 +347,8 @@ struct Player {
 
     vthreads:       usize,
     use_mt:         bool,
+    #[cfg(feature="hwaccel")]
+    use_hwaccel:    bool,
 
     paused:         bool,
     mute:           bool,
@@ -380,6 +387,8 @@ impl Player {
 
             vthreads:       3,
             use_mt:         true,
+            #[cfg(feature="hwaccel")]
+            use_hwaccel:    true,
 
             paused:         false,
             mute:           false,
@@ -660,6 +669,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());
@@ -971,6 +1002,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::<usize>() {
index 7ebf17710fb7e2c38efacfbd18487920b74a3304..295cfc753ee64002f9288eacf7f54f256d6fbbba 100644 (file)
@@ -137,6 +137,16 @@ impl VideoDecoder {
                     return self.convert_buf(bt, ts);
                 }
             },
+            #[cfg(feature="hwaccel")]
+            DecoderType::VideoHW(ref mut vdec) => {
+                let _ = vdec.queue_pkt(pkt);
+                while let Some(frm) = vdec.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
@@ -188,6 +198,15 @@ impl VideoDecoder {
                     return self.convert_buf(bt, ts);
                 }
             },
+            #[cfg(feature="hwaccel")]
+            DecoderType::VideoHW(ref mut vdec) => {
+                while let Some(frm) = vdec.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
@@ -210,6 +229,15 @@ impl VideoDecoder {
                     return self.convert_buf(bt, ts);
                 }
             },
+            #[cfg(feature="hwaccel")]
+            DecoderType::VideoHW(ref mut dec) => {
+                while let Some(frm) = dec.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
@@ -224,6 +252,10 @@ impl VideoDecoder {
                 dec.flush();
                 reord.flush();
             },
+            #[cfg(feature="hwaccel")]
+            DecoderType::VideoHW(ref mut dec) => {
+                dec.flush();
+            },
             _ => {},
         };
     }