2024-11-06 14:27:14 +00:00
|
|
|
use ffmpeg_rs_raw::{get_frame_from_hw, Decoder, Demuxer, DemuxerInfo, Scaler};
|
|
|
|
use ffmpeg_sys_the_third::{av_frame_free, av_packet_free, AVMediaType, AVPixelFormat};
|
2024-11-06 09:34:37 +00:00
|
|
|
use log::{error, info};
|
2024-10-23 19:28:13 +01:00
|
|
|
use std::env::args;
|
|
|
|
use std::fs::File;
|
2024-10-24 12:26:52 +01:00
|
|
|
use std::io::{Cursor, Read};
|
2024-10-23 19:28:13 +01:00
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
fn main() {
|
2024-11-06 09:34:37 +00:00
|
|
|
env_logger::init();
|
2024-10-23 19:28:13 +01:00
|
|
|
let name = args().next().unwrap_or("main".to_string());
|
|
|
|
let path = if let Some(path) = args().skip(1).next() {
|
|
|
|
PathBuf::from(path)
|
|
|
|
} else {
|
2024-11-06 09:34:37 +00:00
|
|
|
error!("Usage: {} <path>", name);
|
2024-10-23 19:28:13 +01:00
|
|
|
std::process::exit(1);
|
|
|
|
};
|
|
|
|
|
2024-10-23 21:56:53 +01:00
|
|
|
let fd = read_as_file(path.clone());
|
|
|
|
scan_input(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_as_custom_io(path: PathBuf) -> Demuxer {
|
2024-10-24 12:26:52 +01:00
|
|
|
let mut data: Vec<u8> = Vec::new();
|
|
|
|
File::open(path).unwrap().read_to_end(&mut data).unwrap();
|
|
|
|
let reader = Cursor::new(data);
|
|
|
|
Demuxer::new_custom_io(reader, None)
|
2024-10-23 21:56:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn read_as_file(path_buf: PathBuf) -> Demuxer {
|
|
|
|
Demuxer::new(path_buf.to_str().unwrap())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn scan_input(mut demuxer: Demuxer) {
|
2024-10-23 19:28:13 +01:00
|
|
|
unsafe {
|
|
|
|
let info = demuxer.probe_input().expect("demuxer failed");
|
2024-11-06 09:34:37 +00:00
|
|
|
info!("{}", info);
|
2024-11-05 10:59:12 +00:00
|
|
|
decode_input(demuxer, info);
|
2024-10-24 12:26:52 +01:00
|
|
|
}
|
|
|
|
}
|
2024-10-23 19:28:13 +01:00
|
|
|
|
2024-11-05 10:59:12 +00:00
|
|
|
unsafe fn decode_input(demuxer: Demuxer, info: DemuxerInfo) {
|
|
|
|
let mut decoder = Decoder::new();
|
2024-11-06 14:27:14 +00:00
|
|
|
decoder.enable_hw_decoder_any();
|
|
|
|
|
2024-11-05 10:59:12 +00:00
|
|
|
for ref stream in info.channels {
|
|
|
|
decoder
|
|
|
|
.setup_decoder(stream, None)
|
|
|
|
.expect("decoder setup failed");
|
|
|
|
}
|
2024-10-24 12:26:52 +01:00
|
|
|
loop_decoder(demuxer, decoder);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn loop_decoder(mut demuxer: Demuxer, mut decoder: Decoder) {
|
2024-11-06 14:27:14 +00:00
|
|
|
let mut scale = Scaler::new();
|
2024-10-24 12:26:52 +01:00
|
|
|
loop {
|
|
|
|
let (mut pkt, stream) = demuxer.get_packet().expect("demuxer failed");
|
|
|
|
if pkt.is_null() {
|
|
|
|
break; // EOF
|
|
|
|
}
|
2024-11-06 09:34:37 +00:00
|
|
|
let media_type = (*(*stream).codecpar).codec_type;
|
|
|
|
// only decode audio/video
|
|
|
|
if media_type != AVMediaType::AVMEDIA_TYPE_VIDEO
|
|
|
|
&& media_type != AVMediaType::AVMEDIA_TYPE_AUDIO
|
|
|
|
{
|
|
|
|
av_packet_free(&mut pkt);
|
|
|
|
continue;
|
|
|
|
}
|
2024-10-24 12:26:52 +01:00
|
|
|
if let Ok(frames) = decoder.decode_pkt(pkt, stream) {
|
|
|
|
for (mut frame, _stream) in frames {
|
|
|
|
// do nothing but decode entire stream
|
2024-11-06 09:34:37 +00:00
|
|
|
if media_type == AVMediaType::AVMEDIA_TYPE_VIDEO {
|
2024-11-06 14:27:14 +00:00
|
|
|
frame = get_frame_from_hw(frame).expect("get frame failed");
|
|
|
|
let mut new_frame = scale
|
|
|
|
.process_frame(frame, 512, 512, AVPixelFormat::AV_PIX_FMT_RGBA)
|
|
|
|
.expect("scale failed");
|
2024-11-06 09:34:37 +00:00
|
|
|
av_frame_free(&mut new_frame);
|
|
|
|
}
|
2024-10-24 12:26:52 +01:00
|
|
|
av_frame_free(&mut frame);
|
2024-10-23 19:28:13 +01:00
|
|
|
}
|
|
|
|
}
|
2024-10-24 12:26:52 +01:00
|
|
|
av_packet_free(&mut pkt);
|
2024-10-23 19:28:13 +01:00
|
|
|
}
|
|
|
|
}
|