Skip to content
Snippets Groups Projects
Commit 504f4e94 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Improve safety yet again

parent 07356602
No related branches found
No related tags found
No related merge requests found
...@@ -103,6 +103,49 @@ impl AVBuffer { ...@@ -103,6 +103,49 @@ impl AVBuffer {
} }
} }
pub struct AVPacket {
base: *mut ffi::AVPacket,
}
impl AVPacket {
pub fn new() -> Result<Self, failure::Error> {
let base = unsafe { ffi::av_packet_alloc() };
if base.is_null() {
bail!("av_packet_alloc() failed");
}
Ok(AVPacket { base })
}
// TODO: Just for testing
pub unsafe fn as_mut(&mut self) -> &mut ffi::AVPacket {
self.base.as_mut().expect("not null")
}
pub fn pts(&self) -> i64 {
let base = unsafe { self.base.as_ref() }.expect("not null");
base.pts
}
pub fn dts(&self) -> i64 {
let base = unsafe { self.base.as_ref() }.expect("not null");
base.dts
}
pub fn stream_index(&self) -> i32 {
let base = unsafe { self.base.as_ref() }.expect("not null");
base.stream_index
}
}
impl Drop for AVPacket {
fn drop(&mut self) {
unsafe { ffi::av_packet_free(&mut self.base) }
}
}
pub struct AVFrame { pub struct AVFrame {
base: *mut ffi::AVFrame, base: *mut ffi::AVFrame,
buffer: AVBuffer, buffer: AVBuffer,
...@@ -415,3 +458,61 @@ impl Drop for AVCodecContext { ...@@ -415,3 +458,61 @@ impl Drop for AVCodecContext {
unsafe { ffi::avcodec_free_context(&mut self.base) } unsafe { ffi::avcodec_free_context(&mut self.base) }
} }
} }
pub struct SwsContext {
base: *mut ffi::SwsContext,
}
impl SwsContext {
pub fn new() -> Self {
SwsContext { base: std::ptr::null_mut() }
}
pub fn reinit(&mut self, source: &AVFrame, target: &AVFrame, scaler: SwsScaler) -> Result<(), failure::Error> {
let base = unsafe {
ffi::sws_getCachedContext(
self.base,
source.width(),
source.height(),
source.format() as ffi::AVPixelFormat,
target.width(),
target.height(),
target.format() as ffi::AVPixelFormat,
scaler as i32,
std::ptr::null_mut(),
std::ptr::null_mut(),
std::ptr::null(),
)
};
if base.is_null() {
bail!("sws_getCachedContext() failed");
}
self.base = base;
Ok(())
}
pub fn scale(&self, source: &AVFrame, target: &mut AVFrame) -> i32 {
self.scale_slice(source, target, 0, source.height())
}
pub fn scale_slice(&self, source: &AVFrame, target: &mut AVFrame, slice_from: i32, slice_to: i32) -> i32 {
unsafe {
ffi::sws_scale(
self.base,
source.data_ptr(),
source.linesize().as_ptr(),
slice_from,
slice_to,
target.data_mut_ptr(),
target.linesize().as_ptr(),
)
}
}
}
impl Drop for SwsContext {
fn drop(&mut self) {
unsafe { ffi::sws_freeContext(self.base) }
}
}
\ No newline at end of file
...@@ -929,6 +929,24 @@ enum_from_primitive! { ...@@ -929,6 +929,24 @@ enum_from_primitive! {
#[doc = "< discard all frames except keyframes"] #[doc = "< discard all frames except keyframes"]
NonKey = ffi::AVDiscard_AVDISCARD_NONKEY, NonKey = ffi::AVDiscard_AVDISCARD_NONKEY,
#[doc = "< discard all"] #[doc = "< discard all"]
All =ffi::AVDiscard_AVDISCARD_ALL All = ffi::AVDiscard_AVDISCARD_ALL,
}
}
enum_from_primitive! {
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(u32)]
pub enum SwsScaler {
FastBilinear = ffi::SWS_FAST_BILINEAR,
Bilinear = ffi::SWS_BILINEAR,
Bicubic = ffi::SWS_BICUBIC,
X = ffi::SWS_X,
Point = ffi::SWS_POINT,
Area = ffi::SWS_AREA,
Bicublin = ffi::SWS_BICUBLIN,
Gauss = ffi::SWS_GAUSS,
Sinc = ffi::SWS_SINC,
Lanczos = ffi::SWS_LANCZOS,
Spline = ffi::SWS_SPLINE,
} }
} }
\ No newline at end of file
...@@ -48,11 +48,9 @@ fn main() -> Result<(), std::io::Error> { ...@@ -48,11 +48,9 @@ fn main() -> Result<(), std::io::Error> {
codec_context.set_skip_idct(AVDiscard::NonKey); codec_context.set_skip_idct(AVDiscard::NonKey);
codec_context.set_skip_frame(AVDiscard::NonKey); codec_context.set_skip_frame(AVDiscard::NonKey);
// TODO: HERE BE DRAGONS let mut packet = AVPacket::new().unwrap_or_else(|error| {
let packet: &mut ffi::AVPacket = unsafe { panic!("Could not init temporary packet: {:?}", error)
ffi::av_packet_alloc().as_mut() });
}.expect("not null");
// TODO: END DRAGONS
let mut frame = AVFrame::new().unwrap_or_else(|error| { let mut frame = AVFrame::new().unwrap_or_else(|error| {
panic!("Could not create input frame: {:?}", error) panic!("Could not create input frame: {:?}", error)
...@@ -63,10 +61,16 @@ fn main() -> Result<(), std::io::Error> { ...@@ -63,10 +61,16 @@ fn main() -> Result<(), std::io::Error> {
println!("Time: {:#?}", before.elapsed().unwrap()); println!("Time: {:#?}", before.elapsed().unwrap());
before = std::time::SystemTime::now(); before = std::time::SystemTime::now();
let mut scale_context = SwsContext::new();
//TODO: HERE BE DRAGONS
while unsafe { ffi::av_read_frame(avformat_context.raw(), packet.as_mut()) } >= 0 && i < 16 {
// TODO: END DRAGONS
if packet.stream_index() == stream.index() {
//TODO: HERE BE DRAGONS //TODO: HERE BE DRAGONS
while unsafe { ffi::av_read_frame(avformat_context.raw(), packet) } >= 0 && i < 10 { unsafe { ffi::avcodec_send_packet(codec_context.raw(), packet.as_mut()) };
if packet.stream_index == stream.index() {
unsafe { ffi::avcodec_send_packet(codec_context.raw(), packet) };
while unsafe { ffi::avcodec_receive_frame(codec_context.raw(), frame.as_mut()) } >= 0 { while unsafe { ffi::avcodec_receive_frame(codec_context.raw(), frame.as_mut()) } >= 0 {
// TODO: END DRAGONS // TODO: END DRAGONS
...@@ -79,40 +83,14 @@ fn main() -> Result<(), std::io::Error> { ...@@ -79,40 +83,14 @@ fn main() -> Result<(), std::io::Error> {
println!("Reading Time: {:#?}", before.elapsed().unwrap()); println!("Reading Time: {:#?}", before.elapsed().unwrap());
before = std::time::SystemTime::now(); before = std::time::SystemTime::now();
// TODO: HERE BE DRAGONS scale_context.reinit(&frame, &output_frame, SwsScaler::FastBilinear).unwrap_or_else(|error| {
let sws_context = unsafe { panic!("Could not reinit scale context: {:?}", error)
ffi::sws_getContext( });
frame.width(), scale_context.scale(&frame, &mut output_frame);
frame.height(),
frame.format() as ffi::AVPixelFormat,
output_frame.width(),
output_frame.height(),
output_frame.format() as ffi::AVPixelFormat,
ffi::SWS_FAST_BILINEAR as i32,
std::ptr::null_mut(),
std::ptr::null_mut(),
std::ptr::null(),
).as_mut()
}.expect("not null");
let success = unsafe {
ffi::sws_scale(
sws_context,
frame.data_ptr(),
frame.linesize().as_ptr(),
0,
frame.height(),
output_frame.data_mut_ptr(),
output_frame.linesize().as_ptr(),
)
};
// TODO: END DRAGONS
println!("success: {}", success);
println!("Processing Time: {:#?}", before.elapsed().unwrap()); println!("Processing Time: {:#?}", before.elapsed().unwrap());
before = std::time::SystemTime::now(); before = std::time::SystemTime::now();
if success > 0 {
image::save_buffer( image::save_buffer(
format!("/home/janne/Workspace/justflix/data/test/image_{}.png", i), format!("/home/janne/Workspace/justflix/data/test/image_{}.png", i),
output_frame.data(0), output_frame.data(0),
...@@ -121,11 +99,10 @@ fn main() -> Result<(), std::io::Error> { ...@@ -121,11 +99,10 @@ fn main() -> Result<(), std::io::Error> {
image::ColorType::Rgb8, image::ColorType::Rgb8,
).unwrap(); ).unwrap();
i += 1;
}
println!("Writing Time: {:#?}", before.elapsed().unwrap()); println!("Writing Time: {:#?}", before.elapsed().unwrap());
before = std::time::SystemTime::now(); before = std::time::SystemTime::now();
i += 1;
} }
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment