simple_image_interface/interface/
video.rs1use ffmpeg_next as ffmpeg;
2use log::info;
3
4pub 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 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}