Skip to content

Commit 96aaa46

Browse files
committed
Rewrite test, more readable and useful
1 parent 0bd4217 commit 96aaa46

File tree

1 file changed

+103
-104
lines changed

1 file changed

+103
-104
lines changed

examples/slice/main.rs

Lines changed: 103 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,70 @@
11
//! Port from Original code: https://github.com/leandromoreira/ffmpeg-libav-tutorial/blob/master/0_hello_world.c
2-
//! Since this is a ported code, many warnings will emits.
3-
#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
42
use rusty_ffmpeg::ffi;
53

64
use std::{
75
ffi::{CStr, CString},
86
fs::File,
97
io::Write,
10-
mem::size_of,
11-
ptr::null_mut,
12-
slice,
8+
ptr, slice,
139
};
1410

1511
fn main() {
1612
let filepath: CString = CString::new("./examples/slice/bear.mp4").unwrap();
1713

1814
println!("initializing all the containers, codecs and protocols.");
1915

20-
let pFormatContext = unsafe { ffi::avformat_alloc_context().as_mut() }
21-
.expect("ERROR could not allocate memory for Format Context");
16+
let mut format_context_ptr = unsafe { ffi::avformat_alloc_context() };
17+
if format_context_ptr.is_null() {
18+
panic!("ERROR could not allocate memory for Format Context");
19+
}
2220

2321
println!(
2422
"opening the input file ({}) and loading format (container) header",
2523
filepath.to_str().unwrap()
2624
);
2725

28-
let result = unsafe {
26+
if unsafe {
2927
ffi::avformat_open_input(
30-
&mut (pFormatContext as *mut _),
28+
&mut format_context_ptr,
3129
filepath.as_ptr(),
32-
null_mut(),
33-
null_mut(),
30+
ptr::null_mut(),
31+
ptr::null_mut(),
3432
)
35-
};
36-
37-
if result != 0 {
33+
} != 0
34+
{
3835
panic!("ERROR could not open the file");
3936
}
4037

41-
let format_name = unsafe { CStr::from_ptr((*pFormatContext.iformat).name) };
42-
let format_name = format_name.to_str().unwrap();
38+
let format_context = unsafe { format_context_ptr.as_mut() }.unwrap();
39+
40+
let format_name = unsafe { CStr::from_ptr((*format_context.iformat).name) }
41+
.to_str()
42+
.unwrap();
4343

4444
println!(
4545
"format {}, duration {} us, bit_rate {}",
46-
format_name, pFormatContext.duration, pFormatContext.bit_rate
46+
format_name, format_context.duration, format_context.bit_rate
4747
);
4848

4949
println!("finding stream info from format");
5050

51-
let result = unsafe { ffi::avformat_find_stream_info(pFormatContext, null_mut()) };
52-
if result < 0 {
51+
if unsafe { ffi::avformat_find_stream_info(format_context, ptr::null_mut()) } < 0 {
5352
panic!("ERROR could not get the stream info");
5453
}
5554

56-
let mut pCodec: *const ffi::AVCodec = null_mut();
57-
let mut pCodecParameters: *const ffi::AVCodecParameters = null_mut();
55+
let mut codec_ptr: *const ffi::AVCodec = ptr::null_mut();
56+
let mut codec_parameters_ptr: *const ffi::AVCodecParameters = ptr::null_mut();
5857
let mut video_stream_index = None;
5958

60-
for i in 0..pFormatContext.nb_streams as i32 {
61-
let stream = unsafe {
62-
slice::from_raw_parts(pFormatContext.streams, size_of::<ffi::AVStream>())[i as usize]
63-
.as_ref()
64-
}
65-
.unwrap();
66-
let pLocalCodecParameters = unsafe { stream.codecpar.as_ref() }.unwrap();
59+
let streams = unsafe {
60+
slice::from_raw_parts(format_context.streams, format_context.nb_streams as usize)
61+
};
62+
63+
for (i, stream) in streams
64+
.iter()
65+
.map(|stream| unsafe { stream.as_ref() }.unwrap())
66+
.enumerate()
67+
{
6768
println!(
6869
"AVStream->time_base before open coded {}/{}",
6970
stream.time_base.num, stream.time_base.den
@@ -76,141 +77,139 @@ fn main() {
7677
println!("AVStream->duration {}", stream.duration);
7778
println!("finding the proper decoder (CODEC)");
7879

79-
let pLocalCodec =
80-
unsafe { ffi::avcodec_find_decoder(pLocalCodecParameters.codec_id).as_ref() }
80+
let local_codec_params = unsafe { stream.codecpar.as_ref() }.unwrap();
81+
let local_codec =
82+
unsafe { ffi::avcodec_find_decoder(local_codec_params.codec_id).as_ref() }
8183
.expect("ERROR unsupported codec!");
8284

83-
if pLocalCodecParameters.codec_type == ffi::AVMediaType_AVMEDIA_TYPE_VIDEO {
84-
if video_stream_index.is_none() {
85-
video_stream_index = Some(i);
86-
pCodec = pLocalCodec;
87-
pCodecParameters = pLocalCodecParameters;
85+
match local_codec_params.codec_type {
86+
ffi::AVMediaType_AVMEDIA_TYPE_VIDEO => {
87+
if video_stream_index.is_none() {
88+
video_stream_index = Some(i);
89+
codec_ptr = local_codec;
90+
codec_parameters_ptr = local_codec_params;
91+
}
92+
93+
println!(
94+
"Video Codec: resolution {} x {}",
95+
local_codec_params.width, local_codec_params.height
96+
);
8897
}
98+
ffi::AVMediaType_AVMEDIA_TYPE_AUDIO => {
99+
println!(
100+
"Audio Codec: {} channels, sample rate {}",
101+
local_codec_params.channels, local_codec_params.sample_rate
102+
);
103+
}
104+
_ => {}
105+
};
89106

90-
println!(
91-
"Video Codec: resolution {} x {}",
92-
pLocalCodecParameters.width, pLocalCodecParameters.height
93-
);
94-
} else if pLocalCodecParameters.codec_type == ffi::AVMediaType_AVMEDIA_TYPE_AUDIO {
95-
println!(
96-
"Audio Codec: {} channels, sample rate {}",
97-
pLocalCodecParameters.channels, pLocalCodecParameters.sample_rate
98-
);
99-
}
100-
101-
let codec_name = unsafe { CStr::from_ptr(pLocalCodec.name) };
102-
103-
let codec_name = codec_name.to_str().unwrap();
107+
let codec_name = unsafe { CStr::from_ptr(local_codec.name) }
108+
.to_str()
109+
.unwrap();
104110

105111
println!(
106112
"\tCodec {} ID {} bit_rate {}",
107-
codec_name, pLocalCodec.id, pLocalCodecParameters.bit_rate
113+
codec_name, local_codec.id, local_codec_params.bit_rate
108114
);
109115
}
110-
let pCodecContext = unsafe { ffi::avcodec_alloc_context3(pCodec).as_mut() }
116+
let codec_context = unsafe { ffi::avcodec_alloc_context3(codec_ptr).as_mut() }
111117
.expect("failed to allocated memory for AVCodecContext");
112118

113-
let result = unsafe { ffi::avcodec_parameters_to_context(pCodecContext, pCodecParameters) };
114-
if result < 0 {
119+
if unsafe { ffi::avcodec_parameters_to_context(codec_context, codec_parameters_ptr) } < 0 {
115120
panic!("failed to copy codec params to codec context");
116121
}
117122

118-
let result = unsafe { ffi::avcodec_open2(pCodecContext, pCodec, null_mut()) };
119-
if result < 0 {
123+
if unsafe { ffi::avcodec_open2(codec_context, codec_ptr, ptr::null_mut()) } < 0 {
120124
panic!("failed to open codec through avcodec_open2");
121125
}
122126

123-
let pFrame =
127+
let frame =
124128
unsafe { ffi::av_frame_alloc().as_mut() }.expect("failed to allocated memory for AVFrame");
125-
let pPacket = unsafe { ffi::av_packet_alloc().as_mut() }
129+
let packet = unsafe { ffi::av_packet_alloc().as_mut() }
126130
.expect("failed to allocated memory for AVPacket");
127131

128-
let mut how_many_packets_to_process = 8;
132+
let mut packets_waiting = 8;
129133

130-
while unsafe { ffi::av_read_frame(pFormatContext, pPacket) } >= 0 {
131-
if Some(pPacket.stream_index) == video_stream_index {
132-
println!("AVPacket->pts {}", pPacket.pts);
133-
if let Err(s) = decode_packet(pPacket, pCodecContext, pFrame) {
134-
panic!(s);
135-
}
136-
how_many_packets_to_process -= 1;
137-
if how_many_packets_to_process <= 0 {
134+
while unsafe { ffi::av_read_frame(format_context, packet) } >= 0 {
135+
if video_stream_index == Some(packet.stream_index as usize) {
136+
println!("AVPacket->pts {}", packet.pts);
137+
decode_packet(packet, codec_context, frame).unwrap();
138+
packets_waiting -= 1;
139+
if packets_waiting <= 0 {
138140
break;
139141
}
140142
}
141-
unsafe { ffi::av_packet_unref(pPacket) };
143+
unsafe { ffi::av_packet_unref(packet) };
142144
}
143145

144146
println!("releasing all the resources");
145147

146148
unsafe {
147-
ffi::avformat_close_input(&mut (pFormatContext as *mut _));
148-
ffi::av_packet_free(&mut (pPacket as *mut _));
149-
ffi::av_frame_free(&mut (pFrame as *mut _));
150-
ffi::avcodec_free_context(&mut (pCodecContext as *mut _));
149+
ffi::avformat_close_input(&mut (format_context as *mut _));
150+
ffi::av_packet_free(&mut (packet as *mut _));
151+
ffi::av_frame_free(&mut (frame as *mut _));
152+
ffi::avcodec_free_context(&mut (codec_context as *mut _));
151153
}
152154
}
153155

154156
fn decode_packet(
155-
pPacket: &ffi::AVPacket,
156-
pCodecContext: &mut ffi::AVCodecContext,
157-
pFrame: &mut ffi::AVFrame,
157+
packet: &ffi::AVPacket,
158+
codec_context: &mut ffi::AVCodecContext,
159+
frame: &mut ffi::AVFrame,
158160
) -> Result<(), String> {
159-
let response = unsafe { ffi::avcodec_send_packet(pCodecContext, pPacket) };
161+
let mut response = unsafe { ffi::avcodec_send_packet(codec_context, packet) };
160162

161163
if response < 0 {
162164
return Err(String::from("Error while sending a packet to the decoder."));
163165
}
164166

165167
while response >= 0 {
166-
let response = unsafe { ffi::avcodec_receive_frame(pCodecContext, pFrame) };
167-
if response == ffi::AVERROR(ffi::EAGAIN as i32) || response == ffi::AVERROR_EOF {
168+
response = unsafe { ffi::avcodec_receive_frame(codec_context, frame) };
169+
if response == ffi::AVERROR(ffi::EAGAIN) || response == ffi::AVERROR_EOF {
168170
break;
169171
} else if response < 0 {
170172
return Err(String::from(
171173
"Error while receiving a frame from the decoder.",
172174
));
173-
}
174-
175-
if response >= 0 {
175+
} else {
176176
println!(
177177
"Frame {} (type={}, size={} bytes) pts {} key_frame {} [DTS {}]",
178-
pCodecContext.frame_number,
179-
unsafe { ffi::av_get_picture_type_char(pFrame.pict_type) },
180-
pFrame.pkt_size,
181-
pFrame.pts,
182-
pFrame.key_frame,
183-
pFrame.coded_picture_number
178+
codec_context.frame_number,
179+
unsafe { ffi::av_get_picture_type_char(frame.pict_type) },
180+
frame.pkt_size,
181+
frame.pts,
182+
frame.key_frame,
183+
frame.coded_picture_number
184184
);
185185

186186
let frame_filename = format!(
187187
"./examples/slice/output/frame-{}.pgm",
188-
pCodecContext.frame_number
188+
codec_context.frame_number
189189
);
190-
let width = pFrame.width as usize;
191-
let height = pFrame.height as usize;
192-
let wrap = pFrame.linesize[0] as usize;
193-
let data = unsafe { slice::from_raw_parts(pFrame.data[0], wrap * height) };
194-
save_gray_frame(data, wrap, width, height, frame_filename);
190+
let width = frame.width as usize;
191+
let height = frame.height as usize;
192+
let wrap = frame.linesize[0] as usize;
193+
let data = unsafe { slice::from_raw_parts(frame.data[0], wrap * height) };
194+
save_gray_frame(data, wrap, width, height, frame_filename).unwrap();
195195
}
196196
}
197197
Ok(())
198198
}
199199

200-
fn save_gray_frame(buf: &[u8], wrap: usize, xsize: usize, ysize: usize, filename: String) -> bool {
201-
let mut file = match File::create(filename) {
202-
Ok(file) => file,
203-
Err(_) => return false,
204-
};
200+
fn save_gray_frame(
201+
buf: &[u8],
202+
wrap: usize,
203+
xsize: usize,
204+
ysize: usize,
205+
filename: String,
206+
) -> Result<(), std::io::Error> {
207+
let mut file = File::create(filename)?;
205208
let data = format!("P5\n{} {}\n{}\n", xsize, ysize, 255);
206-
if let Err(_) = file.write_all(data.as_bytes()) {
207-
return false;
208-
}
209+
file.write_all(data.as_bytes())?;
209210

210211
for i in 0..ysize {
211-
if let Err(_) = file.write_all(&buf[i * wrap..(i * wrap + xsize)]) {
212-
return false;
213-
}
212+
file.write_all(&buf[i * wrap..(i * wrap + xsize)])?;
214213
}
215-
true
214+
Ok(())
216215
}

0 commit comments

Comments
 (0)