2023-01-23 10:22:10 -05:00
|
|
|
extern crate ffmpeg_the_third as ffmpeg;
|
2020-06-09 23:51:54 +05:30
|
|
|
|
2024-04-07 03:31:36 +02:00
|
|
|
use crate::ffmpeg::format::{input, Pixel};
|
|
|
|
use crate::ffmpeg::media::Type;
|
|
|
|
use crate::ffmpeg::software::scaling::{context::Context, flag::Flags};
|
|
|
|
use crate::ffmpeg::util::frame::video::Video;
|
2020-06-09 23:51:54 +05:30
|
|
|
use std::env;
|
|
|
|
use std::fs::File;
|
|
|
|
use std::io::prelude::*;
|
|
|
|
|
|
|
|
fn main() -> Result<(), ffmpeg::Error> {
|
|
|
|
ffmpeg::init().unwrap();
|
|
|
|
|
2024-11-05 03:07:01 +01:00
|
|
|
if let Ok(mut ictx) = input(env::args().nth(1).expect("Cannot open file.")) {
|
2020-06-09 23:51:54 +05:30
|
|
|
let input = ictx
|
|
|
|
.streams()
|
|
|
|
.best(Type::Video)
|
2020-10-11 10:11:38 +08:00
|
|
|
.ok_or(ffmpeg::Error::StreamNotFound)?;
|
2020-07-22 20:45:50 +08:00
|
|
|
let video_stream_index = input.index();
|
2020-06-09 23:51:54 +05:30
|
|
|
|
2022-01-24 21:03:47 +01:00
|
|
|
let context_decoder = ffmpeg::codec::context::Context::from_parameters(input.parameters())?;
|
|
|
|
let mut decoder = context_decoder.decoder().video()?;
|
2020-06-09 23:51:54 +05:30
|
|
|
|
|
|
|
let mut scaler = Context::get(
|
|
|
|
decoder.format(),
|
|
|
|
decoder.width(),
|
|
|
|
decoder.height(),
|
|
|
|
Pixel::RGB24,
|
|
|
|
decoder.width(),
|
|
|
|
decoder.height(),
|
|
|
|
Flags::BILINEAR,
|
|
|
|
)?;
|
|
|
|
|
2020-07-23 10:07:07 +08:00
|
|
|
let mut frame_index = 0;
|
2020-08-08 00:57:44 +08:00
|
|
|
|
|
|
|
let mut receive_and_process_decoded_frames =
|
|
|
|
|decoder: &mut ffmpeg::decoder::Video| -> Result<(), ffmpeg::Error> {
|
|
|
|
let mut decoded = Video::empty();
|
|
|
|
while decoder.receive_frame(&mut decoded).is_ok() {
|
2020-06-09 23:51:54 +05:30
|
|
|
let mut rgb_frame = Video::empty();
|
2020-08-08 00:57:44 +08:00
|
|
|
scaler.run(&decoded, &mut rgb_frame)?;
|
|
|
|
save_file(&rgb_frame, frame_index).unwrap();
|
2020-07-23 10:07:07 +08:00
|
|
|
frame_index += 1;
|
2020-06-09 23:51:54 +05:30
|
|
|
}
|
2020-08-08 00:57:44 +08:00
|
|
|
Ok(())
|
|
|
|
};
|
|
|
|
|
2023-04-15 22:44:12 +02:00
|
|
|
for (stream, packet) in ictx.packets().filter_map(Result::ok) {
|
2020-08-08 00:57:44 +08:00
|
|
|
if stream.index() == video_stream_index {
|
|
|
|
decoder.send_packet(&packet)?;
|
|
|
|
receive_and_process_decoded_frames(&mut decoder)?;
|
2020-06-09 23:51:54 +05:30
|
|
|
}
|
|
|
|
}
|
2020-08-08 00:57:44 +08:00
|
|
|
decoder.send_eof()?;
|
|
|
|
receive_and_process_decoded_frames(&mut decoder)?;
|
2020-06-09 23:51:54 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn save_file(frame: &Video, index: usize) -> std::result::Result<(), std::io::Error> {
|
2023-03-23 12:11:48 -03:00
|
|
|
let mut file = File::create(format!("frame{index}.ppm"))?;
|
2020-06-09 23:51:54 +05:30
|
|
|
file.write_all(format!("P6\n{} {}\n255\n", frame.width(), frame.height()).as_bytes())?;
|
|
|
|
file.write_all(frame.data(0))?;
|
|
|
|
Ok(())
|
|
|
|
}
|