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 {
}
}
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 {
base: *mut ffi::AVFrame,
buffer: AVBuffer,
......@@ -415,3 +458,61 @@ impl Drop for AVCodecContext {
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! {
#[doc = "< discard all frames except keyframes"]
NonKey = ffi::AVDiscard_AVDISCARD_NONKEY,
#[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> {
codec_context.set_skip_idct(AVDiscard::NonKey);
codec_context.set_skip_frame(AVDiscard::NonKey);
// TODO: HERE BE DRAGONS
let packet: &mut ffi::AVPacket = unsafe {
ffi::av_packet_alloc().as_mut()
}.expect("not null");
// TODO: END DRAGONS
let mut packet = AVPacket::new().unwrap_or_else(|error| {
panic!("Could not init temporary packet: {:?}", error)
});
let mut frame = AVFrame::new().unwrap_or_else(|error| {
panic!("Could not create input frame: {:?}", error)
......@@ -63,10 +61,16 @@ fn main() -> Result<(), std::io::Error> {
println!("Time: {:#?}", before.elapsed().unwrap());
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
while unsafe { ffi::av_read_frame(avformat_context.raw(), packet) } >= 0 && i < 10 {
if packet.stream_index == stream.index() {
unsafe { ffi::avcodec_send_packet(codec_context.raw(), packet) };
unsafe { ffi::avcodec_send_packet(codec_context.raw(), packet.as_mut()) };
while unsafe { ffi::avcodec_receive_frame(codec_context.raw(), frame.as_mut()) } >= 0 {
// TODO: END DRAGONS
......@@ -79,40 +83,14 @@ fn main() -> Result<(), std::io::Error> {
println!("Reading Time: {:#?}", before.elapsed().unwrap());
before = std::time::SystemTime::now();
// TODO: HERE BE DRAGONS
let sws_context = unsafe {
ffi::sws_getContext(
frame.width(),
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
scale_context.reinit(&frame, &output_frame, SwsScaler::FastBilinear).unwrap_or_else(|error| {
panic!("Could not reinit scale context: {:?}", error)
});
scale_context.scale(&frame, &mut output_frame);
println!("success: {}", success);
println!("Processing Time: {:#?}", before.elapsed().unwrap());
before = std::time::SystemTime::now();
if success > 0 {
image::save_buffer(
format!("/home/janne/Workspace/justflix/data/test/image_{}.png", i),
output_frame.data(0),
......@@ -121,11 +99,10 @@ fn main() -> Result<(), std::io::Error> {
image::ColorType::Rgb8,
).unwrap();
i += 1;
}
println!("Writing Time: {:#?}", before.elapsed().unwrap());
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