feat: use slimbox + add example
This commit is contained in:
parent
e87c477b15
commit
ccacee9eef
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -101,6 +101,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"ffmpeg-sys-the-third",
|
||||
"libc",
|
||||
"slimbox",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -246,6 +247,12 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "slimbox"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26dfcf7e4fe830e4b9245b9e0def30d3df9ea194aca707e9a78b079d2b646b1a"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.82"
|
||||
|
@ -14,3 +14,4 @@ crate-type = ["lib", "cdylib"]
|
||||
anyhow = "1.0.91"
|
||||
ffmpeg-sys-the-third = { git = "https://github.com/shssoichiro/ffmpeg-the-third.git", branch = "master", package = "ffmpeg-sys-the-third" }
|
||||
libc = { version = "0.2.160" }
|
||||
slimbox = "0.1.0"
|
||||
|
54
examples/main.rs
Normal file
54
examples/main.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use ffmpeg_rs_raw::{Decoder, Demuxer};
|
||||
use ffmpeg_sys_the_third::{av_frame_free, av_packet_free};
|
||||
use std::env::args;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
|
||||
struct DropTest {
|
||||
inner: File,
|
||||
}
|
||||
|
||||
impl Read for DropTest {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DropTest {
|
||||
fn drop(&mut self) {
|
||||
println!("Dropped!");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let name = args().next().unwrap_or("main".to_string());
|
||||
let path = if let Some(path) = args().skip(1).next() {
|
||||
PathBuf::from(path)
|
||||
} else {
|
||||
eprintln!("Usage: {} <path>", name);
|
||||
std::process::exit(1);
|
||||
};
|
||||
|
||||
let file = File::open(path).unwrap();
|
||||
let mut demuxer = Demuxer::new_custom_io(DropTest { inner: file });
|
||||
unsafe {
|
||||
let info = demuxer.probe_input().expect("demuxer failed");
|
||||
println!("{}", info);
|
||||
|
||||
let mut decoder = Decoder::new();
|
||||
loop {
|
||||
let (mut pkt, stream) = demuxer.get_packet().expect("demuxer failed");
|
||||
if pkt.is_null() {
|
||||
break; // EOF
|
||||
}
|
||||
if let Ok(frames) = decoder.decode_pkt(pkt, stream) {
|
||||
for (mut frame, stream) in frames {
|
||||
// do nothing but decode entire stream
|
||||
av_frame_free(&mut frame);
|
||||
}
|
||||
}
|
||||
av_packet_free(&mut pkt);
|
||||
}
|
||||
}
|
||||
}
|
54
src/demux.rs
54
src/demux.rs
@ -1,40 +1,30 @@
|
||||
use anyhow::Error;
|
||||
use ffmpeg_sys_the_third::*;
|
||||
use std::ffi::CStr;
|
||||
use std::time::Instant;
|
||||
use std::{ptr, slice};
|
||||
|
||||
use anyhow::Error;
|
||||
use ffmpeg_sys_the_third::*;
|
||||
|
||||
use crate::get_ffmpeg_error_msg;
|
||||
use crate::return_ffmpeg_error;
|
||||
use slimbox::{slimbox_unsize, SlimBox, SlimMut};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::io::{Read, Write};
|
||||
use std::mem::transmute;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn read_data(
|
||||
opaque: *mut libc::c_void,
|
||||
dst_buffer: *mut libc::c_uchar,
|
||||
size: libc::c_int,
|
||||
) -> libc::c_int {
|
||||
let buffer: *mut Box<dyn Read> = opaque.cast();
|
||||
/// we loop until there is enough data to fill [size]
|
||||
let mut dst_slice: &mut [u8] = slice::from_raw_parts_mut(dst_buffer, size as usize);
|
||||
let mut w_total = 0usize;
|
||||
loop {
|
||||
return match (*buffer).read(dst_slice) {
|
||||
Ok(v) => {
|
||||
w_total += v;
|
||||
if w_total != size as usize {
|
||||
dst_slice = &mut dst_slice[v..];
|
||||
continue;
|
||||
}
|
||||
size
|
||||
}
|
||||
let mut buffer: SlimMut<'_, dyn Read + 'static> = SlimMut::from_raw(opaque);
|
||||
let dst_slice: &mut [u8] = slice::from_raw_parts_mut(dst_buffer, size as usize);
|
||||
match buffer.read_exact(dst_slice) {
|
||||
Ok(_) => size,
|
||||
Err(e) => {
|
||||
eprintln!("read_data {}", e);
|
||||
AVERROR_EOF
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,18 +150,14 @@ impl Display for StreamInfoChannel {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Demuxer<'a> {
|
||||
pub struct Demuxer {
|
||||
ctx: *mut AVFormatContext,
|
||||
input: String,
|
||||
started: Instant,
|
||||
buffer: Option<Box<dyn Read + 'a>>,
|
||||
buffer: Option<SlimBox<dyn Read + 'static>>,
|
||||
}
|
||||
|
||||
unsafe impl Send for Demuxer<'_> {}
|
||||
|
||||
unsafe impl Sync for Demuxer<'_> {}
|
||||
|
||||
impl Demuxer<'_> {
|
||||
impl Demuxer {
|
||||
pub fn new(input: &str) -> Self {
|
||||
unsafe {
|
||||
let ps = avformat_alloc_context();
|
||||
@ -184,33 +170,33 @@ impl Demuxer<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_custom_io<T: Read + 'static>(reader: T) -> Self {
|
||||
pub fn new_custom_io<R: Read + 'static>(reader: R) -> Self {
|
||||
unsafe {
|
||||
let ps = avformat_alloc_context();
|
||||
(*ps).flags |= AVFMT_FLAG_CUSTOM_IO;
|
||||
|
||||
let buffer = Box::new(reader);
|
||||
Self {
|
||||
ctx: ps,
|
||||
input: String::new(),
|
||||
started: Instant::now(),
|
||||
buffer: Some(buffer),
|
||||
buffer: Some(slimbox_unsize!(reader)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn open_input(&mut self) -> libc::c_int {
|
||||
if let Some(mut buffer) = self.buffer.take() {
|
||||
if let Some(buffer) = self.buffer.take() {
|
||||
const BUFFER_SIZE: usize = 4096;
|
||||
let pb = avio_alloc_context(
|
||||
av_mallocz(BUFFER_SIZE) as *mut libc::c_uchar,
|
||||
BUFFER_SIZE as libc::c_int,
|
||||
0,
|
||||
ptr::addr_of_mut!(buffer) as _,
|
||||
buffer.into_raw(),
|
||||
Some(read_data),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
(*self.ctx).pb = pb;
|
||||
avformat_open_input(
|
||||
&mut self.ctx,
|
||||
@ -235,7 +221,7 @@ impl Demuxer<'_> {
|
||||
if avformat_find_stream_info(self.ctx, ptr::null_mut()) < 0 {
|
||||
return Err(Error::msg("Could not find stream info"));
|
||||
}
|
||||
av_dump_format(self.ctx, 0, ptr::null_mut(), 0);
|
||||
//av_dump_format(self.ctx, 0, ptr::null_mut(), 0);
|
||||
|
||||
let mut channel_infos = vec![];
|
||||
|
||||
@ -308,9 +294,13 @@ impl Demuxer<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Demuxer<'_> {
|
||||
impl Drop for Demuxer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if !(*(*self.ctx).pb).opaque.is_null() {
|
||||
let ptr: SlimBox<dyn Read> = SlimBox::from_raw((*(*self.ctx).pb).opaque);
|
||||
drop(ptr)
|
||||
}
|
||||
avformat_free_context(self.ctx);
|
||||
self.ctx = ptr::null_mut();
|
||||
}
|
||||
|
@ -23,3 +23,8 @@ fn get_ffmpeg_error_msg(ret: libc::c_int) -> String {
|
||||
String::from(CStr::from_ptr(buf.as_ptr()).to_str().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
pub use decode::*;
|
||||
pub use demux::*;
|
||||
pub use resample::*;
|
||||
pub use scale::*;
|
||||
|
@ -1,3 +0,0 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user