simple_image_interface/interface/
video.rs

1use ffmpeg_next as ffmpeg;
2use log::info;
3
4/// Video struct
5pub struct Video {
6    decoder: ffmpeg::decoder::Video,
7    ictx: ffmpeg::format::context::Input,
8    scaler: ffmpeg::software::scaling::Context,
9    width: u32,
10    height: u32,
11    video_stream_index: usize,
12}
13
14impl Video {
15    pub fn new(path: impl Into<std::path::PathBuf>) -> Video {
16        ffmpeg::init().unwrap();
17        let path_into = path.into();
18
19        let ictx_ = ffmpeg::format::input(&path_into).unwrap();
20        let input = ictx_.streams().best(ffmpeg::media::Type::Video).unwrap();
21        let video_stream_index = input.index();
22
23        let decoder_ = ffmpeg::codec::context::Context::from_parameters(
24            input.parameters()
25        ).unwrap().decoder().video().unwrap();
26        let width_ = decoder_.width();
27        let height_ = decoder_.height();
28
29        let scaler_ = ffmpeg::software::scaling::context::Context::get(
30            decoder_.format(),
31            width_,
32            height_,
33            ffmpeg::format::Pixel::RGB24,
34            width_,
35            height_,
36            ffmpeg::software::scaling::flag::Flags::BILINEAR,
37        )
38        .unwrap();
39
40        info!("Video {:?}: {} * {}", &path_into, width_, height_);
41        Video {
42            decoder: decoder_,
43            ictx: ictx_,
44            scaler: scaler_,
45            width: width_,
46            height: height_,
47            video_stream_index,
48        }
49    }
50
51    /// Get frame from interface
52    /// If interface do not get a image, return None
53    pub fn get_frame(&mut self) -> Option<image::RgbImage> {
54        loop {
55            let stream_and_packet_iter = self.ictx.packets().next();
56            if stream_and_packet_iter.is_some() {
57                let (stream, packet) = stream_and_packet_iter.unwrap();
58                if stream.index() == self.video_stream_index {
59                    self.decoder.send_packet(&packet).unwrap();
60                    let mut decoded = ffmpeg::util::frame::video::Video::empty();
61                    if self.decoder.receive_frame(&mut decoded).is_ok() {
62                        let mut rgb_frame = ffmpeg::util::frame::video::Video::empty();
63                        self.scaler.run(&decoded, &mut rgb_frame).unwrap();
64
65                        let rgb_image = image::RgbImage::from_vec(
66                            self.width,
67                            self.height,
68                            rgb_frame.data(0).to_vec(),
69                        )
70                        .unwrap();
71                        return Some(rgb_image);
72                    }
73                } else {
74                    break;
75                }
76            } else {
77                break;
78            }
79        }
80        return None;
81    }
82}