make video player use multi-threaded decoders if possible
[nihav-player.git] / videoplayer / src / videodec.rs
index 0a1dcd59220737411ef82e68a5c58f6f46a6327c..ac60466be8fa4827f78b964bcf40f14cb5d1a814 100644 (file)
@@ -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<FrameRecord> {
-        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<FrameRecord> {
+        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<FrameRecord> {
-        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 }