*: format code with rustfmt and fix clippy suggestions

* Add avformat_close_input call to clean up AVFormantContext
* Format code with rustfmt
* Fix clippy lint double_parens
* Fix clippy lint deref_addrof
* Fix clippy lint identity_conversion
* Fix clippy lint match_ref_pats
* Fix clippy lint cast_lossless
* Fix clippy lint cmp_null
* Fix clippy lint clone_on_ref_ptr
* Fix clippy lint map_clone
* Fix clippy lint needless_borrow
* Fix clippy lint needless_pass_by_value
* Fix clippy lints for examples
* Fix clippy lint unused_io_amount
* Fix clippy lint new_without_default
* Ignore inline_always clippy lint
* Add vim temp files to .gitignore
This commit is contained in:
Tadas Barzdžius 2018-04-10 17:06:42 +03:00 committed by meh
parent 20c7ef399a
commit 0bcd4550b8
128 changed files with 10643 additions and 10233 deletions

6
.gitignore vendored
View File

@ -1,2 +1,8 @@
# Rust files
target target
Cargo.lock Cargo.lock
# Vim temporary files
*.swp
*.swo
*.swn

View File

@ -1,10 +1,12 @@
use std::env; use std::env;
fn main() { fn main() {
for (name, _value) in env::vars() { for (name, _value) in env::vars() {
if name.starts_with("DEP_FFMPEG_") { if name.starts_with("DEP_FFMPEG_") {
println!(r#"cargo:rustc-cfg=feature="{}""#, println!(
name["DEP_FFMPEG_".len() .. name.len()].to_lowercase()); r#"cargo:rustc-cfg=feature="{}""#,
} name["DEP_FFMPEG_".len()..name.len()].to_lowercase()
} );
}
}
} }

View File

@ -3,50 +3,58 @@ extern crate ffmpeg;
use std::env; use std::env;
fn main() { fn main() {
ffmpeg::init().unwrap(); ffmpeg::init().unwrap();
match ffmpeg::format::input(&env::args().nth(1).expect("missing input file name")) { match ffmpeg::format::input(&env::args().nth(1).expect("missing input file name")) {
Ok(ictx) => { Ok(ictx) => {
println!("Nb chapters: {}", ictx.nb_chapters()); println!("Nb chapters: {}", ictx.nb_chapters());
for chapter in ictx.chapters() { for chapter in ictx.chapters() {
println!("chapter id {}:", chapter.id()); println!("chapter id {}:", chapter.id());
println!("\ttime_base: {}", chapter.time_base()); println!("\ttime_base: {}", chapter.time_base());
println!("\tstart: {}", chapter.start()); println!("\tstart: {}", chapter.start());
println!("\tend: {}", chapter.end()); println!("\tend: {}", chapter.end());
for (k, v) in chapter.metadata().iter() { for (k, v) in chapter.metadata().iter() {
println!("\t{}: {}", k, v); println!("\t{}: {}", k, v);
} }
} }
let mut octx = ffmpeg::format::output(&"test.mkv".to_owned()).expect(&format!("Couldn't open test file")); let mut octx =
ffmpeg::format::output(&"test.mkv".to_owned()).expect("Couldn't open test file");
for chapter in ictx.chapters() { for chapter in ictx.chapters() {
let title = match chapter.metadata().get("title") { let title = match chapter.metadata().get("title") {
Some(title) => String::from(title), Some(title) => String::from(title),
None => String::new(), None => String::new(),
}; };
match octx.add_chapter(chapter.id(), chapter.time_base(), chapter.start(), chapter.end(), &title) { match octx.add_chapter(
Ok(chapter) => println!("Added chapter with id {} to output", chapter.id()), chapter.id(),
Err(error) => println!("Error adding chapter with id: {} - {}", chapter.id(), error), chapter.time_base(),
} chapter.start(),
} chapter.end(),
&title,
) {
Ok(chapter) => println!("Added chapter with id {} to output", chapter.id()),
Err(error) => {
println!("Error adding chapter with id: {} - {}", chapter.id(), error)
}
}
}
println!("\nOuput: nb chapters: {}", octx.nb_chapters()); println!("\nOuput: nb chapters: {}", octx.nb_chapters());
for chapter in octx.chapters() { for chapter in octx.chapters() {
println!("chapter id {}:", chapter.id()); println!("chapter id {}:", chapter.id());
println!("\ttime_base: {}", chapter.time_base()); println!("\ttime_base: {}", chapter.time_base());
println!("\tstart: {}", chapter.start()); println!("\tstart: {}", chapter.start());
println!("\tend: {}", chapter.end()); println!("\tend: {}", chapter.end());
for (k, v) in chapter.metadata().iter() { for (k, v) in chapter.metadata().iter() {
println!("\t{}: {}", k, v); println!("\t{}: {}", k, v);
} }
} }
} }
Err(error) => Err(error) => println!("error: {}", error),
println!("error: {}", error) }
}
} }

View File

@ -3,119 +3,108 @@ extern crate ffmpeg;
use std::env; use std::env;
fn main() { fn main() {
ffmpeg::init().unwrap(); ffmpeg::init().unwrap();
for arg in env::args().skip(1) { for arg in env::args().skip(1) {
if let Some(codec) = ffmpeg::decoder::find_by_name(&arg) { if let Some(codec) = ffmpeg::decoder::find_by_name(&arg) {
println!("type: decoder"); println!("type: decoder");
println!("\t id: {:?}", codec.id()); println!("\t id: {:?}", codec.id());
println!("\t name: {}", codec.name()); println!("\t name: {}", codec.name());
println!("\t description: {}", codec.description()); println!("\t description: {}", codec.description());
println!("\t medium: {:?}", codec.medium()); println!("\t medium: {:?}", codec.medium());
println!("\t capabilities: {:?}", codec.capabilities()); println!("\t capabilities: {:?}", codec.capabilities());
if let Some(profiles) = codec.profiles() { if let Some(profiles) = codec.profiles() {
println!("\t profiles: {:?}", profiles.collect::<Vec<_>>()); println!("\t profiles: {:?}", profiles.collect::<Vec<_>>());
} } else {
else { println!("\t profiles: none");
println!("\t profiles: none"); }
}
if let Ok(video) = codec.video() { if let Ok(video) = codec.video() {
if let Some(rates) = video.rates() { if let Some(rates) = video.rates() {
println!("\t rates: {:?}", rates.collect::<Vec<_>>()); println!("\t rates: {:?}", rates.collect::<Vec<_>>());
} } else {
else { println!("\t rates: any");
println!("\t rates: any"); }
}
if let Some(formats) = video.formats() { if let Some(formats) = video.formats() {
println!("\t formats: {:?}", formats.collect::<Vec<_>>()); println!("\t formats: {:?}", formats.collect::<Vec<_>>());
} } else {
else { println!("\t formats: any");
println!("\t formats: any"); }
} }
}
if let Ok(audio) = codec.audio() { if let Ok(audio) = codec.audio() {
if let Some(rates) = audio.rates() { if let Some(rates) = audio.rates() {
println!("\t rates: {:?}", rates.collect::<Vec<_>>()); println!("\t rates: {:?}", rates.collect::<Vec<_>>());
} } else {
else { println!("\t rates: any");
println!("\t rates: any"); }
}
if let Some(formats) = audio.formats() { if let Some(formats) = audio.formats() {
println!("\t formats: {:?}", formats.collect::<Vec<_>>()); println!("\t formats: {:?}", formats.collect::<Vec<_>>());
} } else {
else { println!("\t formats: any");
println!("\t formats: any"); }
}
if let Some(layouts) = audio.channel_layouts() { if let Some(layouts) = audio.channel_layouts() {
println!("\t channel_layouts: {:?}", layouts.collect::<Vec<_>>()); println!("\t channel_layouts: {:?}", layouts.collect::<Vec<_>>());
} } else {
else { println!("\t channel_layouts: any");
println!("\t channel_layouts: any"); }
} }
}
println!("\t max_lowres: {:?}", codec.max_lowres()); println!("\t max_lowres: {:?}", codec.max_lowres());
} }
if let Some(codec) = ffmpeg::encoder::find_by_name(&arg) { if let Some(codec) = ffmpeg::encoder::find_by_name(&arg) {
println!(""); println!();
println!("type: encoder"); println!("type: encoder");
println!("\t id: {:?}", codec.id()); println!("\t id: {:?}", codec.id());
println!("\t name: {}", codec.name()); println!("\t name: {}", codec.name());
println!("\t description: {}", codec.description()); println!("\t description: {}", codec.description());
println!("\t medium: {:?}", codec.medium()); println!("\t medium: {:?}", codec.medium());
println!("\t capabilities: {:?}", codec.capabilities()); println!("\t capabilities: {:?}", codec.capabilities());
if let Some(profiles) = codec.profiles() { if let Some(profiles) = codec.profiles() {
println!("\t profiles: {:?}", profiles.collect::<Vec<_>>()); println!("\t profiles: {:?}", profiles.collect::<Vec<_>>());
} }
if let Ok(video) = codec.video() { if let Ok(video) = codec.video() {
if let Some(rates) = video.rates() { if let Some(rates) = video.rates() {
println!("\t rates: {:?}", rates.collect::<Vec<_>>()); println!("\t rates: {:?}", rates.collect::<Vec<_>>());
} } else {
else { println!("\t rates: any");
println!("\t rates: any"); }
}
if let Some(formats) = video.formats() { if let Some(formats) = video.formats() {
println!("\t formats: {:?}", formats.collect::<Vec<_>>()); println!("\t formats: {:?}", formats.collect::<Vec<_>>());
} } else {
else { println!("\t formats: any");
println!("\t formats: any"); }
} }
}
if let Ok(audio) = codec.audio() { if let Ok(audio) = codec.audio() {
if let Some(rates) = audio.rates() { if let Some(rates) = audio.rates() {
println!("\t rates: {:?}", rates.collect::<Vec<_>>()); println!("\t rates: {:?}", rates.collect::<Vec<_>>());
} } else {
else { println!("\t rates: any");
println!("\t rates: any"); }
}
if let Some(formats) = audio.formats() { if let Some(formats) = audio.formats() {
println!("\t formats: {:?}", formats.collect::<Vec<_>>()); println!("\t formats: {:?}", formats.collect::<Vec<_>>());
} } else {
else { println!("\t formats: any");
println!("\t formats: any"); }
}
if let Some(layouts) = audio.channel_layouts() { if let Some(layouts) = audio.channel_layouts() {
println!("\t channel_layouts: {:?}", layouts.collect::<Vec<_>>()); println!("\t channel_layouts: {:?}", layouts.collect::<Vec<_>>());
} } else {
else { println!("\t channel_layouts: any");
println!("\t channel_layouts: any"); }
} }
}
println!("\t max_lowres: {:?}", codec.max_lowres()); println!("\t max_lowres: {:?}", codec.max_lowres());
} }
} }
} }

View File

@ -3,81 +3,87 @@ extern crate ffmpeg;
use std::env; use std::env;
fn main() { fn main() {
ffmpeg::init().unwrap(); ffmpeg::init().unwrap();
match ffmpeg::format::input(&env::args().nth(1).expect("missing file")) { match ffmpeg::format::input(&env::args().nth(1).expect("missing file")) {
Ok(context) => { Ok(context) => {
for (k, v) in context.metadata().iter() { for (k, v) in context.metadata().iter() {
println!("{}: {}", k, v); println!("{}: {}", k, v);
} }
if let Some(stream) = context.streams().best(ffmpeg::media::Type::Video) {
println!("Best video stream index: {}", stream.index());
}
if let Some(stream) = context.streams().best(ffmpeg::media::Type::Audio) {
println!("Best audio stream index: {}", stream.index());
}
if let Some(stream) = context.streams().best(ffmpeg::media::Type::Subtitle) {
println!("Best subtitle stream index: {}", stream.index());
}
println!("duration (seconds): {:.2}", context.duration() as f64 / ffmpeg::ffi::AV_TIME_BASE as f64); if let Some(stream) = context.streams().best(ffmpeg::media::Type::Video) {
println!("Best video stream index: {}", stream.index());
}
for stream in context.streams() { if let Some(stream) = context.streams().best(ffmpeg::media::Type::Audio) {
println!("stream index {}:", stream.index()); println!("Best audio stream index: {}", stream.index());
println!("\ttime_base: {}", stream.time_base()); }
println!("\tstart_time: {}", stream.start_time());
println!("\tduration (stream timebase): {}", stream.duration());
println!("\tduration (seconds): {:.2}", stream.duration() as f64 * f64::from(stream.time_base()));
println!("\tframes: {}", stream.frames());
println!("\tdisposition: {:?}", stream.disposition());
println!("\tdiscard: {:?}", stream.discard());
println!("\trate: {}", stream.rate());
let codec = stream.codec();
println!("\tmedium: {:?}", codec.medium());
println!("\tid: {:?}", codec.id());
if codec.medium() == ffmpeg::media::Type::Video {
if let Ok(video) = codec.decoder().video() {
println!("\tbit_rate: {}", video.bit_rate());
println!("\tmax_rate: {}", video.max_bit_rate());
println!("\tdelay: {}", video.delay());
println!("\tvideo.width: {}", video.width());
println!("\tvideo.height: {}", video.height());
println!("\tvideo.format: {:?}", video.format());
println!("\tvideo.has_b_frames: {}", video.has_b_frames());
println!("\tvideo.aspect_ratio: {}", video.aspect_ratio());
println!("\tvideo.color_space: {:?}", video.color_space());
println!("\tvideo.color_range: {:?}", video.color_range());
println!("\tvideo.color_primaries: {:?}", video.color_primaries());
println!("\tvideo.color_transfer_characteristic: {:?}", video.color_transfer_characteristic());
println!("\tvideo.chroma_location: {:?}", video.chroma_location());
println!("\tvideo.references: {}", video.references());
println!("\tvideo.intra_dc_precision: {}", video.intra_dc_precision());
}
}
else if codec.medium() == ffmpeg::media::Type::Audio {
if let Ok(audio) = codec.decoder().audio() {
println!("\tbit_rate: {}", audio.bit_rate());
println!("\tmax_rate: {}", audio.max_bit_rate());
println!("\tdelay: {}", audio.delay());
println!("\taudio.rate: {}", audio.rate());
println!("\taudio.channels: {}", audio.channels());
println!("\taudio.format: {:?}", audio.format());
println!("\taudio.frames: {}", audio.frames());
println!("\taudio.align: {}", audio.align());
println!("\taudio.channel_layout: {:?}", audio.channel_layout());
println!("\taudio.frame_start: {:?}", audio.frame_start());
}
}
}
} if let Some(stream) = context.streams().best(ffmpeg::media::Type::Subtitle) {
println!("Best subtitle stream index: {}", stream.index());
}
Err(error) => println!(
println!("error: {}", error) "duration (seconds): {:.2}",
} context.duration() as f64 / f64::from(ffmpeg::ffi::AV_TIME_BASE)
);
for stream in context.streams() {
println!("stream index {}:", stream.index());
println!("\ttime_base: {}", stream.time_base());
println!("\tstart_time: {}", stream.start_time());
println!("\tduration (stream timebase): {}", stream.duration());
println!(
"\tduration (seconds): {:.2}",
stream.duration() as f64 * f64::from(stream.time_base())
);
println!("\tframes: {}", stream.frames());
println!("\tdisposition: {:?}", stream.disposition());
println!("\tdiscard: {:?}", stream.discard());
println!("\trate: {}", stream.rate());
let codec = stream.codec();
println!("\tmedium: {:?}", codec.medium());
println!("\tid: {:?}", codec.id());
if codec.medium() == ffmpeg::media::Type::Video {
if let Ok(video) = codec.decoder().video() {
println!("\tbit_rate: {}", video.bit_rate());
println!("\tmax_rate: {}", video.max_bit_rate());
println!("\tdelay: {}", video.delay());
println!("\tvideo.width: {}", video.width());
println!("\tvideo.height: {}", video.height());
println!("\tvideo.format: {:?}", video.format());
println!("\tvideo.has_b_frames: {}", video.has_b_frames());
println!("\tvideo.aspect_ratio: {}", video.aspect_ratio());
println!("\tvideo.color_space: {:?}", video.color_space());
println!("\tvideo.color_range: {:?}", video.color_range());
println!("\tvideo.color_primaries: {:?}", video.color_primaries());
println!(
"\tvideo.color_transfer_characteristic: {:?}",
video.color_transfer_characteristic()
);
println!("\tvideo.chroma_location: {:?}", video.chroma_location());
println!("\tvideo.references: {}", video.references());
println!("\tvideo.intra_dc_precision: {}", video.intra_dc_precision());
}
} else if codec.medium() == ffmpeg::media::Type::Audio {
if let Ok(audio) = codec.decoder().audio() {
println!("\tbit_rate: {}", audio.bit_rate());
println!("\tmax_rate: {}", audio.max_bit_rate());
println!("\tdelay: {}", audio.delay());
println!("\taudio.rate: {}", audio.rate());
println!("\taudio.channels: {}", audio.channels());
println!("\taudio.format: {:?}", audio.format());
println!("\taudio.frames: {}", audio.frames());
println!("\taudio.align: {}", audio.align());
println!("\taudio.channel_layout: {:?}", audio.channel_layout());
println!("\taudio.frame_start: {:?}", audio.frame_start());
}
}
}
}
Err(error) => println!("error: {}", error),
}
} }

View File

@ -3,87 +3,121 @@ extern crate ffmpeg;
use std::env; use std::env;
use std::path::Path; use std::path::Path;
use ffmpeg::{format, codec, frame, media, filter}; use ffmpeg::{codec, filter, format, frame, media};
use ffmpeg::{rescale, Rescale}; use ffmpeg::{rescale, Rescale};
fn filter(spec: &str, decoder: &codec::decoder::Audio, encoder: &codec::encoder::Audio) -> Result<filter::Graph, ffmpeg::Error> { fn filter(
let mut filter = filter::Graph::new(); spec: &str,
decoder: &codec::decoder::Audio,
encoder: &codec::encoder::Audio,
) -> Result<filter::Graph, ffmpeg::Error> {
let mut filter = filter::Graph::new();
let args = format!("time_base={}:sample_rate={}:sample_fmt={}:channel_layout=0x{:x}", let args = format!(
decoder.time_base(), decoder.rate(), decoder.format().name(), decoder.channel_layout().bits()); "time_base={}:sample_rate={}:sample_fmt={}:channel_layout=0x{:x}",
decoder.time_base(),
decoder.rate(),
decoder.format().name(),
decoder.channel_layout().bits()
);
try!(filter.add(&filter::find("abuffer").unwrap(), "in", &args)); filter.add(&filter::find("abuffer").unwrap(), "in", &args)?;
try!(filter.add(&filter::find("abuffersink").unwrap(), "out", "")); filter.add(&filter::find("abuffersink").unwrap(), "out", "")?;
{ {
let mut out = filter.get("out").unwrap(); let mut out = filter.get("out").unwrap();
out.set_sample_format(encoder.format()); out.set_sample_format(encoder.format());
out.set_channel_layout(encoder.channel_layout()); out.set_channel_layout(encoder.channel_layout());
out.set_sample_rate(encoder.rate()); out.set_sample_rate(encoder.rate());
} }
try!(try!(try!(filter.output("in", 0)).input("out", 0)).parse(spec)); filter.output("in", 0)?.input("out", 0)?.parse(spec)?;
try!(filter.validate()); filter.validate()?;
println!("{}", filter.dump()); println!("{}", filter.dump());
if let Some(codec) = encoder.codec() { if let Some(codec) = encoder.codec() {
if !codec.capabilities().contains(ffmpeg::codec::capabilities::VARIABLE_FRAME_SIZE) { if !codec
filter.get("out").unwrap().sink().set_frame_size(encoder.frame_size()); .capabilities()
} .contains(ffmpeg::codec::capabilities::VARIABLE_FRAME_SIZE)
} {
filter
.get("out")
.unwrap()
.sink()
.set_frame_size(encoder.frame_size());
}
}
Ok(filter) Ok(filter)
} }
struct Transcoder { struct Transcoder {
stream: usize, stream: usize,
filter: filter::Graph, filter: filter::Graph,
decoder: codec::decoder::Audio, decoder: codec::decoder::Audio,
encoder: codec::encoder::Audio, encoder: codec::encoder::Audio,
} }
fn transcoder<P: AsRef<Path>>(ictx: &mut format::context::Input, octx: &mut format::context::Output, path: &P, filter_spec: &str) -> Result<Transcoder, ffmpeg::Error> { fn transcoder<P: AsRef<Path>>(
let input = ictx.streams().best(media::Type::Audio).expect("could not find best audio stream"); ictx: &mut format::context::Input,
let mut decoder = try!(input.codec().decoder().audio()); octx: &mut format::context::Output,
let codec = try!(ffmpeg::encoder::find(octx.format().codec(path, media::Type::Audio)).expect("failed to find encoder").audio()); path: &P,
let global = octx.format().flags().contains(ffmpeg::format::flag::GLOBAL_HEADER); filter_spec: &str,
) -> Result<Transcoder, ffmpeg::Error> {
let input = ictx.streams()
.best(media::Type::Audio)
.expect("could not find best audio stream");
let mut decoder = input.codec().decoder().audio()?;
let codec = ffmpeg::encoder::find(octx.format().codec(path, media::Type::Audio))
.expect("failed to find encoder")
.audio()?;
let global = octx.format()
.flags()
.contains(ffmpeg::format::flag::GLOBAL_HEADER);
try!(decoder.set_parameters(input.parameters())); decoder.set_parameters(input.parameters())?;
let mut output = try!(octx.add_stream(codec)); let mut output = octx.add_stream(codec)?;
let mut encoder = try!(output.codec().encoder().audio()); let mut encoder = output.codec().encoder().audio()?;
let channel_layout = codec.channel_layouts() let channel_layout = codec
.map(|cls| cls.best(decoder.channel_layout().channels())) .channel_layouts()
.unwrap_or(ffmpeg::channel_layout::STEREO); .map(|cls| cls.best(decoder.channel_layout().channels()))
.unwrap_or(ffmpeg::channel_layout::STEREO);
if global { if global {
encoder.set_flags(ffmpeg::codec::flag::GLOBAL_HEADER); encoder.set_flags(ffmpeg::codec::flag::GLOBAL_HEADER);
} }
encoder.set_rate(decoder.rate() as i32); encoder.set_rate(decoder.rate() as i32);
encoder.set_channel_layout(channel_layout); encoder.set_channel_layout(channel_layout);
encoder.set_channels(channel_layout.channels()); encoder.set_channels(channel_layout.channels());
encoder.set_format(codec.formats().expect("unknown supported formats").next().unwrap()); encoder.set_format(
encoder.set_bit_rate(decoder.bit_rate()); codec
encoder.set_max_bit_rate(decoder.max_bit_rate()); .formats()
.expect("unknown supported formats")
.next()
.unwrap(),
);
encoder.set_bit_rate(decoder.bit_rate());
encoder.set_max_bit_rate(decoder.max_bit_rate());
encoder.set_time_base((1, decoder.rate() as i32)); encoder.set_time_base((1, decoder.rate() as i32));
output.set_time_base((1, decoder.rate() as i32)); output.set_time_base((1, decoder.rate() as i32));
let encoder = try!(encoder.open_as(codec)); let encoder = encoder.open_as(codec)?;
output.set_parameters(&encoder); output.set_parameters(&encoder);
let filter = try!(filter(filter_spec, &decoder, &encoder)); let filter = filter(filter_spec, &decoder, &encoder)?;
Ok(Transcoder { Ok(Transcoder {
stream: input.index(), stream: input.index(),
filter: filter, filter: filter,
decoder: decoder, decoder: decoder,
encoder: encoder, encoder: encoder,
}) })
} }
// Transcode the `best` audio stream of the input file into a the output file while applying a // Transcode the `best` audio stream of the input file into a the output file while applying a
@ -98,70 +132,94 @@ fn transcoder<P: AsRef<Path>>(ictx: &mut format::context::Input, octx: &mut form
// Example 3: Seek to a specified position (in seconds) // Example 3: Seek to a specified position (in seconds)
// transcode-audio in.mp3 out.mp3 anull 30 // transcode-audio in.mp3 out.mp3 anull 30
fn main() { fn main() {
ffmpeg::init().unwrap(); ffmpeg::init().unwrap();
let input = env::args().nth(1).expect("missing input"); let input = env::args().nth(1).expect("missing input");
let output = env::args().nth(2).expect("missing output"); let output = env::args().nth(2).expect("missing output");
let filter = env::args().nth(3).unwrap_or("anull".to_owned()); let filter = env::args().nth(3).unwrap_or_else(|| "anull".to_owned());
let seek = env::args().nth(4).and_then(|s| s.parse::<i64>().ok()); let seek = env::args().nth(4).and_then(|s| s.parse::<i64>().ok());
let mut ictx = format::input(&input).unwrap(); let mut ictx = format::input(&input).unwrap();
let mut octx = format::output(&output).unwrap(); let mut octx = format::output(&output).unwrap();
let mut transcoder = transcoder(&mut ictx, &mut octx, &output, &filter).unwrap(); let mut transcoder = transcoder(&mut ictx, &mut octx, &output, &filter).unwrap();
if let Some(position) = seek { if let Some(position) = seek {
// If the position was given in seconds, rescale it to ffmpegs base timebase. // If the position was given in seconds, rescale it to ffmpegs base timebase.
let position = position.rescale((1, 1), rescale::TIME_BASE); let position = position.rescale((1, 1), rescale::TIME_BASE);
// If this seek was embedded in the transcoding loop, a call of `flush()` // If this seek was embedded in the transcoding loop, a call of `flush()`
// for every opened buffer after the successful seek would be advisable. // for every opened buffer after the successful seek would be advisable.
ictx.seek(position, ..position).unwrap(); ictx.seek(position, ..position).unwrap();
} }
octx.set_metadata(ictx.metadata().to_owned()); octx.set_metadata(ictx.metadata().to_owned());
octx.write_header().unwrap(); octx.write_header().unwrap();
let in_time_base = transcoder.decoder.time_base(); let in_time_base = transcoder.decoder.time_base();
let out_time_base = octx.stream(0).unwrap().time_base(); let out_time_base = octx.stream(0).unwrap().time_base();
let mut decoded = frame::Audio::empty(); let mut decoded = frame::Audio::empty();
let mut encoded = ffmpeg::Packet::empty(); let mut encoded = ffmpeg::Packet::empty();
for (stream, mut packet) in ictx.packets() { for (stream, mut packet) in ictx.packets() {
if stream.index() == transcoder.stream { if stream.index() == transcoder.stream {
packet.rescale_ts(stream.time_base(), in_time_base); packet.rescale_ts(stream.time_base(), in_time_base);
if let Ok(true) = transcoder.decoder.decode(&packet, &mut decoded) { if let Ok(true) = transcoder.decoder.decode(&packet, &mut decoded) {
let timestamp = decoded.timestamp(); let timestamp = decoded.timestamp();
decoded.set_pts(timestamp); decoded.set_pts(timestamp);
transcoder.filter.get("in").unwrap().source().add(&decoded).unwrap(); transcoder
.filter
.get("in")
.unwrap()
.source()
.add(&decoded)
.unwrap();
while let Ok(..) = transcoder.filter.get("out").unwrap().sink().frame(&mut decoded) { while let Ok(..) = transcoder
if let Ok(true) = transcoder.encoder.encode(&decoded, &mut encoded) { .filter
encoded.set_stream(0); .get("out")
encoded.rescale_ts(in_time_base, out_time_base); .unwrap()
encoded.write_interleaved(&mut octx).unwrap(); .sink()
} .frame(&mut decoded)
} {
} if let Ok(true) = transcoder.encoder.encode(&decoded, &mut encoded) {
} encoded.set_stream(0);
} encoded.rescale_ts(in_time_base, out_time_base);
encoded.write_interleaved(&mut octx).unwrap();
}
}
}
}
}
transcoder.filter.get("in").unwrap().source().flush().unwrap(); transcoder
.filter
.get("in")
.unwrap()
.source()
.flush()
.unwrap();
while let Ok(..) = transcoder.filter.get("out").unwrap().sink().frame(&mut decoded) { while let Ok(..) = transcoder
if let Ok(true) = transcoder.encoder.encode(&decoded, &mut encoded) { .filter
encoded.set_stream(0); .get("out")
encoded.rescale_ts(in_time_base, out_time_base); .unwrap()
encoded.write_interleaved(&mut octx).unwrap(); .sink()
} .frame(&mut decoded)
} {
if let Ok(true) = transcoder.encoder.encode(&decoded, &mut encoded) {
encoded.set_stream(0);
encoded.rescale_ts(in_time_base, out_time_base);
encoded.write_interleaved(&mut octx).unwrap();
}
}
if let Ok(true) = transcoder.encoder.flush(&mut encoded) { if let Ok(true) = transcoder.encoder.flush(&mut encoded) {
encoded.set_stream(0); encoded.set_stream(0);
encoded.rescale_ts(in_time_base, out_time_base); encoded.rescale_ts(in_time_base, out_time_base);
encoded.write_interleaved(&mut octx).unwrap(); encoded.write_interleaved(&mut octx).unwrap();
} }
octx.write_trailer().unwrap(); octx.write_trailer().unwrap();
} }

View File

@ -1,152 +1,149 @@
use std::ops::Deref; use std::ops::Deref;
use {ChannelLayout, format};
use super::codec::Codec; use super::codec::Codec;
use ffi::*; use ffi::*;
use {format, ChannelLayout};
#[derive(PartialEq, Eq, Copy, Clone)] #[derive(PartialEq, Eq, Copy, Clone)]
pub struct Audio { pub struct Audio {
codec: Codec, codec: Codec,
} }
impl Audio { impl Audio {
pub unsafe fn new(codec: Codec) -> Audio { pub unsafe fn new(codec: Codec) -> Audio {
Audio { Audio { codec: codec }
codec: codec, }
}
}
} }
impl Audio { impl Audio {
pub fn rates(&self) -> Option<RateIter> { pub fn rates(&self) -> Option<RateIter> {
unsafe { unsafe {
if (*self.as_ptr()).supported_samplerates.is_null() { if (*self.as_ptr()).supported_samplerates.is_null() {
None None
} } else {
else { Some(RateIter::new((*self.codec.as_ptr()).supported_samplerates))
Some(RateIter::new((*self.codec.as_ptr()).supported_samplerates)) }
} }
} }
}
pub fn formats(&self) -> Option<FormatIter> { pub fn formats(&self) -> Option<FormatIter> {
unsafe { unsafe {
if (*self.codec.as_ptr()).sample_fmts.is_null() { if (*self.codec.as_ptr()).sample_fmts.is_null() {
None None
} } else {
else { Some(FormatIter::new((*self.codec.as_ptr()).sample_fmts))
Some(FormatIter::new((*self.codec.as_ptr()).sample_fmts)) }
} }
} }
}
pub fn channel_layouts(&self) -> Option<ChannelLayoutIter> { pub fn channel_layouts(&self) -> Option<ChannelLayoutIter> {
unsafe { unsafe {
if (*self.codec.as_ptr()).channel_layouts.is_null() { if (*self.codec.as_ptr()).channel_layouts.is_null() {
None None
} } else {
else { Some(ChannelLayoutIter::new(
Some(ChannelLayoutIter::new((*self.codec.as_ptr()).channel_layouts)) (*self.codec.as_ptr()).channel_layouts,
} ))
} }
} }
}
} }
impl Deref for Audio { impl Deref for Audio {
type Target = Codec; type Target = Codec;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.codec &self.codec
} }
} }
pub struct RateIter { pub struct RateIter {
ptr: *const i32, ptr: *const i32,
} }
impl RateIter { impl RateIter {
pub fn new(ptr: *const i32) -> Self { pub fn new(ptr: *const i32) -> Self {
RateIter { ptr: ptr } RateIter { ptr: ptr }
} }
} }
impl Iterator for RateIter { impl Iterator for RateIter {
type Item = i32; type Item = i32;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if *self.ptr == 0 { if *self.ptr == 0 {
return None; return None;
} }
let rate = *self.ptr; let rate = *self.ptr;
self.ptr = self.ptr.offset(1); self.ptr = self.ptr.offset(1);
Some(rate) Some(rate)
} }
} }
} }
pub struct FormatIter { pub struct FormatIter {
ptr: *const AVSampleFormat, ptr: *const AVSampleFormat,
} }
impl FormatIter { impl FormatIter {
pub fn new(ptr: *const AVSampleFormat) -> Self { pub fn new(ptr: *const AVSampleFormat) -> Self {
FormatIter { ptr: ptr } FormatIter { ptr: ptr }
} }
} }
impl Iterator for FormatIter { impl Iterator for FormatIter {
type Item = format::Sample; type Item = format::Sample;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if *self.ptr == AVSampleFormat::AV_SAMPLE_FMT_NONE { if *self.ptr == AVSampleFormat::AV_SAMPLE_FMT_NONE {
return None; return None;
} }
let format = (*self.ptr).into(); let format = (*self.ptr).into();
self.ptr = self.ptr.offset(1); self.ptr = self.ptr.offset(1);
Some(format) Some(format)
} }
} }
} }
pub struct ChannelLayoutIter { pub struct ChannelLayoutIter {
ptr: *const u64, ptr: *const u64,
} }
impl ChannelLayoutIter { impl ChannelLayoutIter {
pub fn new(ptr: *const u64) -> Self { pub fn new(ptr: *const u64) -> Self {
ChannelLayoutIter { ptr: ptr } ChannelLayoutIter { ptr: ptr }
} }
pub fn best(self, max: i32) -> ChannelLayout { pub fn best(self, max: i32) -> ChannelLayout {
self.fold(::channel_layout::MONO, |acc, cur| self.fold(::channel_layout::MONO, |acc, cur| {
if cur.channels() > acc.channels() && cur.channels() <= max { if cur.channels() > acc.channels() && cur.channels() <= max {
cur cur
} } else {
else { acc
acc }
}) })
} }
} }
impl Iterator for ChannelLayoutIter { impl Iterator for ChannelLayoutIter {
type Item = ChannelLayout; type Item = ChannelLayout;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if *self.ptr == 0 { if *self.ptr == 0 {
return None; return None;
} }
let layout = ChannelLayout::from_bits_truncate(*self.ptr); let layout = ChannelLayout::from_bits_truncate(*self.ptr);
self.ptr = self.ptr.offset(1); self.ptr = self.ptr.offset(1);
Some(layout) Some(layout)
} }
} }
} }

View File

@ -1,48 +1,48 @@
use ffi::*;
use ffi::AVAudioServiceType::*; use ffi::AVAudioServiceType::*;
use ffi::*;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum AudioService { pub enum AudioService {
Main, Main,
Effects, Effects,
VisuallyImpaired, VisuallyImpaired,
HearingImpaired, HearingImpaired,
Dialogue, Dialogue,
Commentary, Commentary,
Emergency, Emergency,
VoiceOver, VoiceOver,
Karaoke, Karaoke,
} }
impl From<AVAudioServiceType> for AudioService { impl From<AVAudioServiceType> for AudioService {
fn from(value: AVAudioServiceType) -> Self { fn from(value: AVAudioServiceType) -> Self {
match value { match value {
AV_AUDIO_SERVICE_TYPE_MAIN => AudioService::Main, AV_AUDIO_SERVICE_TYPE_MAIN => AudioService::Main,
AV_AUDIO_SERVICE_TYPE_EFFECTS => AudioService::Effects, AV_AUDIO_SERVICE_TYPE_EFFECTS => AudioService::Effects,
AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED => AudioService::VisuallyImpaired, AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED => AudioService::VisuallyImpaired,
AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED => AudioService::HearingImpaired, AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED => AudioService::HearingImpaired,
AV_AUDIO_SERVICE_TYPE_DIALOGUE => AudioService::Dialogue, AV_AUDIO_SERVICE_TYPE_DIALOGUE => AudioService::Dialogue,
AV_AUDIO_SERVICE_TYPE_COMMENTARY => AudioService::Commentary, AV_AUDIO_SERVICE_TYPE_COMMENTARY => AudioService::Commentary,
AV_AUDIO_SERVICE_TYPE_EMERGENCY => AudioService::Emergency, AV_AUDIO_SERVICE_TYPE_EMERGENCY => AudioService::Emergency,
AV_AUDIO_SERVICE_TYPE_VOICE_OVER => AudioService::VoiceOver, AV_AUDIO_SERVICE_TYPE_VOICE_OVER => AudioService::VoiceOver,
AV_AUDIO_SERVICE_TYPE_KARAOKE => AudioService::Karaoke, AV_AUDIO_SERVICE_TYPE_KARAOKE => AudioService::Karaoke,
AV_AUDIO_SERVICE_TYPE_NB => AudioService::Main AV_AUDIO_SERVICE_TYPE_NB => AudioService::Main,
} }
} }
} }
impl Into<AVAudioServiceType> for AudioService { impl Into<AVAudioServiceType> for AudioService {
fn into(self) -> AVAudioServiceType { fn into(self) -> AVAudioServiceType {
match self { match self {
AudioService::Main => AV_AUDIO_SERVICE_TYPE_MAIN, AudioService::Main => AV_AUDIO_SERVICE_TYPE_MAIN,
AudioService::Effects => AV_AUDIO_SERVICE_TYPE_EFFECTS, AudioService::Effects => AV_AUDIO_SERVICE_TYPE_EFFECTS,
AudioService::VisuallyImpaired => AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED, AudioService::VisuallyImpaired => AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED,
AudioService::HearingImpaired => AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED, AudioService::HearingImpaired => AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED,
AudioService::Dialogue => AV_AUDIO_SERVICE_TYPE_DIALOGUE, AudioService::Dialogue => AV_AUDIO_SERVICE_TYPE_DIALOGUE,
AudioService::Commentary => AV_AUDIO_SERVICE_TYPE_COMMENTARY, AudioService::Commentary => AV_AUDIO_SERVICE_TYPE_COMMENTARY,
AudioService::Emergency => AV_AUDIO_SERVICE_TYPE_EMERGENCY, AudioService::Emergency => AV_AUDIO_SERVICE_TYPE_EMERGENCY,
AudioService::VoiceOver => AV_AUDIO_SERVICE_TYPE_VOICE_OVER, AudioService::VoiceOver => AV_AUDIO_SERVICE_TYPE_VOICE_OVER,
AudioService::Karaoke => AV_AUDIO_SERVICE_TYPE_KARAOKE AudioService::Karaoke => AV_AUDIO_SERVICE_TYPE_KARAOKE,
} }
} }
} }

View File

@ -1,23 +1,23 @@
use libc::c_uint;
use ffi::*; use ffi::*;
use libc::c_uint;
bitflags! { bitflags! {
pub struct Capabilities: c_uint { pub struct Capabilities: c_uint {
const DRAW_HORIZ_BAND = AV_CODEC_CAP_DRAW_HORIZ_BAND; const DRAW_HORIZ_BAND = AV_CODEC_CAP_DRAW_HORIZ_BAND;
const DR1 = AV_CODEC_CAP_DR1; const DR1 = AV_CODEC_CAP_DR1;
const TRUNCATED = AV_CODEC_CAP_TRUNCATED; const TRUNCATED = AV_CODEC_CAP_TRUNCATED;
const DELAY = AV_CODEC_CAP_DELAY; const DELAY = AV_CODEC_CAP_DELAY;
const SMALL_LAST_FRAME = AV_CODEC_CAP_SMALL_LAST_FRAME; const SMALL_LAST_FRAME = AV_CODEC_CAP_SMALL_LAST_FRAME;
const HWACCEL_VDPAU = AV_CODEC_CAP_HWACCEL_VDPAU; const HWACCEL_VDPAU = AV_CODEC_CAP_HWACCEL_VDPAU;
const SUBFRAMES = AV_CODEC_CAP_SUBFRAMES; const SUBFRAMES = AV_CODEC_CAP_SUBFRAMES;
const EXPERIMENTAL = AV_CODEC_CAP_EXPERIMENTAL; const EXPERIMENTAL = AV_CODEC_CAP_EXPERIMENTAL;
const CHANNEL_CONF = AV_CODEC_CAP_CHANNEL_CONF; const CHANNEL_CONF = AV_CODEC_CAP_CHANNEL_CONF;
const FRAME_THREADS = AV_CODEC_CAP_FRAME_THREADS; const FRAME_THREADS = AV_CODEC_CAP_FRAME_THREADS;
const SLICE_THREADS = AV_CODEC_CAP_SLICE_THREADS; const SLICE_THREADS = AV_CODEC_CAP_SLICE_THREADS;
const PARAM_CHANGE = AV_CODEC_CAP_PARAM_CHANGE; const PARAM_CHANGE = AV_CODEC_CAP_PARAM_CHANGE;
const AUTO_THREADS = AV_CODEC_CAP_AUTO_THREADS; const AUTO_THREADS = AV_CODEC_CAP_AUTO_THREADS;
const VARIABLE_FRAME_SIZE = AV_CODEC_CAP_VARIABLE_FRAME_SIZE; const VARIABLE_FRAME_SIZE = AV_CODEC_CAP_VARIABLE_FRAME_SIZE;
const INTRA_ONLY = AV_CODEC_CAP_INTRA_ONLY; const INTRA_ONLY = AV_CODEC_CAP_INTRA_ONLY;
const LOSSLESS = AV_CODEC_CAP_LOSSLESS; const LOSSLESS = AV_CODEC_CAP_LOSSLESS;
} }
} }

View File

@ -1,147 +1,128 @@
use std::ffi::CStr; use std::ffi::CStr;
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;
use super::{Audio, Capabilities, Id, Profile, Video};
use ffi::*; use ffi::*;
use super::{Id, Video, Audio, Capabilities, Profile}; use {media, Error};
use ::{Error, media};
#[derive(PartialEq, Eq, Copy, Clone)] #[derive(PartialEq, Eq, Copy, Clone)]
pub struct Codec { pub struct Codec {
ptr: *mut AVCodec, ptr: *mut AVCodec,
} }
unsafe impl Send for Codec { } unsafe impl Send for Codec {}
unsafe impl Sync for Codec { } unsafe impl Sync for Codec {}
impl Codec { impl Codec {
pub unsafe fn wrap(ptr: *mut AVCodec) -> Self { pub unsafe fn wrap(ptr: *mut AVCodec) -> Self {
Codec { ptr: ptr } Codec { ptr: ptr }
} }
pub unsafe fn as_ptr(&self) -> *const AVCodec { pub unsafe fn as_ptr(&self) -> *const AVCodec {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodec { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodec {
self.ptr self.ptr
} }
} }
impl Codec { impl Codec {
pub fn is_encoder(&self) -> bool { pub fn is_encoder(&self) -> bool {
unsafe { unsafe { av_codec_is_encoder(self.as_ptr()) != 0 }
av_codec_is_encoder(self.as_ptr()) != 0 }
}
}
pub fn is_decoder(&self) -> bool { pub fn is_decoder(&self) -> bool {
unsafe { unsafe { av_codec_is_decoder(self.as_ptr()) != 0 }
av_codec_is_decoder(self.as_ptr()) != 0 }
}
}
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) }
}
}
pub fn description(&self) -> &str { pub fn description(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).long_name).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).long_name).to_bytes()) }
}
}
pub fn medium(&self) -> media::Type { pub fn medium(&self) -> media::Type {
unsafe { unsafe { media::Type::from((*self.as_ptr()).type_) }
media::Type::from((*self.as_ptr()).type_) }
}
}
pub fn id(&self) -> Id { pub fn id(&self) -> Id {
unsafe { unsafe { Id::from((*self.as_ptr()).id) }
Id::from((*self.as_ptr()).id) }
}
}
pub fn is_video(&self) -> bool { pub fn is_video(&self) -> bool {
self.medium() == media::Type::Video self.medium() == media::Type::Video
} }
pub fn video(self) -> Result<Video, Error> { pub fn video(self) -> Result<Video, Error> {
unsafe { unsafe {
if self.medium() == media::Type::Video { if self.medium() == media::Type::Video {
Ok(Video::new(self)) Ok(Video::new(self))
} } else {
else { Err(Error::InvalidData)
Err(Error::InvalidData) }
} }
} }
}
pub fn is_audio(&self) -> bool { pub fn is_audio(&self) -> bool {
self.medium() == media::Type::Audio self.medium() == media::Type::Audio
} }
pub fn audio(self) -> Result<Audio, Error> { pub fn audio(self) -> Result<Audio, Error> {
unsafe { unsafe {
if self.medium() == media::Type::Audio { if self.medium() == media::Type::Audio {
Ok(Audio::new(self)) Ok(Audio::new(self))
} } else {
else { Err(Error::InvalidData)
Err(Error::InvalidData) }
} }
} }
}
pub fn max_lowres(&self) -> i32 { pub fn max_lowres(&self) -> i32 {
unsafe { unsafe { av_codec_get_max_lowres(self.as_ptr()) }
av_codec_get_max_lowres(self.as_ptr()) }
}
}
pub fn capabilities(&self) -> Capabilities { pub fn capabilities(&self) -> Capabilities {
unsafe { unsafe { Capabilities::from_bits_truncate((*self.as_ptr()).capabilities as u32) }
Capabilities::from_bits_truncate((*self.as_ptr()).capabilities as u32) }
}
}
pub fn profiles(&self) -> Option<ProfileIter> { pub fn profiles(&self) -> Option<ProfileIter> {
unsafe { unsafe {
if (*self.as_ptr()).profiles.is_null() { if (*self.as_ptr()).profiles.is_null() {
None None
} } else {
else { Some(ProfileIter::new(self.id(), (*self.as_ptr()).profiles))
Some(ProfileIter::new(self.id(), (*self.as_ptr()).profiles)) }
} }
} }
}
} }
pub struct ProfileIter { pub struct ProfileIter {
id: Id, id: Id,
ptr: *const AVProfile, ptr: *const AVProfile,
} }
impl ProfileIter { impl ProfileIter {
pub fn new(id: Id, ptr: *const AVProfile) -> Self { pub fn new(id: Id, ptr: *const AVProfile) -> Self {
ProfileIter { id: id, ptr: ptr } ProfileIter { id: id, ptr: ptr }
} }
} }
impl Iterator for ProfileIter { impl Iterator for ProfileIter {
type Item = Profile; type Item = Profile;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if (*self.ptr).profile == FF_PROFILE_UNKNOWN { if (*self.ptr).profile == FF_PROFILE_UNKNOWN {
return None; return None;
} }
let profile = Profile::from((self.id, (*self.ptr).profile)); let profile = Profile::from((self.id, (*self.ptr).profile));
self.ptr = self.ptr.offset(1); self.ptr = self.ptr.offset(1);
Some(profile) Some(profile)
} }
} }
} }

View File

@ -1,37 +1,37 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum Compliance { pub enum Compliance {
VeryStrict, VeryStrict,
Strict, Strict,
Normal, Normal,
Unofficial, Unofficial,
Experimental, Experimental,
} }
impl From<c_int> for Compliance { impl From<c_int> for Compliance {
fn from(value: c_int) -> Self { fn from(value: c_int) -> Self {
match value { match value {
FF_COMPLIANCE_VERY_STRICT => Compliance::VeryStrict, FF_COMPLIANCE_VERY_STRICT => Compliance::VeryStrict,
FF_COMPLIANCE_STRICT => Compliance::Strict, FF_COMPLIANCE_STRICT => Compliance::Strict,
FF_COMPLIANCE_NORMAL => Compliance::Normal, FF_COMPLIANCE_NORMAL => Compliance::Normal,
FF_COMPLIANCE_UNOFFICIAL => Compliance::Unofficial, FF_COMPLIANCE_UNOFFICIAL => Compliance::Unofficial,
FF_COMPLIANCE_EXPERIMENTAL => Compliance::Experimental, FF_COMPLIANCE_EXPERIMENTAL => Compliance::Experimental,
_ => Compliance::Normal _ => Compliance::Normal,
} }
} }
} }
impl Into<c_int> for Compliance { impl Into<c_int> for Compliance {
fn into(self) -> c_int { fn into(self) -> c_int {
match self { match self {
Compliance::VeryStrict => FF_COMPLIANCE_VERY_STRICT, Compliance::VeryStrict => FF_COMPLIANCE_VERY_STRICT,
Compliance::Strict => FF_COMPLIANCE_STRICT, Compliance::Strict => FF_COMPLIANCE_STRICT,
Compliance::Normal => FF_COMPLIANCE_NORMAL, Compliance::Normal => FF_COMPLIANCE_NORMAL,
Compliance::Unofficial => FF_COMPLIANCE_UNOFFICIAL, Compliance::Unofficial => FF_COMPLIANCE_UNOFFICIAL,
Compliance::Experimental => FF_COMPLIANCE_EXPERIMENTAL Compliance::Experimental => FF_COMPLIANCE_EXPERIMENTAL,
} }
} }
} }

View File

@ -1,142 +1,149 @@
use std::ptr; use std::ptr;
use std::rc::Rc; use std::rc::Rc;
use libc::c_int;
use ffi::*;
use ::media;
use ::{Codec, Error};
use super::{Flags, Id, Debug, Compliance, threading, Parameters};
use super::decoder::Decoder; use super::decoder::Decoder;
use super::encoder::Encoder; use super::encoder::Encoder;
use super::{threading, Compliance, Debug, Flags, Id, Parameters};
use ffi::*;
use libc::c_int;
use media;
use {Codec, Error};
pub struct Context { pub struct Context {
ptr: *mut AVCodecContext, ptr: *mut AVCodecContext,
owner: Option<Rc<Drop>>, owner: Option<Rc<Drop>>,
} }
unsafe impl Send for Context { } unsafe impl Send for Context {}
impl Context { impl Context {
pub unsafe fn wrap(ptr: *mut AVCodecContext, owner: Option<Rc<Drop>>) -> Self { pub unsafe fn wrap(ptr: *mut AVCodecContext, owner: Option<Rc<Drop>>) -> Self {
Context { ptr: ptr, owner: owner } Context {
} ptr: ptr,
owner: owner,
}
}
pub unsafe fn as_ptr(&self) -> *const AVCodecContext { pub unsafe fn as_ptr(&self) -> *const AVCodecContext {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodecContext { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodecContext {
self.ptr self.ptr
} }
} }
impl Context { impl Context {
pub fn new() -> Self { pub fn new() -> Self {
unsafe { unsafe {
Context { ptr: avcodec_alloc_context3(ptr::null()), owner: None } Context {
} ptr: avcodec_alloc_context3(ptr::null()),
} owner: None,
}
}
}
pub fn decoder(self) -> Decoder { pub fn decoder(self) -> Decoder {
Decoder(self) Decoder(self)
} }
pub fn encoder(self) -> Encoder { pub fn encoder(self) -> Encoder {
Encoder(self) Encoder(self)
} }
pub fn codec(&self) -> Option<Codec> { pub fn codec(&self) -> Option<Codec> {
unsafe { unsafe {
if (*self.as_ptr()).codec.is_null() { if (*self.as_ptr()).codec.is_null() {
None None
} } else {
else { Some(Codec::wrap((*self.as_ptr()).codec as *mut _))
Some(Codec::wrap((*self.as_ptr()).codec as *mut _)) }
} }
} }
}
pub fn medium(&self) -> media::Type { pub fn medium(&self) -> media::Type {
unsafe { unsafe { media::Type::from((*self.as_ptr()).codec_type) }
media::Type::from((*self.as_ptr()).codec_type) }
}
}
pub fn set_flags(&mut self, value: Flags) { pub fn set_flags(&mut self, value: Flags) {
unsafe { unsafe {
(*self.as_mut_ptr()).flags = value.bits() as c_int; (*self.as_mut_ptr()).flags = value.bits() as c_int;
} }
} }
pub fn id(&self) -> Id { pub fn id(&self) -> Id {
unsafe { unsafe { Id::from((*self.as_ptr()).codec_id) }
Id::from((*self.as_ptr()).codec_id) }
}
}
pub fn compliance(&mut self, value: Compliance) { pub fn compliance(&mut self, value: Compliance) {
unsafe { unsafe {
(*self.as_mut_ptr()).strict_std_compliance = value.into(); (*self.as_mut_ptr()).strict_std_compliance = value.into();
} }
} }
pub fn debug(&mut self, value: Debug) { pub fn debug(&mut self, value: Debug) {
unsafe { unsafe {
(*self.as_mut_ptr()).debug = value.bits(); (*self.as_mut_ptr()).debug = value.bits();
} }
} }
pub fn set_threading(&mut self, config: threading::Config) { pub fn set_threading(&mut self, config: threading::Config) {
unsafe { unsafe {
(*self.as_mut_ptr()).thread_type = config.kind.into(); (*self.as_mut_ptr()).thread_type = config.kind.into();
(*self.as_mut_ptr()).thread_count = config.count as c_int; (*self.as_mut_ptr()).thread_count = config.count as c_int;
(*self.as_mut_ptr()).thread_safe_callbacks = if config.safe { 1 } else { 0 }; (*self.as_mut_ptr()).thread_safe_callbacks = if config.safe { 1 } else { 0 };
} }
} }
pub fn threading(&self) -> threading::Config { pub fn threading(&self) -> threading::Config {
unsafe { unsafe {
threading::Config { threading::Config {
kind: threading::Type::from((*self.as_ptr()).active_thread_type), kind: threading::Type::from((*self.as_ptr()).active_thread_type),
count: (*self.as_ptr()).thread_count as usize, count: (*self.as_ptr()).thread_count as usize,
safe: (*self.as_ptr()).thread_safe_callbacks != 0, safe: (*self.as_ptr()).thread_safe_callbacks != 0,
} }
} }
} }
pub fn set_parameters<P: Into<Parameters>>(&mut self, parameters: P) -> Result<(), Error> { pub fn set_parameters<P: Into<Parameters>>(&mut self, parameters: P) -> Result<(), Error> {
let parameters = parameters.into(); let parameters = parameters.into();
unsafe { unsafe {
match avcodec_parameters_to_context(self.as_mut_ptr(), parameters.as_ptr()) { match avcodec_parameters_to_context(self.as_mut_ptr(), parameters.as_ptr()) {
e if e < 0 => Err(Error::from(e)), e if e < 0 => Err(Error::from(e)),
_ => Ok(()), _ => Ok(()),
} }
} }
} }
}
impl Default for Context {
fn default() -> Self {
Self::new()
}
} }
impl Drop for Context { impl Drop for Context {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
if self.owner.is_none() { if self.owner.is_none() {
avcodec_free_context(&mut self.as_mut_ptr()); avcodec_free_context(&mut self.as_mut_ptr());
} }
} }
} }
} }
impl Clone for Context { impl Clone for Context {
fn clone(&self) -> Self { fn clone(&self) -> Self {
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.clone_from(self); ctx.clone_from(self);
ctx ctx
} }
fn clone_from(&mut self, source: &Self) { fn clone_from(&mut self, source: &Self) {
unsafe { unsafe {
avcodec_copy_context(self.as_mut_ptr(), source.as_ptr()); avcodec_copy_context(self.as_mut_ptr(), source.as_ptr());
} }
} }
} }

View File

@ -1,25 +1,25 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Debug: c_int { pub struct Debug: c_int {
const PICT_INFO = FF_DEBUG_PICT_INFO; const PICT_INFO = FF_DEBUG_PICT_INFO;
const RC = FF_DEBUG_RC; const RC = FF_DEBUG_RC;
const BITSTREAM = FF_DEBUG_BITSTREAM; const BITSTREAM = FF_DEBUG_BITSTREAM;
const MB_TYPE = FF_DEBUG_MB_TYPE; const MB_TYPE = FF_DEBUG_MB_TYPE;
const QP = FF_DEBUG_QP; const QP = FF_DEBUG_QP;
const MV = FF_DEBUG_MV; const MV = FF_DEBUG_MV;
const DCT_COEFF = FF_DEBUG_DCT_COEFF; const DCT_COEFF = FF_DEBUG_DCT_COEFF;
const SKIP = FF_DEBUG_SKIP; const SKIP = FF_DEBUG_SKIP;
const STARTCODE = FF_DEBUG_STARTCODE; const STARTCODE = FF_DEBUG_STARTCODE;
const PTS = FF_DEBUG_PTS; const PTS = FF_DEBUG_PTS;
const ER = FF_DEBUG_ER; const ER = FF_DEBUG_ER;
const MMCO = FF_DEBUG_MMCO; const MMCO = FF_DEBUG_MMCO;
const BUGS = FF_DEBUG_BUGS; const BUGS = FF_DEBUG_BUGS;
const VIS_QP = FF_DEBUG_VIS_QP; const VIS_QP = FF_DEBUG_VIS_QP;
const VIS_MB_TYPE = FF_DEBUG_VIS_MB_TYPE; const VIS_MB_TYPE = FF_DEBUG_VIS_MB_TYPE;
const BUFFERS = FF_DEBUG_BUFFERS; const BUFFERS = FF_DEBUG_BUFFERS;
const THREADS = FF_DEBUG_THREADS; const THREADS = FF_DEBUG_THREADS;
const NOMC = FF_DEBUG_NOMC; const NOMC = FF_DEBUG_NOMC;
} }
} }

View File

@ -1,132 +1,123 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
use super::Opened; use super::Opened;
use ::{packet, Error, AudioService, ChannelLayout}; use codec::Context;
use ::frame; use frame;
use ::util::format; use util::format;
use ::codec::Context; use {packet, AudioService, ChannelLayout, Error};
pub struct Audio(pub Opened); pub struct Audio(pub Opened);
impl Audio { impl Audio {
pub fn decode<P: packet::Ref>(&mut self, packet: &P, out: &mut frame::Audio) -> Result<bool, Error> { pub fn decode<P: packet::Ref>(
unsafe { &mut self,
let mut got: c_int = 0; packet: &P,
out: &mut frame::Audio,
) -> Result<bool, Error> {
unsafe {
let mut got: c_int = 0;
match avcodec_decode_audio4(self.as_mut_ptr(), out.as_mut_ptr(), &mut got, packet.as_ptr()) { match avcodec_decode_audio4(
e if e < 0 => Err(Error::from(e)), self.as_mut_ptr(),
_ => Ok(got != 0) out.as_mut_ptr(),
} &mut got,
} packet.as_ptr(),
} ) {
e if e < 0 => Err(Error::from(e)),
_ => Ok(got != 0),
}
}
}
pub fn rate(&self) -> u32 { pub fn rate(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).sample_rate as u32 }
(*self.as_ptr()).sample_rate as u32 }
}
}
pub fn channels(&self) -> u16 { pub fn channels(&self) -> u16 {
unsafe { unsafe { (*self.as_ptr()).channels as u16 }
(*self.as_ptr()).channels as u16 }
}
}
pub fn format(&self) -> format::Sample { pub fn format(&self) -> format::Sample {
unsafe { unsafe { format::Sample::from((*self.as_ptr()).sample_fmt) }
format::Sample::from((*self.as_ptr()).sample_fmt) }
}
}
pub fn request_format(&mut self, value: format::Sample) { pub fn request_format(&mut self, value: format::Sample) {
unsafe { unsafe {
(*self.as_mut_ptr()).request_sample_fmt = value.into(); (*self.as_mut_ptr()).request_sample_fmt = value.into();
} }
} }
pub fn frames(&self) -> usize { pub fn frames(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).frame_number as usize }
(*self.as_ptr()).frame_number as usize }
}
}
pub fn align(&self) -> usize { pub fn align(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).block_align as usize }
(*self.as_ptr()).block_align as usize }
}
}
pub fn channel_layout(&self) -> ChannelLayout { pub fn channel_layout(&self) -> ChannelLayout {
unsafe { unsafe { ChannelLayout::from_bits_truncate((*self.as_ptr()).channel_layout) }
ChannelLayout::from_bits_truncate((*self.as_ptr()).channel_layout) }
}
}
pub fn set_channel_layout(&mut self, value: ChannelLayout) { pub fn set_channel_layout(&mut self, value: ChannelLayout) {
unsafe { unsafe {
(*self.as_mut_ptr()).channel_layout = value.bits(); (*self.as_mut_ptr()).channel_layout = value.bits();
} }
} }
pub fn request_channel_layout(&mut self, value: ChannelLayout) { pub fn request_channel_layout(&mut self, value: ChannelLayout) {
unsafe { unsafe {
(*self.as_mut_ptr()).request_channel_layout = value.bits(); (*self.as_mut_ptr()).request_channel_layout = value.bits();
} }
} }
pub fn audio_service(&mut self) -> AudioService { pub fn audio_service(&mut self) -> AudioService {
unsafe { unsafe { AudioService::from((*self.as_mut_ptr()).audio_service_type) }
AudioService::from((*self.as_mut_ptr()).audio_service_type) }
}
}
pub fn max_bit_rate(&self) -> usize { pub fn max_bit_rate(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).rc_max_rate as usize }
(*self.as_ptr()).rc_max_rate as usize }
}
}
pub fn frame_size(&self) -> u32 { pub fn frame_size(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).frame_size as u32 }
(*self.as_ptr()).frame_size as u32 }
}
}
pub fn frame_start(&self) -> Option<usize> { pub fn frame_start(&self) -> Option<usize> {
unsafe { unsafe {
match (*self.as_ptr()).timecode_frame_start { match (*self.as_ptr()).timecode_frame_start {
-1 => None, -1 => None,
n => Some(n as usize) n => Some(n as usize),
} }
} }
} }
} }
impl Deref for Audio { impl Deref for Audio {
type Target = Opened; type Target = Opened;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Audio { impl DerefMut for Audio {
fn deref_mut(&mut self) -> &mut<Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Audio { impl AsRef<Context> for Audio {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Audio { impl AsMut<Context> for Audio {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,16 +1,16 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Check: c_int { pub struct Check: c_int {
const CRC = AV_EF_CRCCHECK; const CRC = AV_EF_CRCCHECK;
const BISTREAM = AV_EF_BITSTREAM; const BISTREAM = AV_EF_BITSTREAM;
const BUFFER = AV_EF_BUFFER; const BUFFER = AV_EF_BUFFER;
const EXPLODE = AV_EF_EXPLODE; const EXPLODE = AV_EF_EXPLODE;
const IGNORE_ERROR = AV_EF_IGNORE_ERR; const IGNORE_ERROR = AV_EF_IGNORE_ERR;
const CAREFUL = AV_EF_CAREFUL; const CAREFUL = AV_EF_CAREFUL;
const COMPLIANT = AV_EF_COMPLIANT; const COMPLIANT = AV_EF_COMPLIANT;
const AGGRESSIVE = AV_EF_AGGRESSIVE; const AGGRESSIVE = AV_EF_AGGRESSIVE;
} }
} }

View File

@ -1,10 +1,10 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Conceal: c_int { pub struct Conceal: c_int {
const GUESS_MVS = FF_EC_GUESS_MVS; const GUESS_MVS = FF_EC_GUESS_MVS;
const DEBLOCK = FF_EC_DEBLOCK; const DEBLOCK = FF_EC_DEBLOCK;
const FAVOR_INTER = FF_EC_FAVOR_INTER; const FAVOR_INTER = FF_EC_FAVOR_INTER;
} }
} }

View File

@ -1,142 +1,139 @@
use std::ptr;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr;
use super::{Audio, Check, Conceal, Opened, Subtitle, Video};
use codec::{traits, Context};
use ffi::*; use ffi::*;
use codec::{Context, traits}; use {Dictionary, Discard, Error, Rational};
use super::{Opened, Video, Audio, Subtitle, Conceal, Check};
use ::{Error, Discard, Rational, Dictionary};
pub struct Decoder(pub Context); pub struct Decoder(pub Context);
impl Decoder { impl Decoder {
pub fn open(mut self) -> Result<Opened, Error> { pub fn open(mut self) -> Result<Opened, Error> {
unsafe { unsafe {
match avcodec_open2(self.as_mut_ptr(), ptr::null(), ptr::null_mut()) { match avcodec_open2(self.as_mut_ptr(), ptr::null(), ptr::null_mut()) {
0 => Ok(Opened(self)), 0 => Ok(Opened(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn open_as<D: traits::Decoder>(mut self, codec: D) -> Result<Opened, Error> { pub fn open_as<D: traits::Decoder>(mut self, codec: D) -> Result<Opened, Error> {
unsafe { unsafe {
if let Some(codec) = codec.decoder() { if let Some(codec) = codec.decoder() {
match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) { match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) {
0 => Ok(Opened(self)), 0 => Ok(Opened(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} } else {
else { Err(Error::DecoderNotFound)
Err(Error::DecoderNotFound) }
} }
} }
}
pub fn open_as_with<D: traits::Decoder>(mut self, codec: D, options: Dictionary) -> Result<Opened, Error> { pub fn open_as_with<D: traits::Decoder>(
unsafe { mut self,
if let Some(codec) = codec.decoder() { codec: D,
let mut opts = options.disown(); options: Dictionary,
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts); ) -> Result<Opened, Error> {
unsafe {
if let Some(codec) = codec.decoder() {
let mut opts = options.disown();
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => Ok(Opened(self)), 0 => Ok(Opened(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} } else {
else { Err(Error::DecoderNotFound)
Err(Error::DecoderNotFound) }
} }
} }
}
pub fn video(self) -> Result<Video, Error> { pub fn video(self) -> Result<Video, Error> {
if let Some(codec) = super::find(self.id()) { if let Some(codec) = super::find(self.id()) {
self.open_as(codec).and_then(|o| o.video()) self.open_as(codec).and_then(|o| o.video())
} } else {
else { Err(Error::DecoderNotFound)
Err(Error::DecoderNotFound) }
} }
}
pub fn audio(self) -> Result<Audio, Error> { pub fn audio(self) -> Result<Audio, Error> {
if let Some(codec) = super::find(self.id()) { if let Some(codec) = super::find(self.id()) {
self.open_as(codec).and_then(|o| o.audio()) self.open_as(codec).and_then(|o| o.audio())
} } else {
else { Err(Error::DecoderNotFound)
Err(Error::DecoderNotFound) }
} }
}
pub fn subtitle(self) -> Result<Subtitle, Error> { pub fn subtitle(self) -> Result<Subtitle, Error> {
if let Some(codec) = super::find(self.id()) { if let Some(codec) = super::find(self.id()) {
self.open_as(codec).and_then(|o| o.subtitle()) self.open_as(codec).and_then(|o| o.subtitle())
} } else {
else { Err(Error::DecoderNotFound)
Err(Error::DecoderNotFound) }
} }
}
pub fn conceal(&mut self, value: Conceal) { pub fn conceal(&mut self, value: Conceal) {
unsafe { unsafe {
(*self.as_mut_ptr()).error_concealment = value.bits(); (*self.as_mut_ptr()).error_concealment = value.bits();
} }
} }
pub fn check(&mut self, value: Check) { pub fn check(&mut self, value: Check) {
unsafe { unsafe {
(*self.as_mut_ptr()).err_recognition = value.bits(); (*self.as_mut_ptr()).err_recognition = value.bits();
} }
} }
pub fn skip_loop_filter(&mut self, value: Discard) { pub fn skip_loop_filter(&mut self, value: Discard) {
unsafe { unsafe {
(*self.as_mut_ptr()).skip_loop_filter = value.into(); (*self.as_mut_ptr()).skip_loop_filter = value.into();
} }
} }
pub fn skip_idct(&mut self, value: Discard) { pub fn skip_idct(&mut self, value: Discard) {
unsafe { unsafe {
(*self.as_mut_ptr()).skip_idct = value.into(); (*self.as_mut_ptr()).skip_idct = value.into();
} }
} }
pub fn skip_frame(&mut self, value: Discard) { pub fn skip_frame(&mut self, value: Discard) {
unsafe { unsafe {
(*self.as_mut_ptr()).skip_frame = value.into(); (*self.as_mut_ptr()).skip_frame = value.into();
} }
} }
pub fn time_base(&self) -> Rational { pub fn time_base(&self) -> Rational {
unsafe { unsafe { Rational::from((*self.as_ptr()).time_base) }
Rational::from((*self.as_ptr()).time_base) }
}
}
} }
impl Deref for Decoder { impl Deref for Decoder {
type Target = Context; type Target = Context;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Decoder { impl DerefMut for Decoder {
fn deref_mut(&mut self) -> &mut<Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Decoder { impl AsRef<Context> for Decoder {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Decoder { impl AsMut<Context> for Decoder {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }

View File

@ -23,38 +23,36 @@ pub use self::opened::Opened;
use std::ffi::CString; use std::ffi::CString;
use ffi::*;
use codec::Context; use codec::Context;
use ::Codec;
use codec::Id; use codec::Id;
use ffi::*;
use Codec;
pub fn new() -> Decoder { pub fn new() -> Decoder {
Context::new().decoder() Context::new().decoder()
} }
pub fn find(id: Id) -> Option<Codec> { pub fn find(id: Id) -> Option<Codec> {
unsafe { unsafe {
let ptr = avcodec_find_decoder(id.into()); let ptr = avcodec_find_decoder(id.into());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Codec::wrap(ptr))
Some(Codec::wrap(ptr)) }
} }
}
} }
pub fn find_by_name(name: &str) -> Option<Codec> { pub fn find_by_name(name: &str) -> Option<Codec> {
unsafe { unsafe {
let name = CString::new(name).unwrap(); let name = CString::new(name).unwrap();
let ptr = avcodec_find_decoder_by_name(name.as_ptr()); let ptr = avcodec_find_decoder_by_name(name.as_ptr());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Codec::wrap(ptr))
Some(Codec::wrap(ptr)) }
} }
}
} }

View File

@ -1,109 +1,99 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use super::{Audio, Decoder, Subtitle, Video};
use codec::{Context, Profile};
use ffi::*; use ffi::*;
use super::{Video, Audio, Subtitle, Decoder}; use media;
use ::codec::{Profile, Context}; use {Error, Rational};
use ::{Error, Rational};
use ::media;
pub struct Opened(pub Decoder); pub struct Opened(pub Decoder);
impl Opened { impl Opened {
pub fn video(self) -> Result<Video, Error> { pub fn video(self) -> Result<Video, Error> {
if self.medium() == media::Type::Video { if self.medium() == media::Type::Video {
Ok(Video(self)) Ok(Video(self))
} } else {
else { Err(Error::InvalidData)
Err(Error::InvalidData) }
} }
}
pub fn audio(self) -> Result<Audio, Error> { pub fn audio(self) -> Result<Audio, Error> {
if self.medium() == media::Type::Audio { if self.medium() == media::Type::Audio {
Ok(Audio(self)) Ok(Audio(self))
} } else {
else { Err(Error::InvalidData)
Err(Error::InvalidData) }
} }
}
pub fn subtitle(self) -> Result<Subtitle, Error> { pub fn subtitle(self) -> Result<Subtitle, Error> {
if self.medium() == media::Type::Subtitle { if self.medium() == media::Type::Subtitle {
Ok(Subtitle(self)) Ok(Subtitle(self))
} } else {
else { Err(Error::InvalidData)
Err(Error::InvalidData) }
} }
}
pub fn bit_rate(&self) -> usize { pub fn bit_rate(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).bit_rate as usize }
(*self.as_ptr()).bit_rate as usize }
}
}
pub fn delay(&self) -> usize { pub fn delay(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).delay as usize }
(*self.as_ptr()).delay as usize }
}
}
pub fn profile(&self) -> Profile { pub fn profile(&self) -> Profile {
unsafe { unsafe { Profile::from((self.id(), (*self.as_ptr()).profile)) }
Profile::from((self.id(), (*self.as_ptr()).profile)) }
}
}
pub fn frame_rate(&self) -> Option<Rational> { pub fn frame_rate(&self) -> Option<Rational> {
unsafe { unsafe {
let value = (*self.as_ptr()).framerate; let value = (*self.as_ptr()).framerate;
if value == (AVRational { num: 0, den: 1 }) { if value == (AVRational { num: 0, den: 1 }) {
None None
} } else {
else { Some(Rational::from(value))
Some(Rational::from(value)) }
} }
} }
}
pub fn flush(&mut self) { pub fn flush(&mut self) {
unsafe { unsafe {
avcodec_flush_buffers(self.as_mut_ptr()); avcodec_flush_buffers(self.as_mut_ptr());
} }
} }
} }
impl Drop for Opened { impl Drop for Opened {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
avcodec_close(self.as_mut_ptr()); avcodec_close(self.as_mut_ptr());
} }
} }
} }
impl Deref for Opened { impl Deref for Opened {
type Target = Decoder; type Target = Decoder;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Opened { impl DerefMut for Opened {
fn deref_mut(&mut self) -> &mut<Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Opened { impl AsRef<Context> for Opened {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Opened { impl AsMut<Context> for Opened {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,10 +1,10 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Flags: c_int { pub struct Flags: c_int {
const CODED_ORDER = SLICE_FLAG_CODED_ORDER; const CODED_ORDER = SLICE_FLAG_CODED_ORDER;
const ALLOW_FIELD = SLICE_FLAG_ALLOW_FIELD; const ALLOW_FIELD = SLICE_FLAG_ALLOW_FIELD;
const ALLOW_PLANE = SLICE_FLAG_ALLOW_PLANE; const ALLOW_PLANE = SLICE_FLAG_ALLOW_PLANE;
} }
} }

View File

@ -1,49 +1,58 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
use super::Opened; use super::Opened;
use ::{packet, Error}; use codec::Context;
use ::codec::Context; use {packet, Error};
pub struct Subtitle(pub Opened); pub struct Subtitle(pub Opened);
impl Subtitle { impl Subtitle {
pub fn decode<P: packet::Ref>(&mut self, packet: &P, out: &mut ::Subtitle) -> Result<bool, Error> { pub fn decode<P: packet::Ref>(
unsafe { &mut self,
let mut got: c_int = 0; packet: &P,
out: &mut ::Subtitle,
) -> Result<bool, Error> {
unsafe {
let mut got: c_int = 0;
match avcodec_decode_subtitle2(self.as_mut_ptr(), out.as_mut_ptr(), &mut got, packet.as_ptr() as *mut _) { match avcodec_decode_subtitle2(
e if e < 0 => Err(Error::from(e)), self.as_mut_ptr(),
_ => Ok(got != 0) out.as_mut_ptr(),
} &mut got,
} packet.as_ptr() as *mut _,
} ) {
e if e < 0 => Err(Error::from(e)),
_ => Ok(got != 0),
}
}
}
} }
impl Deref for Subtitle { impl Deref for Subtitle {
type Target = Opened; type Target = Opened;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Subtitle { impl DerefMut for Subtitle {
fn deref_mut(&mut self) -> &mut<Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Subtitle { impl AsRef<Context> for Subtitle {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Subtitle { impl AsMut<Context> for Subtitle {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,164 +1,147 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
use super::{Opened, slice}; use super::{slice, Opened};
use ::{packet, Error, Rational, FieldOrder}; use codec::Context;
use ::frame; use color;
use ::util::format; use frame;
use ::util::chroma; use util::chroma;
use ::color; use util::format;
use ::codec::Context; use {packet, Error, FieldOrder, Rational};
pub struct Video(pub Opened); pub struct Video(pub Opened);
impl Video { impl Video {
pub fn decode<P: packet::Ref>(&mut self, packet: &P, out: &mut frame::Video) -> Result<bool, Error> { pub fn decode<P: packet::Ref>(
unsafe { &mut self,
let mut got: c_int = 0; packet: &P,
out: &mut frame::Video,
) -> Result<bool, Error> {
unsafe {
let mut got: c_int = 0;
match avcodec_decode_video2(self.as_mut_ptr(), out.as_mut_ptr(), &mut got, packet.as_ptr()) { match avcodec_decode_video2(
e if e < 0 => Err(Error::from(e)), self.as_mut_ptr(),
_ => Ok(got != 0) out.as_mut_ptr(),
} &mut got,
} packet.as_ptr(),
} ) {
e if e < 0 => Err(Error::from(e)),
_ => Ok(got != 0),
}
}
}
pub fn width(&self) -> u32 { pub fn width(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).width as u32 }
(*self.as_ptr()).width as u32 }
}
}
pub fn height(&self) -> u32 { pub fn height(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).height as u32 }
(*self.as_ptr()).height as u32 }
}
}
pub fn format(&self) -> format::Pixel { pub fn format(&self) -> format::Pixel {
unsafe { unsafe { format::Pixel::from((*self.as_ptr()).pix_fmt) }
format::Pixel::from((*self.as_ptr()).pix_fmt) }
}
}
pub fn has_b_frames(&self) -> bool { pub fn has_b_frames(&self) -> bool {
unsafe { unsafe { (*self.as_ptr()).has_b_frames != 0 }
(*self.as_ptr()).has_b_frames != 0 }
}
}
pub fn aspect_ratio(&self) -> Rational { pub fn aspect_ratio(&self) -> Rational {
unsafe { unsafe { Rational::from((*self.as_ptr()).sample_aspect_ratio) }
Rational::from((*self.as_ptr()).sample_aspect_ratio) }
}
}
pub fn color_space(&self) -> color::Space { pub fn color_space(&self) -> color::Space {
unsafe { unsafe { color::Space::from((*self.as_ptr()).colorspace) }
color::Space::from((*self.as_ptr()).colorspace) }
}
}
pub fn color_range(&self) -> color::Range { pub fn color_range(&self) -> color::Range {
unsafe { unsafe { color::Range::from((*self.as_ptr()).color_range) }
color::Range::from((*self.as_ptr()).color_range) }
}
}
pub fn color_primaries(&self) -> color::Primaries { pub fn color_primaries(&self) -> color::Primaries {
unsafe { unsafe { color::Primaries::from((*self.as_ptr()).color_primaries) }
color::Primaries::from((*self.as_ptr()).color_primaries) }
}
}
pub fn color_transfer_characteristic(&self) -> color::TransferCharacteristic { pub fn color_transfer_characteristic(&self) -> color::TransferCharacteristic {
unsafe { unsafe { color::TransferCharacteristic::from((*self.as_ptr()).color_trc) }
color::TransferCharacteristic::from((*self.as_ptr()).color_trc) }
}
}
pub fn chroma_location(&self) -> chroma::Location { pub fn chroma_location(&self) -> chroma::Location {
unsafe { unsafe { chroma::Location::from((*self.as_ptr()).chroma_sample_location) }
chroma::Location::from((*self.as_ptr()).chroma_sample_location) }
}
}
pub fn set_slice_count(&mut self, value: usize) { pub fn set_slice_count(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).slice_count = value as c_int; (*self.as_mut_ptr()).slice_count = value as c_int;
} }
} }
pub fn set_slice_flags(&mut self, value: slice::Flags) { pub fn set_slice_flags(&mut self, value: slice::Flags) {
unsafe { unsafe {
(*self.as_mut_ptr()).slice_flags = value.bits(); (*self.as_mut_ptr()).slice_flags = value.bits();
} }
} }
pub fn skip_top(&mut self, value: usize) { pub fn skip_top(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).skip_top = value as c_int; (*self.as_mut_ptr()).skip_top = value as c_int;
} }
} }
pub fn skip_bottom(&mut self, value: usize) { pub fn skip_bottom(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).skip_bottom = value as c_int; (*self.as_mut_ptr()).skip_bottom = value as c_int;
} }
} }
pub fn references(&self) -> usize { pub fn references(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).refs as usize }
(*self.as_ptr()).refs as usize }
}
}
pub fn set_field_order(&mut self, value: FieldOrder) { pub fn set_field_order(&mut self, value: FieldOrder) {
unsafe { unsafe {
(*self.as_mut_ptr()).field_order = value.into(); (*self.as_mut_ptr()).field_order = value.into();
} }
} }
// intra_matrix // intra_matrix
// inter_matrix // inter_matrix
pub fn intra_dc_precision(&self) -> u8 { pub fn intra_dc_precision(&self) -> u8 {
unsafe { unsafe { (*self.as_ptr()).intra_dc_precision as u8 }
(*self.as_ptr()).intra_dc_precision as u8 }
}
}
pub fn max_bit_rate(&self) -> usize { pub fn max_bit_rate(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).rc_max_rate as usize }
(*self.as_ptr()).rc_max_rate as usize }
}
}
} }
impl Deref for Video { impl Deref for Video {
type Target = Opened; type Target = Opened;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Video { impl DerefMut for Video {
fn deref_mut(&mut self) -> &mut<Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Video { impl AsRef<Context> for Video {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Video { impl AsMut<Context> for Video {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,41 +1,41 @@
use ffi::*;
use ffi::AVDiscard::*; use ffi::AVDiscard::*;
use ffi::*;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum Discard { pub enum Discard {
None, None,
Default, Default,
NonReference, NonReference,
Bidirectional, Bidirectional,
NonIntra, NonIntra,
NonKey, NonKey,
All, All,
} }
impl From<AVDiscard> for Discard { impl From<AVDiscard> for Discard {
fn from(value: AVDiscard) -> Self { fn from(value: AVDiscard) -> Self {
match value { match value {
AVDISCARD_NONE => Discard::None, AVDISCARD_NONE => Discard::None,
AVDISCARD_DEFAULT => Discard::Default, AVDISCARD_DEFAULT => Discard::Default,
AVDISCARD_NONREF => Discard::NonReference, AVDISCARD_NONREF => Discard::NonReference,
AVDISCARD_BIDIR => Discard::Bidirectional, AVDISCARD_BIDIR => Discard::Bidirectional,
AVDISCARD_NONINTRA => Discard::NonIntra, AVDISCARD_NONINTRA => Discard::NonIntra,
AVDISCARD_NONKEY => Discard::NonKey, AVDISCARD_NONKEY => Discard::NonKey,
AVDISCARD_ALL => Discard::All AVDISCARD_ALL => Discard::All,
} }
} }
} }
impl Into<AVDiscard> for Discard { impl Into<AVDiscard> for Discard {
fn into(self) -> AVDiscard { fn into(self) -> AVDiscard {
match self { match self {
Discard::None => AVDISCARD_NONE, Discard::None => AVDISCARD_NONE,
Discard::Default => AVDISCARD_DEFAULT, Discard::Default => AVDISCARD_DEFAULT,
Discard::NonReference => AVDISCARD_NONREF, Discard::NonReference => AVDISCARD_NONREF,
Discard::Bidirectional => AVDISCARD_BIDIR, Discard::Bidirectional => AVDISCARD_BIDIR,
Discard::NonIntra => AVDISCARD_NONINTRA, Discard::NonIntra => AVDISCARD_NONINTRA,
Discard::NonKey => AVDISCARD_NONKEY, Discard::NonKey => AVDISCARD_NONKEY,
Discard::All => AVDISCARD_ALL Discard::All => AVDISCARD_ALL,
} }
} }
} }

View File

@ -1,200 +1,206 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr; use std::ptr;
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
use super::Encoder as Super; use super::Encoder as Super;
use ::{packet, Error, Dictionary, ChannelLayout, frame};
use ::util::format;
use codec::{traits, Context}; use codec::{traits, Context};
use util::format;
use {frame, packet, ChannelLayout, Dictionary, Error};
pub struct Audio(pub Super); pub struct Audio(pub Super);
impl Audio { impl Audio {
pub fn open(mut self) -> Result<Encoder, Error> { pub fn open(mut self) -> Result<Encoder, Error> {
unsafe { unsafe {
match avcodec_open2(self.as_mut_ptr(), ptr::null(), ptr::null_mut()) { match avcodec_open2(self.as_mut_ptr(), ptr::null(), ptr::null_mut()) {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn open_as<E: traits::Encoder>(mut self, codec: E) -> Result<Encoder, Error> { pub fn open_as<E: traits::Encoder>(mut self, codec: E) -> Result<Encoder, Error> {
unsafe { unsafe {
if let Some(codec) = codec.encoder() { if let Some(codec) = codec.encoder() {
match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) { match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} } else {
else { Err(Error::EncoderNotFound)
Err(Error::EncoderNotFound) }
} }
} }
}
pub fn open_with(mut self, options: Dictionary) -> Result<Encoder, Error> { pub fn open_with(mut self, options: Dictionary) -> Result<Encoder, Error> {
unsafe { unsafe {
let mut opts = options.disown(); let mut opts = options.disown();
let res = avcodec_open2(self.as_mut_ptr(), ptr::null(), &mut opts); let res = avcodec_open2(self.as_mut_ptr(), ptr::null(), &mut opts);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn open_as_with<E: traits::Encoder>(mut self, codec: E, options: Dictionary) -> Result<Encoder, Error> { pub fn open_as_with<E: traits::Encoder>(
unsafe { mut self,
if let Some(codec) = codec.encoder() { codec: E,
let mut opts = options.disown(); options: Dictionary,
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts); ) -> Result<Encoder, Error> {
unsafe {
if let Some(codec) = codec.encoder() {
let mut opts = options.disown();
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} } else {
else { Err(Error::EncoderNotFound)
Err(Error::EncoderNotFound) }
} }
} }
}
pub fn set_rate(&mut self, rate: i32) { pub fn set_rate(&mut self, rate: i32) {
unsafe { unsafe {
(*self.as_mut_ptr()).sample_rate = rate; (*self.as_mut_ptr()).sample_rate = rate;
} }
} }
pub fn rate(&self) -> u32 { pub fn rate(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).sample_rate as u32 }
(*self.as_ptr()).sample_rate as u32 }
}
}
pub fn set_format(&mut self, value: format::Sample) { pub fn set_format(&mut self, value: format::Sample) {
unsafe { unsafe {
(*self.as_mut_ptr()).sample_fmt = value.into(); (*self.as_mut_ptr()).sample_fmt = value.into();
} }
} }
pub fn format(&self) -> format::Sample { pub fn format(&self) -> format::Sample {
unsafe { unsafe { format::Sample::from((*self.as_ptr()).sample_fmt) }
format::Sample::from((*self.as_ptr()).sample_fmt) }
}
}
pub fn set_channel_layout(&mut self, value: ChannelLayout) { pub fn set_channel_layout(&mut self, value: ChannelLayout) {
unsafe { unsafe {
(*self.as_mut_ptr()).channel_layout = value.bits(); (*self.as_mut_ptr()).channel_layout = value.bits();
} }
} }
pub fn channel_layout(&self) -> ChannelLayout { pub fn channel_layout(&self) -> ChannelLayout {
unsafe { unsafe { ChannelLayout::from_bits_truncate((*self.as_ptr()).channel_layout) }
ChannelLayout::from_bits_truncate((*self.as_ptr()).channel_layout) }
}
}
pub fn set_channels(&mut self, value: i32) { pub fn set_channels(&mut self, value: i32) {
unsafe { unsafe {
(*self.as_mut_ptr()).channels = value; (*self.as_mut_ptr()).channels = value;
} }
} }
pub fn channels(&self) -> u16 { pub fn channels(&self) -> u16 {
unsafe { unsafe { (*self.as_ptr()).channels as u16 }
(*self.as_ptr()).channels as u16 }
}
}
} }
impl Deref for Audio { impl Deref for Audio {
type Target = Super; type Target = Super;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Audio { impl DerefMut for Audio {
fn deref_mut(&mut self) -> &mut<Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Audio { impl AsRef<Context> for Audio {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Audio { impl AsMut<Context> for Audio {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }
pub struct Encoder(pub Audio); pub struct Encoder(pub Audio);
impl Encoder { impl Encoder {
pub fn encode<P: packet::Mut>(&mut self, frame: &frame::Audio, out: &mut P) -> Result<bool, Error> { pub fn encode<P: packet::Mut>(
unsafe { &mut self,
if self.format() != frame.format() { frame: &frame::Audio,
return Err(Error::InvalidData); out: &mut P,
} ) -> Result<bool, Error> {
unsafe {
if self.format() != frame.format() {
return Err(Error::InvalidData);
}
let mut got: c_int = 0; let mut got: c_int = 0;
match avcodec_encode_audio2(self.0.as_mut_ptr(), out.as_mut_ptr(), frame.as_ptr(), &mut got) { match avcodec_encode_audio2(
e if e < 0 => Err(Error::from(e)), self.0.as_mut_ptr(),
_ => Ok(got != 0) out.as_mut_ptr(),
} frame.as_ptr(),
} &mut got,
} ) {
e if e < 0 => Err(Error::from(e)),
_ => Ok(got != 0),
}
}
}
pub fn flush<P: packet::Mut>(&mut self, out: &mut P) -> Result<bool, Error> { pub fn flush<P: packet::Mut>(&mut self, out: &mut P) -> Result<bool, Error> {
unsafe { unsafe {
let mut got: c_int = 0; let mut got: c_int = 0;
match avcodec_encode_audio2(self.0.as_mut_ptr(), out.as_mut_ptr(), ptr::null(), &mut got) { match avcodec_encode_audio2(
e if e < 0 => Err(Error::from(e)), self.0.as_mut_ptr(),
_ => Ok(got != 0) out.as_mut_ptr(),
} ptr::null(),
} &mut got,
} ) {
e if e < 0 => Err(Error::from(e)),
_ => Ok(got != 0),
}
}
}
pub fn frame_size(&self) -> u32 { pub fn frame_size(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).frame_size as u32 }
(*self.as_ptr()).frame_size as u32 }
}
}
} }
impl Deref for Encoder { impl Deref for Encoder {
type Target = Audio; type Target = Audio;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl AsRef<Context> for Encoder { impl AsRef<Context> for Encoder {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Encoder { impl AsMut<Context> for Encoder {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,70 +1,70 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum Comparison { pub enum Comparison {
SAD, SAD,
SSE, SSE,
SATD, SATD,
DCT, DCT,
PSNR, PSNR,
BIT, BIT,
RD, RD,
ZERO, ZERO,
VSAD, VSAD,
VSSE, VSSE,
NSSE, NSSE,
W53, W53,
W97, W97,
DCTMAX, DCTMAX,
DCT264, DCT264,
CHROMA, CHROMA,
} }
impl From<c_int> for Comparison { impl From<c_int> for Comparison {
fn from(value: c_int) -> Comparison { fn from(value: c_int) -> Comparison {
match value { match value {
FF_CMP_SAD => Comparison::SAD, FF_CMP_SAD => Comparison::SAD,
FF_CMP_SSE => Comparison::SSE, FF_CMP_SSE => Comparison::SSE,
FF_CMP_SATD => Comparison::SATD, FF_CMP_SATD => Comparison::SATD,
FF_CMP_DCT => Comparison::DCT, FF_CMP_DCT => Comparison::DCT,
FF_CMP_PSNR => Comparison::PSNR, FF_CMP_PSNR => Comparison::PSNR,
FF_CMP_BIT => Comparison::BIT, FF_CMP_BIT => Comparison::BIT,
FF_CMP_RD => Comparison::RD, FF_CMP_RD => Comparison::RD,
FF_CMP_ZERO => Comparison::ZERO, FF_CMP_ZERO => Comparison::ZERO,
FF_CMP_VSAD => Comparison::VSAD, FF_CMP_VSAD => Comparison::VSAD,
FF_CMP_VSSE => Comparison::VSSE, FF_CMP_VSSE => Comparison::VSSE,
FF_CMP_NSSE => Comparison::NSSE, FF_CMP_NSSE => Comparison::NSSE,
FF_CMP_W53 => Comparison::W53, FF_CMP_W53 => Comparison::W53,
FF_CMP_W97 => Comparison::W97, FF_CMP_W97 => Comparison::W97,
FF_CMP_DCTMAX => Comparison::DCTMAX, FF_CMP_DCTMAX => Comparison::DCTMAX,
FF_CMP_DCT264 => Comparison::DCT264, FF_CMP_DCT264 => Comparison::DCT264,
FF_CMP_CHROMA => Comparison::CHROMA, FF_CMP_CHROMA => Comparison::CHROMA,
_ => Comparison::ZERO, _ => Comparison::ZERO,
} }
} }
} }
impl Into<c_int> for Comparison { impl Into<c_int> for Comparison {
fn into(self) -> c_int { fn into(self) -> c_int {
match self { match self {
Comparison::SAD => FF_CMP_SAD, Comparison::SAD => FF_CMP_SAD,
Comparison::SSE => FF_CMP_SSE, Comparison::SSE => FF_CMP_SSE,
Comparison::SATD => FF_CMP_SATD, Comparison::SATD => FF_CMP_SATD,
Comparison::DCT => FF_CMP_DCT, Comparison::DCT => FF_CMP_DCT,
Comparison::PSNR => FF_CMP_PSNR, Comparison::PSNR => FF_CMP_PSNR,
Comparison::BIT => FF_CMP_BIT, Comparison::BIT => FF_CMP_BIT,
Comparison::RD => FF_CMP_RD, Comparison::RD => FF_CMP_RD,
Comparison::ZERO => FF_CMP_ZERO, Comparison::ZERO => FF_CMP_ZERO,
Comparison::VSAD => FF_CMP_VSAD, Comparison::VSAD => FF_CMP_VSAD,
Comparison::VSSE => FF_CMP_VSSE, Comparison::VSSE => FF_CMP_VSSE,
Comparison::NSSE => FF_CMP_NSSE, Comparison::NSSE => FF_CMP_NSSE,
Comparison::W53 => FF_CMP_W53, Comparison::W53 => FF_CMP_W53,
Comparison::W97 => FF_CMP_W97, Comparison::W97 => FF_CMP_W97,
Comparison::DCTMAX => FF_CMP_DCTMAX, Comparison::DCTMAX => FF_CMP_DCTMAX,
Comparison::DCT264 => FF_CMP_DCT264, Comparison::DCT264 => FF_CMP_DCT264,
Comparison::CHROMA => FF_CMP_CHROMA, Comparison::CHROMA => FF_CMP_CHROMA,
} }
} }
} }

View File

@ -1,31 +1,31 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum Decision { pub enum Decision {
Simple, Simple,
Bits, Bits,
RateDistortion, RateDistortion,
} }
impl From<c_int> for Decision { impl From<c_int> for Decision {
fn from(value: c_int) -> Decision { fn from(value: c_int) -> Decision {
match value { match value {
FF_MB_DECISION_SIMPLE => Decision::Simple, FF_MB_DECISION_SIMPLE => Decision::Simple,
FF_MB_DECISION_BITS => Decision::Bits, FF_MB_DECISION_BITS => Decision::Bits,
FF_MB_DECISION_RD => Decision::RateDistortion, FF_MB_DECISION_RD => Decision::RateDistortion,
_ => Decision::Simple, _ => Decision::Simple,
} }
} }
} }
impl Into<c_int> for Decision { impl Into<c_int> for Decision {
fn into(self) -> c_int { fn into(self) -> c_int {
match self { match self {
Decision::Simple => FF_MB_DECISION_SIMPLE, Decision::Simple => FF_MB_DECISION_SIMPLE,
Decision::Bits => FF_MB_DECISION_BITS, Decision::Bits => FF_MB_DECISION_BITS,
Decision::RateDistortion => FF_MB_DECISION_RD, Decision::RateDistortion => FF_MB_DECISION_RD,
} }
} }
} }

View File

@ -1,149 +1,135 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use libc::{c_int, int64_t}; use super::{audio, subtitle, video};
use codec::Context; use codec::Context;
use ::{Error, Rational, media}; use libc::{c_int, int64_t};
use super::{video, audio, subtitle}; use {media, Error, Rational};
pub struct Encoder(pub Context); pub struct Encoder(pub Context);
impl Encoder { impl Encoder {
pub fn video(mut self) -> Result<video::Video, Error> { pub fn video(mut self) -> Result<video::Video, Error> {
match self.medium() { match self.medium() {
media::Type::Unknown => { media::Type::Unknown => {
unsafe { unsafe {
(*self.as_mut_ptr()).codec_type = media::Type::Video.into(); (*self.as_mut_ptr()).codec_type = media::Type::Video.into();
} }
Ok(video::Video(self)) Ok(video::Video(self))
} }
media::Type::Video => { media::Type::Video => Ok(video::Video(self)),
Ok(video::Video(self))
}
_ => { _ => Err(Error::InvalidData),
Err(Error::InvalidData) }
} }
}
}
pub fn audio(mut self) -> Result<audio::Audio, Error> { pub fn audio(mut self) -> Result<audio::Audio, Error> {
match self.medium() { match self.medium() {
media::Type::Unknown => { media::Type::Unknown => {
unsafe { unsafe {
(*self.as_mut_ptr()).codec_type = media::Type::Audio.into(); (*self.as_mut_ptr()).codec_type = media::Type::Audio.into();
} }
Ok(audio::Audio(self)) Ok(audio::Audio(self))
} }
media::Type::Audio => { media::Type::Audio => Ok(audio::Audio(self)),
Ok(audio::Audio(self))
}
_ => { _ => Err(Error::InvalidData),
Err(Error::InvalidData) }
} }
}
}
pub fn subtitle(mut self) -> Result<subtitle::Subtitle, Error> { pub fn subtitle(mut self) -> Result<subtitle::Subtitle, Error> {
match self.medium() { match self.medium() {
media::Type::Unknown => { media::Type::Unknown => {
unsafe { unsafe {
(*self.as_mut_ptr()).codec_type = media::Type::Subtitle.into(); (*self.as_mut_ptr()).codec_type = media::Type::Subtitle.into();
} }
Ok(subtitle::Subtitle(self)) Ok(subtitle::Subtitle(self))
} }
media::Type::Subtitle => { media::Type::Subtitle => Ok(subtitle::Subtitle(self)),
Ok(subtitle::Subtitle(self))
}
_ => { _ => Err(Error::InvalidData),
Err(Error::InvalidData) }
} }
}
}
pub fn set_bit_rate(&mut self, value: usize) { pub fn set_bit_rate(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).bit_rate = value as int64_t; (*self.as_mut_ptr()).bit_rate = value as int64_t;
} }
} }
pub fn set_max_bit_rate(&mut self, value: usize) { pub fn set_max_bit_rate(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).rc_max_rate = value as int64_t; (*self.as_mut_ptr()).rc_max_rate = value as int64_t;
} }
} }
pub fn set_tolerance(&mut self, value: usize) { pub fn set_tolerance(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).bit_rate_tolerance = value as c_int; (*self.as_mut_ptr()).bit_rate_tolerance = value as c_int;
} }
} }
pub fn set_quality(&mut self, value: usize) { pub fn set_quality(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).global_quality = value as c_int; (*self.as_mut_ptr()).global_quality = value as c_int;
} }
} }
pub fn set_compression(&mut self, value: Option<usize>) { pub fn set_compression(&mut self, value: Option<usize>) {
unsafe { unsafe {
if let Some(value) = value { if let Some(value) = value {
(*self.as_mut_ptr()).compression_level = value as c_int; (*self.as_mut_ptr()).compression_level = value as c_int;
} } else {
else { (*self.as_mut_ptr()).compression_level = -1;
(*self.as_mut_ptr()).compression_level = -1; }
} }
} }
}
pub fn set_time_base<R: Into<Rational>>(&mut self, value: R) { pub fn set_time_base<R: Into<Rational>>(&mut self, value: R) {
unsafe { unsafe {
(*self.as_mut_ptr()).time_base = value.into().into(); (*self.as_mut_ptr()).time_base = value.into().into();
} }
} }
pub fn set_frame_rate<R: Into<Rational>>(&mut self, value: Option<R>) { pub fn set_frame_rate<R: Into<Rational>>(&mut self, value: Option<R>) {
unsafe { unsafe {
if let Some(value) = value { if let Some(value) = value {
(*self.as_mut_ptr()).framerate = value.into().into(); (*self.as_mut_ptr()).framerate = value.into().into();
} } else {
else { (*self.as_mut_ptr()).framerate.num = 0;
(*self.as_mut_ptr()).framerate.num = 0; (*self.as_mut_ptr()).framerate.den = 1;
(*self.as_mut_ptr()).framerate.den = 1; }
} }
} }
}
} }
impl Deref for Encoder { impl Deref for Encoder {
type Target = Context; type Target = Context;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Encoder { impl DerefMut for Encoder {
fn deref_mut(&mut self) -> &mut<Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Encoder { impl AsRef<Context> for Encoder {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Encoder { impl AsMut<Context> for Encoder {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut *self &mut *self
} }
} }

View File

@ -24,38 +24,36 @@ pub use self::decision::Decision;
use std::ffi::CString; use std::ffi::CString;
use ffi::*;
use codec::Context; use codec::Context;
use ::Codec;
use codec::Id; use codec::Id;
use ffi::*;
use Codec;
pub fn new() -> Encoder { pub fn new() -> Encoder {
Context::new().encoder() Context::new().encoder()
} }
pub fn find(id: Id) -> Option<Codec> { pub fn find(id: Id) -> Option<Codec> {
unsafe { unsafe {
let ptr = avcodec_find_encoder(id.into()); let ptr = avcodec_find_encoder(id.into());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Codec::wrap(ptr))
Some(Codec::wrap(ptr)) }
} }
}
} }
pub fn find_by_name(name: &str) -> Option<Codec> { pub fn find_by_name(name: &str) -> Option<Codec> {
unsafe { unsafe {
let name = CString::new(name).unwrap(); let name = CString::new(name).unwrap();
let ptr = avcodec_find_encoder_by_name(name.as_ptr()); let ptr = avcodec_find_encoder_by_name(name.as_ptr());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Codec::wrap(ptr))
Some(Codec::wrap(ptr)) }
} }
}
} }

View File

@ -2,50 +2,50 @@ use libc::c_int;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum MotionEstimation { pub enum MotionEstimation {
Zero, Zero,
Full, Full,
Log, Log,
Phods, Phods,
Epzs, Epzs,
X1, X1,
Hex, Hex,
Umh, Umh,
Iter, Iter,
Tesa, Tesa,
} }
impl From<c_int> for MotionEstimation { impl From<c_int> for MotionEstimation {
fn from(value: c_int) -> MotionEstimation { fn from(value: c_int) -> MotionEstimation {
match value { match value {
1 => MotionEstimation::Zero, 1 => MotionEstimation::Zero,
2 => MotionEstimation::Full, 2 => MotionEstimation::Full,
3 => MotionEstimation::Log, 3 => MotionEstimation::Log,
4 => MotionEstimation::Phods, 4 => MotionEstimation::Phods,
5 => MotionEstimation::Epzs, 5 => MotionEstimation::Epzs,
6 => MotionEstimation::X1, 6 => MotionEstimation::X1,
7 => MotionEstimation::Hex, 7 => MotionEstimation::Hex,
8 => MotionEstimation::Umh, 8 => MotionEstimation::Umh,
9 => MotionEstimation::Iter, 9 => MotionEstimation::Iter,
10 => MotionEstimation::Tesa, 10 => MotionEstimation::Tesa,
_ => MotionEstimation::Zero _ => MotionEstimation::Zero,
} }
} }
} }
impl Into<c_int> for MotionEstimation { impl Into<c_int> for MotionEstimation {
fn into(self) -> c_int { fn into(self) -> c_int {
match self { match self {
MotionEstimation::Zero => 1, MotionEstimation::Zero => 1,
MotionEstimation::Full => 2, MotionEstimation::Full => 2,
MotionEstimation::Log => 3, MotionEstimation::Log => 3,
MotionEstimation::Phods => 4, MotionEstimation::Phods => 4,
MotionEstimation::Epzs => 5, MotionEstimation::Epzs => 5,
MotionEstimation::X1 => 6, MotionEstimation::X1 => 6,
MotionEstimation::Hex => 7, MotionEstimation::Hex => 7,
MotionEstimation::Umh => 8, MotionEstimation::Umh => 8,
MotionEstimation::Iter => 9, MotionEstimation::Iter => 9,
MotionEstimation::Tesa => 10 MotionEstimation::Tesa => 10,
} }
} }
} }

View File

@ -1,31 +1,31 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum Prediction { pub enum Prediction {
Left, Left,
Plane, Plane,
Median, Median,
} }
impl From<c_int> for Prediction { impl From<c_int> for Prediction {
fn from(value: c_int) -> Prediction { fn from(value: c_int) -> Prediction {
match value { match value {
FF_PRED_LEFT => Prediction::Left, FF_PRED_LEFT => Prediction::Left,
FF_PRED_PLANE => Prediction::Plane, FF_PRED_PLANE => Prediction::Plane,
FF_PRED_MEDIAN => Prediction::Median, FF_PRED_MEDIAN => Prediction::Median,
_ => Prediction::Left _ => Prediction::Left,
} }
} }
} }
impl Into<c_int> for Prediction { impl Into<c_int> for Prediction {
fn into(self) -> c_int { fn into(self) -> c_int {
match self { match self {
Prediction::Left => FF_PRED_LEFT, Prediction::Left => FF_PRED_LEFT,
Prediction::Plane => FF_PRED_PLANE, Prediction::Plane => FF_PRED_PLANE,
Prediction::Median => FF_PRED_MEDIAN, Prediction::Median => FF_PRED_MEDIAN,
} }
} }
} }

View File

@ -1,114 +1,121 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr; use std::ptr;
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
use super::Encoder as Super; use super::Encoder as Super;
use ::{Error, Dictionary};
use codec::{traits, Context}; use codec::{traits, Context};
use {Dictionary, Error};
pub struct Subtitle(pub Super); pub struct Subtitle(pub Super);
impl Subtitle { impl Subtitle {
pub fn open(mut self) -> Result<Encoder, Error> { pub fn open(mut self) -> Result<Encoder, Error> {
unsafe { unsafe {
match avcodec_open2(self.as_mut_ptr(), ptr::null(), ptr::null_mut()) { match avcodec_open2(self.as_mut_ptr(), ptr::null(), ptr::null_mut()) {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn open_as<E: traits::Encoder>(mut self, codec: E) -> Result<Encoder, Error> { pub fn open_as<E: traits::Encoder>(mut self, codec: E) -> Result<Encoder, Error> {
unsafe { unsafe {
if let Some(codec) = codec.encoder() { if let Some(codec) = codec.encoder() {
match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) { match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} } else {
else { Err(Error::EncoderNotFound)
Err(Error::EncoderNotFound) }
} }
} }
}
pub fn open_as_with<E: traits::Encoder>(mut self, codec: E, options: Dictionary) -> Result<Encoder, Error> { pub fn open_as_with<E: traits::Encoder>(
unsafe { mut self,
if let Some(codec) = codec.encoder() { codec: E,
let mut opts = options.disown(); options: Dictionary,
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts); ) -> Result<Encoder, Error> {
unsafe {
if let Some(codec) = codec.encoder() {
let mut opts = options.disown();
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} } else {
else { Err(Error::EncoderNotFound)
Err(Error::EncoderNotFound) }
} }
} }
}
} }
impl Deref for Subtitle { impl Deref for Subtitle {
type Target = Super; type Target = Super;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Subtitle { impl DerefMut for Subtitle {
fn deref_mut(&mut self) -> &mut<Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Subtitle { impl AsRef<Context> for Subtitle {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Subtitle { impl AsMut<Context> for Subtitle {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }
pub struct Encoder(pub Subtitle); pub struct Encoder(pub Subtitle);
impl Encoder { impl Encoder {
pub fn encode(&mut self, subtitle: &::Subtitle, out: &mut [u8]) -> Result<bool, Error> { pub fn encode(&mut self, subtitle: &::Subtitle, out: &mut [u8]) -> Result<bool, Error> {
unsafe { unsafe {
match avcodec_encode_subtitle(self.0.as_mut_ptr(), out.as_mut_ptr(), out.len() as c_int, subtitle.as_ptr()) { match avcodec_encode_subtitle(
e if e < 0 => Err(Error::from(e)), self.0.as_mut_ptr(),
_ => Ok(true) out.as_mut_ptr(),
} out.len() as c_int,
} subtitle.as_ptr(),
} ) {
e if e < 0 => Err(Error::from(e)),
_ => Ok(true),
}
}
}
} }
impl Deref for Encoder { impl Deref for Encoder {
type Target = Subtitle; type Target = Subtitle;
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl AsRef<Context> for Encoder { impl AsRef<Context> for Encoder {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Encoder { impl AsMut<Context> for Encoder {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,490 +1,494 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr; use std::ptr;
use libc::{c_int, c_float};
use ffi::*; use ffi::*;
use libc::{c_float, c_int};
use super::Encoder as Super; use super::Encoder as Super;
use super::{MotionEstimation, Prediction, Comparison, Decision}; use super::{Comparison, Decision, MotionEstimation, Prediction};
use ::{color, packet, Error, Rational, Dictionary, frame, format};
use codec::{traits, Context}; use codec::{traits, Context};
use {color, format, frame, packet, Dictionary, Error, Rational};
pub struct Video(pub Super); pub struct Video(pub Super);
impl Video { impl Video {
#[inline] #[inline]
pub fn open(mut self) -> Result<Encoder, Error> { pub fn open(mut self) -> Result<Encoder, Error> {
unsafe { unsafe {
match avcodec_open2(self.as_mut_ptr(), ptr::null(), ptr::null_mut()) { match avcodec_open2(self.as_mut_ptr(), ptr::null(), ptr::null_mut()) {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
#[inline] #[inline]
pub fn open_as<E: traits::Encoder>(mut self, codec: E) -> Result<Encoder, Error> { pub fn open_as<E: traits::Encoder>(mut self, codec: E) -> Result<Encoder, Error> {
unsafe { unsafe {
if let Some(codec) = codec.encoder() { if let Some(codec) = codec.encoder() {
match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) { match avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), ptr::null_mut()) {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} } else {
else { Err(Error::EncoderNotFound)
Err(Error::EncoderNotFound) }
} }
} }
}
#[inline] #[inline]
pub fn open_with(mut self, options: Dictionary) -> Result<Encoder, Error> { pub fn open_with(mut self, options: Dictionary) -> Result<Encoder, Error> {
unsafe { unsafe {
let mut opts = options.disown(); let mut opts = options.disown();
let res = avcodec_open2(self.as_mut_ptr(), ptr::null(), &mut opts); let res = avcodec_open2(self.as_mut_ptr(), ptr::null(), &mut opts);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
#[inline] #[inline]
pub fn open_as_with<E: traits::Encoder>(mut self, codec: E, options: Dictionary) -> Result<Encoder, Error> { pub fn open_as_with<E: traits::Encoder>(
unsafe { mut self,
if let Some(codec) = codec.encoder() { codec: E,
let mut opts = options.disown(); options: Dictionary,
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts); ) -> Result<Encoder, Error> {
unsafe {
if let Some(codec) = codec.encoder() {
let mut opts = options.disown();
let res = avcodec_open2(self.as_mut_ptr(), codec.as_ptr(), &mut opts);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => Ok(Encoder(self)), 0 => Ok(Encoder(self)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} } else {
else { Err(Error::EncoderNotFound)
Err(Error::EncoderNotFound) }
} }
} }
}
#[inline] #[inline]
pub fn set_width(&mut self, value: u32) { pub fn set_width(&mut self, value: u32) {
unsafe { unsafe {
(*self.as_mut_ptr()).width = value as c_int; (*self.as_mut_ptr()).width = value as c_int;
} }
} }
#[inline] #[inline]
pub fn width(&self) -> u32 { pub fn width(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).width as u32 }
(*self.as_ptr()).width as u32 }
}
}
#[inline] #[inline]
pub fn set_height(&mut self, value: u32) { pub fn set_height(&mut self, value: u32) {
unsafe { unsafe {
(*self.as_mut_ptr()).height = value as c_int; (*self.as_mut_ptr()).height = value as c_int;
} }
} }
#[inline] #[inline]
pub fn height(&self) -> u32 { pub fn height(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).height as u32 }
(*self.as_ptr()).height as u32 }
}
}
#[inline] #[inline]
pub fn set_gop(&mut self, value: u32) { pub fn set_gop(&mut self, value: u32) {
unsafe { unsafe {
(*self.as_mut_ptr()).gop_size = value as c_int; (*self.as_mut_ptr()).gop_size = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_format(&mut self, value: format::Pixel) { pub fn set_format(&mut self, value: format::Pixel) {
unsafe { unsafe {
(*self.as_mut_ptr()).pix_fmt = value.into(); (*self.as_mut_ptr()).pix_fmt = value.into();
} }
} }
#[inline] #[inline]
pub fn format(&self) -> format::Pixel { pub fn format(&self) -> format::Pixel {
unsafe { unsafe { format::Pixel::from((*self.as_ptr()).pix_fmt) }
format::Pixel::from((*self.as_ptr()).pix_fmt) }
}
}
#[inline] #[inline]
#[cfg(feature = "ff_api_motion_est")] #[cfg(feature = "ff_api_motion_est")]
pub fn set_motion_estimation(&mut self, value: MotionEstimation) { pub fn set_motion_estimation(&mut self, value: MotionEstimation) {
unsafe { unsafe {
(*self.as_mut_ptr()).me_method = value.into(); (*self.as_mut_ptr()).me_method = value.into();
} }
} }
#[inline] #[inline]
pub fn set_max_b_frames(&mut self, value: usize) { pub fn set_max_b_frames(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).max_b_frames = value as c_int; (*self.as_mut_ptr()).max_b_frames = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_b_quant_factor(&mut self, value: f32) { pub fn set_b_quant_factor(&mut self, value: f32) {
unsafe { unsafe {
(*self.as_mut_ptr()).b_quant_factor = value as c_float; (*self.as_mut_ptr()).b_quant_factor = value as c_float;
} }
} }
#[inline] #[inline]
pub fn set_b_quant_offset(&mut self, value: f32) { pub fn set_b_quant_offset(&mut self, value: f32) {
unsafe { unsafe {
(*self.as_mut_ptr()).b_quant_offset = value as c_float; (*self.as_mut_ptr()).b_quant_offset = value as c_float;
} }
} }
#[inline] #[inline]
pub fn set_i_quant_factor(&mut self, value: f32) { pub fn set_i_quant_factor(&mut self, value: f32) {
unsafe { unsafe {
(*self.as_mut_ptr()).i_quant_factor = value as c_float; (*self.as_mut_ptr()).i_quant_factor = value as c_float;
} }
} }
#[inline] #[inline]
pub fn set_i_quant_offset(&mut self, value: f32) { pub fn set_i_quant_offset(&mut self, value: f32) {
unsafe { unsafe {
(*self.as_mut_ptr()).i_quant_offset = value as c_float; (*self.as_mut_ptr()).i_quant_offset = value as c_float;
} }
} }
#[inline] #[inline]
pub fn set_lumi_masking(&mut self, value: f32) { pub fn set_lumi_masking(&mut self, value: f32) {
unsafe { unsafe {
(*self.as_mut_ptr()).lumi_masking = value as c_float; (*self.as_mut_ptr()).lumi_masking = value as c_float;
} }
} }
#[inline] #[inline]
pub fn set_temporal_cplx_masking(&mut self, value: f32) { pub fn set_temporal_cplx_masking(&mut self, value: f32) {
unsafe { unsafe {
(*self.as_mut_ptr()).temporal_cplx_masking = value as c_float; (*self.as_mut_ptr()).temporal_cplx_masking = value as c_float;
} }
} }
#[inline] #[inline]
pub fn set_spatial_cplx_masking(&mut self, value: f32) { pub fn set_spatial_cplx_masking(&mut self, value: f32) {
unsafe { unsafe {
(*self.as_mut_ptr()).spatial_cplx_masking = value as c_float; (*self.as_mut_ptr()).spatial_cplx_masking = value as c_float;
} }
} }
#[inline] #[inline]
pub fn set_p_masking(&mut self, value: f32) { pub fn set_p_masking(&mut self, value: f32) {
unsafe { unsafe {
(*self.as_mut_ptr()).p_masking = value as c_float; (*self.as_mut_ptr()).p_masking = value as c_float;
} }
} }
#[inline] #[inline]
pub fn set_dark_masking(&mut self, value: f32) { pub fn set_dark_masking(&mut self, value: f32) {
unsafe { unsafe {
(*self.as_mut_ptr()).dark_masking = value as c_float; (*self.as_mut_ptr()).dark_masking = value as c_float;
} }
} }
#[inline] #[inline]
pub fn set_prediction(&mut self, value: Prediction) { pub fn set_prediction(&mut self, value: Prediction) {
unsafe { unsafe {
(*self.as_mut_ptr()).prediction_method = value.into(); (*self.as_mut_ptr()).prediction_method = value.into();
} }
} }
#[inline] #[inline]
pub fn set_aspect_ratio<R: Into<Rational>>(&mut self, value: R) { pub fn set_aspect_ratio<R: Into<Rational>>(&mut self, value: R) {
unsafe { unsafe {
(*self.as_mut_ptr()).sample_aspect_ratio = value.into().into(); (*self.as_mut_ptr()).sample_aspect_ratio = value.into().into();
} }
} }
#[inline] #[inline]
pub fn set_me_comparison(&mut self, value: Comparison) { pub fn set_me_comparison(&mut self, value: Comparison) {
unsafe { unsafe {
(*self.as_mut_ptr()).me_cmp = value.into(); (*self.as_mut_ptr()).me_cmp = value.into();
} }
} }
#[inline] #[inline]
pub fn set_me_sub_comparison(&mut self, value: Comparison) { pub fn set_me_sub_comparison(&mut self, value: Comparison) {
unsafe { unsafe {
(*self.as_mut_ptr()).me_sub_cmp = value.into(); (*self.as_mut_ptr()).me_sub_cmp = value.into();
} }
} }
#[inline] #[inline]
pub fn set_mb_comparison(&mut self, value: Comparison) { pub fn set_mb_comparison(&mut self, value: Comparison) {
unsafe { unsafe {
(*self.as_mut_ptr()).mb_cmp = value.into(); (*self.as_mut_ptr()).mb_cmp = value.into();
} }
} }
#[inline] #[inline]
pub fn set_ildct_comparison(&mut self, value: Comparison) { pub fn set_ildct_comparison(&mut self, value: Comparison) {
unsafe { unsafe {
(*self.as_mut_ptr()).ildct_cmp = value.into(); (*self.as_mut_ptr()).ildct_cmp = value.into();
} }
} }
#[inline] #[inline]
pub fn set_dia_size(&mut self, value: usize) { pub fn set_dia_size(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).dia_size = value as c_int; (*self.as_mut_ptr()).dia_size = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_last_predictors(&mut self, value: usize) { pub fn set_last_predictors(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).last_predictor_count = value as c_int; (*self.as_mut_ptr()).last_predictor_count = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_pre_me(&mut self, value: MotionEstimation) { pub fn set_pre_me(&mut self, value: MotionEstimation) {
unsafe { unsafe {
(*self.as_mut_ptr()).pre_me = value.into(); (*self.as_mut_ptr()).pre_me = value.into();
} }
} }
#[inline] #[inline]
pub fn set_me_pre_comparison(&mut self, value: Comparison) { pub fn set_me_pre_comparison(&mut self, value: Comparison) {
unsafe { unsafe {
(*self.as_mut_ptr()).me_pre_cmp = value.into(); (*self.as_mut_ptr()).me_pre_cmp = value.into();
} }
} }
#[inline] #[inline]
pub fn set_pre_dia_size(&mut self, value: usize) { pub fn set_pre_dia_size(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).pre_dia_size = value as c_int; (*self.as_mut_ptr()).pre_dia_size = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_me_subpel_quality(&mut self, value: usize) { pub fn set_me_subpel_quality(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).me_subpel_quality = value as c_int; (*self.as_mut_ptr()).me_subpel_quality = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_me_range(&mut self, value: usize) { pub fn set_me_range(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).me_range = value as c_int; (*self.as_mut_ptr()).me_range = value as c_int;
} }
} }
#[inline] #[inline]
#[cfg(feature = "ff_api_quant_bias")] #[cfg(feature = "ff_api_quant_bias")]
pub fn set_intra_quant_bias(&mut self, value: Option<usize>) { pub fn set_intra_quant_bias(&mut self, value: Option<usize>) {
unsafe { unsafe {
if let Some(value) = value { if let Some(value) = value {
(*self.as_mut_ptr()).intra_quant_bias = value as c_int; (*self.as_mut_ptr()).intra_quant_bias = value as c_int;
} } else {
else { (*self.as_mut_ptr()).intra_quant_bias = FF_DEFAULT_QUANT_BIAS;
(*self.as_mut_ptr()).intra_quant_bias = FF_DEFAULT_QUANT_BIAS; }
} }
} }
}
#[inline] #[inline]
#[cfg(feature = "ff_api_quant_bias")] #[cfg(feature = "ff_api_quant_bias")]
pub fn set_inter_quant_bias(&mut self, value: Option<usize>) { pub fn set_inter_quant_bias(&mut self, value: Option<usize>) {
unsafe { unsafe {
if let Some(value) = value { if let Some(value) = value {
(*self.as_mut_ptr()).inter_quant_bias = value as c_int; (*self.as_mut_ptr()).inter_quant_bias = value as c_int;
} } else {
else { (*self.as_mut_ptr()).inter_quant_bias = FF_DEFAULT_QUANT_BIAS;
(*self.as_mut_ptr()).inter_quant_bias = FF_DEFAULT_QUANT_BIAS; }
} }
} }
}
#[inline] #[inline]
pub fn set_mb_decision(&mut self, value: Decision) { pub fn set_mb_decision(&mut self, value: Decision) {
unsafe { unsafe {
(*self.as_mut_ptr()).mb_decision = value.into(); (*self.as_mut_ptr()).mb_decision = value.into();
} }
} }
#[inline] #[inline]
pub fn set_mb_lmin(&mut self, value: i32) { pub fn set_mb_lmin(&mut self, value: i32) {
unsafe { unsafe {
(*self.as_mut_ptr()).mb_lmin = value as c_int; (*self.as_mut_ptr()).mb_lmin = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_mb_lmax(&mut self, value: i32) { pub fn set_mb_lmax(&mut self, value: i32) {
unsafe { unsafe {
(*self.as_mut_ptr()).mb_lmax = value as c_int; (*self.as_mut_ptr()).mb_lmax = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_intra_dc_precision(&mut self, value: u8) { pub fn set_intra_dc_precision(&mut self, value: u8) {
unsafe { unsafe {
(*self.as_mut_ptr()).intra_dc_precision = value as c_int; (*self.as_mut_ptr()).intra_dc_precision = i32::from(value);
} }
} }
#[inline] #[inline]
pub fn set_qmin(&mut self, value: i32) { pub fn set_qmin(&mut self, value: i32) {
unsafe { unsafe {
(*self.as_mut_ptr()).qmin = value as c_int; (*self.as_mut_ptr()).qmin = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_qmax(&mut self, value: i32) { pub fn set_qmax(&mut self, value: i32) {
unsafe { unsafe {
(*self.as_mut_ptr()).qmax = value as c_int; (*self.as_mut_ptr()).qmax = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_global_quality(&mut self, value: i32) { pub fn set_global_quality(&mut self, value: i32) {
unsafe { unsafe {
(*self.as_mut_ptr()).global_quality = value as c_int; (*self.as_mut_ptr()).global_quality = value as c_int;
} }
} }
#[inline] #[inline]
pub fn set_colorspace(&mut self, value: color::Space) { pub fn set_colorspace(&mut self, value: color::Space) {
unsafe { unsafe {
(*self.as_mut_ptr()).colorspace = value.into(); (*self.as_mut_ptr()).colorspace = value.into();
} }
} }
#[inline] #[inline]
pub fn colorspace(&self) -> color::Space { pub fn colorspace(&self) -> color::Space {
unsafe { unsafe { (*self.as_ptr()).colorspace.into() }
(*self.as_ptr()).colorspace.into() }
}
}
#[inline] #[inline]
pub fn set_color_range(&mut self, value: color::Range) { pub fn set_color_range(&mut self, value: color::Range) {
unsafe { unsafe {
(*self.as_mut_ptr()).color_range = value.into(); (*self.as_mut_ptr()).color_range = value.into();
} }
} }
#[inline] #[inline]
pub fn color_range(&self) -> color::Range { pub fn color_range(&self) -> color::Range {
unsafe { unsafe { (*self.as_ptr()).color_range.into() }
(*self.as_ptr()).color_range.into() }
}
}
} }
impl Deref for Video { impl Deref for Video {
type Target = Super; type Target = Super;
#[inline(always)] #[inline(always)]
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Video { impl DerefMut for Video {
#[inline(always)] #[inline(always)]
fn deref_mut(&mut self) -> &mut<Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Video { impl AsRef<Context> for Video {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Video { impl AsMut<Context> for Video {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }
pub struct Encoder(pub Video); pub struct Encoder(pub Video);
impl Encoder { impl Encoder {
#[inline] #[inline]
pub fn encode<P: packet::Mut>(&mut self, frame: &frame::Video, out: &mut P) -> Result<bool, Error> { pub fn encode<P: packet::Mut>(
unsafe { &mut self,
if self.format() != frame.format() || self.width() != frame.width() || self.height() != frame.height() { frame: &frame::Video,
return Err(Error::InvalidData); out: &mut P,
} ) -> Result<bool, Error> {
unsafe {
if self.format() != frame.format() || self.width() != frame.width()
|| self.height() != frame.height()
{
return Err(Error::InvalidData);
}
let mut got: c_int = 0; let mut got: c_int = 0;
match avcodec_encode_video2(self.0.as_mut_ptr(), out.as_mut_ptr(), frame.as_ptr(), &mut got) { match avcodec_encode_video2(
e if e < 0 => Err(Error::from(e)), self.0.as_mut_ptr(),
_ => Ok(got != 0) out.as_mut_ptr(),
} frame.as_ptr(),
} &mut got,
} ) {
e if e < 0 => Err(Error::from(e)),
_ => Ok(got != 0),
}
}
}
#[inline] #[inline]
pub fn flush<P: packet::Mut>(&mut self, out: &mut P) -> Result<bool, Error> { pub fn flush<P: packet::Mut>(&mut self, out: &mut P) -> Result<bool, Error> {
unsafe { unsafe {
let mut got: c_int = 0; let mut got: c_int = 0;
match avcodec_encode_video2(self.0.as_mut_ptr(), out.as_mut_ptr(), ptr::null(), &mut got) { match avcodec_encode_video2(
e if e < 0 => Err(Error::from(e)), self.0.as_mut_ptr(),
_ => Ok(got != 0) out.as_mut_ptr(),
} ptr::null(),
} &mut got,
} ) {
e if e < 0 => Err(Error::from(e)),
_ => Ok(got != 0),
}
}
}
#[inline] #[inline]
pub fn frame_size(&self) -> u32 { pub fn frame_size(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).frame_size as u32 }
(*self.as_ptr()).frame_size as u32 }
}
}
} }
impl Deref for Encoder { impl Deref for Encoder {
type Target = Video; type Target = Video;
#[inline] #[inline]
fn deref(&self) -> &<Self as Deref>::Target { fn deref(&self) -> &<Self as Deref>::Target {
&self.0 &self.0
} }
} }
impl DerefMut for Encoder { impl DerefMut for Encoder {
#[inline] #[inline]
fn deref_mut(&mut self) -> &mut <Self as Deref>::Target { fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.0 &mut self.0
} }
} }
impl AsRef<Context> for Encoder { impl AsRef<Context> for Encoder {
fn as_ref(&self) -> &Context { fn as_ref(&self) -> &Context {
&self self
} }
} }
impl AsMut<Context> for Encoder { impl AsMut<Context> for Encoder {
fn as_mut(&mut self) -> &mut Context { fn as_mut(&mut self) -> &mut Context {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,38 +1,38 @@
use ffi::*;
use ffi::AVFieldOrder::*; use ffi::AVFieldOrder::*;
use ffi::*;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum FieldOrder { pub enum FieldOrder {
Unknown, Unknown,
Progressive, Progressive,
TT, TT,
BB, BB,
TB, TB,
BT, BT,
} }
impl From<AVFieldOrder> for FieldOrder { impl From<AVFieldOrder> for FieldOrder {
fn from(value: AVFieldOrder) -> Self { fn from(value: AVFieldOrder) -> Self {
match value { match value {
AV_FIELD_UNKNOWN => FieldOrder::Unknown, AV_FIELD_UNKNOWN => FieldOrder::Unknown,
AV_FIELD_PROGRESSIVE => FieldOrder::Progressive, AV_FIELD_PROGRESSIVE => FieldOrder::Progressive,
AV_FIELD_TT => FieldOrder::TT, AV_FIELD_TT => FieldOrder::TT,
AV_FIELD_BB => FieldOrder::BB, AV_FIELD_BB => FieldOrder::BB,
AV_FIELD_TB => FieldOrder::TB, AV_FIELD_TB => FieldOrder::TB,
AV_FIELD_BT => FieldOrder::BT AV_FIELD_BT => FieldOrder::BT,
} }
} }
} }
impl Into<AVFieldOrder> for FieldOrder { impl Into<AVFieldOrder> for FieldOrder {
fn into(self) -> AVFieldOrder { fn into(self) -> AVFieldOrder {
match self { match self {
FieldOrder::Unknown => AV_FIELD_UNKNOWN, FieldOrder::Unknown => AV_FIELD_UNKNOWN,
FieldOrder::Progressive => AV_FIELD_PROGRESSIVE, FieldOrder::Progressive => AV_FIELD_PROGRESSIVE,
FieldOrder::TT => AV_FIELD_TT, FieldOrder::TT => AV_FIELD_TT,
FieldOrder::BB => AV_FIELD_BB, FieldOrder::BB => AV_FIELD_BB,
FieldOrder::TB => AV_FIELD_TB, FieldOrder::TB => AV_FIELD_TB,
FieldOrder::BT => AV_FIELD_BT FieldOrder::BT => AV_FIELD_BT,
} }
} }
} }

View File

@ -1,26 +1,25 @@
use libc::c_uint;
use ffi::*; use ffi::*;
use libc::c_uint;
bitflags! { bitflags! {
pub struct Flags: c_uint { pub struct Flags: c_uint {
const UNALIGNED = AV_CODEC_FLAG_UNALIGNED; const UNALIGNED = AV_CODEC_FLAG_UNALIGNED;
const QSCALE = AV_CODEC_FLAG_QSCALE; const QSCALE = AV_CODEC_FLAG_QSCALE;
const _4MV = AV_CODEC_FLAG_4MV; const _4MV = AV_CODEC_FLAG_4MV;
const OUTPUT_CORRUPT = AV_CODEC_FLAG_OUTPUT_CORRUPT; const OUTPUT_CORRUPT = AV_CODEC_FLAG_OUTPUT_CORRUPT;
const QPEL = AV_CODEC_FLAG_QPEL; const QPEL = AV_CODEC_FLAG_QPEL;
const PASS1 = AV_CODEC_FLAG_PASS1; const PASS1 = AV_CODEC_FLAG_PASS1;
const PASS2 = AV_CODEC_FLAG_PASS2; const PASS2 = AV_CODEC_FLAG_PASS2;
const GRAY = AV_CODEC_FLAG_GRAY; const GRAY = AV_CODEC_FLAG_GRAY;
const PSNR = AV_CODEC_FLAG_PSNR; const PSNR = AV_CODEC_FLAG_PSNR;
const TRUNCATED = AV_CODEC_FLAG_TRUNCATED; const TRUNCATED = AV_CODEC_FLAG_TRUNCATED;
const INTERLACED_DCT = AV_CODEC_FLAG_INTERLACED_DCT; const INTERLACED_DCT = AV_CODEC_FLAG_INTERLACED_DCT;
const LOW_DELAY = AV_CODEC_FLAG_LOW_DELAY; const LOW_DELAY = AV_CODEC_FLAG_LOW_DELAY;
const GLOBAL_HEADER = AV_CODEC_FLAG_GLOBAL_HEADER; const GLOBAL_HEADER = AV_CODEC_FLAG_GLOBAL_HEADER;
const BITEXACT = AV_CODEC_FLAG_BITEXACT; const BITEXACT = AV_CODEC_FLAG_BITEXACT;
const AC_PRED = AV_CODEC_FLAG_AC_PRED; const AC_PRED = AV_CODEC_FLAG_AC_PRED;
const LOOP_FILTER = AV_CODEC_FLAG_LOOP_FILTER; const LOOP_FILTER = AV_CODEC_FLAG_LOOP_FILTER;
const INTERLACED_ME = AV_CODEC_FLAG_INTERLACED_ME; const INTERLACED_ME = AV_CODEC_FLAG_INTERLACED_ME;
const CLOSED_GOP = AV_CODEC_FLAG_CLOSED_GOP; const CLOSED_GOP = AV_CODEC_FLAG_CLOSED_GOP;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -29,8 +29,8 @@ pub use self::video::Video;
pub mod audio; pub mod audio;
pub use self::audio::Audio; pub use self::audio::Audio;
pub mod field_order;
pub mod audio_service; pub mod audio_service;
pub mod field_order;
pub mod compliance; pub mod compliance;
pub use self::compliance::Compliance; pub use self::compliance::Compliance;
@ -43,8 +43,8 @@ pub use self::profile::Profile;
pub mod threading; pub mod threading;
pub mod encoder;
pub mod decoder; pub mod decoder;
pub mod encoder;
pub mod traits; pub mod traits;
use std::ffi::CStr; use std::ffi::CStr;
@ -53,19 +53,13 @@ use std::str::from_utf8_unchecked;
use ffi::*; use ffi::*;
pub fn version() -> u32 { pub fn version() -> u32 {
unsafe { unsafe { avcodec_version() }
avcodec_version()
}
} }
pub fn configuration() -> &'static str { pub fn configuration() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(avcodec_configuration()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(avcodec_configuration()).to_bytes())
}
} }
pub fn license() -> &'static str { pub fn license() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(avcodec_license()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(avcodec_license()).to_bytes())
}
} }

View File

@ -1,54 +1,54 @@
use std::mem; use std::mem;
use std::ptr; use std::ptr;
use libc::c_int;
use ffi::*;
use super::Ref; use super::Ref;
use ffi::*;
use libc::c_int;
pub struct Borrow<'a> { pub struct Borrow<'a> {
packet: AVPacket, packet: AVPacket,
data: &'a [u8], data: &'a [u8],
} }
impl<'a> Borrow<'a> { impl<'a> Borrow<'a> {
pub fn new(data: &[u8]) -> Borrow { pub fn new(data: &[u8]) -> Borrow {
unsafe { unsafe {
let mut packet: AVPacket = mem::zeroed(); let mut packet: AVPacket = mem::zeroed();
packet.data = data.as_ptr() as *mut _; packet.data = data.as_ptr() as *mut _;
packet.size = data.len() as c_int; packet.size = data.len() as c_int;
Borrow { Borrow {
packet: packet, packet: packet,
data: data, data: data,
} }
} }
} }
#[inline] #[inline]
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
self.packet.size as usize self.packet.size as usize
} }
#[inline] #[inline]
pub fn data(&self) -> Option<&[u8]> { pub fn data(&self) -> Option<&[u8]> {
Some(self.data) Some(self.data)
} }
} }
impl<'a> Ref for Borrow<'a> { impl<'a> Ref for Borrow<'a> {
fn as_ptr(&self) -> *const AVPacket { fn as_ptr(&self) -> *const AVPacket {
&self.packet &self.packet
} }
} }
impl<'a> Drop for Borrow<'a> { impl<'a> Drop for Borrow<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
self.packet.data = ptr::null_mut(); self.packet.data = ptr::null_mut();
self.packet.size = 0; self.packet.size = 0;
av_free_packet(&mut self.packet); av_free_packet(&mut self.packet);
} }
} }
} }

View File

@ -1,9 +1,9 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Flags: c_int { pub struct Flags: c_int {
const KEY = AV_PKT_FLAG_KEY; const KEY = AV_PKT_FLAG_KEY;
const CORRUPT = AV_PKT_FLAG_CORRUPT; const CORRUPT = AV_PKT_FLAG_CORRUPT;
} }
} }

View File

@ -1,5 +1,5 @@
pub mod traits; pub mod traits;
pub use self::traits::{Ref, Mut}; pub use self::traits::{Mut, Ref};
pub mod packet; pub mod packet;
pub use self::packet::Packet; pub use self::packet::Packet;

View File

@ -2,308 +2,316 @@ use std::marker::PhantomData;
use std::mem; use std::mem;
use std::slice; use std::slice;
use libc::c_int; use super::{flag, Borrow, Flags, Mut, Ref, SideData};
use ffi::*; use ffi::*;
use ::{Error, Rational, format}; use libc::c_int;
use super::{flag, Flags, SideData, Ref, Mut, Borrow}; use {format, Error, Rational};
pub struct Packet(AVPacket); pub struct Packet(AVPacket);
unsafe impl Send for Packet { } unsafe impl Send for Packet {}
unsafe impl Sync for Packet { } unsafe impl Sync for Packet {}
impl Packet { impl Packet {
#[inline(always)] #[inline(always)]
pub unsafe fn is_empty(&self) -> bool { pub unsafe fn is_empty(&self) -> bool {
self.0.size == 0 self.0.size == 0
} }
} }
impl Packet { impl Packet {
#[inline] #[inline]
pub fn empty() -> Self { pub fn empty() -> Self {
unsafe { unsafe {
let mut pkt: AVPacket = mem::zeroed(); let mut pkt: AVPacket = mem::zeroed();
av_init_packet(&mut pkt); av_init_packet(&mut pkt);
Packet(pkt) Packet(pkt)
} }
} }
#[inline] #[inline]
pub fn new(size: usize) -> Self { pub fn new(size: usize) -> Self {
unsafe { unsafe {
let mut pkt: AVPacket = mem::zeroed(); let mut pkt: AVPacket = mem::zeroed();
av_init_packet(&mut pkt); av_init_packet(&mut pkt);
av_new_packet(&mut pkt, size as c_int); av_new_packet(&mut pkt, size as c_int);
Packet(pkt) Packet(pkt)
} }
} }
#[inline] #[inline]
pub fn copy(data: &[u8]) -> Self { pub fn copy(data: &[u8]) -> Self {
use std::io::Write; use std::io::Write;
let mut packet = Packet::new(data.len()); let mut packet = Packet::new(data.len());
packet.data_mut().unwrap().write(data).unwrap(); packet.data_mut().unwrap().write_all(data).unwrap();
packet packet
} }
#[inline] #[inline]
pub fn borrow(data: &[u8]) -> Borrow { pub fn borrow(data: &[u8]) -> Borrow {
Borrow::new(data) Borrow::new(data)
} }
#[inline] #[inline]
pub fn shrink(&mut self, size: usize) { pub fn shrink(&mut self, size: usize) {
unsafe { unsafe {
av_shrink_packet(&mut self.0, size as c_int); av_shrink_packet(&mut self.0, size as c_int);
} }
} }
#[inline] #[inline]
pub fn grow(&mut self, size: usize) { pub fn grow(&mut self, size: usize) {
unsafe { unsafe {
av_grow_packet(&mut self.0, size as c_int); av_grow_packet(&mut self.0, size as c_int);
} }
} }
#[inline] #[inline]
pub fn rescale_ts<S, D>(&mut self, source: S, destination: D) pub fn rescale_ts<S, D>(&mut self, source: S, destination: D)
where S: Into<Rational>, where
D: Into<Rational> S: Into<Rational>,
{ D: Into<Rational>,
unsafe { {
av_packet_rescale_ts(self.as_mut_ptr(), source.into().into(), destination.into().into()); unsafe {
} av_packet_rescale_ts(
} self.as_mut_ptr(),
source.into().into(),
destination.into().into(),
);
}
}
#[inline] #[inline]
pub fn flags(&self) -> Flags { pub fn flags(&self) -> Flags {
Flags::from_bits_truncate(self.0.flags) Flags::from_bits_truncate(self.0.flags)
} }
#[inline] #[inline]
pub fn set_flags(&mut self, value: Flags) { pub fn set_flags(&mut self, value: Flags) {
self.0.flags = value.bits(); self.0.flags = value.bits();
} }
#[inline] #[inline]
pub fn is_key(&self) -> bool { pub fn is_key(&self) -> bool {
self.flags().contains(flag::KEY) self.flags().contains(flag::KEY)
} }
#[inline] #[inline]
pub fn is_corrupt(&self) -> bool { pub fn is_corrupt(&self) -> bool {
self.flags().contains(flag::CORRUPT) self.flags().contains(flag::CORRUPT)
} }
#[inline] #[inline]
pub fn stream(&self) -> usize { pub fn stream(&self) -> usize {
self.0.stream_index as usize self.0.stream_index as usize
} }
#[inline] #[inline]
pub fn set_stream(&mut self, index: usize) { pub fn set_stream(&mut self, index: usize) {
self.0.stream_index = index as c_int; self.0.stream_index = index as c_int;
} }
#[inline] #[inline]
pub fn pts(&self) -> Option<i64> { pub fn pts(&self) -> Option<i64> {
match self.0.pts { match self.0.pts {
AV_NOPTS_VALUE => None, AV_NOPTS_VALUE => None,
pts => Some(pts as i64), pts => Some(pts as i64),
} }
} }
#[inline] #[inline]
pub fn set_pts(&mut self, value: Option<i64>) { pub fn set_pts(&mut self, value: Option<i64>) {
unsafe { unsafe {
(*self.as_mut_ptr()).pts = value.unwrap_or(AV_NOPTS_VALUE); (*self.as_mut_ptr()).pts = value.unwrap_or(AV_NOPTS_VALUE);
} }
} }
#[inline] #[inline]
pub fn dts(&self) -> Option<i64> { pub fn dts(&self) -> Option<i64> {
match self.0.dts { match self.0.dts {
AV_NOPTS_VALUE => None, AV_NOPTS_VALUE => None,
dts => Some(dts as i64), dts => Some(dts as i64),
} }
} }
#[inline] #[inline]
pub fn set_dts(&mut self, value: Option<i64>) { pub fn set_dts(&mut self, value: Option<i64>) {
unsafe { unsafe {
(*self.as_mut_ptr()).dts = value.unwrap_or(AV_NOPTS_VALUE); (*self.as_mut_ptr()).dts = value.unwrap_or(AV_NOPTS_VALUE);
} }
} }
#[inline] #[inline]
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
self.0.size as usize self.0.size as usize
} }
#[inline] #[inline]
pub fn duration(&self) -> i64 { pub fn duration(&self) -> i64 {
self.0.duration as i64 self.0.duration as i64
} }
#[inline] #[inline]
pub fn position(&self) -> isize { pub fn position(&self) -> isize {
self.0.pos as isize self.0.pos as isize
} }
#[inline] #[inline]
pub fn convergence(&self) -> isize { pub fn convergence(&self) -> isize {
self.0.convergence_duration as isize self.0.convergence_duration as isize
} }
#[inline] #[inline]
pub fn side_data(&self) -> SideDataIter { pub fn side_data(&self) -> SideDataIter {
SideDataIter::new(&self.0) SideDataIter::new(&self.0)
} }
#[inline] #[inline]
pub fn data(&self) -> Option<&[u8]> { pub fn data(&self) -> Option<&[u8]> {
unsafe { unsafe {
if self.0.data.is_null() { if self.0.data.is_null() {
None None
} } else {
else { Some(slice::from_raw_parts(self.0.data, self.0.size as usize))
Some(slice::from_raw_parts(self.0.data, self.0.size as usize)) }
} }
} }
}
#[inline] #[inline]
pub fn data_mut(&mut self) -> Option<&mut [u8]> { pub fn data_mut(&mut self) -> Option<&mut [u8]> {
unsafe { unsafe {
if self.0.data.is_null() { if self.0.data.is_null() {
None None
} } else {
else { Some(slice::from_raw_parts_mut(self.0.data, self.0.size as usize))
Some(slice::from_raw_parts_mut(self.0.data, self.0.size as usize)) }
} }
} }
}
#[inline] #[inline]
pub fn read(&mut self, format: &mut format::context::Input) -> Result<(), Error> { pub fn read(&mut self, format: &mut format::context::Input) -> Result<(), Error> {
unsafe { unsafe {
match av_read_frame(format.as_mut_ptr(), self.as_mut_ptr()) { match av_read_frame(format.as_mut_ptr(), self.as_mut_ptr()) {
0 => Ok(()), 0 => Ok(()),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
#[inline] #[inline]
pub fn write(&self, format: &mut format::context::Output) -> Result<bool, Error> { pub fn write(&self, format: &mut format::context::Output) -> Result<bool, Error> {
unsafe { unsafe {
if self.is_empty() { if self.is_empty() {
return Err(Error::InvalidData); return Err(Error::InvalidData);
} }
match av_write_frame(format.as_mut_ptr(), self.as_ptr() as *mut _) { match av_write_frame(format.as_mut_ptr(), self.as_ptr() as *mut _) {
1 => Ok(true), 1 => Ok(true),
0 => Ok(false), 0 => Ok(false),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
#[inline] #[inline]
pub fn write_interleaved(&self, format: &mut format::context::Output) -> Result<bool, Error> { pub fn write_interleaved(&self, format: &mut format::context::Output) -> Result<bool, Error> {
unsafe { unsafe {
if self.is_empty() { if self.is_empty() {
return Err(Error::InvalidData); return Err(Error::InvalidData);
} }
match av_interleaved_write_frame(format.as_mut_ptr(), self.as_ptr() as *mut _) { match av_interleaved_write_frame(format.as_mut_ptr(), self.as_ptr() as *mut _) {
1 => Ok(true), 1 => Ok(true),
0 => Ok(false), 0 => Ok(false),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
} }
impl Ref for Packet { impl Ref for Packet {
fn as_ptr(&self) -> *const AVPacket { fn as_ptr(&self) -> *const AVPacket {
&self.0 &self.0
} }
} }
impl Mut for Packet { impl Mut for Packet {
fn as_mut_ptr(&mut self) -> *mut AVPacket { fn as_mut_ptr(&mut self) -> *mut AVPacket {
&mut self.0 &mut self.0
} }
} }
impl Clone for Packet { impl Clone for Packet {
#[inline] #[inline]
fn clone(&self) -> Self { fn clone(&self) -> Self {
let mut pkt = Packet::empty(); let mut pkt = Packet::empty();
pkt.clone_from(self); pkt.clone_from(self);
pkt pkt
} }
#[inline] #[inline]
fn clone_from(&mut self, source: &Self) { fn clone_from(&mut self, source: &Self) {
unsafe { unsafe {
av_copy_packet(&mut self.0, &source.0); av_copy_packet(&mut self.0, &source.0);
} }
} }
} }
impl Drop for Packet { impl Drop for Packet {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
av_packet_unref(&mut self.0); av_packet_unref(&mut self.0);
} }
} }
} }
pub struct SideDataIter<'a> { pub struct SideDataIter<'a> {
ptr: *const AVPacket, ptr: *const AVPacket,
cur: c_int, cur: c_int,
_marker: PhantomData<&'a Packet>, _marker: PhantomData<&'a Packet>,
} }
impl<'a> SideDataIter<'a> { impl<'a> SideDataIter<'a> {
pub fn new(ptr: *const AVPacket) -> Self { pub fn new(ptr: *const AVPacket) -> Self {
SideDataIter { ptr: ptr, cur: 0, _marker: PhantomData } SideDataIter {
} ptr: ptr,
cur: 0,
_marker: PhantomData,
}
}
} }
impl<'a> Iterator for SideDataIter<'a> { impl<'a> Iterator for SideDataIter<'a> {
type Item = SideData<'a>; type Item = SideData<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if self.cur >= (*self.ptr).side_data_elems { if self.cur >= (*self.ptr).side_data_elems {
None None
} } else {
else { self.cur += 1;
self.cur += 1; Some(SideData::wrap(
Some(SideData::wrap((*self.ptr).side_data.offset((self.cur - 1) as isize))) (*self.ptr).side_data.offset((self.cur - 1) as isize),
} ))
} }
} }
}
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
unsafe { unsafe {
let length = (*self.ptr).side_data_elems as usize; let length = (*self.ptr).side_data_elems as usize;
(length - self.cur as usize, Some(length - self.cur as usize)) (length - self.cur as usize, Some(length - self.cur as usize))
} }
} }
} }
impl<'a> ExactSizeIterator for SideDataIter<'a> { } impl<'a> ExactSizeIterator for SideDataIter<'a> {}

View File

@ -1,132 +1,131 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use std::slice; use std::slice;
use ffi::*;
use ffi::AVPacketSideDataType::*;
use super::Packet; use super::Packet;
use ffi::AVPacketSideDataType::*;
use ffi::*;
#[derive(Eq, PartialEq, Copy, Clone, Debug)] #[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Type { pub enum Type {
Palette, Palette,
NewExtraData, NewExtraData,
ParamChange, ParamChange,
H263MbInfo, H263MbInfo,
ReplayGain, ReplayGain,
DisplayMatrix, DisplayMatrix,
Stereo3d, Stereo3d,
AudioServiceType, AudioServiceType,
QualityStats, QualityStats,
FallbackTrack, FallbackTrack,
CBPProperties, CBPProperties,
SkipSamples, SkipSamples,
JpDualMono, JpDualMono,
StringsMetadata, StringsMetadata,
SubtitlePosition, SubtitlePosition,
MatroskaBlockAdditional, MatroskaBlockAdditional,
WebVTTIdentifier, WebVTTIdentifier,
WebVTTSettings, WebVTTSettings,
MetadataUpdate, MetadataUpdate,
MPEGTSStreamID, MPEGTSStreamID,
MasteringDisplayMetadata, MasteringDisplayMetadata,
DataSpherical, DataSpherical,
DataNb, DataNb,
ContentLightLevel, ContentLightLevel,
A53CC, A53CC,
} }
impl From<AVPacketSideDataType> for Type { impl From<AVPacketSideDataType> for Type {
fn from(value: AVPacketSideDataType) -> Self { fn from(value: AVPacketSideDataType) -> Self {
match value { match value {
AV_PKT_DATA_PALETTE => Type::Palette, AV_PKT_DATA_PALETTE => Type::Palette,
AV_PKT_DATA_NEW_EXTRADATA => Type::NewExtraData, AV_PKT_DATA_NEW_EXTRADATA => Type::NewExtraData,
AV_PKT_DATA_PARAM_CHANGE => Type::ParamChange, AV_PKT_DATA_PARAM_CHANGE => Type::ParamChange,
AV_PKT_DATA_H263_MB_INFO => Type::H263MbInfo, AV_PKT_DATA_H263_MB_INFO => Type::H263MbInfo,
AV_PKT_DATA_REPLAYGAIN => Type::ReplayGain, AV_PKT_DATA_REPLAYGAIN => Type::ReplayGain,
AV_PKT_DATA_DISPLAYMATRIX => Type::DisplayMatrix, AV_PKT_DATA_DISPLAYMATRIX => Type::DisplayMatrix,
AV_PKT_DATA_STEREO3D => Type::Stereo3d, AV_PKT_DATA_STEREO3D => Type::Stereo3d,
AV_PKT_DATA_AUDIO_SERVICE_TYPE => Type::AudioServiceType, AV_PKT_DATA_AUDIO_SERVICE_TYPE => Type::AudioServiceType,
AV_PKT_DATA_QUALITY_STATS => Type::QualityStats, AV_PKT_DATA_QUALITY_STATS => Type::QualityStats,
AV_PKT_DATA_FALLBACK_TRACK => Type::FallbackTrack, AV_PKT_DATA_FALLBACK_TRACK => Type::FallbackTrack,
AV_PKT_DATA_CPB_PROPERTIES => Type::CBPProperties, AV_PKT_DATA_CPB_PROPERTIES => Type::CBPProperties,
AV_PKT_DATA_SKIP_SAMPLES => Type::SkipSamples, AV_PKT_DATA_SKIP_SAMPLES => Type::SkipSamples,
AV_PKT_DATA_JP_DUALMONO => Type::JpDualMono, AV_PKT_DATA_JP_DUALMONO => Type::JpDualMono,
AV_PKT_DATA_STRINGS_METADATA => Type::StringsMetadata, AV_PKT_DATA_STRINGS_METADATA => Type::StringsMetadata,
AV_PKT_DATA_SUBTITLE_POSITION => Type::SubtitlePosition, AV_PKT_DATA_SUBTITLE_POSITION => Type::SubtitlePosition,
AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL => Type::MatroskaBlockAdditional, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL => Type::MatroskaBlockAdditional,
AV_PKT_DATA_WEBVTT_IDENTIFIER => Type::WebVTTIdentifier, AV_PKT_DATA_WEBVTT_IDENTIFIER => Type::WebVTTIdentifier,
AV_PKT_DATA_WEBVTT_SETTINGS => Type::WebVTTSettings, AV_PKT_DATA_WEBVTT_SETTINGS => Type::WebVTTSettings,
AV_PKT_DATA_METADATA_UPDATE => Type::MetadataUpdate, AV_PKT_DATA_METADATA_UPDATE => Type::MetadataUpdate,
AV_PKT_DATA_MPEGTS_STREAM_ID => Type::MPEGTSStreamID, AV_PKT_DATA_MPEGTS_STREAM_ID => Type::MPEGTSStreamID,
AV_PKT_DATA_MASTERING_DISPLAY_METADATA => Type::MasteringDisplayMetadata, AV_PKT_DATA_MASTERING_DISPLAY_METADATA => Type::MasteringDisplayMetadata,
AV_PKT_DATA_SPHERICAL => Type::DataSpherical, AV_PKT_DATA_SPHERICAL => Type::DataSpherical,
AV_PKT_DATA_NB => Type::DataNb, AV_PKT_DATA_NB => Type::DataNb,
AV_PKT_DATA_CONTENT_LIGHT_LEVEL => Type::ContentLightLevel, AV_PKT_DATA_CONTENT_LIGHT_LEVEL => Type::ContentLightLevel,
AV_PKT_DATA_A53_CC => Type::A53CC, AV_PKT_DATA_A53_CC => Type::A53CC,
} }
} }
} }
impl Into<AVPacketSideDataType> for Type { impl Into<AVPacketSideDataType> for Type {
fn into(self) -> AVPacketSideDataType { fn into(self) -> AVPacketSideDataType {
match self { match self {
Type::Palette => AV_PKT_DATA_PALETTE, Type::Palette => AV_PKT_DATA_PALETTE,
Type::NewExtraData => AV_PKT_DATA_NEW_EXTRADATA, Type::NewExtraData => AV_PKT_DATA_NEW_EXTRADATA,
Type::ParamChange => AV_PKT_DATA_PARAM_CHANGE, Type::ParamChange => AV_PKT_DATA_PARAM_CHANGE,
Type::H263MbInfo => AV_PKT_DATA_H263_MB_INFO, Type::H263MbInfo => AV_PKT_DATA_H263_MB_INFO,
Type::ReplayGain => AV_PKT_DATA_REPLAYGAIN, Type::ReplayGain => AV_PKT_DATA_REPLAYGAIN,
Type::DisplayMatrix => AV_PKT_DATA_DISPLAYMATRIX, Type::DisplayMatrix => AV_PKT_DATA_DISPLAYMATRIX,
Type::Stereo3d => AV_PKT_DATA_STEREO3D, Type::Stereo3d => AV_PKT_DATA_STEREO3D,
Type::AudioServiceType => AV_PKT_DATA_AUDIO_SERVICE_TYPE, Type::AudioServiceType => AV_PKT_DATA_AUDIO_SERVICE_TYPE,
Type::QualityStats => AV_PKT_DATA_QUALITY_STATS, Type::QualityStats => AV_PKT_DATA_QUALITY_STATS,
Type::FallbackTrack => AV_PKT_DATA_FALLBACK_TRACK, Type::FallbackTrack => AV_PKT_DATA_FALLBACK_TRACK,
Type::CBPProperties => AV_PKT_DATA_CPB_PROPERTIES, Type::CBPProperties => AV_PKT_DATA_CPB_PROPERTIES,
Type::SkipSamples => AV_PKT_DATA_SKIP_SAMPLES, Type::SkipSamples => AV_PKT_DATA_SKIP_SAMPLES,
Type::JpDualMono => AV_PKT_DATA_JP_DUALMONO, Type::JpDualMono => AV_PKT_DATA_JP_DUALMONO,
Type::StringsMetadata => AV_PKT_DATA_STRINGS_METADATA, Type::StringsMetadata => AV_PKT_DATA_STRINGS_METADATA,
Type::SubtitlePosition => AV_PKT_DATA_SUBTITLE_POSITION, Type::SubtitlePosition => AV_PKT_DATA_SUBTITLE_POSITION,
Type::MatroskaBlockAdditional => AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, Type::MatroskaBlockAdditional => AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
Type::WebVTTIdentifier => AV_PKT_DATA_WEBVTT_IDENTIFIER, Type::WebVTTIdentifier => AV_PKT_DATA_WEBVTT_IDENTIFIER,
Type::WebVTTSettings => AV_PKT_DATA_WEBVTT_SETTINGS, Type::WebVTTSettings => AV_PKT_DATA_WEBVTT_SETTINGS,
Type::MetadataUpdate => AV_PKT_DATA_METADATA_UPDATE, Type::MetadataUpdate => AV_PKT_DATA_METADATA_UPDATE,
Type::MPEGTSStreamID => AV_PKT_DATA_MPEGTS_STREAM_ID, Type::MPEGTSStreamID => AV_PKT_DATA_MPEGTS_STREAM_ID,
Type::MasteringDisplayMetadata => AV_PKT_DATA_MASTERING_DISPLAY_METADATA, Type::MasteringDisplayMetadata => AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
Type::DataSpherical => AV_PKT_DATA_SPHERICAL, Type::DataSpherical => AV_PKT_DATA_SPHERICAL,
Type::DataNb => AV_PKT_DATA_NB, Type::DataNb => AV_PKT_DATA_NB,
Type::ContentLightLevel => AV_PKT_DATA_CONTENT_LIGHT_LEVEL, Type::ContentLightLevel => AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
Type::A53CC => AV_PKT_DATA_A53_CC, Type::A53CC => AV_PKT_DATA_A53_CC,
} }
} }
} }
pub struct SideData<'a> { pub struct SideData<'a> {
ptr: *mut AVPacketSideData, ptr: *mut AVPacketSideData,
_marker: PhantomData<&'a Packet> _marker: PhantomData<&'a Packet>,
} }
impl<'a> SideData<'a> { impl<'a> SideData<'a> {
pub unsafe fn wrap(ptr: *mut AVPacketSideData) -> Self { pub unsafe fn wrap(ptr: *mut AVPacketSideData) -> Self {
SideData { ptr: ptr, _marker: PhantomData } SideData {
} ptr: ptr,
_marker: PhantomData,
}
}
pub unsafe fn as_ptr(&self) -> *const AVPacketSideData { pub unsafe fn as_ptr(&self) -> *const AVPacketSideData {
self.ptr as *const _ self.ptr as *const _
} }
} }
impl<'a> SideData<'a> { impl<'a> SideData<'a> {
pub fn kind(&self) -> Type { pub fn kind(&self) -> Type {
unsafe { unsafe { Type::from((*self.as_ptr()).type_) }
Type::from((*self.as_ptr()).type_) }
}
}
pub fn data(&self) -> &[u8] { pub fn data(&self) -> &[u8] {
unsafe { unsafe { slice::from_raw_parts((*self.as_ptr()).data, (*self.as_ptr()).size as usize) }
slice::from_raw_parts((*self.as_ptr()).data, (*self.as_ptr()).size as usize) }
}
}
} }

View File

@ -1,9 +1,9 @@
use ffi::*; use ffi::*;
pub trait Ref { pub trait Ref {
fn as_ptr(&self) -> *const AVPacket; fn as_ptr(&self) -> *const AVPacket;
} }
pub trait Mut { pub trait Mut {
fn as_mut_ptr(&mut self) -> *mut AVPacket; fn as_mut_ptr(&mut self) -> *mut AVPacket;
} }

View File

@ -1,82 +1,90 @@
use std::rc::Rc; use std::rc::Rc;
use super::{Context, Id};
use ffi::*; use ffi::*;
use media; use media;
use super::{Id, Context};
pub struct Parameters { pub struct Parameters {
ptr: *mut AVCodecParameters, ptr: *mut AVCodecParameters,
owner: Option<Rc<Drop>>, owner: Option<Rc<Drop>>,
} }
unsafe impl Send for Parameters { } unsafe impl Send for Parameters {}
impl Parameters { impl Parameters {
pub unsafe fn wrap(ptr: *mut AVCodecParameters, owner: Option<Rc<Drop>>) -> Self { pub unsafe fn wrap(ptr: *mut AVCodecParameters, owner: Option<Rc<Drop>>) -> Self {
Parameters { ptr: ptr, owner: owner } Parameters {
} ptr: ptr,
owner: owner,
}
}
pub unsafe fn as_ptr(&self) -> *const AVCodecParameters { pub unsafe fn as_ptr(&self) -> *const AVCodecParameters {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodecParameters { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVCodecParameters {
self.ptr self.ptr
} }
} }
impl Parameters { impl Parameters {
pub fn new() -> Self { pub fn new() -> Self {
unsafe { unsafe {
Parameters { ptr: avcodec_parameters_alloc(), owner: None } Parameters {
} ptr: avcodec_parameters_alloc(),
} owner: None,
}
}
}
pub fn medium(&self) -> media::Type { pub fn medium(&self) -> media::Type {
unsafe { unsafe { media::Type::from((*self.as_ptr()).codec_type) }
media::Type::from((*self.as_ptr()).codec_type) }
}
}
pub fn id(&self) -> Id { pub fn id(&self) -> Id {
unsafe { unsafe { Id::from((*self.as_ptr()).codec_id) }
Id::from((*self.as_ptr()).codec_id) }
} }
}
impl Default for Parameters {
fn default() -> Self {
Self::new()
}
} }
impl Drop for Parameters { impl Drop for Parameters {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
if self.owner.is_none() { if self.owner.is_none() {
avcodec_parameters_free(&mut self.as_mut_ptr()); avcodec_parameters_free(&mut self.as_mut_ptr());
} }
} }
} }
} }
impl Clone for Parameters { impl Clone for Parameters {
fn clone(&self) -> Self { fn clone(&self) -> Self {
let mut ctx = Parameters::new(); let mut ctx = Parameters::new();
ctx.clone_from(self); ctx.clone_from(self);
ctx ctx
} }
fn clone_from(&mut self, source: &Self) { fn clone_from(&mut self, source: &Self) {
unsafe { unsafe {
avcodec_parameters_copy(self.as_mut_ptr(), source.as_ptr()); avcodec_parameters_copy(self.as_mut_ptr(), source.as_ptr());
} }
} }
} }
impl<C: AsRef<Context>> From<C> for Parameters { impl<C: AsRef<Context>> From<C> for Parameters {
fn from(context: C) -> Parameters { fn from(context: C) -> Parameters {
let mut parameters = Parameters::new(); let mut parameters = Parameters::new();
let context = context.as_ref(); let context = context.as_ref();
unsafe { unsafe {
avcodec_parameters_from_context(parameters.as_mut_ptr(), context.as_ptr()); avcodec_parameters_from_context(parameters.as_mut_ptr(), context.as_ptr());
} }
parameters parameters
} }
} }

View File

@ -1,166 +1,219 @@
use std::marker::PhantomData;
use std::mem; use std::mem;
use std::slice; use std::slice;
use std::marker::PhantomData;
use libc::{c_int, size_t};
use ffi::*; use ffi::*;
use ::format; use format;
use ::Error; use libc::{c_int, size_t};
use Error;
pub struct Picture<'a> { pub struct Picture<'a> {
ptr: *mut AVPicture, ptr: *mut AVPicture,
format: format::Pixel, format: format::Pixel,
width: u32, width: u32,
height: u32, height: u32,
_own: bool, _own: bool,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> Picture<'a> { impl<'a> Picture<'a> {
pub unsafe fn wrap(ptr: *mut AVPicture, format: format::Pixel, width: u32, height: u32) -> Self { pub unsafe fn wrap(
Picture { ptr: *mut AVPicture,
ptr: ptr, format: format::Pixel,
width: u32,
height: u32,
) -> Self {
Picture {
ptr: ptr,
format: format, format: format,
width: width, width: width,
height: height, height: height,
_own: false, _own: false,
_marker: PhantomData _marker: PhantomData,
} }
} }
pub unsafe fn as_ptr(&self) -> *const AVPicture { pub unsafe fn as_ptr(&self) -> *const AVPicture {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVPicture { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVPicture {
self.ptr self.ptr
} }
} }
impl<'a> Picture<'a> { impl<'a> Picture<'a> {
pub fn size(format: format::Pixel, width: u32, height: u32) -> Result<usize, Error> { pub fn size(format: format::Pixel, width: u32, height: u32) -> Result<usize, Error> {
unsafe { unsafe {
match avpicture_get_size(format.into(), width as c_int, height as c_int) { match avpicture_get_size(format.into(), width as c_int, height as c_int) {
v if v >= 0 => Ok(v as usize), v if v >= 0 => Ok(v as usize),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn new(format: format::Pixel, width: u32, height: u32) -> Result<Self, Error> { pub fn new(format: format::Pixel, width: u32, height: u32) -> Result<Self, Error> {
unsafe { unsafe {
let ptr = av_malloc(mem::size_of::<AVPicture>() as size_t) as *mut AVPicture; let ptr = av_malloc(mem::size_of::<AVPicture>() as size_t) as *mut AVPicture;
match avpicture_alloc(ptr, format.into(), width as c_int, height as c_int) { match avpicture_alloc(ptr, format.into(), width as c_int, height as c_int) {
0 => Ok(Picture { 0 => Ok(Picture {
ptr: ptr, ptr: ptr,
format: format, format: format,
width: width, width: width,
height: height, height: height,
_own: true, _own: true,
_marker: PhantomData _marker: PhantomData,
}), }),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn format(&self) -> format::Pixel { pub fn format(&self) -> format::Pixel {
self.format self.format
} }
pub fn width(&self) -> u32 { pub fn width(&self) -> u32 {
self.width self.width
} }
pub fn height(&self) -> u32 { pub fn height(&self) -> u32 {
self.height self.height
} }
pub fn layout(&self, out: &mut [u8]) -> Result<usize, Error> { pub fn layout(&self, out: &mut [u8]) -> Result<usize, Error> {
unsafe { unsafe {
match avpicture_layout(self.ptr, self.format.into(), self.width as c_int, self.height as c_int, out.as_mut_ptr(), out.len() as c_int) { match avpicture_layout(
s if s >= 0 => Ok(s as usize), self.ptr,
e => Err(Error::from(e)) self.format.into(),
} self.width as c_int,
} self.height as c_int,
} out.as_mut_ptr(),
out.len() as c_int,
) {
s if s >= 0 => Ok(s as usize),
e => Err(Error::from(e)),
}
}
}
pub fn layout_as(&self, format: format::Pixel, width: u32, height: u32, out: &mut [u8]) -> Result<usize, Error> { pub fn layout_as(
unsafe { &self,
match avpicture_layout(self.as_ptr(), format.into(), width as c_int, height as c_int, out.as_mut_ptr(), out.len() as c_int) { format: format::Pixel,
s if s >= 0 => Ok(s as usize), width: u32,
e => Err(Error::from(e)) height: u32,
} out: &mut [u8],
} ) -> Result<usize, Error> {
} unsafe {
match avpicture_layout(
self.as_ptr(),
format.into(),
width as c_int,
height as c_int,
out.as_mut_ptr(),
out.len() as c_int,
) {
s if s >= 0 => Ok(s as usize),
e => Err(Error::from(e)),
}
}
}
pub fn crop(&self, source: &mut Picture, top: u32, left: u32) -> Result<(), Error> { pub fn crop(&self, source: &mut Picture, top: u32, left: u32) -> Result<(), Error> {
if self.format != source.format { if self.format != source.format {
return Err(Error::Bug); return Err(Error::Bug);
} }
unsafe { unsafe {
match av_picture_crop(source.as_mut_ptr(), self.as_ptr(), self.format.into(), top as c_int, left as c_int) { match av_picture_crop(
0 => Ok(()), source.as_mut_ptr(),
e => Err(Error::from(e)) self.as_ptr(),
} self.format.into(),
} top as c_int,
} left as c_int,
) {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
}
pub fn data(&self) -> Vec<&[u8]> { pub fn data(&self) -> Vec<&[u8]> {
let mut result = Vec::new(); let mut result = Vec::new();
unsafe { unsafe {
for (i, length) in (*self.as_ptr()).linesize.iter().take_while(|l| **l > 0).enumerate() { for (i, length) in (*self.as_ptr())
result.push(slice::from_raw_parts((*self.as_ptr()).data[i], (*length as usize) * (self.height as usize))) .linesize
} .iter()
} .take_while(|l| **l > 0)
.enumerate()
{
result.push(slice::from_raw_parts(
(*self.as_ptr()).data[i],
(*length as usize) * (self.height as usize),
))
}
}
result result
} }
pub fn data_mut(&mut self) -> Vec<&mut [u8]> { pub fn data_mut(&mut self) -> Vec<&mut [u8]> {
let mut result = Vec::new(); let mut result = Vec::new();
unsafe { unsafe {
for (i, length) in (*self.as_ptr()).linesize.iter().take_while(|l| **l > 0).enumerate() { for (i, length) in (*self.as_ptr())
result.push(slice::from_raw_parts_mut((*self.as_ptr()).data[i], (*length as usize) * (self.height as usize))) .linesize
} .iter()
} .take_while(|l| **l > 0)
.enumerate()
{
result.push(slice::from_raw_parts_mut(
(*self.as_ptr()).data[i],
(*length as usize) * (self.height as usize),
))
}
}
result result
} }
} }
impl<'a> Clone for Picture<'a> { impl<'a> Clone for Picture<'a> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
let mut pic = Picture::new(self.format, self.width, self.height).unwrap(); let mut pic = Picture::new(self.format, self.width, self.height).unwrap();
pic.clone_from(self); pic.clone_from(self);
pic pic
} }
fn clone_from(&mut self, source: &Self) { fn clone_from(&mut self, source: &Self) {
unsafe { unsafe {
av_picture_copy(self.as_mut_ptr(), source.as_ptr(), source.format.into(), source.width as c_int, source.height as c_int); av_picture_copy(
} self.as_mut_ptr(),
} source.as_ptr(),
source.format.into(),
source.width as c_int,
source.height as c_int,
);
}
}
} }
impl<'a> Drop for Picture<'a> { impl<'a> Drop for Picture<'a> {
fn drop(&mut self) { fn drop(&mut self) {
if self._own { if self._own {
unsafe { unsafe {
av_free(self.as_mut_ptr() as *mut _); av_free(self.as_mut_ptr() as *mut _);
} }
} }
} }
} }

View File

@ -1,357 +1,377 @@
use libc::c_int;
use ffi::*;
use super::Id; use super::Id;
use ffi::*;
use libc::c_int;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum Profile { pub enum Profile {
Unknown, Unknown,
Reserved, Reserved,
AAC(AAC), AAC(AAC),
MPEG2(MPEG2), MPEG2(MPEG2),
DTS(DTS), DTS(DTS),
H264(H264), H264(H264),
VC1(VC1), VC1(VC1),
MPEG4(MPEG4), MPEG4(MPEG4),
JPEG2000(JPEG2000), JPEG2000(JPEG2000),
HEVC(HEVC), HEVC(HEVC),
VP9(VP9), VP9(VP9),
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum AAC { pub enum AAC {
Main, Main,
Low, Low,
SSR, SSR,
LTP, LTP,
HE, HE,
HEv2, HEv2,
LD, LD,
ELD, ELD,
MPEG2Low, MPEG2Low,
MPEG2HE, MPEG2HE,
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum DTS { pub enum DTS {
Default, Default,
ES, ES,
_96_24, _96_24,
HD_HRA, HD_HRA,
HD_MA, HD_MA,
Express, Express,
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum MPEG2 { pub enum MPEG2 {
_422, _422,
High, High,
SS, SS,
SNRScalable, SNRScalable,
Main, Main,
Simple, Simple,
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum H264 { pub enum H264 {
Constrained, Constrained,
Intra, Intra,
Baseline, Baseline,
ConstrainedBaseline, ConstrainedBaseline,
Main, Main,
Extended, Extended,
High, High,
High10, High10,
High10Intra, High10Intra,
High422, High422,
High422Intra, High422Intra,
High444, High444,
High444Predictive, High444Predictive,
High444Intra, High444Intra,
CAVLC444, CAVLC444,
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum VC1 { pub enum VC1 {
Simple, Simple,
Main, Main,
Complex, Complex,
Advanced, Advanced,
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum MPEG4 { pub enum MPEG4 {
Simple, Simple,
SimpleScalable, SimpleScalable,
Core, Core,
Main, Main,
NBit, NBit,
ScalableTexture, ScalableTexture,
SimpleFaceAnimation, SimpleFaceAnimation,
BasicAnimatedTexture, BasicAnimatedTexture,
Hybrid, Hybrid,
AdvancedRealTime, AdvancedRealTime,
CoreScalable, CoreScalable,
AdvancedCoding, AdvancedCoding,
AdvancedCore, AdvancedCore,
AdvancedScalableTexture, AdvancedScalableTexture,
SimpleStudio, SimpleStudio,
AdvancedSimple, AdvancedSimple,
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum JPEG2000 { pub enum JPEG2000 {
CStreamRestriction0, CStreamRestriction0,
CStreamRestriction1, CStreamRestriction1,
CStreamNoRestriction, CStreamNoRestriction,
DCinema2K, DCinema2K,
DCinema4K, DCinema4K,
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum HEVC { pub enum HEVC {
Main, Main,
Main10, Main10,
MainStillPicture, MainStillPicture,
Rext, Rext,
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum VP9 { pub enum VP9 {
_0, _0,
_1, _1,
_2, _2,
_3, _3,
} }
impl From<(Id, c_int)> for Profile { impl From<(Id, c_int)> for Profile {
fn from((id, value): (Id, c_int)) -> Profile { fn from((id, value): (Id, c_int)) -> Profile {
if value == FF_PROFILE_UNKNOWN { if value == FF_PROFILE_UNKNOWN {
return Profile::Unknown; return Profile::Unknown;
} }
if value == FF_PROFILE_RESERVED { if value == FF_PROFILE_RESERVED {
return Profile::Reserved; return Profile::Reserved;
} }
match id { match id {
Id::AAC => match value { Id::AAC => match value {
FF_PROFILE_AAC_MAIN => Profile::AAC(AAC::Main), FF_PROFILE_AAC_MAIN => Profile::AAC(AAC::Main),
FF_PROFILE_AAC_LOW => Profile::AAC(AAC::Low), FF_PROFILE_AAC_LOW => Profile::AAC(AAC::Low),
FF_PROFILE_AAC_SSR => Profile::AAC(AAC::SSR), FF_PROFILE_AAC_SSR => Profile::AAC(AAC::SSR),
FF_PROFILE_AAC_LTP => Profile::AAC(AAC::LTP), FF_PROFILE_AAC_LTP => Profile::AAC(AAC::LTP),
FF_PROFILE_AAC_HE => Profile::AAC(AAC::HE), FF_PROFILE_AAC_HE => Profile::AAC(AAC::HE),
FF_PROFILE_AAC_HE_V2 => Profile::AAC(AAC::HEv2), FF_PROFILE_AAC_HE_V2 => Profile::AAC(AAC::HEv2),
FF_PROFILE_AAC_LD => Profile::AAC(AAC::LD), FF_PROFILE_AAC_LD => Profile::AAC(AAC::LD),
FF_PROFILE_AAC_ELD => Profile::AAC(AAC::ELD), FF_PROFILE_AAC_ELD => Profile::AAC(AAC::ELD),
FF_PROFILE_MPEG2_AAC_LOW => Profile::AAC(AAC::MPEG2Low), FF_PROFILE_MPEG2_AAC_LOW => Profile::AAC(AAC::MPEG2Low),
FF_PROFILE_MPEG2_AAC_HE => Profile::AAC(AAC::MPEG2HE), FF_PROFILE_MPEG2_AAC_HE => Profile::AAC(AAC::MPEG2HE),
_ => Profile::Unknown _ => Profile::Unknown,
}, },
Id::DTS => match value { Id::DTS => match value {
FF_PROFILE_DTS => Profile::DTS(DTS::Default), FF_PROFILE_DTS => Profile::DTS(DTS::Default),
FF_PROFILE_DTS_ES => Profile::DTS(DTS::ES), FF_PROFILE_DTS_ES => Profile::DTS(DTS::ES),
FF_PROFILE_DTS_96_24 => Profile::DTS(DTS::_96_24), FF_PROFILE_DTS_96_24 => Profile::DTS(DTS::_96_24),
FF_PROFILE_DTS_HD_HRA => Profile::DTS(DTS::HD_HRA), FF_PROFILE_DTS_HD_HRA => Profile::DTS(DTS::HD_HRA),
FF_PROFILE_DTS_HD_MA => Profile::DTS(DTS::HD_MA), FF_PROFILE_DTS_HD_MA => Profile::DTS(DTS::HD_MA),
FF_PROFILE_DTS_EXPRESS => Profile::DTS(DTS::Express), FF_PROFILE_DTS_EXPRESS => Profile::DTS(DTS::Express),
_ => Profile::Unknown, _ => Profile::Unknown,
}, },
Id::MPEG2VIDEO => match value { Id::MPEG2VIDEO => match value {
FF_PROFILE_MPEG2_422 => Profile::MPEG2(MPEG2::_422), FF_PROFILE_MPEG2_422 => Profile::MPEG2(MPEG2::_422),
FF_PROFILE_MPEG2_HIGH => Profile::MPEG2(MPEG2::High), FF_PROFILE_MPEG2_HIGH => Profile::MPEG2(MPEG2::High),
FF_PROFILE_MPEG2_SS => Profile::MPEG2(MPEG2::SS), FF_PROFILE_MPEG2_SS => Profile::MPEG2(MPEG2::SS),
FF_PROFILE_MPEG2_SNR_SCALABLE => Profile::MPEG2(MPEG2::SNRScalable), FF_PROFILE_MPEG2_SNR_SCALABLE => Profile::MPEG2(MPEG2::SNRScalable),
FF_PROFILE_MPEG2_MAIN => Profile::MPEG2(MPEG2::Main), FF_PROFILE_MPEG2_MAIN => Profile::MPEG2(MPEG2::Main),
FF_PROFILE_MPEG2_SIMPLE => Profile::MPEG2(MPEG2::Simple), FF_PROFILE_MPEG2_SIMPLE => Profile::MPEG2(MPEG2::Simple),
_ => Profile::Unknown, _ => Profile::Unknown,
}, },
Id::H264 => match value { Id::H264 => match value {
FF_PROFILE_H264_CONSTRAINED => Profile::H264(H264::Constrained), FF_PROFILE_H264_CONSTRAINED => Profile::H264(H264::Constrained),
FF_PROFILE_H264_INTRA => Profile::H264(H264::Intra), FF_PROFILE_H264_INTRA => Profile::H264(H264::Intra),
FF_PROFILE_H264_BASELINE => Profile::H264(H264::Baseline), FF_PROFILE_H264_BASELINE => Profile::H264(H264::Baseline),
FF_PROFILE_H264_CONSTRAINED_BASELINE => Profile::H264(H264::ConstrainedBaseline), FF_PROFILE_H264_CONSTRAINED_BASELINE => Profile::H264(H264::ConstrainedBaseline),
FF_PROFILE_H264_MAIN => Profile::H264(H264::Main), FF_PROFILE_H264_MAIN => Profile::H264(H264::Main),
FF_PROFILE_H264_EXTENDED => Profile::H264(H264::Extended), FF_PROFILE_H264_EXTENDED => Profile::H264(H264::Extended),
FF_PROFILE_H264_HIGH => Profile::H264(H264::High), FF_PROFILE_H264_HIGH => Profile::H264(H264::High),
FF_PROFILE_H264_HIGH_10 => Profile::H264(H264::High10), FF_PROFILE_H264_HIGH_10 => Profile::H264(H264::High10),
FF_PROFILE_H264_HIGH_10_INTRA => Profile::H264(H264::High10Intra), FF_PROFILE_H264_HIGH_10_INTRA => Profile::H264(H264::High10Intra),
FF_PROFILE_H264_HIGH_422 => Profile::H264(H264::High422), FF_PROFILE_H264_HIGH_422 => Profile::H264(H264::High422),
FF_PROFILE_H264_HIGH_422_INTRA => Profile::H264(H264::High422Intra), FF_PROFILE_H264_HIGH_422_INTRA => Profile::H264(H264::High422Intra),
FF_PROFILE_H264_HIGH_444 => Profile::H264(H264::High444), FF_PROFILE_H264_HIGH_444 => Profile::H264(H264::High444),
FF_PROFILE_H264_HIGH_444_PREDICTIVE => Profile::H264(H264::High444Predictive), FF_PROFILE_H264_HIGH_444_PREDICTIVE => Profile::H264(H264::High444Predictive),
FF_PROFILE_H264_HIGH_444_INTRA => Profile::H264(H264::High444Intra), FF_PROFILE_H264_HIGH_444_INTRA => Profile::H264(H264::High444Intra),
FF_PROFILE_H264_CAVLC_444 => Profile::H264(H264::CAVLC444), FF_PROFILE_H264_CAVLC_444 => Profile::H264(H264::CAVLC444),
_ => Profile::Unknown, _ => Profile::Unknown,
}, },
Id::VC1 => match value { Id::VC1 => match value {
FF_PROFILE_VC1_SIMPLE => Profile::VC1(VC1::Simple), FF_PROFILE_VC1_SIMPLE => Profile::VC1(VC1::Simple),
FF_PROFILE_VC1_MAIN => Profile::VC1(VC1::Main), FF_PROFILE_VC1_MAIN => Profile::VC1(VC1::Main),
FF_PROFILE_VC1_COMPLEX => Profile::VC1(VC1::Complex), FF_PROFILE_VC1_COMPLEX => Profile::VC1(VC1::Complex),
FF_PROFILE_VC1_ADVANCED => Profile::VC1(VC1::Advanced), FF_PROFILE_VC1_ADVANCED => Profile::VC1(VC1::Advanced),
_ => Profile::Unknown, _ => Profile::Unknown,
}, },
Id::MPEG4 => match value { Id::MPEG4 => match value {
FF_PROFILE_MPEG4_SIMPLE => Profile::MPEG4(MPEG4::Simple), FF_PROFILE_MPEG4_SIMPLE => Profile::MPEG4(MPEG4::Simple),
FF_PROFILE_MPEG4_SIMPLE_SCALABLE => Profile::MPEG4(MPEG4::SimpleScalable), FF_PROFILE_MPEG4_SIMPLE_SCALABLE => Profile::MPEG4(MPEG4::SimpleScalable),
FF_PROFILE_MPEG4_CORE => Profile::MPEG4(MPEG4::Core), FF_PROFILE_MPEG4_CORE => Profile::MPEG4(MPEG4::Core),
FF_PROFILE_MPEG4_MAIN => Profile::MPEG4(MPEG4::Main), FF_PROFILE_MPEG4_MAIN => Profile::MPEG4(MPEG4::Main),
FF_PROFILE_MPEG4_N_BIT => Profile::MPEG4(MPEG4::NBit), FF_PROFILE_MPEG4_N_BIT => Profile::MPEG4(MPEG4::NBit),
FF_PROFILE_MPEG4_SCALABLE_TEXTURE => Profile::MPEG4(MPEG4::ScalableTexture), FF_PROFILE_MPEG4_SCALABLE_TEXTURE => Profile::MPEG4(MPEG4::ScalableTexture),
FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION => Profile::MPEG4(MPEG4::SimpleFaceAnimation), FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION => {
FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE => Profile::MPEG4(MPEG4::BasicAnimatedTexture), Profile::MPEG4(MPEG4::SimpleFaceAnimation)
FF_PROFILE_MPEG4_HYBRID => Profile::MPEG4(MPEG4::Hybrid), }
FF_PROFILE_MPEG4_ADVANCED_REAL_TIME => Profile::MPEG4(MPEG4::AdvancedRealTime), FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE => {
FF_PROFILE_MPEG4_CORE_SCALABLE => Profile::MPEG4(MPEG4::CoreScalable), Profile::MPEG4(MPEG4::BasicAnimatedTexture)
FF_PROFILE_MPEG4_ADVANCED_CODING => Profile::MPEG4(MPEG4::AdvancedCoding), }
FF_PROFILE_MPEG4_ADVANCED_CORE => Profile::MPEG4(MPEG4::AdvancedCore), FF_PROFILE_MPEG4_HYBRID => Profile::MPEG4(MPEG4::Hybrid),
FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE => Profile::MPEG4(MPEG4::AdvancedScalableTexture), FF_PROFILE_MPEG4_ADVANCED_REAL_TIME => Profile::MPEG4(MPEG4::AdvancedRealTime),
FF_PROFILE_MPEG4_SIMPLE_STUDIO => Profile::MPEG4(MPEG4::SimpleStudio), FF_PROFILE_MPEG4_CORE_SCALABLE => Profile::MPEG4(MPEG4::CoreScalable),
FF_PROFILE_MPEG4_ADVANCED_SIMPLE => Profile::MPEG4(MPEG4::AdvancedSimple), FF_PROFILE_MPEG4_ADVANCED_CODING => Profile::MPEG4(MPEG4::AdvancedCoding),
FF_PROFILE_MPEG4_ADVANCED_CORE => Profile::MPEG4(MPEG4::AdvancedCore),
FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE => {
Profile::MPEG4(MPEG4::AdvancedScalableTexture)
}
FF_PROFILE_MPEG4_SIMPLE_STUDIO => Profile::MPEG4(MPEG4::SimpleStudio),
FF_PROFILE_MPEG4_ADVANCED_SIMPLE => Profile::MPEG4(MPEG4::AdvancedSimple),
_ => Profile::Unknown, _ => Profile::Unknown,
}, },
Id::JPEG2000 => match value { Id::JPEG2000 => match value {
FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 => Profile::JPEG2000(JPEG2000::CStreamRestriction0), FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0 => {
FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 => Profile::JPEG2000(JPEG2000::CStreamRestriction1), Profile::JPEG2000(JPEG2000::CStreamRestriction0)
FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION => Profile::JPEG2000(JPEG2000::CStreamNoRestriction), }
FF_PROFILE_JPEG2000_DCINEMA_2K => Profile::JPEG2000(JPEG2000::DCinema2K), FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1 => {
FF_PROFILE_JPEG2000_DCINEMA_4K => Profile::JPEG2000(JPEG2000::DCinema4K), Profile::JPEG2000(JPEG2000::CStreamRestriction1)
}
FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION => {
Profile::JPEG2000(JPEG2000::CStreamNoRestriction)
}
FF_PROFILE_JPEG2000_DCINEMA_2K => Profile::JPEG2000(JPEG2000::DCinema2K),
FF_PROFILE_JPEG2000_DCINEMA_4K => Profile::JPEG2000(JPEG2000::DCinema4K),
_ => Profile::Unknown, _ => Profile::Unknown,
}, },
Id::HEVC => match value { Id::HEVC => match value {
FF_PROFILE_HEVC_MAIN => Profile::HEVC(HEVC::Main), FF_PROFILE_HEVC_MAIN => Profile::HEVC(HEVC::Main),
FF_PROFILE_HEVC_MAIN_10 => Profile::HEVC(HEVC::Main10), FF_PROFILE_HEVC_MAIN_10 => Profile::HEVC(HEVC::Main10),
FF_PROFILE_HEVC_MAIN_STILL_PICTURE => Profile::HEVC(HEVC::MainStillPicture), FF_PROFILE_HEVC_MAIN_STILL_PICTURE => Profile::HEVC(HEVC::MainStillPicture),
FF_PROFILE_HEVC_REXT => Profile::HEVC(HEVC::Rext), FF_PROFILE_HEVC_REXT => Profile::HEVC(HEVC::Rext),
_ => Profile::Unknown, _ => Profile::Unknown,
}, },
Id::VP9 => match value { Id::VP9 => match value {
FF_PROFILE_VP9_0 => Profile::VP9(VP9::_0), FF_PROFILE_VP9_0 => Profile::VP9(VP9::_0),
FF_PROFILE_VP9_1 => Profile::VP9(VP9::_1), FF_PROFILE_VP9_1 => Profile::VP9(VP9::_1),
FF_PROFILE_VP9_2 => Profile::VP9(VP9::_2), FF_PROFILE_VP9_2 => Profile::VP9(VP9::_2),
FF_PROFILE_VP9_3 => Profile::VP9(VP9::_3), FF_PROFILE_VP9_3 => Profile::VP9(VP9::_3),
_ => Profile::Unknown, _ => Profile::Unknown,
}, },
_ => Profile::Unknown _ => Profile::Unknown,
} }
} }
} }
impl Into<c_int> for Profile { impl Into<c_int> for Profile {
fn into(self) -> c_int { fn into(self) -> c_int {
match self { match self {
Profile::Unknown => FF_PROFILE_UNKNOWN, Profile::Unknown => FF_PROFILE_UNKNOWN,
Profile::Reserved => FF_PROFILE_RESERVED, Profile::Reserved => FF_PROFILE_RESERVED,
Profile::AAC(AAC::Main) => FF_PROFILE_AAC_MAIN, Profile::AAC(AAC::Main) => FF_PROFILE_AAC_MAIN,
Profile::AAC(AAC::Low) => FF_PROFILE_AAC_LOW, Profile::AAC(AAC::Low) => FF_PROFILE_AAC_LOW,
Profile::AAC(AAC::SSR) => FF_PROFILE_AAC_SSR, Profile::AAC(AAC::SSR) => FF_PROFILE_AAC_SSR,
Profile::AAC(AAC::LTP) => FF_PROFILE_AAC_LTP, Profile::AAC(AAC::LTP) => FF_PROFILE_AAC_LTP,
Profile::AAC(AAC::HE) => FF_PROFILE_AAC_HE, Profile::AAC(AAC::HE) => FF_PROFILE_AAC_HE,
Profile::AAC(AAC::HEv2) => FF_PROFILE_AAC_HE_V2, Profile::AAC(AAC::HEv2) => FF_PROFILE_AAC_HE_V2,
Profile::AAC(AAC::LD) => FF_PROFILE_AAC_LD, Profile::AAC(AAC::LD) => FF_PROFILE_AAC_LD,
Profile::AAC(AAC::ELD) => FF_PROFILE_AAC_ELD, Profile::AAC(AAC::ELD) => FF_PROFILE_AAC_ELD,
Profile::AAC(AAC::MPEG2Low) => FF_PROFILE_MPEG2_AAC_LOW, Profile::AAC(AAC::MPEG2Low) => FF_PROFILE_MPEG2_AAC_LOW,
Profile::AAC(AAC::MPEG2HE) => FF_PROFILE_MPEG2_AAC_HE, Profile::AAC(AAC::MPEG2HE) => FF_PROFILE_MPEG2_AAC_HE,
Profile::DTS(DTS::Default) => FF_PROFILE_DTS, Profile::DTS(DTS::Default) => FF_PROFILE_DTS,
Profile::DTS(DTS::ES) => FF_PROFILE_DTS_ES, Profile::DTS(DTS::ES) => FF_PROFILE_DTS_ES,
Profile::DTS(DTS::_96_24) => FF_PROFILE_DTS_96_24, Profile::DTS(DTS::_96_24) => FF_PROFILE_DTS_96_24,
Profile::DTS(DTS::HD_HRA) => FF_PROFILE_DTS_HD_HRA, Profile::DTS(DTS::HD_HRA) => FF_PROFILE_DTS_HD_HRA,
Profile::DTS(DTS::HD_MA) => FF_PROFILE_DTS_HD_MA, Profile::DTS(DTS::HD_MA) => FF_PROFILE_DTS_HD_MA,
Profile::DTS(DTS::Express) => FF_PROFILE_DTS_EXPRESS, Profile::DTS(DTS::Express) => FF_PROFILE_DTS_EXPRESS,
Profile::MPEG2(MPEG2::_422) => FF_PROFILE_MPEG2_422, Profile::MPEG2(MPEG2::_422) => FF_PROFILE_MPEG2_422,
Profile::MPEG2(MPEG2::High) => FF_PROFILE_MPEG2_HIGH, Profile::MPEG2(MPEG2::High) => FF_PROFILE_MPEG2_HIGH,
Profile::MPEG2(MPEG2::SS) => FF_PROFILE_MPEG2_SS, Profile::MPEG2(MPEG2::SS) => FF_PROFILE_MPEG2_SS,
Profile::MPEG2(MPEG2::SNRScalable) => FF_PROFILE_MPEG2_SNR_SCALABLE, Profile::MPEG2(MPEG2::SNRScalable) => FF_PROFILE_MPEG2_SNR_SCALABLE,
Profile::MPEG2(MPEG2::Main) => FF_PROFILE_MPEG2_MAIN, Profile::MPEG2(MPEG2::Main) => FF_PROFILE_MPEG2_MAIN,
Profile::MPEG2(MPEG2::Simple) => FF_PROFILE_MPEG2_SIMPLE, Profile::MPEG2(MPEG2::Simple) => FF_PROFILE_MPEG2_SIMPLE,
Profile::H264(H264::Constrained) => FF_PROFILE_H264_CONSTRAINED, Profile::H264(H264::Constrained) => FF_PROFILE_H264_CONSTRAINED,
Profile::H264(H264::Intra) => FF_PROFILE_H264_INTRA, Profile::H264(H264::Intra) => FF_PROFILE_H264_INTRA,
Profile::H264(H264::Baseline) => FF_PROFILE_H264_BASELINE, Profile::H264(H264::Baseline) => FF_PROFILE_H264_BASELINE,
Profile::H264(H264::ConstrainedBaseline) => FF_PROFILE_H264_CONSTRAINED_BASELINE, Profile::H264(H264::ConstrainedBaseline) => FF_PROFILE_H264_CONSTRAINED_BASELINE,
Profile::H264(H264::Main) => FF_PROFILE_H264_MAIN, Profile::H264(H264::Main) => FF_PROFILE_H264_MAIN,
Profile::H264(H264::Extended) => FF_PROFILE_H264_EXTENDED, Profile::H264(H264::Extended) => FF_PROFILE_H264_EXTENDED,
Profile::H264(H264::High) => FF_PROFILE_H264_HIGH, Profile::H264(H264::High) => FF_PROFILE_H264_HIGH,
Profile::H264(H264::High10) => FF_PROFILE_H264_HIGH_10, Profile::H264(H264::High10) => FF_PROFILE_H264_HIGH_10,
Profile::H264(H264::High10Intra) => FF_PROFILE_H264_HIGH_10_INTRA, Profile::H264(H264::High10Intra) => FF_PROFILE_H264_HIGH_10_INTRA,
Profile::H264(H264::High422) => FF_PROFILE_H264_HIGH_422, Profile::H264(H264::High422) => FF_PROFILE_H264_HIGH_422,
Profile::H264(H264::High422Intra) => FF_PROFILE_H264_HIGH_422_INTRA, Profile::H264(H264::High422Intra) => FF_PROFILE_H264_HIGH_422_INTRA,
Profile::H264(H264::High444) => FF_PROFILE_H264_HIGH_444, Profile::H264(H264::High444) => FF_PROFILE_H264_HIGH_444,
Profile::H264(H264::High444Predictive) => FF_PROFILE_H264_HIGH_444_PREDICTIVE, Profile::H264(H264::High444Predictive) => FF_PROFILE_H264_HIGH_444_PREDICTIVE,
Profile::H264(H264::High444Intra) => FF_PROFILE_H264_HIGH_444_INTRA, Profile::H264(H264::High444Intra) => FF_PROFILE_H264_HIGH_444_INTRA,
Profile::H264(H264::CAVLC444) => FF_PROFILE_H264_CAVLC_444, Profile::H264(H264::CAVLC444) => FF_PROFILE_H264_CAVLC_444,
Profile::VC1(VC1::Simple) => FF_PROFILE_VC1_SIMPLE, Profile::VC1(VC1::Simple) => FF_PROFILE_VC1_SIMPLE,
Profile::VC1(VC1::Main) => FF_PROFILE_VC1_MAIN, Profile::VC1(VC1::Main) => FF_PROFILE_VC1_MAIN,
Profile::VC1(VC1::Complex) => FF_PROFILE_VC1_COMPLEX, Profile::VC1(VC1::Complex) => FF_PROFILE_VC1_COMPLEX,
Profile::VC1(VC1::Advanced) => FF_PROFILE_VC1_ADVANCED, Profile::VC1(VC1::Advanced) => FF_PROFILE_VC1_ADVANCED,
Profile::MPEG4(MPEG4::Simple) => FF_PROFILE_MPEG4_SIMPLE, Profile::MPEG4(MPEG4::Simple) => FF_PROFILE_MPEG4_SIMPLE,
Profile::MPEG4(MPEG4::SimpleScalable) => FF_PROFILE_MPEG4_SIMPLE_SCALABLE, Profile::MPEG4(MPEG4::SimpleScalable) => FF_PROFILE_MPEG4_SIMPLE_SCALABLE,
Profile::MPEG4(MPEG4::Core) => FF_PROFILE_MPEG4_CORE, Profile::MPEG4(MPEG4::Core) => FF_PROFILE_MPEG4_CORE,
Profile::MPEG4(MPEG4::Main) => FF_PROFILE_MPEG4_MAIN, Profile::MPEG4(MPEG4::Main) => FF_PROFILE_MPEG4_MAIN,
Profile::MPEG4(MPEG4::NBit) => FF_PROFILE_MPEG4_N_BIT, Profile::MPEG4(MPEG4::NBit) => FF_PROFILE_MPEG4_N_BIT,
Profile::MPEG4(MPEG4::ScalableTexture) => FF_PROFILE_MPEG4_SCALABLE_TEXTURE, Profile::MPEG4(MPEG4::ScalableTexture) => FF_PROFILE_MPEG4_SCALABLE_TEXTURE,
Profile::MPEG4(MPEG4::SimpleFaceAnimation) => FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION, Profile::MPEG4(MPEG4::SimpleFaceAnimation) => FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION,
Profile::MPEG4(MPEG4::BasicAnimatedTexture) => FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE, Profile::MPEG4(MPEG4::BasicAnimatedTexture) => FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE,
Profile::MPEG4(MPEG4::Hybrid) => FF_PROFILE_MPEG4_HYBRID, Profile::MPEG4(MPEG4::Hybrid) => FF_PROFILE_MPEG4_HYBRID,
Profile::MPEG4(MPEG4::AdvancedRealTime) => FF_PROFILE_MPEG4_ADVANCED_REAL_TIME, Profile::MPEG4(MPEG4::AdvancedRealTime) => FF_PROFILE_MPEG4_ADVANCED_REAL_TIME,
Profile::MPEG4(MPEG4::CoreScalable) => FF_PROFILE_MPEG4_CORE_SCALABLE, Profile::MPEG4(MPEG4::CoreScalable) => FF_PROFILE_MPEG4_CORE_SCALABLE,
Profile::MPEG4(MPEG4::AdvancedCoding) => FF_PROFILE_MPEG4_ADVANCED_CODING, Profile::MPEG4(MPEG4::AdvancedCoding) => FF_PROFILE_MPEG4_ADVANCED_CODING,
Profile::MPEG4(MPEG4::AdvancedCore) => FF_PROFILE_MPEG4_ADVANCED_CORE, Profile::MPEG4(MPEG4::AdvancedCore) => FF_PROFILE_MPEG4_ADVANCED_CORE,
Profile::MPEG4(MPEG4::AdvancedScalableTexture) => FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE, Profile::MPEG4(MPEG4::AdvancedScalableTexture) => {
Profile::MPEG4(MPEG4::SimpleStudio) => FF_PROFILE_MPEG4_SIMPLE_STUDIO, FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE
Profile::MPEG4(MPEG4::AdvancedSimple) => FF_PROFILE_MPEG4_ADVANCED_SIMPLE, }
Profile::MPEG4(MPEG4::SimpleStudio) => FF_PROFILE_MPEG4_SIMPLE_STUDIO,
Profile::MPEG4(MPEG4::AdvancedSimple) => FF_PROFILE_MPEG4_ADVANCED_SIMPLE,
Profile::JPEG2000(JPEG2000::CStreamRestriction0) => FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0, Profile::JPEG2000(JPEG2000::CStreamRestriction0) => {
Profile::JPEG2000(JPEG2000::CStreamRestriction1) => FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1, FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0
Profile::JPEG2000(JPEG2000::CStreamNoRestriction) => FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION, }
Profile::JPEG2000(JPEG2000::DCinema2K) => FF_PROFILE_JPEG2000_DCINEMA_2K, Profile::JPEG2000(JPEG2000::CStreamRestriction1) => {
Profile::JPEG2000(JPEG2000::DCinema4K) => FF_PROFILE_JPEG2000_DCINEMA_4K, FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1
}
Profile::JPEG2000(JPEG2000::CStreamNoRestriction) => {
FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION
}
Profile::JPEG2000(JPEG2000::DCinema2K) => FF_PROFILE_JPEG2000_DCINEMA_2K,
Profile::JPEG2000(JPEG2000::DCinema4K) => FF_PROFILE_JPEG2000_DCINEMA_4K,
Profile::HEVC(HEVC::Main) => FF_PROFILE_HEVC_MAIN, Profile::HEVC(HEVC::Main) => FF_PROFILE_HEVC_MAIN,
Profile::HEVC(HEVC::Main10) => FF_PROFILE_HEVC_MAIN_10, Profile::HEVC(HEVC::Main10) => FF_PROFILE_HEVC_MAIN_10,
Profile::HEVC(HEVC::MainStillPicture) => FF_PROFILE_HEVC_MAIN_STILL_PICTURE, Profile::HEVC(HEVC::MainStillPicture) => FF_PROFILE_HEVC_MAIN_STILL_PICTURE,
Profile::HEVC(HEVC::Rext) => FF_PROFILE_HEVC_REXT, Profile::HEVC(HEVC::Rext) => FF_PROFILE_HEVC_REXT,
Profile::VP9(VP9::_0) => FF_PROFILE_VP9_0, Profile::VP9(VP9::_0) => FF_PROFILE_VP9_0,
Profile::VP9(VP9::_1) => FF_PROFILE_VP9_1, Profile::VP9(VP9::_1) => FF_PROFILE_VP9_1,
Profile::VP9(VP9::_2) => FF_PROFILE_VP9_2, Profile::VP9(VP9::_2) => FF_PROFILE_VP9_2,
Profile::VP9(VP9::_3) => FF_PROFILE_VP9_3, Profile::VP9(VP9::_3) => FF_PROFILE_VP9_3,
} }
} }
} }

View File

@ -1,8 +1,8 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Flags: c_int { pub struct Flags: c_int {
const FORCED = AV_SUBTITLE_FLAG_FORCED; const FORCED = AV_SUBTITLE_FLAG_FORCED;
} }
} }

View File

@ -2,193 +2,209 @@ pub mod flag;
pub use self::flag::Flags; pub use self::flag::Flags;
mod rect; mod rect;
pub use self::rect::{Rect, Bitmap, Text, Ass}; pub use self::rect::{Ass, Bitmap, Rect, Text};
mod rect_mut; mod rect_mut;
pub use self::rect_mut::{RectMut, BitmapMut, TextMut, AssMut}; pub use self::rect_mut::{AssMut, BitmapMut, RectMut, TextMut};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use libc::{c_uint, uint32_t, size_t};
use ffi::*;
use ffi::AVSubtitleType::*; use ffi::AVSubtitleType::*;
use ffi::*;
use libc::{c_uint, size_t, uint32_t};
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum Type { pub enum Type {
None, None,
Bitmap, Bitmap,
Text, Text,
Ass, Ass,
} }
impl From<AVSubtitleType> for Type { impl From<AVSubtitleType> for Type {
fn from(value: AVSubtitleType) -> Type { fn from(value: AVSubtitleType) -> Type {
match value { match value {
SUBTITLE_NONE => Type::None, SUBTITLE_NONE => Type::None,
SUBTITLE_BITMAP => Type::Bitmap, SUBTITLE_BITMAP => Type::Bitmap,
SUBTITLE_TEXT => Type::Text, SUBTITLE_TEXT => Type::Text,
SUBTITLE_ASS => Type::Ass SUBTITLE_ASS => Type::Ass,
} }
} }
} }
impl Into<AVSubtitleType> for Type { impl Into<AVSubtitleType> for Type {
fn into(self) -> AVSubtitleType { fn into(self) -> AVSubtitleType {
match self { match self {
Type::None => SUBTITLE_NONE, Type::None => SUBTITLE_NONE,
Type::Bitmap => SUBTITLE_BITMAP, Type::Bitmap => SUBTITLE_BITMAP,
Type::Text => SUBTITLE_TEXT, Type::Text => SUBTITLE_TEXT,
Type::Ass => SUBTITLE_ASS Type::Ass => SUBTITLE_ASS,
} }
} }
} }
pub struct Subtitle(AVSubtitle); pub struct Subtitle(AVSubtitle);
impl Subtitle { impl Subtitle {
pub unsafe fn as_ptr(&self) -> *const AVSubtitle { pub unsafe fn as_ptr(&self) -> *const AVSubtitle {
&self.0 &self.0
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitle { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitle {
&mut self.0 &mut self.0
} }
} }
impl Subtitle { impl Subtitle {
pub fn new() -> Self { pub fn new() -> Self {
unsafe { unsafe { Subtitle(mem::zeroed()) }
Subtitle(mem::zeroed()) }
}
}
pub fn pts(&self) -> Option<i64> { pub fn pts(&self) -> Option<i64> {
match self.0.pts { match self.0.pts {
AV_NOPTS_VALUE => None, AV_NOPTS_VALUE => None,
pts => Some(pts) pts => Some(pts),
} }
} }
pub fn set_pts(&mut self, value: Option<i64>) { pub fn set_pts(&mut self, value: Option<i64>) {
self.0.pts = value.unwrap_or(AV_NOPTS_VALUE); self.0.pts = value.unwrap_or(AV_NOPTS_VALUE);
} }
pub fn start(&self) -> u32 { pub fn start(&self) -> u32 {
self.0.start_display_time as u32 self.0.start_display_time as u32
} }
pub fn set_start(&mut self, value: u32) { pub fn set_start(&mut self, value: u32) {
self.0.start_display_time = value as uint32_t; self.0.start_display_time = value as uint32_t;
} }
pub fn end(&self) -> u32 { pub fn end(&self) -> u32 {
self.0.end_display_time as u32 self.0.end_display_time as u32
} }
pub fn set_end(&mut self, value: u32) { pub fn set_end(&mut self, value: u32) {
self.0.end_display_time = value as uint32_t; self.0.end_display_time = value as uint32_t;
} }
pub fn rects(&self) -> RectIter { pub fn rects(&self) -> RectIter {
RectIter::new(&self.0) RectIter::new(&self.0)
} }
pub fn rects_mut(&mut self) -> RectMutIter { pub fn rects_mut(&mut self) -> RectMutIter {
RectMutIter::new(&mut self.0) RectMutIter::new(&mut self.0)
} }
pub fn add_rect(&mut self, kind: Type) -> RectMut { pub fn add_rect(&mut self, kind: Type) -> RectMut {
unsafe { unsafe {
self.0.num_rects += 1; self.0.num_rects += 1;
self.0.rects = av_realloc(self.0.rects as *mut _, self.0.rects = av_realloc(
(mem::size_of::<*const AVSubtitleRect>() * self.0.num_rects as usize) as size_t) self.0.rects as *mut _,
as *mut _; (mem::size_of::<*const AVSubtitleRect>() * self.0.num_rects as usize) as size_t,
) as *mut _;
let rect = av_mallocz(mem::size_of::<AVSubtitleRect>() as size_t) as *mut AVSubtitleRect; let rect =
(*rect).type_ = kind.into(); av_mallocz(mem::size_of::<AVSubtitleRect>() as size_t) as *mut AVSubtitleRect;
(*rect).type_ = kind.into();
*self.0.rects.offset((self.0.num_rects - 1) as isize) = rect; *self.0.rects.offset((self.0.num_rects - 1) as isize) = rect;
RectMut::wrap(rect) RectMut::wrap(rect)
} }
} }
}
impl Default for Subtitle {
fn default() -> Self {
Self::new()
}
} }
pub struct RectIter<'a> { pub struct RectIter<'a> {
ptr: *const AVSubtitle, ptr: *const AVSubtitle,
cur: c_uint, cur: c_uint,
_marker: PhantomData<&'a Subtitle>, _marker: PhantomData<&'a Subtitle>,
} }
impl<'a> RectIter<'a> { impl<'a> RectIter<'a> {
pub fn new(ptr: *const AVSubtitle) -> Self { pub fn new(ptr: *const AVSubtitle) -> Self {
RectIter { ptr: ptr, cur: 0, _marker: PhantomData } RectIter {
} ptr: ptr,
cur: 0,
_marker: PhantomData,
}
}
} }
impl<'a> Iterator for RectIter<'a> { impl<'a> Iterator for RectIter<'a> {
type Item = Rect<'a>; type Item = Rect<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if self.cur >= (*self.ptr).num_rects { if self.cur >= (*self.ptr).num_rects {
None None
} } else {
else { self.cur += 1;
self.cur += 1; Some(Rect::wrap(*(*self.ptr)
Some(Rect::wrap(*(*self.ptr).rects.offset((self.cur - 1) as isize))) .rects
} .offset((self.cur - 1) as isize)))
} }
} }
}
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
unsafe { unsafe {
let length = (*self.ptr).num_rects as usize; let length = (*self.ptr).num_rects as usize;
(length - self.cur as usize, Some(length - self.cur as usize)) (length - self.cur as usize, Some(length - self.cur as usize))
} }
} }
} }
impl<'a> ExactSizeIterator for RectIter<'a> { } impl<'a> ExactSizeIterator for RectIter<'a> {}
pub struct RectMutIter<'a> { pub struct RectMutIter<'a> {
ptr: *mut AVSubtitle, ptr: *mut AVSubtitle,
cur: c_uint, cur: c_uint,
_marker: PhantomData<&'a Subtitle>, _marker: PhantomData<&'a Subtitle>,
} }
impl<'a> RectMutIter<'a> { impl<'a> RectMutIter<'a> {
pub fn new(ptr: *mut AVSubtitle) -> Self { pub fn new(ptr: *mut AVSubtitle) -> Self {
RectMutIter { ptr: ptr, cur: 0, _marker: PhantomData } RectMutIter {
} ptr: ptr,
cur: 0,
_marker: PhantomData,
}
}
} }
impl<'a> Iterator for RectMutIter<'a> { impl<'a> Iterator for RectMutIter<'a> {
type Item = RectMut<'a>; type Item = RectMut<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if self.cur >= (*self.ptr).num_rects { if self.cur >= (*self.ptr).num_rects {
None None
} } else {
else { self.cur += 1;
self.cur += 1; Some(RectMut::wrap(*(*self.ptr)
Some(RectMut::wrap(*(*self.ptr).rects.offset((self.cur - 1) as isize))) .rects
} .offset((self.cur - 1) as isize)))
} }
} }
}
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
unsafe { unsafe {
let length = (*self.ptr).num_rects as usize; let length = (*self.ptr).num_rects as usize;
(length - self.cur as usize, Some(length - self.cur as usize)) (length - self.cur as usize, Some(length - self.cur as usize))
} }
} }
} }
impl<'a> ExactSizeIterator for RectMutIter<'a> { } impl<'a> ExactSizeIterator for RectMutIter<'a> {}

View File

@ -1,150 +1,150 @@
use std::marker::PhantomData;
use std::ffi::CStr; use std::ffi::CStr;
use std::marker::PhantomData;
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;
use super::{Flags, Type};
use ffi::*; use ffi::*;
use super::{Type, Flags}; use {format, Picture};
use ::{format, Picture};
pub enum Rect<'a> { pub enum Rect<'a> {
None(*const AVSubtitleRect), None(*const AVSubtitleRect),
Bitmap(Bitmap<'a>), Bitmap(Bitmap<'a>),
Text(Text<'a>), Text(Text<'a>),
Ass(Ass<'a>), Ass(Ass<'a>),
} }
impl<'a> Rect<'a> { impl<'a> Rect<'a> {
pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self { pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self {
match Type::from((*ptr).type_) { match Type::from((*ptr).type_) {
Type::None => Rect::None(ptr), Type::None => Rect::None(ptr),
Type::Bitmap => Rect::Bitmap(Bitmap::wrap(ptr)), Type::Bitmap => Rect::Bitmap(Bitmap::wrap(ptr)),
Type::Text => Rect::Text(Text::wrap(ptr)), Type::Text => Rect::Text(Text::wrap(ptr)),
Type::Ass => Rect::Ass(Ass::wrap(ptr)) Type::Ass => Rect::Ass(Ass::wrap(ptr)),
} }
} }
pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect {
match self { match *self {
&Rect::None(ptr) => ptr, Rect::None(ptr) => ptr,
&Rect::Bitmap(ref b) => b.as_ptr(), Rect::Bitmap(ref b) => b.as_ptr(),
&Rect::Text(ref t) => t.as_ptr(), Rect::Text(ref t) => t.as_ptr(),
&Rect::Ass(ref a) => a.as_ptr() Rect::Ass(ref a) => a.as_ptr(),
} }
} }
} }
impl<'a> Rect<'a> { impl<'a> Rect<'a> {
pub fn flags(&self) -> Flags { pub fn flags(&self) -> Flags {
unsafe { unsafe {
Flags::from_bits_truncate(match self { Flags::from_bits_truncate(match *self {
&Rect::None(ptr) => (*ptr).flags, Rect::None(ptr) => (*ptr).flags,
&Rect::Bitmap(ref b) => (*b.as_ptr()).flags, Rect::Bitmap(ref b) => (*b.as_ptr()).flags,
&Rect::Text(ref t) => (*t.as_ptr()).flags, Rect::Text(ref t) => (*t.as_ptr()).flags,
&Rect::Ass(ref a) => (*a.as_ptr()).flags Rect::Ass(ref a) => (*a.as_ptr()).flags,
}) })
} }
} }
} }
pub struct Bitmap<'a> { pub struct Bitmap<'a> {
ptr: *const AVSubtitleRect, ptr: *const AVSubtitleRect,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> Bitmap<'a> { impl<'a> Bitmap<'a> {
pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self { pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self {
Bitmap { ptr: ptr, _marker: PhantomData } Bitmap {
} ptr: ptr,
_marker: PhantomData,
}
}
pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect {
self.ptr self.ptr
} }
} }
impl<'a> Bitmap<'a> { impl<'a> Bitmap<'a> {
pub fn x(&self) -> usize { pub fn x(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).x as usize }
(*self.as_ptr()).x as usize }
}
}
pub fn y(&self) -> usize { pub fn y(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).y as usize }
(*self.as_ptr()).y as usize }
}
}
pub fn width(&self) -> u32 { pub fn width(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).w as u32 }
(*self.as_ptr()).w as u32 }
}
}
pub fn height(&self) -> u32 { pub fn height(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).h as u32 }
(*self.as_ptr()).h as u32 }
}
}
pub fn colors(&self) -> usize { pub fn colors(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).nb_colors as usize }
(*self.as_ptr()).nb_colors as usize }
}
}
// XXX: must split Picture and PictureMut // XXX: must split Picture and PictureMut
pub fn picture(&self, format: format::Pixel) -> Picture<'a> { pub fn picture(&self, format: format::Pixel) -> Picture<'a> {
unsafe { unsafe {
Picture::wrap(&(*self.as_ptr()).pict as *const _ as *mut _, format, (*self.as_ptr()).w as u32, (*self.as_ptr()).h as u32) Picture::wrap(
} &(*self.as_ptr()).pict as *const _ as *mut _,
} format,
(*self.as_ptr()).w as u32,
(*self.as_ptr()).h as u32,
)
}
}
} }
pub struct Text<'a> { pub struct Text<'a> {
ptr: *const AVSubtitleRect, ptr: *const AVSubtitleRect,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> Text<'a> { impl<'a> Text<'a> {
pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self { pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self {
Text { ptr: ptr, _marker: PhantomData } Text {
} ptr: ptr,
_marker: PhantomData,
}
}
pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect {
self.ptr self.ptr
} }
} }
impl<'a> Text<'a> { impl<'a> Text<'a> {
pub fn get(&self) -> &str { pub fn get(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).text).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).text).to_bytes()) }
}
}
} }
pub struct Ass<'a> { pub struct Ass<'a> {
ptr: *const AVSubtitleRect, ptr: *const AVSubtitleRect,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> Ass<'a> { impl<'a> Ass<'a> {
pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self { pub unsafe fn wrap(ptr: *const AVSubtitleRect) -> Self {
Ass { ptr: ptr, _marker: PhantomData } Ass {
} ptr: ptr,
_marker: PhantomData,
}
}
pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect {
self.ptr self.ptr
} }
} }
impl<'a> Ass<'a> { impl<'a> Ass<'a> {
pub fn get(&self) -> &str { pub fn get(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).ass).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).ass).to_bytes()) }
}
}
} }

View File

@ -1,173 +1,179 @@
use std::ops::Deref;
use std::ffi::CString; use std::ffi::CString;
use std::ops::Deref;
use libc::c_int; use super::{Ass, Bitmap, Flags, Text, Type};
use ffi::*; use ffi::*;
use super::{Type, Flags, Bitmap, Text, Ass}; use libc::c_int;
pub enum RectMut<'a> { pub enum RectMut<'a> {
None(*mut AVSubtitleRect), None(*mut AVSubtitleRect),
Bitmap(BitmapMut<'a>), Bitmap(BitmapMut<'a>),
Text(TextMut<'a>), Text(TextMut<'a>),
Ass(AssMut<'a>), Ass(AssMut<'a>),
} }
impl<'a> RectMut<'a> { impl<'a> RectMut<'a> {
pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self {
match Type::from((*ptr).type_) { match Type::from((*ptr).type_) {
Type::None => RectMut::None(ptr), Type::None => RectMut::None(ptr),
Type::Bitmap => RectMut::Bitmap(BitmapMut::wrap(ptr)), Type::Bitmap => RectMut::Bitmap(BitmapMut::wrap(ptr)),
Type::Text => RectMut::Text(TextMut::wrap(ptr)), Type::Text => RectMut::Text(TextMut::wrap(ptr)),
Type::Ass => RectMut::Ass(AssMut::wrap(ptr)) Type::Ass => RectMut::Ass(AssMut::wrap(ptr)),
} }
} }
pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect { pub unsafe fn as_ptr(&self) -> *const AVSubtitleRect {
match self { match *self {
&RectMut::None(ptr) => ptr as *const _, RectMut::None(ptr) => ptr as *const _,
&RectMut::Bitmap(ref b) => b.as_ptr(), RectMut::Bitmap(ref b) => b.as_ptr(),
&RectMut::Text(ref t) => t.as_ptr(), RectMut::Text(ref t) => t.as_ptr(),
&RectMut::Ass(ref a) => a.as_ptr() RectMut::Ass(ref a) => a.as_ptr(),
} }
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect {
match self { match *self {
&mut RectMut::None(ptr) => ptr, RectMut::None(ptr) => ptr,
&mut RectMut::Bitmap(ref mut b) => b.as_mut_ptr(), RectMut::Bitmap(ref mut b) => b.as_mut_ptr(),
&mut RectMut::Text(ref mut t) => t.as_mut_ptr(), RectMut::Text(ref mut t) => t.as_mut_ptr(),
&mut RectMut::Ass(ref mut a) => a.as_mut_ptr() RectMut::Ass(ref mut a) => a.as_mut_ptr(),
} }
} }
} }
impl<'a> RectMut<'a> { impl<'a> RectMut<'a> {
pub fn flags(&self) -> Flags { pub fn flags(&self) -> Flags {
unsafe { unsafe {
Flags::from_bits_truncate(match self { Flags::from_bits_truncate(match *self {
&RectMut::None(ptr) => (*ptr).flags, RectMut::None(ptr) => (*ptr).flags,
&RectMut::Bitmap(ref b) => (*b.as_ptr()).flags, RectMut::Bitmap(ref b) => (*b.as_ptr()).flags,
&RectMut::Text(ref t) => (*t.as_ptr()).flags, RectMut::Text(ref t) => (*t.as_ptr()).flags,
&RectMut::Ass(ref a) => (*a.as_ptr()).flags RectMut::Ass(ref a) => (*a.as_ptr()).flags,
}) })
} }
} }
} }
pub struct BitmapMut<'a> { pub struct BitmapMut<'a> {
immutable: Bitmap<'a>, immutable: Bitmap<'a>,
} }
impl<'a> BitmapMut<'a> { impl<'a> BitmapMut<'a> {
pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self {
BitmapMut { immutable: Bitmap::wrap(ptr as *const _) } BitmapMut {
} immutable: Bitmap::wrap(ptr as *const _),
}
}
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect {
self.as_ptr() as *mut _ self.as_ptr() as *mut _
} }
} }
impl<'a> BitmapMut<'a> { impl<'a> BitmapMut<'a> {
pub fn set_x(&mut self, value: usize) { pub fn set_x(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).x = value as c_int; (*self.as_mut_ptr()).x = value as c_int;
} }
} }
pub fn set_y(&mut self, value: usize) { pub fn set_y(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).y = value as c_int; (*self.as_mut_ptr()).y = value as c_int;
} }
} }
pub fn set_width(&mut self, value: u32) { pub fn set_width(&mut self, value: u32) {
unsafe { unsafe {
(*self.as_mut_ptr()).w = value as c_int; (*self.as_mut_ptr()).w = value as c_int;
} }
} }
pub fn set_height(&mut self, value: u32) { pub fn set_height(&mut self, value: u32) {
unsafe { unsafe {
(*self.as_mut_ptr()).h = value as c_int; (*self.as_mut_ptr()).h = value as c_int;
} }
} }
pub fn set_colors(&mut self, value: usize) { pub fn set_colors(&mut self, value: usize) {
unsafe { unsafe {
(*self.as_mut_ptr()).nb_colors = value as c_int; (*self.as_mut_ptr()).nb_colors = value as c_int;
} }
} }
} }
impl<'a> Deref for BitmapMut<'a> { impl<'a> Deref for BitmapMut<'a> {
type Target = Bitmap<'a>; type Target = Bitmap<'a>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.immutable &self.immutable
} }
} }
pub struct TextMut<'a> { pub struct TextMut<'a> {
immutable: Text<'a>, immutable: Text<'a>,
} }
impl<'a> TextMut<'a> { impl<'a> TextMut<'a> {
pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self {
TextMut { immutable: Text::wrap(ptr as *const _) } TextMut {
} immutable: Text::wrap(ptr as *const _),
}
}
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect {
self.as_ptr() as *mut _ self.as_ptr() as *mut _
} }
} }
impl<'a> TextMut<'a> { impl<'a> TextMut<'a> {
pub fn set(&mut self, value: &str) { pub fn set(&mut self, value: &str) {
let value = CString::new(value).unwrap(); let value = CString::new(value).unwrap();
unsafe { unsafe {
(*self.as_mut_ptr()).text = av_strdup(value.as_ptr()); (*self.as_mut_ptr()).text = av_strdup(value.as_ptr());
} }
} }
} }
impl<'a> Deref for TextMut<'a> { impl<'a> Deref for TextMut<'a> {
type Target = Text<'a>; type Target = Text<'a>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.immutable &self.immutable
} }
} }
pub struct AssMut<'a> { pub struct AssMut<'a> {
immutable: Ass<'a>, immutable: Ass<'a>,
} }
impl<'a> AssMut<'a> { impl<'a> AssMut<'a> {
pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self { pub unsafe fn wrap(ptr: *mut AVSubtitleRect) -> Self {
AssMut { immutable: Ass::wrap(ptr) } AssMut {
} immutable: Ass::wrap(ptr),
}
}
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVSubtitleRect {
self.as_ptr() as *mut _ self.as_ptr() as *mut _
} }
} }
impl<'a> AssMut<'a> { impl<'a> AssMut<'a> {
pub fn set(&mut self, value: &str) { pub fn set(&mut self, value: &str) {
let value = CString::new(value).unwrap(); let value = CString::new(value).unwrap();
unsafe { unsafe {
(*self.as_mut_ptr()).ass = av_strdup(value.as_ptr()); (*self.as_mut_ptr()).ass = av_strdup(value.as_ptr());
} }
} }
} }
impl<'a> Deref for AssMut<'a> { impl<'a> Deref for AssMut<'a> {
type Target = Ass<'a>; type Target = Ass<'a>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.immutable &self.immutable
} }
} }

View File

@ -1,61 +1,70 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub struct Config { pub struct Config {
pub kind: Type, pub kind: Type,
pub count: usize, pub count: usize,
pub safe: bool, pub safe: bool,
} }
impl Config { impl Config {
pub fn kind(value: Type) -> Self { pub fn kind(value: Type) -> Self {
Config { kind: value, .. Default::default() } Config {
} kind: value,
..Default::default()
}
}
pub fn count(value: usize) -> Self { pub fn count(value: usize) -> Self {
Config { count: value, .. Default::default() } Config {
} count: value,
..Default::default()
}
}
pub fn safe(value: bool) -> Self { pub fn safe(value: bool) -> Self {
Config { safe: value, .. Default::default() } Config {
} safe: value,
..Default::default()
}
}
} }
impl Default for Config { impl Default for Config {
fn default() -> Self { fn default() -> Self {
Config { Config {
kind: Type::None, kind: Type::None,
count: 0, count: 0,
safe: false, safe: false,
} }
} }
} }
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum Type { pub enum Type {
None, None,
Frame, Frame,
Slice, Slice,
} }
impl From<c_int> for Type { impl From<c_int> for Type {
fn from(value: c_int) -> Type { fn from(value: c_int) -> Type {
match value { match value {
FF_THREAD_FRAME => Type::Frame, FF_THREAD_FRAME => Type::Frame,
FF_THREAD_SLICE => Type::Slice, FF_THREAD_SLICE => Type::Slice,
_ => Type::None, _ => Type::None,
} }
} }
} }
impl Into<c_int> for Type { impl Into<c_int> for Type {
fn into(self) -> c_int { fn into(self) -> c_int {
match self { match self {
Type::None => 0, Type::None => 0,
Type::Frame => FF_THREAD_FRAME, Type::Frame => FF_THREAD_FRAME,
Type::Slice => FF_THREAD_SLICE Type::Slice => FF_THREAD_SLICE,
} }
} }
} }

View File

@ -1,113 +1,107 @@
use ::Codec;
use codec::{Id, Audio, Video};
use super::{decoder, encoder}; use super::{decoder, encoder};
use codec::{Audio, Id, Video};
use Codec;
pub trait Decoder { pub trait Decoder {
fn decoder(self) -> Option<Codec>; fn decoder(self) -> Option<Codec>;
} }
impl<'a> Decoder for &'a str { impl<'a> Decoder for &'a str {
fn decoder(self) -> Option<Codec> { fn decoder(self) -> Option<Codec> {
decoder::find_by_name(self) decoder::find_by_name(self)
} }
} }
impl Decoder for Id { impl Decoder for Id {
fn decoder(self) -> Option<Codec> { fn decoder(self) -> Option<Codec> {
decoder::find(self) decoder::find(self)
} }
} }
impl Decoder for Codec { impl Decoder for Codec {
fn decoder(self) -> Option<Codec> { fn decoder(self) -> Option<Codec> {
if self.is_decoder() { if self.is_decoder() {
Some(self) Some(self)
} } else {
else { None
None }
} }
}
} }
impl Decoder for Option<Codec> { impl Decoder for Option<Codec> {
fn decoder(self) -> Option<Codec> { fn decoder(self) -> Option<Codec> {
self.and_then(|c| c.decoder()) self.and_then(|c| c.decoder())
} }
} }
impl Decoder for Audio { impl Decoder for Audio {
fn decoder(self) -> Option<Codec> { fn decoder(self) -> Option<Codec> {
if self.is_decoder() { if self.is_decoder() {
Some(*&*self) Some(*self)
} } else {
else { None
None }
} }
}
} }
impl Decoder for Video { impl Decoder for Video {
fn decoder(self) -> Option<Codec> { fn decoder(self) -> Option<Codec> {
if self.is_decoder() { if self.is_decoder() {
Some(*&*self) Some(*self)
} } else {
else { None
None }
} }
}
} }
pub trait Encoder { pub trait Encoder {
fn encoder(self) -> Option<Codec>; fn encoder(self) -> Option<Codec>;
} }
impl<'a> Encoder for &'a str { impl<'a> Encoder for &'a str {
fn encoder(self) -> Option<Codec> { fn encoder(self) -> Option<Codec> {
encoder::find_by_name(self) encoder::find_by_name(self)
} }
} }
impl Encoder for Id { impl Encoder for Id {
fn encoder(self) -> Option<Codec> { fn encoder(self) -> Option<Codec> {
encoder::find(self) encoder::find(self)
} }
} }
impl Encoder for Codec { impl Encoder for Codec {
fn encoder(self) -> Option<Codec> { fn encoder(self) -> Option<Codec> {
if self.is_encoder() { if self.is_encoder() {
Some(self) Some(self)
} } else {
else { None
None }
} }
}
} }
impl Encoder for Option<Codec> { impl Encoder for Option<Codec> {
fn encoder(self) -> Option<Codec> { fn encoder(self) -> Option<Codec> {
self.and_then(|c| c.encoder()) self.and_then(|c| c.encoder())
} }
} }
impl Encoder for Audio { impl Encoder for Audio {
fn encoder(self) -> Option<Codec> { fn encoder(self) -> Option<Codec> {
if self.is_encoder() { if self.is_encoder() {
Some(*&*self) Some(*self)
} } else {
else { None
None }
} }
}
} }
impl Encoder for Video { impl Encoder for Video {
fn encoder(self) -> Option<Codec> { fn encoder(self) -> Option<Codec> {
if self.is_encoder() { if self.is_encoder() {
Some(*&*self) Some(*self)
} } else {
else { None
None }
} }
}
} }

View File

@ -1,104 +1,100 @@
use std::ops::Deref; use std::ops::Deref;
use {Rational, format};
use super::codec::Codec; use super::codec::Codec;
use ffi::*; use ffi::*;
use {format, Rational};
#[derive(PartialEq, Eq, Copy, Clone)] #[derive(PartialEq, Eq, Copy, Clone)]
pub struct Video { pub struct Video {
codec: Codec, codec: Codec,
} }
impl Video { impl Video {
pub unsafe fn new(codec: Codec) -> Video { pub unsafe fn new(codec: Codec) -> Video {
Video { Video { codec: codec }
codec: codec, }
}
}
} }
impl Video { impl Video {
pub fn rates(&self) -> Option<RateIter> { pub fn rates(&self) -> Option<RateIter> {
unsafe { unsafe {
if (*self.codec.as_ptr()).supported_framerates.is_null() { if (*self.codec.as_ptr()).supported_framerates.is_null() {
None None
} } else {
else { Some(RateIter::new((*self.codec.as_ptr()).supported_framerates))
Some(RateIter::new((*self.codec.as_ptr()).supported_framerates)) }
} }
} }
}
pub fn formats(&self) -> Option<FormatIter> { pub fn formats(&self) -> Option<FormatIter> {
unsafe { unsafe {
if (*self.codec.as_ptr()).pix_fmts.is_null() { if (*self.codec.as_ptr()).pix_fmts.is_null() {
None None
} } else {
else { Some(FormatIter::new((*self.codec.as_ptr()).pix_fmts))
Some(FormatIter::new((*self.codec.as_ptr()).pix_fmts)) }
} }
} }
}
} }
impl Deref for Video { impl Deref for Video {
type Target = Codec; type Target = Codec;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.codec &self.codec
} }
} }
pub struct RateIter { pub struct RateIter {
ptr: *const AVRational, ptr: *const AVRational,
} }
impl RateIter { impl RateIter {
pub fn new(ptr: *const AVRational) -> Self { pub fn new(ptr: *const AVRational) -> Self {
RateIter { ptr: ptr } RateIter { ptr: ptr }
} }
} }
impl Iterator for RateIter { impl Iterator for RateIter {
type Item = Rational; type Item = Rational;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if (*self.ptr).num == 0 && (*self.ptr).den == 0 { if (*self.ptr).num == 0 && (*self.ptr).den == 0 {
return None; return None;
} }
let rate = (*self.ptr).into(); let rate = (*self.ptr).into();
self.ptr = self.ptr.offset(1); self.ptr = self.ptr.offset(1);
Some(rate) Some(rate)
} }
} }
} }
pub struct FormatIter { pub struct FormatIter {
ptr: *const AVPixelFormat, ptr: *const AVPixelFormat,
} }
impl FormatIter { impl FormatIter {
pub fn new(ptr: *const AVPixelFormat) -> Self { pub fn new(ptr: *const AVPixelFormat) -> Self {
FormatIter { ptr: ptr } FormatIter { ptr: ptr }
} }
} }
impl Iterator for FormatIter { impl Iterator for FormatIter {
type Item = format::Pixel; type Item = format::Pixel;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if *self.ptr == AVPixelFormat::AV_PIX_FMT_NONE { if *self.ptr == AVPixelFormat::AV_PIX_FMT_NONE {
return None; return None;
} }
let format = (*self.ptr).into(); let format = (*self.ptr).into();
self.ptr = self.ptr.offset(1); self.ptr = self.ptr.offset(1);
Some(format) Some(format)
} }
} }
} }

View File

@ -1,79 +1,78 @@
use std::ptr;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ptr;
use device;
use ffi::*; use ffi::*;
use ::Error; use format::context::common::Context;
use ::format::context::common::Context;
use ::device;
use libc::c_int; use libc::c_int;
use Error;
impl Context { impl Context {
pub fn devices(&self) -> Result<DeviceIter, Error> { pub fn devices(&self) -> Result<DeviceIter, Error> {
unsafe { unsafe { DeviceIter::wrap(self.as_ptr()) }
DeviceIter::wrap(self.as_ptr()) }
}
}
} }
pub struct DeviceIter<'a> { pub struct DeviceIter<'a> {
ptr: *mut AVDeviceInfoList, ptr: *mut AVDeviceInfoList,
cur: c_int, cur: c_int,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> DeviceIter<'a> { impl<'a> DeviceIter<'a> {
pub unsafe fn wrap(ctx: *const AVFormatContext) -> Result<Self, Error> { pub unsafe fn wrap(ctx: *const AVFormatContext) -> Result<Self, Error> {
let mut ptr: *mut AVDeviceInfoList = ptr::null_mut(); let mut ptr: *mut AVDeviceInfoList = ptr::null_mut();
match avdevice_list_devices(ctx as *mut _, &mut ptr) { match avdevice_list_devices(ctx as *mut _, &mut ptr) {
n if n < 0 => n if n < 0 => Err(Error::from(n)),
Err(Error::from(n)),
_ => _ => Ok(DeviceIter {
Ok(DeviceIter { ptr: ptr, cur: 0, _marker: PhantomData }) ptr: ptr,
} cur: 0,
} _marker: PhantomData,
}),
}
}
} }
impl<'a> DeviceIter<'a> { impl<'a> DeviceIter<'a> {
pub fn default(&self) -> usize { pub fn default(&self) -> usize {
unsafe { unsafe { (*self.ptr).default_device as usize }
(*self.ptr).default_device as usize }
}
}
} }
impl<'a> Drop for DeviceIter<'a> { impl<'a> Drop for DeviceIter<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
avdevice_free_list_devices(&mut self.ptr); avdevice_free_list_devices(&mut self.ptr);
} }
} }
} }
impl<'a> Iterator for DeviceIter<'a> { impl<'a> Iterator for DeviceIter<'a> {
type Item = device::Info<'a>; type Item = device::Info<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if self.cur >= (*self.ptr).nb_devices { if self.cur >= (*self.ptr).nb_devices {
None None
} } else {
else { self.cur += 1;
self.cur += 1; Some(device::Info::wrap(*(*self.ptr)
Some(device::Info::wrap(*(*self.ptr).devices.offset((self.cur - 1) as isize))) .devices
} .offset((self.cur - 1) as isize)))
} }
} }
}
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
unsafe { unsafe {
let length = (*self.ptr).nb_devices as usize; let length = (*self.ptr).nb_devices as usize;
(length - self.cur as usize, Some(length - self.cur as usize)) (length - self.cur as usize, Some(length - self.cur as usize))
} }
} }
} }
impl<'a> ExactSizeIterator for DeviceIter<'a> { } impl<'a> ExactSizeIterator for DeviceIter<'a> {}

View File

@ -1,55 +1,53 @@
use std::ptr; use std::ptr;
use ffi::*; use ffi::*;
use ::format; use format;
use ::Format; use Format;
pub struct AudioIter(*mut AVInputFormat); pub struct AudioIter(*mut AVInputFormat);
impl Iterator for AudioIter { impl Iterator for AudioIter {
type Item = Format; type Item = Format;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
let ptr = av_input_audio_device_next(self.0); let ptr = av_input_audio_device_next(self.0);
if ptr.is_null() && !self.0.is_null() { if ptr.is_null() && !self.0.is_null() {
None None
} } else {
else { self.0 = ptr;
self.0 = ptr;
Some(Format::Input(format::Input::wrap(ptr))) Some(Format::Input(format::Input::wrap(ptr)))
} }
} }
} }
} }
pub fn audio() -> AudioIter { pub fn audio() -> AudioIter {
AudioIter(ptr::null_mut()) AudioIter(ptr::null_mut())
} }
pub struct VideoIter(*mut AVInputFormat); pub struct VideoIter(*mut AVInputFormat);
impl Iterator for VideoIter { impl Iterator for VideoIter {
type Item = Format; type Item = Format;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
let ptr = av_input_video_device_next(self.0); let ptr = av_input_video_device_next(self.0);
if ptr.is_null() && !self.0.is_null() { if ptr.is_null() && !self.0.is_null() {
None None
} } else {
else { self.0 = ptr;
self.0 = ptr;
Some(Format::Input(format::Input::wrap(ptr))) Some(Format::Input(format::Input::wrap(ptr)))
} }
} }
} }
} }
pub fn video() -> VideoIter { pub fn video() -> VideoIter {
VideoIter(ptr::null_mut()) VideoIter(ptr::null_mut())
} }

View File

@ -1,67 +1,62 @@
pub mod extensions;
pub mod input; pub mod input;
pub mod output; pub mod output;
pub mod extensions;
use std::ffi::CStr; use std::ffi::CStr;
use std::str::from_utf8_unchecked;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::str::from_utf8_unchecked;
use ffi::*; use ffi::*;
pub struct Info<'a> { pub struct Info<'a> {
ptr: *mut AVDeviceInfo, ptr: *mut AVDeviceInfo,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> Info<'a> { impl<'a> Info<'a> {
pub unsafe fn wrap(ptr: *mut AVDeviceInfo) -> Self { pub unsafe fn wrap(ptr: *mut AVDeviceInfo) -> Self {
Info { ptr: ptr, _marker: PhantomData } Info {
} ptr: ptr,
_marker: PhantomData,
}
}
pub unsafe fn as_ptr(&self) -> *const AVDeviceInfo { pub unsafe fn as_ptr(&self) -> *const AVDeviceInfo {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVDeviceInfo { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVDeviceInfo {
self.ptr self.ptr
} }
} }
impl<'a> Info<'a> { impl<'a> Info<'a> {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).device_name).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).device_name).to_bytes()) }
}
}
pub fn description(&self) -> &str { pub fn description(&self) -> &str {
unsafe { unsafe {
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).device_description).to_bytes()) from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).device_description).to_bytes())
} }
} }
} }
pub fn register_all() { pub fn register_all() {
unsafe { unsafe {
avdevice_register_all(); avdevice_register_all();
} }
} }
pub fn version() -> u32 { pub fn version() -> u32 {
unsafe { unsafe { avdevice_version() }
avdevice_version()
}
} }
pub fn configuration() -> &'static str { pub fn configuration() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(avdevice_configuration()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(avdevice_configuration()).to_bytes())
}
} }
pub fn license() -> &'static str { pub fn license() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(avdevice_license()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(avdevice_license()).to_bytes())
}
} }

View File

@ -1,55 +1,53 @@
use std::ptr; use std::ptr;
use ffi::*; use ffi::*;
use ::format; use format;
use ::Format; use Format;
pub struct AudioIter(*mut AVOutputFormat); pub struct AudioIter(*mut AVOutputFormat);
impl Iterator for AudioIter { impl Iterator for AudioIter {
type Item = Format; type Item = Format;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
let ptr = av_output_audio_device_next(self.0); let ptr = av_output_audio_device_next(self.0);
if ptr.is_null() && !self.0.is_null() { if ptr.is_null() && !self.0.is_null() {
None None
} } else {
else { self.0 = ptr;
self.0 = ptr;
Some(Format::Output(format::Output::wrap(ptr))) Some(Format::Output(format::Output::wrap(ptr)))
} }
} }
} }
} }
pub fn audio() -> AudioIter { pub fn audio() -> AudioIter {
AudioIter(ptr::null_mut()) AudioIter(ptr::null_mut())
} }
pub struct VideoIter(*mut AVOutputFormat); pub struct VideoIter(*mut AVOutputFormat);
impl Iterator for VideoIter { impl Iterator for VideoIter {
type Item = Format; type Item = Format;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
let ptr = av_output_video_device_next(self.0); let ptr = av_output_video_device_next(self.0);
if ptr.is_null() && !self.0.is_null() { if ptr.is_null() && !self.0.is_null() {
None None
} } else {
else { self.0 = ptr;
self.0 = ptr;
Some(Format::Output(format::Output::wrap(ptr))) Some(Format::Output(format::Output::wrap(ptr)))
} }
} }
} }
} }
pub fn video() -> VideoIter { pub fn video() -> VideoIter {
VideoIter(ptr::null_mut()) VideoIter(ptr::null_mut())
} }

View File

@ -1,68 +1,67 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use super::{Sink, Source};
use ffi::*; use ffi::*;
use libc::c_void; use libc::c_void;
use ::{option, format, ChannelLayout}; use {format, option, ChannelLayout};
use super::{Source, Sink};
pub struct Context<'a> { pub struct Context<'a> {
ptr: *mut AVFilterContext, ptr: *mut AVFilterContext,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> Context<'a> { impl<'a> Context<'a> {
pub unsafe fn wrap(ptr: *mut AVFilterContext) -> Self { pub unsafe fn wrap(ptr: *mut AVFilterContext) -> Self {
Context { ptr: ptr, _marker: PhantomData } Context {
} ptr: ptr,
_marker: PhantomData,
}
}
pub unsafe fn as_ptr(&self) -> *const AVFilterContext { pub unsafe fn as_ptr(&self) -> *const AVFilterContext {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFilterContext { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFilterContext {
self.ptr self.ptr
} }
} }
impl<'a> Context<'a> { impl<'a> Context<'a> {
pub fn source(&'a mut self) -> Source<'a> { pub fn source(&'a mut self) -> Source<'a> {
unsafe { unsafe { Source::wrap(self) }
Source::wrap(self) }
}
}
pub fn sink(&'a mut self) -> Sink<'a> { pub fn sink(&'a mut self) -> Sink<'a> {
unsafe { unsafe { Sink::wrap(self) }
Sink::wrap(self) }
}
}
pub fn set_pixel_format(&mut self, value: format::Pixel) { pub fn set_pixel_format(&mut self, value: format::Pixel) {
let _ = option::Settable::set::<AVPixelFormat>(self, "pix_fmts", &value.into()); let _ = option::Settable::set::<AVPixelFormat>(self, "pix_fmts", &value.into());
} }
pub fn set_sample_format(&mut self, value: format::Sample) { pub fn set_sample_format(&mut self, value: format::Sample) {
let _ = option::Settable::set::<AVSampleFormat>(self, "sample_fmts", &value.into()); let _ = option::Settable::set::<AVSampleFormat>(self, "sample_fmts", &value.into());
} }
pub fn set_sample_rate(&mut self, value: u32) { pub fn set_sample_rate(&mut self, value: u32) {
let _ = option::Settable::set(self, "sample_rates", &(value as i64)); let _ = option::Settable::set(self, "sample_rates", &i64::from(value));
} }
pub fn set_channel_layout(&mut self, value: ChannelLayout) { pub fn set_channel_layout(&mut self, value: ChannelLayout) {
let _ = option::Settable::set(self, "channel_layouts", &value.bits()); let _ = option::Settable::set(self, "channel_layouts", &value.bits());
} }
} }
unsafe impl<'a> option::Target for Context<'a> { unsafe impl<'a> option::Target for Context<'a> {
fn as_ptr(&self) -> *const c_void { fn as_ptr(&self) -> *const c_void {
self.ptr as *const _ self.ptr as *const _
} }
fn as_mut_ptr(&mut self) -> *mut c_void { fn as_mut_ptr(&mut self) -> *mut c_void {
self.ptr as *mut _ self.ptr as *mut _
} }
} }
impl<'a> option::Settable for Context<'a> { } impl<'a> option::Settable for Context<'a> {}

View File

@ -1,40 +1,44 @@
use super::Context;
use ffi::*; use ffi::*;
use libc::c_int; use libc::c_int;
use ::{Frame, Error}; use {Error, Frame};
use super::Context;
pub struct Sink<'a> { pub struct Sink<'a> {
ctx: &'a mut Context<'a>, ctx: &'a mut Context<'a>,
} }
impl<'a> Sink<'a> { impl<'a> Sink<'a> {
pub unsafe fn wrap<'b>(ctx: &'b mut Context<'b>) -> Sink<'b> { pub unsafe fn wrap<'b>(ctx: &'b mut Context<'b>) -> Sink<'b> {
Sink { ctx: ctx } Sink { ctx: ctx }
} }
} }
impl<'a> Sink<'a> { impl<'a> Sink<'a> {
pub fn frame(&mut self, frame: &mut Frame) -> Result<(), Error> { pub fn frame(&mut self, frame: &mut Frame) -> Result<(), Error> {
unsafe { unsafe {
match av_buffersink_get_frame(self.ctx.as_mut_ptr(), frame.as_mut_ptr()) { match av_buffersink_get_frame(self.ctx.as_mut_ptr(), frame.as_mut_ptr()) {
n if n >= 0 => Ok(()), n if n >= 0 => Ok(()),
e => Err(Error::from(e)), e => Err(Error::from(e)),
} }
} }
} }
pub fn samples(&mut self, frame: &mut Frame, samples: usize) -> Result<(), Error> { pub fn samples(&mut self, frame: &mut Frame, samples: usize) -> Result<(), Error> {
unsafe { unsafe {
match av_buffersink_get_samples(self.ctx.as_mut_ptr(), frame.as_mut_ptr(), samples as c_int) { match av_buffersink_get_samples(
n if n >= 0 => Ok(()), self.ctx.as_mut_ptr(),
e => Err(Error::from(e)), frame.as_mut_ptr(),
} samples as c_int,
} ) {
} n if n >= 0 => Ok(()),
e => Err(Error::from(e)),
}
}
}
pub fn set_frame_size(&mut self, value: u32) { pub fn set_frame_size(&mut self, value: u32) {
unsafe { unsafe {
av_buffersink_set_frame_size(self.ctx.as_mut_ptr(), value); av_buffersink_set_frame_size(self.ctx.as_mut_ptr(), value);
} }
} }
} }

View File

@ -1,38 +1,34 @@
use std::ptr; use std::ptr;
use ffi::*;
use ::{Error, Frame};
use super::Context; use super::Context;
use ffi::*;
use {Error, Frame};
pub struct Source<'a> { pub struct Source<'a> {
ctx: &'a mut Context<'a>, ctx: &'a mut Context<'a>,
} }
impl<'a> Source<'a> { impl<'a> Source<'a> {
pub unsafe fn wrap<'b>(ctx: &'b mut Context<'b>) -> Source<'b> { pub unsafe fn wrap<'b>(ctx: &'b mut Context<'b>) -> Source<'b> {
Source { ctx: ctx } Source { ctx: ctx }
} }
} }
impl<'a> Source<'a> { impl<'a> Source<'a> {
pub fn failed_requests(&self) -> usize { pub fn failed_requests(&self) -> usize {
unsafe { unsafe { av_buffersrc_get_nb_failed_requests(self.ctx.as_ptr() as *mut _) as usize }
av_buffersrc_get_nb_failed_requests(self.ctx.as_ptr() as *mut _) as usize }
}
}
pub fn add(&mut self, frame: &Frame) -> Result<(), Error> { pub fn add(&mut self, frame: &Frame) -> Result<(), Error> {
unsafe { unsafe {
match av_buffersrc_add_frame(self.ctx.as_mut_ptr(), frame.as_ptr() as *mut _) { match av_buffersrc_add_frame(self.ctx.as_mut_ptr(), frame.as_ptr() as *mut _) {
0 => Ok(()), 0 => Ok(()),
e => Err(Error::from(e)), e => Err(Error::from(e)),
} }
} }
} }
pub fn flush(&mut self) -> Result<(), Error> { pub fn flush(&mut self) -> Result<(), Error> {
unsafe { unsafe { self.add(&Frame::wrap(ptr::null_mut())) }
self.add(&Frame::wrap(ptr::null_mut())) }
}
}
} }

View File

@ -1,107 +1,104 @@
use std::ffi::CStr; use std::ffi::CStr;
use std::str::from_utf8_unchecked;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::str::from_utf8_unchecked;
use super::{Flags, Pad};
use ffi::*; use ffi::*;
use super::{Pad, Flags};
pub struct Filter { pub struct Filter {
ptr: *mut AVFilter, ptr: *mut AVFilter,
} }
impl Filter { impl Filter {
pub unsafe fn wrap(ptr: *mut AVFilter) -> Self { pub unsafe fn wrap(ptr: *mut AVFilter) -> Self {
Filter { ptr: ptr } Filter { ptr: ptr }
} }
pub unsafe fn as_ptr(&self) -> *const AVFilter { pub unsafe fn as_ptr(&self) -> *const AVFilter {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFilter { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFilter {
self.ptr self.ptr
} }
} }
impl Filter { impl Filter {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) }
}
}
pub fn description(&self) -> Option<&str> { pub fn description(&self) -> Option<&str> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).description; let ptr = (*self.as_ptr()).description;
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()))
Some(from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes())) }
} }
} }
}
pub fn inputs(&self) -> Option<PadIter> { pub fn inputs(&self) -> Option<PadIter> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).inputs; let ptr = (*self.as_ptr()).inputs;
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(PadIter::new((*self.as_ptr()).inputs))
Some(PadIter::new((*self.as_ptr()).inputs)) }
} }
} }
}
pub fn outputs(&self) -> Option<PadIter> { pub fn outputs(&self) -> Option<PadIter> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).outputs; let ptr = (*self.as_ptr()).outputs;
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(PadIter::new((*self.as_ptr()).outputs))
Some(PadIter::new((*self.as_ptr()).outputs)) }
} }
} }
}
pub fn flags(&self) -> Flags { pub fn flags(&self) -> Flags {
unsafe { unsafe { Flags::from_bits_truncate((*self.as_ptr()).flags) }
Flags::from_bits_truncate((*self.as_ptr()).flags) }
}
}
} }
pub struct PadIter<'a> { pub struct PadIter<'a> {
ptr: *const AVFilterPad, ptr: *const AVFilterPad,
cur: isize, cur: isize,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> PadIter<'a> { impl<'a> PadIter<'a> {
pub fn new(ptr: *const AVFilterPad) -> Self { pub fn new(ptr: *const AVFilterPad) -> Self {
PadIter { ptr: ptr, cur: 0, _marker: PhantomData } PadIter {
} ptr: ptr,
cur: 0,
_marker: PhantomData,
}
}
} }
impl<'a> Iterator for PadIter<'a> { impl<'a> Iterator for PadIter<'a> {
type Item = Pad<'a>; type Item = Pad<'a>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
unsafe { unsafe {
if self.cur >= avfilter_pad_count(self.ptr) as isize { if self.cur >= avfilter_pad_count(self.ptr) as isize {
return None; return None;
} }
let pad = Pad::wrap(self.ptr.offset(self.cur)); let pad = Pad::wrap(self.ptr.offset(self.cur));
self.cur += 1; self.cur += 1;
Some(pad) Some(pad)
} }
} }
} }

View File

@ -1,13 +1,13 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Flags: c_int { pub struct Flags: c_int {
const DYNAMIC_INPUTS = AVFILTER_FLAG_DYNAMIC_INPUTS; const DYNAMIC_INPUTS = AVFILTER_FLAG_DYNAMIC_INPUTS;
const DYNAMIC_OUTPUTS = AVFILTER_FLAG_DYNAMIC_OUTPUTS; const DYNAMIC_OUTPUTS = AVFILTER_FLAG_DYNAMIC_OUTPUTS;
const SLICE_THREADS = AVFILTER_FLAG_SLICE_THREADS; const SLICE_THREADS = AVFILTER_FLAG_SLICE_THREADS;
const SUPPORT_TIMELINE_GENERIC = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC; const SUPPORT_TIMELINE_GENERIC = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC;
const SUPPORT_TIMELINE_INTERNAL = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL; const SUPPORT_TIMELINE_INTERNAL = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL;
const SUPPORT_TIMELINE = AVFILTER_FLAG_SUPPORT_TIMELINE; const SUPPORT_TIMELINE = AVFILTER_FLAG_SUPPORT_TIMELINE;
} }
} }

View File

@ -1,205 +1,224 @@
use std::ffi::{CStr, CString};
use std::ptr; use std::ptr;
use std::ffi::{CString, CStr};
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;
use super::{Context, Filter};
use ffi::*; use ffi::*;
use libc::c_int; use libc::c_int;
use ::Error; use Error;
use super::{Context, Filter};
pub struct Graph { pub struct Graph {
ptr: *mut AVFilterGraph, ptr: *mut AVFilterGraph,
} }
unsafe impl Send for Graph { } unsafe impl Send for Graph {}
unsafe impl Sync for Graph { } unsafe impl Sync for Graph {}
impl Graph { impl Graph {
pub unsafe fn wrap(ptr: *mut AVFilterGraph) -> Self { pub unsafe fn wrap(ptr: *mut AVFilterGraph) -> Self {
Graph { ptr: ptr } Graph { ptr: ptr }
} }
pub unsafe fn as_ptr(&self) -> *const AVFilterGraph { pub unsafe fn as_ptr(&self) -> *const AVFilterGraph {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFilterGraph { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFilterGraph {
self.ptr self.ptr
} }
} }
impl Graph { impl Graph {
pub fn new() -> Self { pub fn new() -> Self {
unsafe { unsafe {
let ptr = avfilter_graph_alloc(); let ptr = avfilter_graph_alloc();
if ptr.is_null() { if ptr.is_null() {
panic!("out of memory"); panic!("out of memory");
} }
Graph::wrap(ptr) Graph::wrap(ptr)
} }
} }
pub fn validate(&mut self) -> Result<(), Error> { pub fn validate(&mut self) -> Result<(), Error> {
unsafe { unsafe {
match avfilter_graph_config(self.as_mut_ptr(), ptr::null_mut()) { match avfilter_graph_config(self.as_mut_ptr(), ptr::null_mut()) {
0 => Ok(()), 0 => Ok(()),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn add<'a, 'b>(&'a mut self, filter: &Filter, name: &str, args: &str) -> Result<Context<'b>, Error> where 'a: 'b { pub fn add<'a, 'b>(
unsafe { &'a mut self,
let name = CString::new(name).unwrap(); filter: &Filter,
let args = CString::new(args).unwrap(); name: &str,
let mut context = ptr::null_mut(); args: &str,
) -> Result<Context<'b>, Error>
where
'a: 'b,
{
unsafe {
let name = CString::new(name).unwrap();
let args = CString::new(args).unwrap();
let mut context = ptr::null_mut();
match avfilter_graph_create_filter(&mut context as *mut *mut AVFilterContext, match avfilter_graph_create_filter(
filter.as_ptr(), &mut context as *mut *mut AVFilterContext,
name.as_ptr(), filter.as_ptr(),
args.as_ptr(), name.as_ptr(),
ptr::null_mut(), args.as_ptr(),
self.as_mut_ptr()) ptr::null_mut(),
{ self.as_mut_ptr(),
n if n >= 0 => Ok(Context::wrap(context)), ) {
e => Err(Error::from(e)), n if n >= 0 => Ok(Context::wrap(context)),
} e => Err(Error::from(e)),
} }
} }
}
pub fn get<'a, 'b>(&'b mut self, name: &str) -> Option<Context<'b>> where 'a: 'b { pub fn get<'a, 'b>(&'b mut self, name: &str) -> Option<Context<'b>>
unsafe { where
let name = CString::new(name).unwrap(); 'a: 'b,
let ptr = avfilter_graph_get_filter(self.as_mut_ptr(), name.as_ptr()); {
unsafe {
let name = CString::new(name).unwrap();
let ptr = avfilter_graph_get_filter(self.as_mut_ptr(), name.as_ptr());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Context::wrap(ptr))
Some(Context::wrap(ptr)) }
} }
} }
}
pub fn dump(&self) -> String { pub fn dump(&self) -> String {
unsafe { unsafe {
let ptr = avfilter_graph_dump(self.as_ptr() as *mut _, ptr::null()); let ptr = avfilter_graph_dump(self.as_ptr() as *mut _, ptr::null());
let cstr = from_utf8_unchecked(CStr::from_ptr((ptr)).to_bytes()); let cstr = from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes());
let string = cstr.to_owned(); let string = cstr.to_owned();
av_free(ptr as *mut _); av_free(ptr as *mut _);
string string
} }
} }
pub fn input(&mut self, name: &str, pad: usize) -> Result<Parser, Error> { pub fn input(&mut self, name: &str, pad: usize) -> Result<Parser, Error> {
Parser::new(self).input(name, pad) Parser::new(self).input(name, pad)
} }
pub fn output(&mut self, name: &str, pad: usize) -> Result<Parser, Error> { pub fn output(&mut self, name: &str, pad: usize) -> Result<Parser, Error> {
Parser::new(self).output(name, pad) Parser::new(self).output(name, pad)
} }
pub fn parse(&mut self, spec: &str) -> Result<(), Error> { pub fn parse(&mut self, spec: &str) -> Result<(), Error> {
Parser::new(self).parse(spec) Parser::new(self).parse(spec)
} }
} }
impl Drop for Graph { impl Drop for Graph {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
avfilter_graph_free(&mut self.as_mut_ptr()); avfilter_graph_free(&mut self.as_mut_ptr());
} }
} }
} }
pub struct Parser<'a> { pub struct Parser<'a> {
graph: &'a mut Graph, graph: &'a mut Graph,
inputs: *mut AVFilterInOut, inputs: *mut AVFilterInOut,
outputs: *mut AVFilterInOut, outputs: *mut AVFilterInOut,
} }
impl<'a> Parser<'a> { impl<'a> Parser<'a> {
pub fn new(graph: &mut Graph) -> Parser { pub fn new(graph: &mut Graph) -> Parser {
Parser { Parser {
graph: graph, graph: graph,
inputs: ptr::null_mut(), inputs: ptr::null_mut(),
outputs: ptr::null_mut(), outputs: ptr::null_mut(),
} }
} }
pub fn input(mut self, name: &str, pad: usize) -> Result<Self, Error> { pub fn input(mut self, name: &str, pad: usize) -> Result<Self, Error> {
unsafe { unsafe {
let mut context = try!(self.graph.get(name).ok_or(Error::InvalidData)); let mut context = self.graph.get(name).ok_or(Error::InvalidData)?;
let input = avfilter_inout_alloc(); let input = avfilter_inout_alloc();
if input.is_null() { if input.is_null() {
panic!("out of memory"); panic!("out of memory");
} }
let name = CString::new(name).unwrap(); let name = CString::new(name).unwrap();
(*input).name = av_strdup(name.as_ptr()); (*input).name = av_strdup(name.as_ptr());
(*input).filter_ctx = context.as_mut_ptr(); (*input).filter_ctx = context.as_mut_ptr();
(*input).pad_idx = pad as c_int; (*input).pad_idx = pad as c_int;
(*input).next = ptr::null_mut(); (*input).next = ptr::null_mut();
if self.inputs.is_null() { if self.inputs.is_null() {
self.inputs = input; self.inputs = input;
} } else {
else { (*self.inputs).next = input;
(*self.inputs).next = input; }
} }
}
Ok(self) Ok(self)
} }
pub fn output(mut self, name: &str, pad: usize) -> Result<Self, Error> { pub fn output(mut self, name: &str, pad: usize) -> Result<Self, Error> {
unsafe { unsafe {
let mut context = try!(self.graph.get(name).ok_or(Error::InvalidData)); let mut context = self.graph.get(name).ok_or(Error::InvalidData)?;
let output = avfilter_inout_alloc(); let output = avfilter_inout_alloc();
if output.is_null() { if output.is_null() {
panic!("out of memory"); panic!("out of memory");
} }
let name = CString::new(name).unwrap(); let name = CString::new(name).unwrap();
(*output).name = av_strdup(name.as_ptr()); (*output).name = av_strdup(name.as_ptr());
(*output).filter_ctx = context.as_mut_ptr(); (*output).filter_ctx = context.as_mut_ptr();
(*output).pad_idx = pad as c_int; (*output).pad_idx = pad as c_int;
(*output).next = ptr::null_mut(); (*output).next = ptr::null_mut();
if self.outputs.is_null() { if self.outputs.is_null() {
self.outputs = output; self.outputs = output;
} } else {
else { (*self.outputs).next = output;
(*self.outputs).next = output; }
} }
}
Ok(self) Ok(self)
} }
pub fn parse(mut self, spec: &str) -> Result<(), Error> { pub fn parse(mut self, spec: &str) -> Result<(), Error> {
unsafe { unsafe {
let spec = CString::new(spec).unwrap(); let spec = CString::new(spec).unwrap();
let result = avfilter_graph_parse_ptr(self.graph.as_mut_ptr(), let result = avfilter_graph_parse_ptr(
spec.as_ptr(), &mut self.inputs, &mut self.outputs, self.graph.as_mut_ptr(),
ptr::null_mut()); spec.as_ptr(),
&mut self.inputs,
&mut self.outputs,
ptr::null_mut(),
);
avfilter_inout_free(&mut self.inputs); avfilter_inout_free(&mut self.inputs);
avfilter_inout_free(&mut self.outputs); avfilter_inout_free(&mut self.outputs);
match result { match result {
n if n >= 0 => Ok(()), n if n >= 0 => Ok(()),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
}
impl Default for Graph {
fn default() -> Self {
Self::new()
}
} }

View File

@ -8,60 +8,53 @@ pub mod filter;
pub use self::filter::Filter; pub use self::filter::Filter;
pub mod context; pub mod context;
pub use self::context::{Context, Source, Sink}; pub use self::context::{Context, Sink, Source};
pub mod graph; pub mod graph;
pub use self::graph::Graph; pub use self::graph::Graph;
use std::ffi::{CString, CStr}; use std::ffi::{CStr, CString};
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;
use ffi::*; use ffi::*;
use ::Error; use Error;
pub fn register_all() { pub fn register_all() {
unsafe { unsafe {
avfilter_register_all(); avfilter_register_all();
} }
} }
pub fn register(filter: &Filter) -> Result<(), Error> { pub fn register(filter: &Filter) -> Result<(), Error> {
unsafe { unsafe {
match avfilter_register(filter.as_ptr() as *mut _) { match avfilter_register(filter.as_ptr() as *mut _) {
0 => Ok(()), 0 => Ok(()),
_ => Err(Error::InvalidData), _ => Err(Error::InvalidData),
} }
} }
} }
pub fn version() -> u32 { pub fn version() -> u32 {
unsafe { unsafe { avfilter_version() }
avfilter_version()
}
} }
pub fn configuration() -> &'static str { pub fn configuration() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(avfilter_configuration()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(avfilter_configuration()).to_bytes())
}
} }
pub fn license() -> &'static str { pub fn license() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(avfilter_license()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(avfilter_license()).to_bytes())
}
} }
pub fn find(name: &str) -> Option<Filter> { pub fn find(name: &str) -> Option<Filter> {
unsafe { unsafe {
let name = CString::new(name).unwrap(); let name = CString::new(name).unwrap();
let ptr = avfilter_get_by_name(name.as_ptr()); let ptr = avfilter_get_by_name(name.as_ptr());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Filter::wrap(ptr))
Some(Filter::wrap(ptr)) }
} }
}
} }

View File

@ -1,47 +1,47 @@
use std::ffi::CStr; use std::ffi::CStr;
use std::str::from_utf8_unchecked;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::str::from_utf8_unchecked;
use ffi::*; use ffi::*;
use ::media; use media;
pub struct Pad<'a> { pub struct Pad<'a> {
ptr: *const AVFilterPad, ptr: *const AVFilterPad,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> Pad<'a> { impl<'a> Pad<'a> {
pub unsafe fn wrap(ptr: *const AVFilterPad) -> Self { pub unsafe fn wrap(ptr: *const AVFilterPad) -> Self {
Pad { ptr: ptr, _marker: PhantomData } Pad {
} ptr: ptr,
_marker: PhantomData,
}
}
pub unsafe fn as_ptr(&self) -> *const AVFilterPad { pub unsafe fn as_ptr(&self) -> *const AVFilterPad {
self.ptr self.ptr
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFilterPad { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFilterPad {
self.ptr as *mut _ self.ptr as *mut _
} }
} }
impl<'a> Pad<'a> { impl<'a> Pad<'a> {
pub fn name(&self) -> Option<&str> { pub fn name(&self) -> Option<&str> {
unsafe { unsafe {
let ptr = avfilter_pad_get_name(self.ptr, 0); let ptr = avfilter_pad_get_name(self.ptr, 0);
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()))
Some(from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes())) }
} }
} }
}
pub fn medium(&self) -> media::Type { pub fn medium(&self) -> media::Type {
unsafe { unsafe { media::Type::from(avfilter_pad_get_type(self.ptr, 0)) }
media::Type::from(avfilter_pad_get_type(self.ptr, 0)) }
}
}
} }

View File

@ -1,65 +1,58 @@
use ffi::*; use ffi::*;
use ::{Rational, DictionaryRef}; use {DictionaryRef, Rational};
use format::context::common::Context; use format::context::common::Context;
// WARNING: index refers to the offset in the chapters array (starting from 0) // WARNING: index refers to the offset in the chapters array (starting from 0)
// it is not necessarly equal to the id (which may start at 1) // it is not necessarly equal to the id (which may start at 1)
pub struct Chapter<'a> { pub struct Chapter<'a> {
context: &'a Context, context: &'a Context,
index: usize, index: usize,
} }
impl<'a> Chapter<'a> { impl<'a> Chapter<'a> {
pub unsafe fn wrap(context: &Context, index: usize) -> Chapter { pub unsafe fn wrap(context: &Context, index: usize) -> Chapter {
Chapter { context: context, index: index } Chapter {
} context: context,
index: index,
}
}
pub unsafe fn as_ptr(&self) -> *const AVChapter { pub unsafe fn as_ptr(&self) -> *const AVChapter {
*(*self.context.as_ptr()).chapters.offset(self.index as isize) *(*self.context.as_ptr())
} .chapters
.offset(self.index as isize)
}
} }
impl<'a> Chapter<'a> { impl<'a> Chapter<'a> {
pub fn index(&self) -> usize { pub fn index(&self) -> usize {
self.index self.index
} }
pub fn id(&self) -> i32 { pub fn id(&self) -> i32 {
unsafe { unsafe { (*self.as_ptr()).id }
(*self.as_ptr()).id }
}
}
pub fn time_base(&self) -> Rational { pub fn time_base(&self) -> Rational {
unsafe { unsafe { Rational::from((*self.as_ptr()).time_base) }
Rational::from((*self.as_ptr()).time_base) }
}
}
pub fn start(&self) -> i64 { pub fn start(&self) -> i64 {
unsafe { unsafe { (*self.as_ptr()).start }
(*self.as_ptr()).start }
}
}
pub fn end(&self) -> i64 { pub fn end(&self) -> i64 {
unsafe { unsafe { (*self.as_ptr()).end }
(*self.as_ptr()).end }
}
}
pub fn metadata(&self) -> DictionaryRef { pub fn metadata(&self) -> DictionaryRef {
unsafe { unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) }
DictionaryRef::wrap((*self.as_ptr()).metadata) }
}
}
} }
impl<'a> PartialEq for Chapter<'a> { impl<'a> PartialEq for Chapter<'a> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
unsafe { unsafe { self.as_ptr() == other.as_ptr() }
self.as_ptr() == other.as_ptr() }
}
}
} }

View File

@ -1,81 +1,81 @@
use std::ops::Deref;
use std::mem; use std::mem;
use std::ops::Deref;
use ffi::*;
use ::{Rational, Dictionary, DictionaryMut};
use super::Chapter; use super::Chapter;
use ffi::*;
use format::context::common::Context; use format::context::common::Context;
use {Dictionary, DictionaryMut, Rational};
// WARNING: index refers to the offset in the chapters array (starting from 0) // WARNING: index refers to the offset in the chapters array (starting from 0)
// it is not necessarly equal to the id (which may start at 1) // it is not necessarly equal to the id (which may start at 1)
pub struct ChapterMut<'a> { pub struct ChapterMut<'a> {
context: &'a mut Context, context: &'a mut Context,
index: usize, index: usize,
immutable: Chapter<'a>, immutable: Chapter<'a>,
} }
impl<'a> ChapterMut<'a> { impl<'a> ChapterMut<'a> {
pub unsafe fn wrap(context: &mut Context, index: usize) -> ChapterMut { pub unsafe fn wrap(context: &mut Context, index: usize) -> ChapterMut {
ChapterMut { ChapterMut {
context: mem::transmute_copy(&context), context: mem::transmute_copy(&context),
index: index, index: index,
immutable: Chapter::wrap(mem::transmute_copy(&context), index) immutable: Chapter::wrap(mem::transmute_copy(&context), index),
} }
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVChapter { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVChapter {
*(*self.context.as_mut_ptr()).chapters.offset(self.index as isize) *(*self.context.as_mut_ptr())
} .chapters
.offset(self.index as isize)
}
} }
impl<'a> ChapterMut<'a> { impl<'a> ChapterMut<'a> {
pub fn set_id(&mut self, value: i32) { pub fn set_id(&mut self, value: i32) {
unsafe { unsafe {
(*self.as_mut_ptr()).id = value; (*self.as_mut_ptr()).id = value;
} }
} }
pub fn set_time_base<R: Into<Rational>>(&mut self, value: R) { pub fn set_time_base<R: Into<Rational>>(&mut self, value: R) {
unsafe { unsafe {
(*self.as_mut_ptr()).time_base = value.into().into(); (*self.as_mut_ptr()).time_base = value.into().into();
} }
} }
pub fn set_start(&mut self, value: i64) { pub fn set_start(&mut self, value: i64) {
unsafe { unsafe {
(*self.as_mut_ptr()).start = value; (*self.as_mut_ptr()).start = value;
} }
} }
pub fn set_end(&mut self, value: i64) { pub fn set_end(&mut self, value: i64) {
unsafe { unsafe {
(*self.as_mut_ptr()).end = value; (*self.as_mut_ptr()).end = value;
} }
} }
pub fn set_metadata<K: AsRef<str>, V: AsRef<str>>(&mut self, key: K, value: V) { pub fn set_metadata<K: AsRef<str>, V: AsRef<str>>(&mut self, key: K, value: V) {
// dictionary.set() allocates the AVDictionary the first time a key/value is inserted // dictionary.set() allocates the AVDictionary the first time a key/value is inserted
// so we want to update the metadata dictionary afterwards // so we want to update the metadata dictionary afterwards
unsafe { unsafe {
let mut dictionary = Dictionary::own(self.metadata().as_mut_ptr()); let mut dictionary = Dictionary::own(self.metadata().as_mut_ptr());
dictionary.set(key.as_ref(), value.as_ref()); dictionary.set(key.as_ref(), value.as_ref());
(*self.as_mut_ptr()).metadata = dictionary.disown(); (*self.as_mut_ptr()).metadata = dictionary.disown();
} }
} }
pub fn metadata(&mut self) -> DictionaryMut { pub fn metadata(&mut self) -> DictionaryMut {
unsafe { unsafe { DictionaryMut::wrap((*self.as_mut_ptr()).metadata) }
DictionaryMut::wrap((*self.as_mut_ptr()).metadata) }
}
}
} }
impl<'a> Deref for ChapterMut<'a> { impl<'a> Deref for ChapterMut<'a> {
type Target = Chapter<'a>; type Target = Chapter<'a>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.immutable &self.immutable
} }
} }

View File

@ -1,325 +1,378 @@
use std::rc::Rc;
use std::ptr;
use std::mem; use std::mem;
use std::ptr;
use std::rc::Rc;
use super::destructor::{self, Destructor};
use ffi::*; use ffi::*;
use libc::{c_int, c_uint}; use libc::{c_int, c_uint};
use ::{media, Stream, StreamMut, Chapter, ChapterMut, DictionaryRef}; use {media, Chapter, ChapterMut, DictionaryRef, Stream, StreamMut};
use super::destructor::{self, Destructor};
pub struct Context { pub struct Context {
ptr: *mut AVFormatContext, ptr: *mut AVFormatContext,
dtor: Rc<Destructor>, dtor: Rc<Destructor>,
} }
unsafe impl Send for Context { } unsafe impl Send for Context {}
impl Context { impl Context {
pub unsafe fn wrap(ptr: *mut AVFormatContext, mode: destructor::Mode) -> Self { pub unsafe fn wrap(ptr: *mut AVFormatContext, mode: destructor::Mode) -> Self {
Context { ptr: ptr, dtor: Rc::new(Destructor::new(ptr, mode)) } Context {
} ptr: ptr,
dtor: Rc::new(Destructor::new(ptr, mode)),
}
}
pub unsafe fn as_ptr(&self) -> *const AVFormatContext { pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
self.ptr self.ptr
} }
pub unsafe fn destructor(&self) -> Rc<Destructor> { pub unsafe fn destructor(&self) -> Rc<Destructor> {
self.dtor.clone() Rc::clone(&self.dtor)
} }
} }
impl Context { impl Context {
pub fn stream<'a, 'b>(&'a self, index: usize) -> Option<Stream<'b>> where 'a: 'b { pub fn stream<'a, 'b>(&'a self, index: usize) -> Option<Stream<'b>>
unsafe { where
if index >= (*self.as_ptr()).nb_streams as usize { 'a: 'b,
None {
} unsafe {
else { if index >= (*self.as_ptr()).nb_streams as usize {
Some(Stream::wrap(self, index)) None
} } else {
} Some(Stream::wrap(self, index))
} }
}
}
pub fn stream_mut<'a, 'b>(&'a mut self, index: usize) -> Option<StreamMut<'b>> where 'a: 'b { pub fn stream_mut<'a, 'b>(&'a mut self, index: usize) -> Option<StreamMut<'b>>
unsafe { where
if index >= (*self.as_ptr()).nb_streams as usize { 'a: 'b,
None {
} unsafe {
else { if index >= (*self.as_ptr()).nb_streams as usize {
Some(StreamMut::wrap(self, index)) None
} } else {
} Some(StreamMut::wrap(self, index))
} }
}
}
pub fn streams(&self) -> StreamIter { pub fn streams(&self) -> StreamIter {
StreamIter::new(self) StreamIter::new(self)
} }
pub fn streams_mut(&mut self) -> StreamIterMut { pub fn streams_mut(&mut self) -> StreamIterMut {
StreamIterMut::new(self) StreamIterMut::new(self)
} }
pub fn duration(&self) -> i64 { pub fn duration(&self) -> i64 {
unsafe { unsafe { (*self.as_ptr()).duration }
(*self.as_ptr()).duration }
}
}
pub fn nb_chapters(&self) -> u32 { pub fn nb_chapters(&self) -> u32 {
unsafe { unsafe { (*self.as_ptr()).nb_chapters }
(*self.as_ptr()).nb_chapters }
}
}
pub fn chapter<'a, 'b>(&'a self, index: usize) -> Option<Chapter<'b>> where 'a: 'b { pub fn chapter<'a, 'b>(&'a self, index: usize) -> Option<Chapter<'b>>
unsafe { where
if index >= (*self.as_ptr()).nb_chapters as usize { 'a: 'b,
None {
} unsafe {
else { if index >= (*self.as_ptr()).nb_chapters as usize {
Some(Chapter::wrap(self, index)) None
} } else {
} Some(Chapter::wrap(self, index))
} }
}
}
pub fn chapter_mut<'a, 'b>(&'a mut self, index: usize) -> Option<ChapterMut<'b>> where 'a: 'b { pub fn chapter_mut<'a, 'b>(&'a mut self, index: usize) -> Option<ChapterMut<'b>>
unsafe { where
if index >= (*self.as_ptr()).nb_chapters as usize { 'a: 'b,
None {
} unsafe {
else { if index >= (*self.as_ptr()).nb_chapters as usize {
Some(ChapterMut::wrap(self, index)) None
} } else {
} Some(ChapterMut::wrap(self, index))
} }
}
}
pub fn chapters(&self) -> ChapterIter { pub fn chapters(&self) -> ChapterIter {
ChapterIter::new(self) ChapterIter::new(self)
} }
pub fn chapters_mut(&mut self) -> ChapterIterMut { pub fn chapters_mut(&mut self) -> ChapterIterMut {
ChapterIterMut::new(self) ChapterIterMut::new(self)
} }
pub fn metadata(&self) -> DictionaryRef { pub fn metadata(&self) -> DictionaryRef {
unsafe { unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) }
DictionaryRef::wrap((*self.as_ptr()).metadata) }
}
}
} }
pub struct Best<'a> { pub struct Best<'a> {
context: &'a Context, context: &'a Context,
wanted: i32, wanted: i32,
related: i32, related: i32,
} }
impl<'a> Best<'a> { impl<'a> Best<'a> {
pub unsafe fn new<'b, 'c: 'b>(context: &'c Context) -> Best<'b> { pub unsafe fn new<'b, 'c: 'b>(context: &'c Context) -> Best<'b> {
Best { Best {
context: context, context: context,
wanted: -1, wanted: -1,
related: -1, related: -1,
} }
} }
pub fn wanted<'b>(mut self, stream: &'b Stream) -> Best<'a> where 'a: 'b { pub fn wanted<'b>(mut self, stream: &'b Stream) -> Best<'a>
self.wanted = stream.index() as i32; where
self 'a: 'b,
} {
self.wanted = stream.index() as i32;
self
}
pub fn related<'b>(mut self, stream: &'b Stream) -> Best<'a> where 'a: 'b { pub fn related<'b>(mut self, stream: &'b Stream) -> Best<'a>
self.related = stream.index() as i32; where
self 'a: 'b,
} {
self.related = stream.index() as i32;
self
}
pub fn best<'b>(self, kind: media::Type) -> Option<Stream<'b>> where 'a: 'b { pub fn best<'b>(self, kind: media::Type) -> Option<Stream<'b>>
unsafe { where
let mut decoder = ptr::null_mut(); 'a: 'b,
let index = av_find_best_stream(self.context.ptr, {
kind.into(), self.wanted as c_int, self.related as c_int, unsafe {
&mut decoder, 0); let mut decoder = ptr::null_mut();
let index = av_find_best_stream(
self.context.ptr,
kind.into(),
self.wanted as c_int,
self.related as c_int,
&mut decoder,
0,
);
if index >= 0 && !decoder.is_null() { if index >= 0 && !decoder.is_null() {
Some(Stream::wrap(self.context, index as usize)) Some(Stream::wrap(self.context, index as usize))
} } else {
else { None
None }
} }
} }
}
} }
pub struct StreamIter<'a> { pub struct StreamIter<'a> {
context: &'a Context, context: &'a Context,
current: c_uint, current: c_uint,
} }
impl<'a> StreamIter<'a> { impl<'a> StreamIter<'a> {
pub fn new<'s, 'c: 's>(context: &'c Context) -> StreamIter<'s> { pub fn new<'s, 'c: 's>(context: &'c Context) -> StreamIter<'s> {
StreamIter { context: context, current: 0 } StreamIter {
} context: context,
current: 0,
}
}
} }
impl<'a> StreamIter<'a> { impl<'a> StreamIter<'a> {
pub fn wanted<'b, 'c>(&self, stream: &'b Stream) -> Best<'c> where 'a: 'b, 'a: 'c { pub fn wanted<'b, 'c>(&self, stream: &'b Stream) -> Best<'c>
unsafe { where
Best::new(self.context).wanted(stream) 'a: 'b,
} 'a: 'c,
} {
unsafe { Best::new(self.context).wanted(stream) }
}
pub fn related<'b, 'c>(&self, stream: &'b Stream) -> Best<'c> where 'a: 'b, 'a: 'c { pub fn related<'b, 'c>(&self, stream: &'b Stream) -> Best<'c>
unsafe { where
Best::new(self.context).related(stream) 'a: 'b,
} 'a: 'c,
} {
unsafe { Best::new(self.context).related(stream) }
}
pub fn best<'b>(&self, kind: media::Type) -> Option<Stream<'b>> where 'a: 'b { pub fn best<'b>(&self, kind: media::Type) -> Option<Stream<'b>>
unsafe { where
Best::new(self.context).best(kind) 'a: 'b,
} {
} unsafe { Best::new(self.context).best(kind) }
}
} }
impl<'a> Iterator for StreamIter<'a> { impl<'a> Iterator for StreamIter<'a> {
type Item = Stream<'a>; type Item = Stream<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if self.current >= (*self.context.as_ptr()).nb_streams { if self.current >= (*self.context.as_ptr()).nb_streams {
return None; return None;
} }
self.current += 1; self.current += 1;
Some(Stream::wrap(self.context, (self.current - 1) as usize)) Some(Stream::wrap(self.context, (self.current - 1) as usize))
} }
} }
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
unsafe { unsafe {
let length = (*self.context.as_ptr()).nb_streams as usize; let length = (*self.context.as_ptr()).nb_streams as usize;
(length - self.current as usize, Some(length - self.current as usize)) (
} length - self.current as usize,
} Some(length - self.current as usize),
)
}
}
} }
impl<'a> ExactSizeIterator for StreamIter<'a> { } impl<'a> ExactSizeIterator for StreamIter<'a> {}
pub struct StreamIterMut<'a> { pub struct StreamIterMut<'a> {
context: &'a mut Context, context: &'a mut Context,
current: c_uint, current: c_uint,
} }
impl<'a> StreamIterMut<'a> { impl<'a> StreamIterMut<'a> {
pub fn new<'s, 'c: 's>(context: &'c mut Context) -> StreamIterMut<'s> { pub fn new<'s, 'c: 's>(context: &'c mut Context) -> StreamIterMut<'s> {
StreamIterMut { context: context, current: 0 } StreamIterMut {
} context: context,
current: 0,
}
}
} }
impl<'a> Iterator for StreamIterMut<'a> { impl<'a> Iterator for StreamIterMut<'a> {
type Item = StreamMut<'a>; type Item = StreamMut<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if self.current >= (*self.context.as_ptr()).nb_streams { if self.current >= (*self.context.as_ptr()).nb_streams {
return None return None;
} }
self.current += 1; self.current += 1;
Some(StreamMut::wrap(mem::transmute_copy(&self.context), (self.current - 1) as usize)) Some(StreamMut::wrap(
} mem::transmute_copy(&self.context),
} (self.current - 1) as usize,
))
}
}
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
unsafe { unsafe {
let length = (*self.context.as_ptr()).nb_streams as usize; let length = (*self.context.as_ptr()).nb_streams as usize;
(length - self.current as usize, Some(length - self.current as usize)) (
} length - self.current as usize,
} Some(length - self.current as usize),
)
}
}
} }
impl<'a> ExactSizeIterator for StreamIterMut<'a> { } impl<'a> ExactSizeIterator for StreamIterMut<'a> {}
pub struct ChapterIter<'a> { pub struct ChapterIter<'a> {
context: &'a Context, context: &'a Context,
current: c_uint, current: c_uint,
} }
impl<'a> ChapterIter<'a> { impl<'a> ChapterIter<'a> {
pub fn new<'s, 'c: 's>(context: &'c Context) -> ChapterIter<'s> { pub fn new<'s, 'c: 's>(context: &'c Context) -> ChapterIter<'s> {
ChapterIter { context: context, current: 0 } ChapterIter {
} context: context,
current: 0,
}
}
} }
impl<'a> Iterator for ChapterIter<'a> { impl<'a> Iterator for ChapterIter<'a> {
type Item = Chapter<'a>; type Item = Chapter<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if self.current >= (*self.context.as_ptr()).nb_chapters { if self.current >= (*self.context.as_ptr()).nb_chapters {
return None; return None;
} }
self.current += 1; self.current += 1;
Some(Chapter::wrap(self.context, (self.current - 1) as usize)) Some(Chapter::wrap(self.context, (self.current - 1) as usize))
} }
} }
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
unsafe { unsafe {
let length = (*self.context.as_ptr()).nb_chapters as usize; let length = (*self.context.as_ptr()).nb_chapters as usize;
(length - self.current as usize, Some(length - self.current as usize)) (
} length - self.current as usize,
} Some(length - self.current as usize),
)
}
}
} }
impl<'a> ExactSizeIterator for ChapterIter<'a> { } impl<'a> ExactSizeIterator for ChapterIter<'a> {}
pub struct ChapterIterMut<'a> { pub struct ChapterIterMut<'a> {
context: &'a mut Context, context: &'a mut Context,
current: c_uint, current: c_uint,
} }
impl<'a> ChapterIterMut<'a> { impl<'a> ChapterIterMut<'a> {
pub fn new<'s, 'c: 's>(context: &'c mut Context) -> ChapterIterMut<'s> { pub fn new<'s, 'c: 's>(context: &'c mut Context) -> ChapterIterMut<'s> {
ChapterIterMut { context: context, current: 0 } ChapterIterMut {
} context: context,
current: 0,
}
}
} }
impl<'a> Iterator for ChapterIterMut<'a> { impl<'a> Iterator for ChapterIterMut<'a> {
type Item = ChapterMut<'a>; type Item = ChapterMut<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if self.current >= (*self.context.as_ptr()).nb_chapters { if self.current >= (*self.context.as_ptr()).nb_chapters {
return None return None;
} }
self.current += 1; self.current += 1;
Some(ChapterMut::wrap(mem::transmute_copy(&self.context), (self.current - 1) as usize)) Some(ChapterMut::wrap(
} mem::transmute_copy(&self.context),
} (self.current - 1) as usize,
))
}
}
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
unsafe { unsafe {
let length = (*self.context.as_ptr()).nb_chapters as usize; let length = (*self.context.as_ptr()).nb_chapters as usize;
(length - self.current as usize, Some(length - self.current as usize)) (
} length - self.current as usize,
} Some(length - self.current as usize),
)
}
}
} }
impl<'a> ExactSizeIterator for ChapterIterMut<'a> { } impl<'a> ExactSizeIterator for ChapterIterMut<'a> {}

View File

@ -2,36 +2,35 @@ use ffi::*;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum Mode { pub enum Mode {
Input, Input,
Output, Output,
} }
pub struct Destructor { pub struct Destructor {
ptr: *mut AVFormatContext, ptr: *mut AVFormatContext,
mode: Mode, mode: Mode,
} }
impl Destructor { impl Destructor {
pub unsafe fn new(ptr: *mut AVFormatContext, mode: Mode) -> Self { pub unsafe fn new(ptr: *mut AVFormatContext, mode: Mode) -> Self {
Destructor { Destructor {
ptr: ptr, ptr: ptr,
mode: mode, mode: mode,
} }
} }
} }
impl Drop for Destructor { impl Drop for Destructor {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
match self.mode { match self.mode {
Mode::Input => Mode::Input => avformat_close_input(&mut self.ptr),
avformat_close_input(&mut self.ptr),
Mode::Output => { Mode::Output => {
avio_close((*self.ptr).pb); avio_close((*self.ptr).pb);
avformat_free_context(self.ptr); avformat_free_context(self.ptr);
} }
} }
} }
} }
} }

View File

@ -1,188 +1,190 @@
use std::ffi::CString;
use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr; use std::ptr;
use std::mem;
use std::ffi::CString;
use ffi::*;
use ::{Error, Codec, Stream, Packet, format};
use super::common::Context; use super::common::Context;
use super::destructor; use super::destructor;
use ffi::*;
use util::range::Range; use util::range::Range;
use {format, Codec, Error, Packet, Stream};
pub struct Input { pub struct Input {
ptr: *mut AVFormatContext, ptr: *mut AVFormatContext,
ctx: Context, ctx: Context,
} }
unsafe impl Send for Input { } unsafe impl Send for Input {}
impl Input { impl Input {
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self { pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
Input { ptr: ptr, ctx: Context::wrap(ptr, destructor::Mode::Input) } Input {
} ptr: ptr,
ctx: Context::wrap(ptr, destructor::Mode::Input),
}
}
pub unsafe fn as_ptr(&self) -> *const AVFormatContext { pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
self.ptr self.ptr
} }
} }
impl Input { impl Input {
pub fn format(&self) -> format::Input { pub fn format(&self) -> format::Input {
unsafe { unsafe { format::Input::wrap((*self.as_ptr()).iformat) }
format::Input::wrap((*self.as_ptr()).iformat) }
}
}
pub fn video_codec(&self) -> Option<Codec> { pub fn video_codec(&self) -> Option<Codec> {
unsafe { unsafe {
let ptr = av_format_get_video_codec(self.as_ptr()); let ptr = av_format_get_video_codec(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Codec::wrap(ptr))
Some(Codec::wrap(ptr)) }
} }
} }
}
pub fn audio_codec(&self) -> Option<Codec> { pub fn audio_codec(&self) -> Option<Codec> {
unsafe { unsafe {
let ptr = av_format_get_audio_codec(self.as_ptr()); let ptr = av_format_get_audio_codec(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Codec::wrap(ptr))
Some(Codec::wrap(ptr)) }
} }
} }
}
pub fn subtitle_codec(&self) -> Option<Codec> { pub fn subtitle_codec(&self) -> Option<Codec> {
unsafe { unsafe {
let ptr = av_format_get_subtitle_codec(self.as_ptr()); let ptr = av_format_get_subtitle_codec(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Codec::wrap(ptr))
Some(Codec::wrap(ptr)) }
} }
} }
}
pub fn data_codec(&self) -> Option<Codec> { pub fn data_codec(&self) -> Option<Codec> {
unsafe { unsafe {
let ptr = av_format_get_data_codec(self.as_ptr()); let ptr = av_format_get_data_codec(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
None None
} } else {
else { Some(Codec::wrap(ptr))
Some(Codec::wrap(ptr)) }
} }
} }
}
pub fn probe_score(&self) -> i32 { pub fn probe_score(&self) -> i32 {
unsafe { unsafe { av_format_get_probe_score(self.as_ptr()) }
av_format_get_probe_score(self.as_ptr()) }
}
}
pub fn packets(&mut self) -> PacketIter { pub fn packets(&mut self) -> PacketIter {
PacketIter::new(self) PacketIter::new(self)
} }
pub fn pause(&mut self) -> Result<(), Error> { pub fn pause(&mut self) -> Result<(), Error> {
unsafe { unsafe {
match av_read_pause(self.as_mut_ptr()) { match av_read_pause(self.as_mut_ptr()) {
0 => Ok(()), 0 => Ok(()),
e => Err(Error::from(e)), e => Err(Error::from(e)),
} }
} }
} }
pub fn play(&mut self) -> Result<(), Error> { pub fn play(&mut self) -> Result<(), Error> {
unsafe { unsafe {
match av_read_play(self.as_mut_ptr()) { match av_read_play(self.as_mut_ptr()) {
0 => Ok(()), 0 => Ok(()),
e => Err(Error::from(e)), e => Err(Error::from(e)),
} }
} }
} }
pub fn seek<R: Range<i64>>(&mut self, ts: i64, range: R) -> Result<(), Error> { pub fn seek<R: Range<i64>>(&mut self, ts: i64, range: R) -> Result<(), Error> {
unsafe { unsafe {
match avformat_seek_file(self.as_mut_ptr(), -1, match avformat_seek_file(
range.start().map(|v| *v).unwrap_or(i64::min_value()), ts, self.as_mut_ptr(),
range.end().map(|v| *v).unwrap_or(i64::max_value()), 0) -1,
{ range.start().cloned().unwrap_or(i64::min_value()),
s if s >= 0 => Ok(()), ts,
e => Err(Error::from(e)), range.end().cloned().unwrap_or(i64::max_value()),
} 0,
} ) {
} s if s >= 0 => Ok(()),
e => Err(Error::from(e)),
}
}
}
} }
impl Deref for Input { impl Deref for Input {
type Target = Context; type Target = Context;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.ctx &self.ctx
} }
} }
impl DerefMut for Input { impl DerefMut for Input {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.ctx &mut self.ctx
} }
} }
pub struct PacketIter<'a> { pub struct PacketIter<'a> {
context: &'a mut Input, context: &'a mut Input,
} }
impl<'a> PacketIter<'a> { impl<'a> PacketIter<'a> {
pub fn new(context: &mut Input) -> PacketIter { pub fn new(context: &mut Input) -> PacketIter {
PacketIter { context: context } PacketIter { context: context }
} }
} }
impl<'a> Iterator for PacketIter<'a> { impl<'a> Iterator for PacketIter<'a> {
type Item = (Stream<'a>, Packet); type Item = (Stream<'a>, Packet);
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
let mut packet = Packet::empty(); let mut packet = Packet::empty();
loop { loop {
match packet.read(self.context) { match packet.read(self.context) {
Ok(..) => unsafe { Ok(..) => unsafe {
return Some(( return Some((
Stream::wrap(mem::transmute_copy(&self.context), packet.stream()), Stream::wrap(mem::transmute_copy(&self.context), packet.stream()),
packet)); packet,
}, ));
},
Err(Error::Eof) => Err(Error::Eof) => return None,
return None,
Err(..) => Err(..) => (),
() }
} }
} }
}
} }
pub fn dump(ctx: &Input, index: i32, url: Option<&str>) { pub fn dump(ctx: &Input, index: i32, url: Option<&str>) {
let url = url.map(|u| CString::new(u).unwrap()); let url = url.map(|u| CString::new(u).unwrap());
unsafe { unsafe {
av_dump_format(ctx.as_ptr() as *mut _, index, av_dump_format(
url.map(|u| u.as_ptr()).unwrap_or(ptr::null()), 0); ctx.as_ptr() as *mut _,
} index,
url.map(|u| u.as_ptr()).unwrap_or(ptr::null()),
0,
);
}
} }

View File

@ -11,44 +11,42 @@ pub use self::output::Output;
pub mod common; pub mod common;
pub enum Context { pub enum Context {
Input(Input), Input(Input),
Output(Output), Output(Output),
} }
unsafe impl Send for Context { } unsafe impl Send for Context {}
impl Context { impl Context {
pub fn is_input(&self) -> bool { pub fn is_input(&self) -> bool {
if let &Context::Input(..) = self { if let Context::Input(..) = *self {
true true
} } else {
else { false
false }
} }
}
pub fn input(self) -> Input { pub fn input(self) -> Input {
if let Context::Input(context) = self { if let Context::Input(context) = self {
return context; return context;
} }
unreachable!(); unreachable!();
} }
pub fn is_output(&self) -> bool { pub fn is_output(&self) -> bool {
if let &Context::Output(..) = self { if let Context::Output(..) = *self {
true true
} } else {
else { false
false }
} }
}
pub fn output(self) -> Output { pub fn output(self) -> Output {
if let Context::Output(context) = self { if let Context::Output(context) = self {
return context; return context;
} }
unreachable!(); unreachable!();
} }
} }

View File

@ -1,174 +1,180 @@
use std::ffi::CString;
use std::mem::size_of;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::ptr; use std::ptr;
use std::mem::size_of;
use std::ffi::CString;
use libc; use libc;
use ffi::*;
use ::{Error, StreamMut, ChapterMut, Rational, Dictionary, format};
use super::common::Context; use super::common::Context;
use super::destructor; use super::destructor;
use codec::traits; use codec::traits;
use ffi::*;
use {format, ChapterMut, Dictionary, Error, Rational, StreamMut};
pub struct Output { pub struct Output {
ptr: *mut AVFormatContext, ptr: *mut AVFormatContext,
ctx: Context, ctx: Context,
} }
unsafe impl Send for Output { } unsafe impl Send for Output {}
impl Output { impl Output {
pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self { pub unsafe fn wrap(ptr: *mut AVFormatContext) -> Self {
Output { ptr: ptr, ctx: Context::wrap(ptr, destructor::Mode::Output) } Output {
} ptr: ptr,
ctx: Context::wrap(ptr, destructor::Mode::Output),
}
}
pub unsafe fn as_ptr(&self) -> *const AVFormatContext { pub unsafe fn as_ptr(&self) -> *const AVFormatContext {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFormatContext {
self.ptr self.ptr
} }
} }
impl Output { impl Output {
pub fn format(&self) -> format::Output { pub fn format(&self) -> format::Output {
unsafe { unsafe { format::Output::wrap((*self.as_ptr()).oformat) }
format::Output::wrap((*self.as_ptr()).oformat) }
}
}
pub fn write_header(&mut self) -> Result<(), Error> { pub fn write_header(&mut self) -> Result<(), Error> {
unsafe { unsafe {
match avformat_write_header(self.as_mut_ptr(), ptr::null_mut()) { match avformat_write_header(self.as_mut_ptr(), ptr::null_mut()) {
0 => Ok(()), 0 => Ok(()),
e => Err(Error::from(e)), e => Err(Error::from(e)),
} }
} }
} }
pub fn write_header_with(&mut self, options: Dictionary) -> Result<Dictionary, Error> { pub fn write_header_with(&mut self, options: Dictionary) -> Result<Dictionary, Error> {
unsafe { unsafe {
let mut opts = options.disown(); let mut opts = options.disown();
let res = avformat_write_header(self.as_mut_ptr(), &mut opts); let res = avformat_write_header(self.as_mut_ptr(), &mut opts);
match res { match res {
0 => Ok(Dictionary::own(opts)), 0 => Ok(Dictionary::own(opts)),
e => Err(Error::from(e)), e => Err(Error::from(e)),
} }
} }
} }
pub fn write_trailer(&mut self) -> Result<(), Error> { pub fn write_trailer(&mut self) -> Result<(), Error> {
unsafe { unsafe {
match av_write_trailer(self.as_mut_ptr()) { match av_write_trailer(self.as_mut_ptr()) {
0 => Ok(()), 0 => Ok(()),
e => Err(Error::from(e)), e => Err(Error::from(e)),
} }
} }
} }
pub fn add_stream<E: traits::Encoder>(&mut self, codec: E) -> Result<StreamMut, Error> { pub fn add_stream<E: traits::Encoder>(&mut self, codec: E) -> Result<StreamMut, Error> {
unsafe { unsafe {
let codec = try!(codec.encoder().ok_or(Error::EncoderNotFound)); let codec = codec.encoder().ok_or(Error::EncoderNotFound)?;
let ptr = avformat_new_stream(self.as_mut_ptr(), codec.as_ptr()); let ptr = avformat_new_stream(self.as_mut_ptr(), codec.as_ptr());
if ptr.is_null() { if ptr.is_null() {
panic!("out of memory"); panic!("out of memory");
} }
let index = (*self.ctx.as_ptr()).nb_streams - 1; let index = (*self.ctx.as_ptr()).nb_streams - 1;
Ok(StreamMut::wrap(&mut self.ctx, index as usize)) Ok(StreamMut::wrap(&mut self.ctx, index as usize))
} }
} }
pub fn add_chapter<R: Into<Rational>, S: AsRef<str>>(&mut self, pub fn add_chapter<R: Into<Rational>, S: AsRef<str>>(
id: i32, &mut self,
time_base: R, id: i32,
start: i64, time_base: R,
end: i64, start: i64,
title: S) -> Result<ChapterMut, Error> end: i64,
{ title: S,
// avpriv_new_chapter is private (libavformat/internal.h) ) -> Result<ChapterMut, Error> {
// avpriv_new_chapter is private (libavformat/internal.h)
if start > end { if start > end {
return Err(Error::InvalidData); return Err(Error::InvalidData);
} }
let mut existing = None; let mut existing = None;
for chapter in self.chapters() { for chapter in self.chapters() {
if chapter.id() == id { if chapter.id() == id {
existing = Some(chapter.index()); existing = Some(chapter.index());
break; break;
} }
} }
let index = match existing { let index = match existing {
Some(index) => index, Some(index) => index,
None => unsafe { None => unsafe {
let ptr = av_mallocz(size_of::<AVChapter>()).as_mut().ok_or(Error::Bug)?; let ptr = av_mallocz(size_of::<AVChapter>())
let mut nb_chapters = (*self.as_ptr()).nb_chapters as i32; .as_mut()
.ok_or(Error::Bug)?;
let mut nb_chapters = (*self.as_ptr()).nb_chapters as i32;
// chapters array will be freed by `avformat_free_context` // chapters array will be freed by `avformat_free_context`
av_dynarray_add( av_dynarray_add(
&mut (*self.as_mut_ptr()).chapters as *mut _ as *mut libc::c_void, &mut (*self.as_mut_ptr()).chapters as *mut _ as *mut libc::c_void,
&mut nb_chapters, &mut nb_chapters,
ptr ptr,
); );
if nb_chapters > 0 { if nb_chapters > 0 {
(*self.as_mut_ptr()).nb_chapters = nb_chapters as u32; (*self.as_mut_ptr()).nb_chapters = nb_chapters as u32;
let index = (*self.ctx.as_ptr()).nb_chapters - 1; let index = (*self.ctx.as_ptr()).nb_chapters - 1;
index as usize index as usize
} } else {
else { // failed to add the chapter
// failed to add the chapter av_freep(ptr);
av_freep(ptr); return Err(Error::Bug);
return Err(Error::Bug); }
} },
}, };
};
let mut chapter = self.chapter_mut(index) let mut chapter = self.chapter_mut(index).ok_or(Error::Bug)?;
.ok_or(Error::Bug)?;
chapter.set_id(id); chapter.set_id(id);
chapter.set_time_base(time_base); chapter.set_time_base(time_base);
chapter.set_start(start); chapter.set_start(start);
chapter.set_end(end); chapter.set_end(end);
chapter.set_metadata("title", title); chapter.set_metadata("title", title);
Ok(chapter) Ok(chapter)
} }
pub fn set_metadata(&mut self, dictionary: Dictionary) { pub fn set_metadata(&mut self, dictionary: Dictionary) {
unsafe { unsafe {
(*self.as_mut_ptr()).metadata = dictionary.disown(); (*self.as_mut_ptr()).metadata = dictionary.disown();
} }
} }
} }
impl Deref for Output { impl Deref for Output {
type Target = Context; type Target = Context;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.ctx &self.ctx
} }
} }
impl DerefMut for Output { impl DerefMut for Output {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.ctx &mut self.ctx
} }
} }
pub fn dump(ctx: &Output, index: i32, url: Option<&str>) { pub fn dump(ctx: &Output, index: i32, url: Option<&str>) {
let url = url.map(|u| CString::new(u).unwrap()); let url = url.map(|u| CString::new(u).unwrap());
unsafe { unsafe {
av_dump_format(ctx.as_ptr() as *mut _, index, av_dump_format(
url.map(|u| u.as_ptr()).unwrap_or(ptr::null()), 1); ctx.as_ptr() as *mut _,
} index,
url.map(|u| u.as_ptr()).unwrap_or(ptr::null()),
1,
);
}
} }

View File

@ -1,26 +1,25 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Flags: c_int { pub struct Flags: c_int {
const NO_FILE = AVFMT_NOFILE; const NO_FILE = AVFMT_NOFILE;
const NEED_NUMBER = AVFMT_NEEDNUMBER; const NEED_NUMBER = AVFMT_NEEDNUMBER;
const SHOW_IDS = AVFMT_SHOW_IDS; const SHOW_IDS = AVFMT_SHOW_IDS;
const RAW_PICTURE = AVFMT_RAWPICTURE; const RAW_PICTURE = AVFMT_RAWPICTURE;
const GLOBAL_HEADER = AVFMT_GLOBALHEADER; const GLOBAL_HEADER = AVFMT_GLOBALHEADER;
const NO_TIMESTAMPS = AVFMT_NOTIMESTAMPS; const NO_TIMESTAMPS = AVFMT_NOTIMESTAMPS;
const GENERIC_INDEX = AVFMT_GENERIC_INDEX; const GENERIC_INDEX = AVFMT_GENERIC_INDEX;
const TS_DISCONT = AVFMT_TS_DISCONT; const TS_DISCONT = AVFMT_TS_DISCONT;
const VARIABLE_FPS = AVFMT_VARIABLE_FPS; const VARIABLE_FPS = AVFMT_VARIABLE_FPS;
const NO_DIMENSIONS = AVFMT_NODIMENSIONS; const NO_DIMENSIONS = AVFMT_NODIMENSIONS;
const NO_STREAMS = AVFMT_NOSTREAMS; const NO_STREAMS = AVFMT_NOSTREAMS;
const NO_BINSEARCH = AVFMT_NOBINSEARCH; const NO_BINSEARCH = AVFMT_NOBINSEARCH;
const NO_GENSEARCH = AVFMT_NOGENSEARCH; const NO_GENSEARCH = AVFMT_NOGENSEARCH;
const NO_BYTE_SEEK = AVFMT_NO_BYTE_SEEK; const NO_BYTE_SEEK = AVFMT_NO_BYTE_SEEK;
const ALLOW_FLUSH = AVFMT_ALLOW_FLUSH; const ALLOW_FLUSH = AVFMT_ALLOW_FLUSH;
const TS_NONSTRICT = AVFMT_TS_NONSTRICT; const TS_NONSTRICT = AVFMT_TS_NONSTRICT;
const TS_NEGATIVE = AVFMT_TS_NEGATIVE; const TS_NEGATIVE = AVFMT_TS_NEGATIVE;
const SEEK_TO_PTS = AVFMT_SEEK_TO_PTS; const SEEK_TO_PTS = AVFMT_SEEK_TO_PTS;
} }
} }

View File

@ -4,59 +4,57 @@ use std::str::from_utf8_unchecked;
use ffi::*; use ffi::*;
pub struct Input { pub struct Input {
ptr: *mut AVInputFormat, ptr: *mut AVInputFormat,
} }
impl Input { impl Input {
pub unsafe fn wrap(ptr: *mut AVInputFormat) -> Self { pub unsafe fn wrap(ptr: *mut AVInputFormat) -> Self {
Input { ptr: ptr } Input { ptr: ptr }
} }
pub unsafe fn as_ptr(&self) -> *const AVInputFormat { pub unsafe fn as_ptr(&self) -> *const AVInputFormat {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVInputFormat { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVInputFormat {
self.ptr self.ptr
} }
} }
impl Input { impl Input {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) }
}
}
pub fn description(&self) -> &str { pub fn description(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).long_name).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).long_name).to_bytes()) }
}
}
pub fn extensions(&self) -> Vec<&str> { pub fn extensions(&self) -> Vec<&str> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).extensions; let ptr = (*self.as_ptr()).extensions;
if ptr.is_null() { if ptr.is_null() {
Vec::new() Vec::new()
} } else {
else { from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes())
from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() .split(',')
} .collect()
} }
} }
}
pub fn mime_types(&self) -> Vec<&str> { pub fn mime_types(&self) -> Vec<&str> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).mime_type; let ptr = (*self.as_ptr()).mime_type;
if ptr.is_null() { if ptr.is_null() {
Vec::new() Vec::new()
} } else {
else { from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes())
from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() .split(',')
} .collect()
} }
} }
}
} }

View File

@ -1,65 +1,72 @@
use std::ptr; use std::ptr;
use ffi::*;
use super::{Format, Input, Output}; use super::{Format, Input, Output};
use ffi::*;
pub struct Iter { pub struct Iter {
input: *mut AVInputFormat, input: *mut AVInputFormat,
output: *mut AVOutputFormat, output: *mut AVOutputFormat,
step: Step, step: Step,
} }
enum Step { enum Step {
Input, Input,
Output, Output,
Done, Done,
} }
impl Iter { impl Iter {
pub fn new() -> Self { pub fn new() -> Self {
Iter { input: ptr::null_mut(), output: ptr::null_mut(), step: Step::Input } Iter {
} input: ptr::null_mut(),
output: ptr::null_mut(),
step: Step::Input,
}
}
}
impl Default for Iter {
fn default() -> Self {
Self::new()
}
} }
impl Iterator for Iter { impl Iterator for Iter {
type Item = Format; type Item = Format;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
match self.step { match self.step {
Step::Input => { Step::Input => {
let ptr = av_iformat_next(self.input); let ptr = av_iformat_next(self.input);
if ptr.is_null() && !self.input.is_null() { if ptr.is_null() && !self.input.is_null() {
self.step = Step::Output; self.step = Step::Output;
self.next() self.next()
} } else {
else { self.input = ptr;
self.input = ptr;
Some(Format::Input(Input::wrap(ptr))) Some(Format::Input(Input::wrap(ptr)))
} }
} }
Step::Output => { Step::Output => {
let ptr = av_oformat_next(self.output); let ptr = av_oformat_next(self.output);
if ptr.is_null() && !self.output.is_null() { if ptr.is_null() && !self.output.is_null() {
self.step = Step::Done; self.step = Step::Done;
self.next() self.next()
} } else {
else { self.output = ptr;
self.output = ptr;
Some(Format::Output(Output::wrap(ptr))) Some(Format::Output(Output::wrap(ptr)))
} }
} }
Step::Done => Step::Done => None,
None }
} }
} }
}
} }

View File

@ -11,40 +11,40 @@ mod iter;
pub use self::iter::Iter; pub use self::iter::Iter;
pub enum Format { pub enum Format {
Input(Input), Input(Input),
Output(Output), Output(Output),
} }
impl Format { impl Format {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
match self { match *self {
&Format::Input(ref f) => f.name(), Format::Input(ref f) => f.name(),
&Format::Output(ref f) => f.name() Format::Output(ref f) => f.name(),
} }
} }
pub fn description(&self) -> &str { pub fn description(&self) -> &str {
match self { match *self {
&Format::Input(ref f) => f.description(), Format::Input(ref f) => f.description(),
&Format::Output(ref f) => f.description() Format::Output(ref f) => f.description(),
} }
} }
pub fn extensions(&self) -> Vec<&str> { pub fn extensions(&self) -> Vec<&str> {
match self { match *self {
&Format::Input(ref f) => f.extensions(), Format::Input(ref f) => f.extensions(),
&Format::Output(ref f) => f.extensions() Format::Output(ref f) => f.extensions(),
} }
} }
pub fn mime_types(&self) -> Vec<&str> { pub fn mime_types(&self) -> Vec<&str> {
match self { match *self {
&Format::Input(ref f) => f.mime_types(), Format::Input(ref f) => f.mime_types(),
&Format::Output(ref f) => f.mime_types() Format::Output(ref f) => f.mime_types(),
} }
} }
} }
pub fn list() -> Iter { pub fn list() -> Iter {
Iter::new() Iter::new()
} }

View File

@ -1,82 +1,84 @@
use std::path::Path; use std::path::Path;
use std::ptr;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::ptr;
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;
use super::Flags;
use ffi::*; use ffi::*;
use {codec, media}; use {codec, media};
use super::Flags;
pub struct Output { pub struct Output {
ptr: *mut AVOutputFormat, ptr: *mut AVOutputFormat,
} }
impl Output { impl Output {
pub unsafe fn wrap(ptr: *mut AVOutputFormat) -> Self { pub unsafe fn wrap(ptr: *mut AVOutputFormat) -> Self {
Output { ptr: ptr } Output { ptr: ptr }
} }
pub unsafe fn as_ptr(&self) -> *const AVOutputFormat { pub unsafe fn as_ptr(&self) -> *const AVOutputFormat {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVOutputFormat { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVOutputFormat {
self.ptr self.ptr
} }
} }
impl Output { impl Output {
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).name).to_bytes()) }
}
}
pub fn description(&self) -> &str { pub fn description(&self) -> &str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).long_name).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr((*self.as_ptr()).long_name).to_bytes()) }
}
}
pub fn extensions(&self) -> Vec<&str> { pub fn extensions(&self) -> Vec<&str> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).extensions; let ptr = (*self.as_ptr()).extensions;
if ptr.is_null() { if ptr.is_null() {
Vec::new() Vec::new()
} } else {
else { from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes())
from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() .split(',')
} .collect()
} }
} }
}
pub fn mime_types(&self) -> Vec<&str> { pub fn mime_types(&self) -> Vec<&str> {
unsafe { unsafe {
let ptr = (*self.as_ptr()).mime_type; let ptr = (*self.as_ptr()).mime_type;
if ptr.is_null() { if ptr.is_null() {
Vec::new() Vec::new()
} } else {
else { from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes())
from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()).split(',').collect() .split(',')
} .collect()
} }
} }
}
pub fn codec<P: AsRef<Path>>(&self, path: &P, kind: media::Type) -> codec::Id { pub fn codec<P: AsRef<Path>>(&self, path: &P, kind: media::Type) -> codec::Id {
// XXX: use to_cstring when stable // XXX: use to_cstring when stable
let path = CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap(); let path = CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap();
unsafe { unsafe {
codec::Id::from(av_guess_codec(self.as_ptr() as *mut _, ptr::null(), path.as_ptr(), ptr::null(), kind.into())) codec::Id::from(av_guess_codec(
} self.as_ptr() as *mut _,
} ptr::null(),
path.as_ptr(),
ptr::null(),
kind.into(),
))
}
}
pub fn flags(&self) -> Flags { pub fn flags(&self) -> Flags {
unsafe { unsafe { Flags::from_bits_truncate((*self.as_ptr()).flags) }
Flags::from_bits_truncate((*self.as_ptr()).flags) }
}
}
} }

View File

@ -1,6 +1,6 @@
pub use ::util::format::{sample, Sample}; pub use util::format::{pixel, Pixel};
pub use ::util::format::{pixel, Pixel}; pub use util::format::{sample, Sample};
use ::util::interrupt; use util::interrupt;
pub mod stream; pub mod stream;
@ -10,276 +10,316 @@ pub mod context;
pub use self::context::Context; pub use self::context::Context;
pub mod format; pub mod format;
pub use self::format::{Input, Output, list};
pub use self::format::{flag, Flags}; pub use self::format::{flag, Flags};
pub use self::format::{list, Input, Output};
pub mod network; pub mod network;
use std::ptr; use std::ffi::{CStr, CString};
use std::path::Path; use std::path::Path;
use std::ffi::{CString, CStr}; use std::ptr;
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;
use ffi::*; use ffi::*;
use ::{Error, Format, Dictionary}; use {Dictionary, Error, Format};
pub fn register_all() { pub fn register_all() {
unsafe { unsafe {
av_register_all(); av_register_all();
} }
} }
pub fn register(format: &Format) { pub fn register(format: &Format) {
match format { match *format {
&Format::Input(ref format) => unsafe { Format::Input(ref format) => unsafe {
av_register_input_format(format.as_ptr() as *mut _); av_register_input_format(format.as_ptr() as *mut _);
}, },
&Format::Output(ref format) => unsafe { Format::Output(ref format) => unsafe {
av_register_output_format(format.as_ptr() as *mut _); av_register_output_format(format.as_ptr() as *mut _);
} },
} }
} }
pub fn version() -> u32 { pub fn version() -> u32 {
unsafe { unsafe { avformat_version() }
avformat_version()
}
} }
pub fn configuration() -> &'static str { pub fn configuration() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(avformat_configuration()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(avformat_configuration()).to_bytes())
}
} }
pub fn license() -> &'static str { pub fn license() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(avformat_license()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(avformat_license()).to_bytes())
}
} }
// XXX: use to_cstring when stable // XXX: use to_cstring when stable
fn from_path<P: AsRef<Path>>(path: &P) -> CString { fn from_path<P: AsRef<Path>>(path: &P) -> CString {
CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap() CString::new(path.as_ref().as_os_str().to_str().unwrap()).unwrap()
} }
// NOTE: this will be better with specialization or anonymous return types // NOTE: this will be better with specialization or anonymous return types
pub fn open<P: AsRef<Path>>(path: &P, format: &Format) -> Result<Context, Error> { pub fn open<P: AsRef<Path>>(path: &P, format: &Format) -> Result<Context, Error> {
unsafe { unsafe {
let mut ps = ptr::null_mut(); let mut ps = ptr::null_mut();
let path = from_path(path); let path = from_path(path);
match format { match *format {
&Format::Input(ref format) => { Format::Input(ref format) => match avformat_open_input(
match avformat_open_input(&mut ps, path.as_ptr(), format.as_ptr() as *mut _, ptr::null_mut()) { &mut ps,
0 => { path.as_ptr(),
match avformat_find_stream_info(ps, ptr::null_mut()) { format.as_ptr() as *mut _,
r if r >= 0 => Ok(Context::Input(context::Input::wrap(ps))), ptr::null_mut(),
e => Err(Error::from(e)), ) {
} 0 => match avformat_find_stream_info(ps, ptr::null_mut()) {
} r if r >= 0 => Ok(Context::Input(context::Input::wrap(ps))),
e => Err(Error::from(e)),
},
e => Err(Error::from(e)) e => Err(Error::from(e)),
} },
}
&Format::Output(ref format) => { Format::Output(ref format) => match avformat_alloc_output_context2(
match avformat_alloc_output_context2(&mut ps, format.as_ptr() as *mut _, ptr::null(), path.as_ptr()) { &mut ps,
0 => { format.as_ptr() as *mut _,
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { ptr::null(),
0 => Ok(Context::Output(context::Output::wrap(ps))), path.as_ptr(),
e => Err(Error::from(e)), ) {
} 0 => match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
} 0 => Ok(Context::Output(context::Output::wrap(ps))),
e => Err(Error::from(e)),
},
e => Err(Error::from(e)) e => Err(Error::from(e)),
} },
} }
} }
}
} }
pub fn open_with<P: AsRef<Path>>(path: &P, format: &Format, options: Dictionary) -> Result<Context, Error> { pub fn open_with<P: AsRef<Path>>(
unsafe { path: &P,
let mut ps = ptr::null_mut(); format: &Format,
let path = from_path(path); options: Dictionary,
let mut opts = options.disown(); ) -> Result<Context, Error> {
unsafe {
let mut ps = ptr::null_mut();
let path = from_path(path);
let mut opts = options.disown();
match format { match *format {
&Format::Input(ref format) => { Format::Input(ref format) => {
let res = avformat_open_input(&mut ps, path.as_ptr(), format.as_ptr() as *mut _, &mut opts); let res = avformat_open_input(
&mut ps,
path.as_ptr(),
format.as_ptr() as *mut _,
&mut opts,
);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => { 0 => match avformat_find_stream_info(ps, ptr::null_mut()) {
match avformat_find_stream_info(ps, ptr::null_mut()) { r if r >= 0 => Ok(Context::Input(context::Input::wrap(ps))),
r if r >= 0 => Ok(Context::Input(context::Input::wrap(ps))), e => Err(Error::from(e)),
e => Err(Error::from(e)), },
}
}
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
&Format::Output(ref format) => { Format::Output(ref format) => match avformat_alloc_output_context2(
match avformat_alloc_output_context2(&mut ps, format.as_ptr() as *mut _, ptr::null(), path.as_ptr()) { &mut ps,
0 => { format.as_ptr() as *mut _,
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { ptr::null(),
0 => Ok(Context::Output(context::Output::wrap(ps))), path.as_ptr(),
e => Err(Error::from(e)), ) {
} 0 => match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
} 0 => Ok(Context::Output(context::Output::wrap(ps))),
e => Err(Error::from(e)),
},
e => Err(Error::from(e)) e => Err(Error::from(e)),
} },
} }
} }
}
} }
pub fn input<P: AsRef<Path>>(path: &P) -> Result<context::Input, Error> { pub fn input<P: AsRef<Path>>(path: &P) -> Result<context::Input, Error> {
unsafe { unsafe {
let mut ps = ptr::null_mut(); let mut ps = ptr::null_mut();
let path = from_path(path); let path = from_path(path);
match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut()) { match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut()) {
0 => { 0 => match avformat_find_stream_info(ps, ptr::null_mut()) {
match avformat_find_stream_info(ps, ptr::null_mut()) { r if r >= 0 => Ok(context::Input::wrap(ps)),
r if r >= 0 => Ok(context::Input::wrap(ps)), e => {
e => Err(Error::from(e)), avformat_close_input(&mut ps);
} Err(Error::from(e))
} }
},
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn input_with_dictionary<P: AsRef<Path>>(path: &P, options: Dictionary) -> Result<context::Input, Error> { pub fn input_with_dictionary<P: AsRef<Path>>(
unsafe { path: &P,
let mut ps = ptr::null_mut(); options: Dictionary,
let path = from_path(path); ) -> Result<context::Input, Error> {
let mut opts = options.disown(); unsafe {
let res = avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), &mut opts); let mut ps = ptr::null_mut();
let path = from_path(path);
let mut opts = options.disown();
let res = avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), &mut opts);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => { 0 => match avformat_find_stream_info(ps, ptr::null_mut()) {
match avformat_find_stream_info(ps, ptr::null_mut()) { r if r >= 0 => Ok(context::Input::wrap(ps)),
r if r >= 0 => Ok(context::Input::wrap(ps)), e => {
e => Err(Error::from(e)), avformat_close_input(&mut ps);
} Err(Error::from(e))
} }
},
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn input_with_interrupt<P: AsRef<Path>, F>(path: &P, closure: F) -> Result<context::Input, Error> pub fn input_with_interrupt<P: AsRef<Path>, F>(
where F: FnMut() -> bool { path: &P,
unsafe { closure: F,
let mut ps = avformat_alloc_context(); ) -> Result<context::Input, Error>
let path = from_path(path); where
(*ps).interrupt_callback = interrupt::new(Box::new(closure)).interrupt; F: FnMut() -> bool,
{
unsafe {
let mut ps = avformat_alloc_context();
let path = from_path(path);
(*ps).interrupt_callback = interrupt::new(Box::new(closure)).interrupt;
match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut()) { match avformat_open_input(&mut ps, path.as_ptr(), ptr::null_mut(), ptr::null_mut()) {
0 => { 0 => match avformat_find_stream_info(ps, ptr::null_mut()) {
match avformat_find_stream_info(ps, ptr::null_mut()) { r if r >= 0 => Ok(context::Input::wrap(ps)),
r if r >= 0 => Ok(context::Input::wrap(ps)), e => {
e => Err(Error::from(e)), avformat_close_input(&mut ps);
} Err(Error::from(e))
} }
},
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn output<P: AsRef<Path>>(path: &P) -> Result<context::Output, Error> { pub fn output<P: AsRef<Path>>(path: &P) -> Result<context::Output, Error> {
unsafe { unsafe {
let mut ps = ptr::null_mut(); let mut ps = ptr::null_mut();
let path = from_path(path); let path = from_path(path);
match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), ptr::null(), path.as_ptr()) { match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), ptr::null(), path.as_ptr()) {
0 => { 0 => match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { 0 => Ok(context::Output::wrap(ps)),
0 => Ok(context::Output::wrap(ps)), e => Err(Error::from(e)),
e => Err(Error::from(e)) },
}
}
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn output_with<P: AsRef<Path>>(path: &P, options: Dictionary) -> Result<context::Output, Error> { pub fn output_with<P: AsRef<Path>>(
unsafe { path: &P,
let mut ps = ptr::null_mut(); options: Dictionary,
let path = from_path(path); ) -> Result<context::Output, Error> {
let mut opts = options.disown(); unsafe {
let mut ps = ptr::null_mut();
let path = from_path(path);
let mut opts = options.disown();
match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), ptr::null(), path.as_ptr()) { match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), ptr::null(), path.as_ptr()) {
0 => { 0 => {
let res = avio_open2(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE, ptr::null(), &mut opts,); let res = avio_open2(
&mut (*ps).pb,
path.as_ptr(),
AVIO_FLAG_WRITE,
ptr::null(),
&mut opts,
);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => Ok(context::Output::wrap(ps)), 0 => Ok(context::Output::wrap(ps)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn output_as<P: AsRef<Path>>(path: &P, format: &str) -> Result<context::Output, Error> { pub fn output_as<P: AsRef<Path>>(path: &P, format: &str) -> Result<context::Output, Error> {
unsafe { unsafe {
let mut ps = ptr::null_mut(); let mut ps = ptr::null_mut();
let path = from_path(path); let path = from_path(path);
let format = CString::new(format).unwrap(); let format = CString::new(format).unwrap();
match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), format.as_ptr(), path.as_ptr()) { match avformat_alloc_output_context2(
0 => { &mut ps,
match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) { ptr::null_mut(),
0 => Ok(context::Output::wrap(ps)), format.as_ptr(),
e => Err(Error::from(e)) path.as_ptr(),
} ) {
} 0 => match avio_open(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE) {
0 => Ok(context::Output::wrap(ps)),
e => Err(Error::from(e)),
},
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }
pub fn output_as_with<P: AsRef<Path>>(path: &P, format: &str, options: Dictionary) -> Result<context::Output, Error> { pub fn output_as_with<P: AsRef<Path>>(
unsafe { path: &P,
let mut ps = ptr::null_mut(); format: &str,
let path = from_path(path); options: Dictionary,
let format = CString::new(format).unwrap(); ) -> Result<context::Output, Error> {
let mut opts = options.disown(); unsafe {
let mut ps = ptr::null_mut();
let path = from_path(path);
let format = CString::new(format).unwrap();
let mut opts = options.disown();
match avformat_alloc_output_context2(&mut ps, ptr::null_mut(), format.as_ptr(), path.as_ptr()) { match avformat_alloc_output_context2(
0 => { &mut ps,
let res = avio_open2(&mut (*ps).pb, path.as_ptr(), AVIO_FLAG_WRITE, ptr::null(), &mut opts,); ptr::null_mut(),
format.as_ptr(),
path.as_ptr(),
) {
0 => {
let res = avio_open2(
&mut (*ps).pb,
path.as_ptr(),
AVIO_FLAG_WRITE,
ptr::null(),
&mut opts,
);
Dictionary::own(opts); Dictionary::own(opts);
match res { match res {
0 => Ok(context::Output::wrap(ps)), 0 => Ok(context::Output::wrap(ps)),
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
e => Err(Error::from(e)) e => Err(Error::from(e)),
} }
} }
} }

View File

@ -1,13 +1,13 @@
use ffi::*; use ffi::*;
pub fn init() { pub fn init() {
unsafe { unsafe {
avformat_network_init(); avformat_network_init();
} }
} }
pub fn deinit() { pub fn deinit() {
unsafe { unsafe {
avformat_network_deinit(); avformat_network_deinit();
} }
} }

View File

@ -1,21 +1,21 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Disposition: c_int { pub struct Disposition: c_int {
const DEFAULT = AV_DISPOSITION_DEFAULT; const DEFAULT = AV_DISPOSITION_DEFAULT;
const DUB = AV_DISPOSITION_DUB; const DUB = AV_DISPOSITION_DUB;
const ORIGINAL = AV_DISPOSITION_ORIGINAL; const ORIGINAL = AV_DISPOSITION_ORIGINAL;
const COMMENT = AV_DISPOSITION_COMMENT; const COMMENT = AV_DISPOSITION_COMMENT;
const LYRICS = AV_DISPOSITION_LYRICS; const LYRICS = AV_DISPOSITION_LYRICS;
const KARAOKE = AV_DISPOSITION_KARAOKE; const KARAOKE = AV_DISPOSITION_KARAOKE;
const FORCED = AV_DISPOSITION_FORCED; const FORCED = AV_DISPOSITION_FORCED;
const HEARING_IMPAIRED = AV_DISPOSITION_HEARING_IMPAIRED; const HEARING_IMPAIRED = AV_DISPOSITION_HEARING_IMPAIRED;
const VISUAL_IMPAIRED = AV_DISPOSITION_VISUAL_IMPAIRED; const VISUAL_IMPAIRED = AV_DISPOSITION_VISUAL_IMPAIRED;
const CLEAN_EFFECTS = AV_DISPOSITION_CLEAN_EFFECTS; const CLEAN_EFFECTS = AV_DISPOSITION_CLEAN_EFFECTS;
const ATTACHED_PIC = AV_DISPOSITION_ATTACHED_PIC; const ATTACHED_PIC = AV_DISPOSITION_ATTACHED_PIC;
const CAPTIONS = AV_DISPOSITION_CAPTIONS; const CAPTIONS = AV_DISPOSITION_CAPTIONS;
const DESCRIPTIONS = AV_DISPOSITION_DESCRIPTIONS; const DESCRIPTIONS = AV_DISPOSITION_DESCRIPTIONS;
const METADATA = AV_DISPOSITION_METADATA; const METADATA = AV_DISPOSITION_METADATA;
} }
} }

View File

@ -1,153 +1,139 @@
use libc::c_int;
use ffi::*;
use ::codec::{self, packet};
use ::{Rational, Discard, DictionaryRef};
use super::Disposition; use super::Disposition;
use codec::{self, packet};
use ffi::*;
use format::context::common::Context; use format::context::common::Context;
use libc::c_int;
use {DictionaryRef, Discard, Rational};
pub struct Stream<'a> { pub struct Stream<'a> {
context: &'a Context, context: &'a Context,
index: usize, index: usize,
} }
impl<'a> Stream<'a> { impl<'a> Stream<'a> {
pub unsafe fn wrap(context: &Context, index: usize) -> Stream { pub unsafe fn wrap(context: &Context, index: usize) -> Stream {
Stream { context: context, index: index } Stream {
} context: context,
index: index,
}
}
pub unsafe fn as_ptr(&self) -> *const AVStream { pub unsafe fn as_ptr(&self) -> *const AVStream {
*(*self.context.as_ptr()).streams.offset(self.index as isize) *(*self.context.as_ptr()).streams.offset(self.index as isize)
} }
} }
impl<'a> Stream<'a> { impl<'a> Stream<'a> {
pub fn id(&self) -> i32 { pub fn id(&self) -> i32 {
unsafe { unsafe { (*self.as_ptr()).id }
i32::from((*self.as_ptr()).id) }
}
}
pub fn codec(&self) -> codec::Context { pub fn codec(&self) -> codec::Context {
unsafe { unsafe { codec::Context::wrap((*self.as_ptr()).codec, Some(self.context.destructor())) }
codec::Context::wrap((*self.as_ptr()).codec, Some(self.context.destructor())) }
}
}
pub fn parameters(&self) -> codec::Parameters { pub fn parameters(&self) -> codec::Parameters {
unsafe { unsafe {
codec::Parameters::wrap((*self.as_ptr()).codecpar, Some(self.context.destructor())) codec::Parameters::wrap((*self.as_ptr()).codecpar, Some(self.context.destructor()))
} }
} }
pub fn index(&self) -> usize { pub fn index(&self) -> usize {
unsafe { unsafe { (*self.as_ptr()).index as usize }
(*self.as_ptr()).index as usize }
}
}
pub fn time_base(&self) -> Rational { pub fn time_base(&self) -> Rational {
unsafe { unsafe { Rational::from((*self.as_ptr()).time_base) }
Rational::from((*self.as_ptr()).time_base) }
}
}
pub fn start_time(&self) -> i64 { pub fn start_time(&self) -> i64 {
unsafe { unsafe { (*self.as_ptr()).start_time }
(*self.as_ptr()).start_time }
}
}
pub fn duration(&self) -> i64 { pub fn duration(&self) -> i64 {
unsafe { unsafe { (*self.as_ptr()).duration }
(*self.as_ptr()).duration }
}
}
pub fn frames(&self) -> i64 { pub fn frames(&self) -> i64 {
unsafe { unsafe { (*self.as_ptr()).nb_frames }
(*self.as_ptr()).nb_frames }
}
}
pub fn disposition(&self) -> Disposition { pub fn disposition(&self) -> Disposition {
unsafe { unsafe { Disposition::from_bits_truncate((*self.as_ptr()).disposition) }
Disposition::from_bits_truncate((*self.as_ptr()).disposition) }
}
}
pub fn discard(&self) -> Discard { pub fn discard(&self) -> Discard {
unsafe { unsafe { Discard::from((*self.as_ptr()).discard) }
Discard::from((*self.as_ptr()).discard) }
}
}
pub fn side_data(&self) -> SideDataIter { pub fn side_data(&self) -> SideDataIter {
SideDataIter::new(self) SideDataIter::new(self)
} }
pub fn rate(&self) -> Rational { pub fn rate(&self) -> Rational {
unsafe { unsafe { Rational::from(av_stream_get_r_frame_rate(self.as_ptr())) }
Rational::from(av_stream_get_r_frame_rate(self.as_ptr())) }
}
}
pub fn avg_frame_rate(&self) -> Rational { pub fn avg_frame_rate(&self) -> Rational {
unsafe { unsafe { Rational::from((*self.as_ptr()).avg_frame_rate) }
Rational::from((*self.as_ptr()).avg_frame_rate) }
}
}
pub fn metadata(&self) -> DictionaryRef { pub fn metadata(&self) -> DictionaryRef {
unsafe { unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) }
DictionaryRef::wrap((*self.as_ptr()).metadata) }
}
}
} }
impl<'a> PartialEq for Stream<'a> { impl<'a> PartialEq for Stream<'a> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
unsafe { unsafe { self.as_ptr() == other.as_ptr() }
self.as_ptr() == other.as_ptr() }
}
}
} }
impl<'a> Eq for Stream<'a> { } impl<'a> Eq for Stream<'a> {}
pub struct SideDataIter<'a> { pub struct SideDataIter<'a> {
stream: &'a Stream<'a>, stream: &'a Stream<'a>,
current: c_int, current: c_int,
} }
impl<'a> SideDataIter<'a> { impl<'a> SideDataIter<'a> {
pub fn new<'sd, 's: 'sd>(stream: &'s Stream) -> SideDataIter<'sd> { pub fn new<'sd, 's: 'sd>(stream: &'s Stream) -> SideDataIter<'sd> {
SideDataIter { stream: stream, current: 0 } SideDataIter {
} stream: stream,
current: 0,
}
}
} }
impl<'a> Iterator for SideDataIter<'a> { impl<'a> Iterator for SideDataIter<'a> {
type Item = packet::SideData<'a>; type Item = packet::SideData<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> { fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe { unsafe {
if self.current >= (*self.stream.as_ptr()).nb_side_data { if self.current >= (*self.stream.as_ptr()).nb_side_data {
return None; return None;
} }
self.current += 1; self.current += 1;
Some(packet::SideData::wrap( Some(packet::SideData::wrap(
(*self.stream.as_ptr()).side_data.offset((self.current - 1) as isize))) (*self.stream.as_ptr())
} .side_data
} .offset((self.current - 1) as isize),
))
}
}
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
unsafe { unsafe {
let length = (*self.stream.as_ptr()).nb_side_data as usize; let length = (*self.stream.as_ptr()).nb_side_data as usize;
(length - self.current as usize, Some(length - self.current as usize)) (
} length - self.current as usize,
} Some(length - self.current as usize),
)
}
}
} }
impl<'a> ExactSizeIterator for SideDataIter<'a> { } impl<'a> ExactSizeIterator for SideDataIter<'a> {}

View File

@ -1,65 +1,67 @@
use std::ops::Deref;
use std::mem; use std::mem;
use std::ops::Deref;
use ffi::*;
use ::{Rational, codec};
use super::Stream; use super::Stream;
use ffi::*;
use format::context::common::Context; use format::context::common::Context;
use {codec, Rational};
pub struct StreamMut<'a> { pub struct StreamMut<'a> {
context: &'a mut Context, context: &'a mut Context,
index: usize, index: usize,
immutable: Stream<'a>, immutable: Stream<'a>,
} }
impl<'a> StreamMut<'a> { impl<'a> StreamMut<'a> {
pub unsafe fn wrap(context: &mut Context, index: usize) -> StreamMut { pub unsafe fn wrap(context: &mut Context, index: usize) -> StreamMut {
StreamMut { StreamMut {
context: mem::transmute_copy(&context), context: mem::transmute_copy(&context),
index: index, index: index,
immutable: Stream::wrap(mem::transmute_copy(&context), index) immutable: Stream::wrap(mem::transmute_copy(&context), index),
} }
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut AVStream { pub unsafe fn as_mut_ptr(&mut self) -> *mut AVStream {
*(*self.context.as_mut_ptr()).streams.offset(self.index as isize) *(*self.context.as_mut_ptr())
} .streams
.offset(self.index as isize)
}
} }
impl<'a> StreamMut<'a> { impl<'a> StreamMut<'a> {
pub fn set_time_base<R: Into<Rational>>(&mut self, value: R) { pub fn set_time_base<R: Into<Rational>>(&mut self, value: R) {
unsafe { unsafe {
(*self.as_mut_ptr()).time_base = value.into().into(); (*self.as_mut_ptr()).time_base = value.into().into();
} }
} }
pub fn set_rate<R: Into<Rational>>(&mut self, value: R) { pub fn set_rate<R: Into<Rational>>(&mut self, value: R) {
unsafe { unsafe {
av_stream_set_r_frame_rate(self.as_mut_ptr(), value.into().into()); av_stream_set_r_frame_rate(self.as_mut_ptr(), value.into().into());
} }
} }
pub fn set_avg_frame_rate<R: Into<Rational>>(&mut self, value: R) { pub fn set_avg_frame_rate<R: Into<Rational>>(&mut self, value: R) {
unsafe { unsafe {
(*self.as_mut_ptr()).avg_frame_rate = value.into().into(); (*self.as_mut_ptr()).avg_frame_rate = value.into().into();
} }
} }
pub fn set_parameters<P: Into<codec::Parameters>>(&mut self, parameters: P) { pub fn set_parameters<P: Into<codec::Parameters>>(&mut self, parameters: P) {
let parameters = parameters.into(); let parameters = parameters.into();
unsafe { unsafe {
avcodec_parameters_copy((*self.as_mut_ptr()).codecpar, parameters.as_ptr()); avcodec_parameters_copy((*self.as_mut_ptr()).codecpar, parameters.as_ptr());
} }
} }
} }
impl<'a> Deref for StreamMut<'a> { impl<'a> Deref for StreamMut<'a> {
type Target = Stream<'a>; type Target = Stream<'a>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.immutable &self.immutable
} }
} }

View File

@ -1,59 +1,62 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![cfg_attr(feature = "cargo-clippy", allow(inline_always))]
extern crate libc; #[macro_use]
extern crate bitflags;
pub extern crate ffmpeg_sys as sys; pub extern crate ffmpeg_sys as sys;
#[macro_use] extern crate bitflags; #[cfg(feature = "image")]
#[cfg(feature = "image")] extern crate image; extern crate image;
extern crate libc;
pub use sys as ffi; pub use sys as ffi;
#[macro_use] #[macro_use]
pub mod util; pub mod util;
pub use util::error::Error; pub use util::channel_layout::{self, ChannelLayout};
pub use util::chroma;
pub use util::color;
pub use util::dictionary; pub use util::dictionary;
pub use util::dictionary::Mut as DictionaryMut;
pub use util::dictionary::Owned as Dictionary; pub use util::dictionary::Owned as Dictionary;
pub use util::dictionary::Ref as DictionaryRef; pub use util::dictionary::Ref as DictionaryRef;
pub use util::dictionary::Mut as DictionaryMut; pub use util::error::Error;
pub use util::rational::{self, Rational};
pub use util::media;
pub use util::picture;
pub use util::color;
pub use util::chroma;
pub use util::time;
pub use util::frame::{self, Frame}; pub use util::frame::{self, Frame};
pub use util::channel_layout::{self, ChannelLayout}; pub use util::mathematics::{self, rescale, Rescale, Rounding};
pub use util::media;
pub use util::option; pub use util::option;
pub use util::mathematics::{self, Rounding, Rescale, rescale}; pub use util::picture;
pub use util::rational::{self, Rational};
pub use util::time;
#[cfg(feature = "format")] #[cfg(feature = "format")]
pub mod format; pub mod format;
#[cfg(feature = "format")] #[cfg(feature = "format")]
pub use format::chapter::{Chapter, ChapterMut};
#[cfg(feature = "format")]
pub use format::format::Format; pub use format::format::Format;
#[cfg(feature = "format")] #[cfg(feature = "format")]
pub use format::stream::{Stream, StreamMut}; pub use format::stream::{Stream, StreamMut};
#[cfg(feature = "format")]
pub use format::chapter::{Chapter, ChapterMut};
#[cfg(feature = "codec")] #[cfg(feature = "codec")]
pub mod codec; pub mod codec;
#[cfg(feature = "codec")] #[cfg(feature = "codec")]
pub use codec::packet::{self, Packet}; pub use codec::audio_service::AudioService;
#[cfg(feature = "codec")]
pub use codec::subtitle::{self, Subtitle};
#[cfg(feature = "codec")]
pub use codec::picture::Picture;
#[cfg(feature = "codec")]
pub use codec::discard::Discard;
#[cfg(feature = "codec")] #[cfg(feature = "codec")]
pub use codec::codec::Codec; pub use codec::codec::Codec;
#[cfg(feature = "codec")] #[cfg(feature = "codec")]
pub use codec::{decoder, encoder}; pub use codec::discard::Discard;
#[cfg(feature = "codec")] #[cfg(feature = "codec")]
pub use codec::field_order::FieldOrder; pub use codec::field_order::FieldOrder;
#[cfg(feature = "codec")] #[cfg(feature = "codec")]
pub use codec::audio_service::AudioService; pub use codec::packet::{self, Packet};
#[cfg(feature = "codec")]
pub use codec::picture::Picture;
#[cfg(feature = "codec")]
pub use codec::subtitle::{self, Subtitle};
#[cfg(feature = "codec")] #[cfg(feature = "codec")]
pub use codec::threading; pub use codec::threading;
#[cfg(feature = "codec")]
pub use codec::{decoder, encoder};
#[cfg(feature = "device")] #[cfg(feature = "device")]
pub mod device; pub mod device;
@ -66,38 +69,38 @@ pub use filter::Filter;
pub mod software; pub mod software;
fn init_error() { fn init_error() {
util::error::register_all(); util::error::register_all();
} }
#[cfg(feature = "format")] #[cfg(feature = "format")]
fn init_format() { fn init_format() {
format::register_all(); format::register_all();
} }
#[cfg(not(feature = "format"))] #[cfg(not(feature = "format"))]
fn init_format() { } fn init_format() {}
#[cfg(feature = "device")] #[cfg(feature = "device")]
fn init_device() { fn init_device() {
device::register_all(); device::register_all();
} }
#[cfg(not(feature = "device"))] #[cfg(not(feature = "device"))]
fn init_device() { } fn init_device() {}
#[cfg(feature = "filter")] #[cfg(feature = "filter")]
fn init_filter() { fn init_filter() {
filter::register_all(); filter::register_all();
} }
#[cfg(not(feature = "filter"))] #[cfg(not(feature = "filter"))]
fn init_filter() { } fn init_filter() {}
pub fn init() -> Result<(), Error> { pub fn init() -> Result<(), Error> {
init_error(); init_error();
init_format(); init_format();
init_device(); init_device();
init_filter(); init_filter();
Ok(()) Ok(())
} }

View File

@ -3,20 +3,33 @@ pub mod scaling;
#[cfg(feature = "software-scaling")] #[cfg(feature = "software-scaling")]
#[inline] #[inline]
pub fn scaler(format: ::format::Pixel, flags: scaling::Flags, pub fn scaler(
(in_width, in_height): (u32, u32), format: ::format::Pixel,
(out_width, out_height): (u32, u32)) flags: scaling::Flags,
-> Result<scaling::Context, ::Error> { (in_width, in_height): (u32, u32),
scaling::Context::get(format, in_width, in_height, format, out_width, out_height, flags) (out_width, out_height): (u32, u32),
) -> Result<scaling::Context, ::Error> {
scaling::Context::get(
format, in_width, in_height, format, out_width, out_height, flags,
)
} }
#[cfg(feature = "software-scaling")] #[cfg(feature = "software-scaling")]
#[inline] #[inline]
pub fn converter((width, height): (u32, u32), pub fn converter(
input: ::format::Pixel, (width, height): (u32, u32),
output: ::format::Pixel) input: ::format::Pixel,
-> Result<scaling::Context, ::Error> { output: ::format::Pixel,
scaling::Context::get(input, width, height, output, width, height, scaling::flag::FAST_BILINEAR) ) -> Result<scaling::Context, ::Error> {
scaling::Context::get(
input,
width,
height,
output,
width,
height,
scaling::flag::FAST_BILINEAR,
)
} }
#[cfg(feature = "software-resampling")] #[cfg(feature = "software-resampling")]
@ -24,8 +37,11 @@ pub mod resampling;
#[cfg(feature = "software-resampling")] #[cfg(feature = "software-resampling")]
#[inline] #[inline]
pub fn resampler((in_format, in_layout, in_rate): (::format::Sample, ::ChannelLayout, u32), pub fn resampler(
(out_format, out_layout, out_rate): (::format::Sample, ::ChannelLayout, u32)) (in_format, in_layout, in_rate): (::format::Sample, ::ChannelLayout, u32),
-> Result<resampling::Context, ::Error> { (out_format, out_layout, out_rate): (::format::Sample, ::ChannelLayout, u32),
resampling::Context::get(in_format, in_layout, in_rate, out_format, out_layout, out_rate) ) -> Result<resampling::Context, ::Error> {
resampling::Context::get(
in_format, in_layout, in_rate, out_format, out_layout, out_rate,
)
} }

View File

@ -1,139 +1,153 @@
use std::ptr; use std::ptr;
use libc::{c_int, int64_t};
use ffi::*;
use ::util::format;
use ::{Error, ChannelLayout, frame};
use super::Delay; use super::Delay;
use ffi::*;
use libc::{c_int, int64_t};
use util::format;
use {frame, ChannelLayout, Error};
#[derive(Eq, PartialEq, Copy, Clone)] #[derive(Eq, PartialEq, Copy, Clone)]
pub struct Definition { pub struct Definition {
pub format: format::Sample, pub format: format::Sample,
pub channel_layout: ChannelLayout, pub channel_layout: ChannelLayout,
pub rate: u32, pub rate: u32,
} }
pub struct Context { pub struct Context {
ptr: *mut SwrContext, ptr: *mut SwrContext,
input: Definition, input: Definition,
output: Definition, output: Definition,
} }
impl Context { impl Context {
#[doc(hidden)] #[doc(hidden)]
pub unsafe fn as_ptr(&self) -> *const SwrContext { pub unsafe fn as_ptr(&self) -> *const SwrContext {
self.ptr as *const _ self.ptr as *const _
} }
#[doc(hidden)] #[doc(hidden)]
pub unsafe fn as_mut_ptr(&mut self) -> *mut SwrContext { pub unsafe fn as_mut_ptr(&mut self) -> *mut SwrContext {
self.ptr self.ptr
} }
} }
impl Context { impl Context {
/// Create a resampler with the given definitions. /// Create a resampler with the given definitions.
pub fn get(src_format: format::Sample, src_channel_layout: ChannelLayout, src_rate: u32, pub fn get(
dst_format: format::Sample, dst_channel_layout: ChannelLayout, dst_rate: u32) -> Result<Self, Error> { src_format: format::Sample,
unsafe { src_channel_layout: ChannelLayout,
let ptr = swr_alloc_set_opts(ptr::null_mut(), src_rate: u32,
dst_channel_layout.bits() as int64_t, dst_format.into(), dst_rate as c_int, dst_format: format::Sample,
src_channel_layout.bits() as int64_t, src_format.into(), src_rate as c_int, dst_channel_layout: ChannelLayout,
0, ptr::null_mut()); dst_rate: u32,
) -> Result<Self, Error> {
unsafe {
let ptr = swr_alloc_set_opts(
ptr::null_mut(),
dst_channel_layout.bits() as int64_t,
dst_format.into(),
dst_rate as c_int,
src_channel_layout.bits() as int64_t,
src_format.into(),
src_rate as c_int,
0,
ptr::null_mut(),
);
if ptr != ptr::null_mut() { if ptr.is_null() {
match swr_init(ptr) { match swr_init(ptr) {
e if e < 0 => e if e < 0 => Err(Error::from(e)),
Err(Error::from(e)),
_ => _ => Ok(Context {
Ok(Context { ptr: ptr,
ptr: ptr,
input: Definition { input: Definition {
format: src_format, format: src_format,
channel_layout: src_channel_layout, channel_layout: src_channel_layout,
rate: src_rate, rate: src_rate,
}, },
output: Definition { output: Definition {
format: dst_format, format: dst_format,
channel_layout: dst_channel_layout, channel_layout: dst_channel_layout,
rate: dst_rate, rate: dst_rate,
} },
}) }),
} }
} } else {
else { Err(Error::InvalidData)
Err(Error::InvalidData) }
} }
} }
}
/// Get the input definition. /// Get the input definition.
pub fn input(&self) -> &Definition { pub fn input(&self) -> &Definition {
&self.input &self.input
} }
/// Get the output definition. /// Get the output definition.
pub fn output(&self) -> &Definition { pub fn output(&self) -> &Definition {
&self.output &self.output
} }
/// Get the remaining delay. /// Get the remaining delay.
pub fn delay(&self) -> Option<Delay> { pub fn delay(&self) -> Option<Delay> {
unsafe { unsafe {
match swr_get_delay(self.as_ptr() as *mut _, 1) { match swr_get_delay(self.as_ptr() as *mut _, 1) {
0 => None, 0 => None,
_ => Some(Delay::from(self)) _ => Some(Delay::from(self)),
} }
} }
} }
/// Run the resampler from the given input to the given output. /// Run the resampler from the given input to the given output.
/// ///
/// When there are internal frames to process it will return `Ok(Some(Delay { .. }))`. /// When there are internal frames to process it will return `Ok(Some(Delay { .. }))`.
pub fn run(&mut self, input: &frame::Audio, output: &mut frame::Audio) -> Result<Option<Delay>, Error> { pub fn run(
output.set_rate(self.output.rate); &mut self,
input: &frame::Audio,
output: &mut frame::Audio,
) -> Result<Option<Delay>, Error> {
output.set_rate(self.output.rate);
unsafe { unsafe {
if output.is_empty() { if output.is_empty() {
output.alloc(self.output.format, input.samples(), self.output.channel_layout); output.alloc(
} self.output.format,
input.samples(),
self.output.channel_layout,
);
}
match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), input.as_ptr()) { match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), input.as_ptr()) {
0 => 0 => Ok(self.delay()),
Ok(self.delay()),
e => e => Err(Error::from(e)),
Err(Error::from(e)) }
} }
} }
}
/// Convert one of the remaining internal frames. /// Convert one of the remaining internal frames.
/// ///
/// When there are no more internal frames `Ok(None)` will be returned. /// When there are no more internal frames `Ok(None)` will be returned.
pub fn flush(&mut self, output: &mut frame::Audio) -> Result<Option<Delay>, Error> { pub fn flush(&mut self, output: &mut frame::Audio) -> Result<Option<Delay>, Error> {
output.set_rate(self.output.rate); output.set_rate(self.output.rate);
unsafe { unsafe {
match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), ptr::null()) { match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), ptr::null()) {
0 => 0 => Ok(self.delay()),
Ok(self.delay()),
e => e => Err(Error::from(e)),
Err(Error::from(e)) }
} }
} }
}
} }
impl Drop for Context { impl Drop for Context {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
swr_free(&mut self.as_mut_ptr()); swr_free(&mut self.as_mut_ptr());
} }
} }
} }

View File

@ -1,24 +1,23 @@
use libc::int64_t;
use ffi::*;
use super::Context; use super::Context;
use ffi::*;
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct Delay { pub struct Delay {
pub seconds: i64, pub seconds: i64,
pub milliseconds: i64, pub milliseconds: i64,
pub input: i64, pub input: i64,
pub output: i64, pub output: i64,
} }
impl Delay { impl Delay {
pub fn from(context: &Context) -> Self { pub fn from(context: &Context) -> Self {
unsafe { unsafe {
Delay { Delay {
seconds: swr_get_delay(context.as_ptr() as *mut _, 1), seconds: swr_get_delay(context.as_ptr() as *mut _, 1),
milliseconds: swr_get_delay(context.as_ptr() as *mut _, 1000), milliseconds: swr_get_delay(context.as_ptr() as *mut _, 1000),
input: swr_get_delay(context.as_ptr() as *mut _, context.input().rate as int64_t), input: swr_get_delay(context.as_ptr() as *mut _, i64::from(context.input().rate)),
output: swr_get_delay(context.as_ptr() as *mut _, context.output().rate as int64_t), output: swr_get_delay(context.as_ptr() as *mut _, i64::from(context.output().rate)),
} }
} }
} }
} }

View File

@ -1,58 +1,58 @@
use ffi::*;
use ffi::SwrDitherType::*; use ffi::SwrDitherType::*;
use ffi::*;
#[derive(Eq, PartialEq, Copy, Clone, Debug)] #[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Dither { pub enum Dither {
None, None,
Rectangular, Rectangular,
Triangular, Triangular,
TriangularHighPass, TriangularHighPass,
NoiseShapingLipshitz, NoiseShapingLipshitz,
NoiseShapingFWeighted, NoiseShapingFWeighted,
NoiseShapingModifiedEWeighted, NoiseShapingModifiedEWeighted,
NoiseShapingImprovedEWeighted, NoiseShapingImprovedEWeighted,
NoiseShapingShibata, NoiseShapingShibata,
NoiseShapingLowShibata, NoiseShapingLowShibata,
NoiseShapingHighShibata, NoiseShapingHighShibata,
} }
impl From<SwrDitherType> for Dither { impl From<SwrDitherType> for Dither {
fn from(value: SwrDitherType) -> Dither { fn from(value: SwrDitherType) -> Dither {
match value { match value {
SWR_DITHER_NONE => Dither::None, SWR_DITHER_NONE => Dither::None,
SWR_DITHER_RECTANGULAR => Dither::Rectangular, SWR_DITHER_RECTANGULAR => Dither::Rectangular,
SWR_DITHER_TRIANGULAR => Dither::Triangular, SWR_DITHER_TRIANGULAR => Dither::Triangular,
SWR_DITHER_TRIANGULAR_HIGHPASS => Dither::TriangularHighPass, SWR_DITHER_TRIANGULAR_HIGHPASS => Dither::TriangularHighPass,
SWR_DITHER_NS => Dither::None, SWR_DITHER_NS => Dither::None,
SWR_DITHER_NS_LIPSHITZ => Dither::NoiseShapingLipshitz, SWR_DITHER_NS_LIPSHITZ => Dither::NoiseShapingLipshitz,
SWR_DITHER_NS_F_WEIGHTED => Dither::NoiseShapingFWeighted, SWR_DITHER_NS_F_WEIGHTED => Dither::NoiseShapingFWeighted,
SWR_DITHER_NS_MODIFIED_E_WEIGHTED => Dither::NoiseShapingModifiedEWeighted, SWR_DITHER_NS_MODIFIED_E_WEIGHTED => Dither::NoiseShapingModifiedEWeighted,
SWR_DITHER_NS_IMPROVED_E_WEIGHTED => Dither::NoiseShapingImprovedEWeighted, SWR_DITHER_NS_IMPROVED_E_WEIGHTED => Dither::NoiseShapingImprovedEWeighted,
SWR_DITHER_NS_SHIBATA => Dither::NoiseShapingShibata, SWR_DITHER_NS_SHIBATA => Dither::NoiseShapingShibata,
SWR_DITHER_NS_LOW_SHIBATA => Dither::NoiseShapingLowShibata, SWR_DITHER_NS_LOW_SHIBATA => Dither::NoiseShapingLowShibata,
SWR_DITHER_NS_HIGH_SHIBATA => Dither::NoiseShapingHighShibata, SWR_DITHER_NS_HIGH_SHIBATA => Dither::NoiseShapingHighShibata,
SWR_DITHER_NB => Dither::None, SWR_DITHER_NB => Dither::None,
} }
} }
} }
impl Into<SwrDitherType> for Dither { impl Into<SwrDitherType> for Dither {
fn into(self) -> SwrDitherType { fn into(self) -> SwrDitherType {
match self { match self {
Dither::None => SWR_DITHER_NONE, Dither::None => SWR_DITHER_NONE,
Dither::Rectangular => SWR_DITHER_RECTANGULAR, Dither::Rectangular => SWR_DITHER_RECTANGULAR,
Dither::Triangular => SWR_DITHER_TRIANGULAR, Dither::Triangular => SWR_DITHER_TRIANGULAR,
Dither::TriangularHighPass => SWR_DITHER_TRIANGULAR_HIGHPASS, Dither::TriangularHighPass => SWR_DITHER_TRIANGULAR_HIGHPASS,
Dither::NoiseShapingLipshitz => SWR_DITHER_NS_LIPSHITZ, Dither::NoiseShapingLipshitz => SWR_DITHER_NS_LIPSHITZ,
Dither::NoiseShapingFWeighted => SWR_DITHER_NS_F_WEIGHTED, Dither::NoiseShapingFWeighted => SWR_DITHER_NS_F_WEIGHTED,
Dither::NoiseShapingModifiedEWeighted => SWR_DITHER_NS_MODIFIED_E_WEIGHTED, Dither::NoiseShapingModifiedEWeighted => SWR_DITHER_NS_MODIFIED_E_WEIGHTED,
Dither::NoiseShapingImprovedEWeighted => SWR_DITHER_NS_IMPROVED_E_WEIGHTED, Dither::NoiseShapingImprovedEWeighted => SWR_DITHER_NS_IMPROVED_E_WEIGHTED,
Dither::NoiseShapingShibata => SWR_DITHER_NS_SHIBATA, Dither::NoiseShapingShibata => SWR_DITHER_NS_SHIBATA,
Dither::NoiseShapingLowShibata => SWR_DITHER_NS_LOW_SHIBATA, Dither::NoiseShapingLowShibata => SWR_DITHER_NS_LOW_SHIBATA,
Dither::NoiseShapingHighShibata => SWR_DITHER_NS_HIGH_SHIBATA, Dither::NoiseShapingHighShibata => SWR_DITHER_NS_HIGH_SHIBATA,
} }
} }
} }

View File

@ -3,25 +3,25 @@ use sys::SwrEngine::*;
#[derive(Eq, PartialEq, Copy, Clone, Debug)] #[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Engine { pub enum Engine {
Software, Software,
SoundExchange, SoundExchange,
} }
impl From<SwrEngine> for Engine { impl From<SwrEngine> for Engine {
fn from(value: SwrEngine) -> Engine { fn from(value: SwrEngine) -> Engine {
match value { match value {
SWR_ENGINE_SWR => Engine::Software, SWR_ENGINE_SWR => Engine::Software,
SWR_ENGINE_SOXR => Engine::SoundExchange, SWR_ENGINE_SOXR => Engine::SoundExchange,
SWR_ENGINE_NB => Engine::Software, SWR_ENGINE_NB => Engine::Software,
} }
} }
} }
impl Into<SwrEngine> for Engine { impl Into<SwrEngine> for Engine {
fn into(self) -> SwrEngine { fn into(self) -> SwrEngine {
match self { match self {
Engine::Software => SWR_ENGINE_SWR, Engine::Software => SWR_ENGINE_SWR,
Engine::SoundExchange => SWR_ENGINE_SOXR, Engine::SoundExchange => SWR_ENGINE_SOXR,
} }
} }
} }

View File

@ -1,19 +1,41 @@
use util::format;
use ::{decoder, Error, ChannelLayout, frame};
use super::Context; use super::Context;
use util::format;
use {decoder, frame, ChannelLayout, Error};
impl frame::Audio { impl frame::Audio {
#[inline] #[inline]
pub fn resampler(&self, format: format::Sample, channel_layout: ChannelLayout, rate: u32) -> Result<Context, Error> { pub fn resampler(
Context::get(self.format(), self.channel_layout(), self.rate(), &self,
format, channel_layout, rate) format: format::Sample,
} channel_layout: ChannelLayout,
rate: u32,
) -> Result<Context, Error> {
Context::get(
self.format(),
self.channel_layout(),
self.rate(),
format,
channel_layout,
rate,
)
}
} }
impl decoder::Audio { impl decoder::Audio {
#[inline] #[inline]
pub fn resampler(&self, format: format::Sample, channel_layout: ChannelLayout, rate: u32) -> Result<Context, Error> { pub fn resampler(
Context::get(self.format(), self.channel_layout(), self.rate(), &self,
format, channel_layout, rate) format: format::Sample,
} channel_layout: ChannelLayout,
rate: u32,
) -> Result<Context, Error> {
Context::get(
self.format(),
self.channel_layout(),
self.rate(),
format,
channel_layout,
rate,
)
}
} }

View File

@ -1,29 +1,29 @@
use ffi::*;
use ffi::SwrFilterType::*; use ffi::SwrFilterType::*;
use ffi::*;
#[derive(Eq, PartialEq, Copy, Clone, Debug)] #[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Filter { pub enum Filter {
Cubic, Cubic,
BlackmanNuttall, BlackmanNuttall,
Kaiser, Kaiser,
} }
impl From<SwrFilterType> for Filter { impl From<SwrFilterType> for Filter {
fn from(value: SwrFilterType) -> Filter { fn from(value: SwrFilterType) -> Filter {
match value { match value {
SWR_FILTER_TYPE_CUBIC => Filter::Cubic, SWR_FILTER_TYPE_CUBIC => Filter::Cubic,
SWR_FILTER_TYPE_BLACKMAN_NUTTALL => Filter::BlackmanNuttall, SWR_FILTER_TYPE_BLACKMAN_NUTTALL => Filter::BlackmanNuttall,
SWR_FILTER_TYPE_KAISER => Filter::Kaiser, SWR_FILTER_TYPE_KAISER => Filter::Kaiser,
} }
} }
} }
impl Into<SwrFilterType> for Filter { impl Into<SwrFilterType> for Filter {
fn into(self) -> SwrFilterType { fn into(self) -> SwrFilterType {
match self { match self {
Filter::Cubic => SWR_FILTER_TYPE_CUBIC, Filter::Cubic => SWR_FILTER_TYPE_CUBIC,
Filter::BlackmanNuttall => SWR_FILTER_TYPE_BLACKMAN_NUTTALL, Filter::BlackmanNuttall => SWR_FILTER_TYPE_BLACKMAN_NUTTALL,
Filter::Kaiser => SWR_FILTER_TYPE_KAISER, Filter::Kaiser => SWR_FILTER_TYPE_KAISER,
} }
} }
} }

View File

@ -1,8 +1,8 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Flags: c_int { pub struct Flags: c_int {
const FORCE = SWR_FLAG_RESAMPLE; const FORCE = SWR_FLAG_RESAMPLE;
} }
} }

View File

@ -24,19 +24,13 @@ use std::str::from_utf8_unchecked;
use ffi::*; use ffi::*;
pub fn version() -> u32 { pub fn version() -> u32 {
unsafe { unsafe { swresample_version() }
swresample_version()
}
} }
pub fn configuration() -> &'static str { pub fn configuration() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(swresample_configuration()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(swresample_configuration()).to_bytes())
}
} }
pub fn license() -> &'static str { pub fn license() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(swresample_license()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(swresample_license()).to_bytes())
}
} }

View File

@ -1,41 +1,41 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
#[derive(Eq, PartialEq, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum ColorSpace { pub enum ColorSpace {
Default, Default,
ITU709, ITU709,
FCC, FCC,
ITU601, ITU601,
ITU624, ITU624,
SMPTE170M, SMPTE170M,
SMPTE240M, SMPTE240M,
} }
impl From<c_int> for ColorSpace { impl From<c_int> for ColorSpace {
fn from(value: c_int) -> ColorSpace { fn from(value: c_int) -> ColorSpace {
match value { match value {
SWS_CS_ITU709 => ColorSpace::ITU709, SWS_CS_ITU709 => ColorSpace::ITU709,
SWS_CS_FCC => ColorSpace::FCC, SWS_CS_FCC => ColorSpace::FCC,
SWS_CS_DEFAULT => ColorSpace::Default, SWS_CS_DEFAULT => ColorSpace::Default,
SWS_CS_SMPTE240M => ColorSpace::SMPTE240M, SWS_CS_SMPTE240M => ColorSpace::SMPTE240M,
_ => ColorSpace::Default _ => ColorSpace::Default,
} }
} }
} }
impl Into<c_int> for ColorSpace { impl Into<c_int> for ColorSpace {
fn into(self) -> c_int { fn into(self) -> c_int {
match self { match self {
ColorSpace::Default => SWS_CS_DEFAULT, ColorSpace::Default => SWS_CS_DEFAULT,
ColorSpace::ITU709 => SWS_CS_ITU709, ColorSpace::ITU709 => SWS_CS_ITU709,
ColorSpace::FCC => SWS_CS_FCC, ColorSpace::FCC => SWS_CS_FCC,
ColorSpace::ITU601 => SWS_CS_ITU601, ColorSpace::ITU601 => SWS_CS_ITU601,
ColorSpace::ITU624 => SWS_CS_ITU624, ColorSpace::ITU624 => SWS_CS_ITU624,
ColorSpace::SMPTE170M => SWS_CS_SMPTE170M, ColorSpace::SMPTE170M => SWS_CS_SMPTE170M,
ColorSpace::SMPTE240M => SWS_CS_SMPTE240M ColorSpace::SMPTE240M => SWS_CS_SMPTE240M,
} }
} }
} }

View File

@ -1,135 +1,171 @@
use std::ptr; use std::ptr;
use libc::{c_int};
use ffi::*;
use ::{Error, frame};
use ::util::format;
use super::Flags; use super::Flags;
use ffi::*;
use libc::c_int;
use util::format;
use {frame, Error};
#[derive(Eq, PartialEq, Copy, Clone, Debug)] #[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct Definition { pub struct Definition {
pub format: format::Pixel, pub format: format::Pixel,
pub width: u32, pub width: u32,
pub height: u32, pub height: u32,
} }
pub struct Context { pub struct Context {
ptr: *mut SwsContext, ptr: *mut SwsContext,
input: Definition, input: Definition,
output: Definition, output: Definition,
} }
impl Context { impl Context {
#[inline(always)] #[inline(always)]
pub unsafe fn as_ptr(&self) -> *const SwsContext { pub unsafe fn as_ptr(&self) -> *const SwsContext {
self.ptr as *const _ self.ptr as *const _
} }
#[inline(always)] #[inline(always)]
pub unsafe fn as_mut_ptr(&mut self) -> *mut SwsContext { pub unsafe fn as_mut_ptr(&mut self) -> *mut SwsContext {
self.ptr self.ptr
} }
} }
impl Context { impl Context {
pub fn get(src_format: format::Pixel, src_w: u32, src_h: u32, pub fn get(
dst_format: format::Pixel, dst_w: u32, dst_h: u32, src_format: format::Pixel,
flags: Flags) -> Result<Self, Error> { src_w: u32,
unsafe { src_h: u32,
let ptr = sws_getContext( dst_format: format::Pixel,
src_w as c_int, src_h as c_int, src_format.into(), dst_w: u32,
dst_w as c_int, dst_h as c_int, dst_format.into(), dst_h: u32,
flags.bits(), flags: Flags,
ptr::null_mut(), ptr::null_mut(), ptr::null_mut()); ) -> Result<Self, Error> {
unsafe {
let ptr = sws_getContext(
src_w as c_int,
src_h as c_int,
src_format.into(),
dst_w as c_int,
dst_h as c_int,
dst_format.into(),
flags.bits(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
);
if ptr != ptr::null_mut() { if ptr.is_null() {
Ok(Context { Ok(Context {
ptr: ptr, ptr: ptr,
input: Definition { input: Definition {
format: src_format, format: src_format,
width: src_w, width: src_w,
height: src_h, height: src_h,
}, },
output: Definition { output: Definition {
format: dst_format, format: dst_format,
width: dst_w, width: dst_w,
height: dst_h, height: dst_h,
}, },
}) })
} } else {
else { Err(Error::InvalidData)
Err(Error::InvalidData) }
} }
} }
}
pub fn cached(&mut self, pub fn cached(
src_format: format::Pixel, src_w: u32, src_h: u32, &mut self,
dst_format: format::Pixel, dst_w: u32, dst_h: u32, src_format: format::Pixel,
flags: Flags) { src_w: u32,
self.input = Definition { src_h: u32,
format: src_format, dst_format: format::Pixel,
width: src_w, dst_w: u32,
height: src_h, dst_h: u32,
}; flags: Flags,
) {
self.input = Definition {
format: src_format,
width: src_w,
height: src_h,
};
self.output = Definition { self.output = Definition {
format: dst_format, format: dst_format,
width: dst_w, width: dst_w,
height: dst_h, height: dst_h,
}; };
unsafe { unsafe {
self.ptr = sws_getCachedContext(self.as_mut_ptr(), self.ptr = sws_getCachedContext(
src_w as c_int, src_h as c_int, src_format.into(), self.as_mut_ptr(),
dst_w as c_int, dst_h as c_int, dst_format.into(), src_w as c_int,
flags.bits(), ptr::null_mut(), ptr::null_mut(), ptr::null()); src_h as c_int,
} src_format.into(),
} dst_w as c_int,
dst_h as c_int,
dst_format.into(),
flags.bits(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null(),
);
}
}
#[inline] #[inline]
pub fn input(&self) -> &Definition { pub fn input(&self) -> &Definition {
&self.input &self.input
} }
#[inline] #[inline]
pub fn output(&self) -> &Definition { pub fn output(&self) -> &Definition {
&self.output &self.output
} }
pub fn run(&mut self, input: &frame::Video, output: &mut frame::Video) -> Result<(), Error> { pub fn run(&mut self, input: &frame::Video, output: &mut frame::Video) -> Result<(), Error> {
if input.format() != self.input.format || input.width() != self.input.width || input.height() != self.input.height { if input.format() != self.input.format || input.width() != self.input.width
return Err(Error::InputChanged); || input.height() != self.input.height
} {
return Err(Error::InputChanged);
}
unsafe { unsafe {
if output.is_empty() { if output.is_empty() {
output.alloc(self.output.format, self.output.width, self.output.height); output.alloc(self.output.format, self.output.width, self.output.height);
} }
} }
if output.format() != self.output.format || output.width() != self.output.width || output.height() != self.output.height { if output.format() != self.output.format || output.width() != self.output.width
return Err(Error::OutputChanged); || output.height() != self.output.height
} {
return Err(Error::OutputChanged);
}
unsafe { unsafe {
sws_scale(self.as_mut_ptr(), sws_scale(
(*input.as_ptr()).data.as_ptr() as *const *const _, (*input.as_ptr()).linesize.as_ptr() as *const _, self.as_mut_ptr(),
0, self.output.height as c_int, (*input.as_ptr()).data.as_ptr() as *const *const _,
(*output.as_mut_ptr()).data.as_ptr() as *const *const _, (*output.as_mut_ptr()).linesize.as_ptr() as *mut _); (*input.as_ptr()).linesize.as_ptr() as *const _,
} 0,
self.output.height as c_int,
(*output.as_mut_ptr()).data.as_ptr() as *const *const _,
(*output.as_mut_ptr()).linesize.as_ptr() as *mut _,
);
}
Ok(()) Ok(())
} }
} }
impl Drop for Context { impl Drop for Context {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
sws_freeContext(self.as_mut_ptr()); sws_freeContext(self.as_mut_ptr());
} }
} }
} }

View File

@ -1,52 +1,87 @@
use super::{flag, Context, Flags};
use util::format; use util::format;
use ::{Picture, decoder, Error, frame}; use {decoder, frame, Error, Picture};
use super::{Context, Flags, flag};
impl<'a> Picture<'a> { impl<'a> Picture<'a> {
#[inline] #[inline]
pub fn scaler(&self, width: u32, height: u32, flags: Flags) -> Result<Context, Error> { pub fn scaler(&self, width: u32, height: u32, flags: Flags) -> Result<Context, Error> {
Context::get(self.format(), self.width(), self.height(), Context::get(
self.format(), width, height, self.format(),
flags) self.width(),
} self.height(),
self.format(),
width,
height,
flags,
)
}
#[inline] #[inline]
pub fn converter(&self, format: format::Pixel) -> Result<Context, Error> { pub fn converter(&self, format: format::Pixel) -> Result<Context, Error> {
Context::get(self.format(), self.width(), self.height(), Context::get(
format, self.width(), self.height(), self.format(),
flag::FAST_BILINEAR) self.width(),
} self.height(),
format,
self.width(),
self.height(),
flag::FAST_BILINEAR,
)
}
} }
impl frame::Video { impl frame::Video {
#[inline] #[inline]
pub fn scaler(&self, width: u32, height: u32, flags: Flags) -> Result<Context, Error> { pub fn scaler(&self, width: u32, height: u32, flags: Flags) -> Result<Context, Error> {
Context::get(self.format(), self.width(), self.height(), Context::get(
self.format(), width, height, self.format(),
flags) self.width(),
} self.height(),
self.format(),
width,
height,
flags,
)
}
#[inline] #[inline]
pub fn converter(&self, format: format::Pixel) -> Result<Context, Error> { pub fn converter(&self, format: format::Pixel) -> Result<Context, Error> {
Context::get(self.format(), self.width(), self.height(), Context::get(
format, self.width(), self.height(), self.format(),
flag::FAST_BILINEAR) self.width(),
} self.height(),
format,
self.width(),
self.height(),
flag::FAST_BILINEAR,
)
}
} }
impl decoder::Video { impl decoder::Video {
#[inline] #[inline]
pub fn scaler(&self, width: u32, height: u32, flags: Flags) -> Result<Context, Error> { pub fn scaler(&self, width: u32, height: u32, flags: Flags) -> Result<Context, Error> {
Context::get(self.format(), self.width(), self.height(), Context::get(
self.format(), width, height, self.format(),
flags) self.width(),
} self.height(),
self.format(),
width,
height,
flags,
)
}
#[inline] #[inline]
pub fn converter(&self, format: format::Pixel) -> Result<Context, Error> { pub fn converter(&self, format: format::Pixel) -> Result<Context, Error> {
Context::get(self.format(), self.width(), self.height(), Context::get(
format, self.width(), self.height(), self.format(),
flag::FAST_BILINEAR) self.width(),
} self.height(),
format,
self.width(),
self.height(),
flag::FAST_BILINEAR,
)
}
} }

View File

@ -1,90 +1,91 @@
use ffi::*;
use super::Vector; use super::Vector;
use ffi::*;
pub struct Filter { pub struct Filter {
ptr: *mut SwsFilter, ptr: *mut SwsFilter,
} }
impl Filter { impl Filter {
pub unsafe fn as_ptr(&self) -> *const SwsFilter { pub unsafe fn as_ptr(&self) -> *const SwsFilter {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut SwsFilter { pub unsafe fn as_mut_ptr(&mut self) -> *mut SwsFilter {
self.ptr self.ptr
} }
} }
impl Filter { impl Filter {
pub fn get(luma_g_blur: f32, chroma_g_blur: f32, pub fn get(
luma_sharpen: f32, chroma_sharpen: f32, luma_g_blur: f32,
chroma_h_shift: f32, chroma_v_shift: f32) -> Self { chroma_g_blur: f32,
unsafe { luma_sharpen: f32,
Filter { chroma_sharpen: f32,
ptr: sws_getDefaultFilter(luma_g_blur, chroma_g_blur, chroma_h_shift: f32,
luma_sharpen, chroma_sharpen, chroma_v_shift: f32,
chroma_h_shift, chroma_v_shift, 0) ) -> Self {
} unsafe {
} Filter {
} ptr: sws_getDefaultFilter(
luma_g_blur,
chroma_g_blur,
luma_sharpen,
chroma_sharpen,
chroma_h_shift,
chroma_v_shift,
0,
),
}
}
}
pub fn new() -> Self { pub fn new() -> Self {
Self::get(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) Self::get(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
} }
pub fn luma_horizontal(&self) -> Vector { pub fn luma_horizontal(&self) -> Vector {
unsafe { unsafe { Vector::wrap((*self.as_ptr()).lumH) }
Vector::wrap((*self.as_ptr()).lumH) }
}
}
pub fn luma_horizontal_mut(&mut self) -> Vector {
unsafe {
Vector::wrap((*self.as_mut_ptr()).lumH)
}
}
pub fn luma_vertical(&self) -> Vector { pub fn luma_horizontal_mut(&mut self) -> Vector {
unsafe { unsafe { Vector::wrap((*self.as_mut_ptr()).lumH) }
Vector::wrap((*self.as_ptr()).lumV) }
}
}
pub fn luma_vertical_mut(&mut self) -> Vector {
unsafe {
Vector::wrap((*self.as_mut_ptr()).lumV)
}
}
pub fn chroma_horizontal(&self) -> Vector { pub fn luma_vertical(&self) -> Vector {
unsafe { unsafe { Vector::wrap((*self.as_ptr()).lumV) }
Vector::wrap((*self.as_ptr()).lumV) }
}
}
pub fn chroma_horizontal_mut(&mut self) -> Vector {
unsafe {
Vector::wrap((*self.as_mut_ptr()).lumV)
}
}
pub fn chroma_vertical(&self) -> Vector { pub fn luma_vertical_mut(&mut self) -> Vector {
unsafe { unsafe { Vector::wrap((*self.as_mut_ptr()).lumV) }
Vector::wrap((*self.as_ptr()).lumV) }
}
} pub fn chroma_horizontal(&self) -> Vector {
unsafe { Vector::wrap((*self.as_ptr()).lumV) }
pub fn chroma_vertical_mut(&mut self) -> Vector { }
unsafe {
Vector::wrap((*self.as_mut_ptr()).lumV) pub fn chroma_horizontal_mut(&mut self) -> Vector {
} unsafe { Vector::wrap((*self.as_mut_ptr()).lumV) }
} }
pub fn chroma_vertical(&self) -> Vector {
unsafe { Vector::wrap((*self.as_ptr()).lumV) }
}
pub fn chroma_vertical_mut(&mut self) -> Vector {
unsafe { Vector::wrap((*self.as_mut_ptr()).lumV) }
}
}
impl Default for Filter {
fn default() -> Self {
Self::new()
}
} }
impl Drop for Filter { impl Drop for Filter {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
sws_freeFilter(self.as_mut_ptr()); sws_freeFilter(self.as_mut_ptr());
} }
} }
} }

View File

@ -1,28 +1,28 @@
use libc::c_int;
use ffi::*; use ffi::*;
use libc::c_int;
bitflags! { bitflags! {
pub struct Flags: c_int { pub struct Flags: c_int {
const FAST_BILINEAR = SWS_FAST_BILINEAR; const FAST_BILINEAR = SWS_FAST_BILINEAR;
const BILINEAR = SWS_BILINEAR; const BILINEAR = SWS_BILINEAR;
const BICUBIC = SWS_BICUBIC; const BICUBIC = SWS_BICUBIC;
const X = SWS_X; const X = SWS_X;
const POINT = SWS_POINT; const POINT = SWS_POINT;
const AREA = SWS_AREA; const AREA = SWS_AREA;
const BICUBLIN = SWS_BICUBLIN; const BICUBLIN = SWS_BICUBLIN;
const GAUSS = SWS_GAUSS; const GAUSS = SWS_GAUSS;
const SINC = SWS_SINC; const SINC = SWS_SINC;
const LANCZOS = SWS_LANCZOS; const LANCZOS = SWS_LANCZOS;
const SPLINE = SWS_SPLINE; const SPLINE = SWS_SPLINE;
const SRC_V_CHR_DROP_MASK = SWS_SRC_V_CHR_DROP_MASK; const SRC_V_CHR_DROP_MASK = SWS_SRC_V_CHR_DROP_MASK;
const SRC_V_CHR_DROP_SHIFT = SWS_SRC_V_CHR_DROP_SHIFT; const SRC_V_CHR_DROP_SHIFT = SWS_SRC_V_CHR_DROP_SHIFT;
const PARAM_DEFAULT = SWS_PARAM_DEFAULT; const PARAM_DEFAULT = SWS_PARAM_DEFAULT;
const PRINT_INFO = SWS_PRINT_INFO; const PRINT_INFO = SWS_PRINT_INFO;
const FULL_CHR_H_INT = SWS_FULL_CHR_H_INT; const FULL_CHR_H_INT = SWS_FULL_CHR_H_INT;
const FULL_CHR_H_INP = SWS_FULL_CHR_H_INP; const FULL_CHR_H_INP = SWS_FULL_CHR_H_INP;
const DIRECT_BGR = SWS_DIRECT_BGR; const DIRECT_BGR = SWS_DIRECT_BGR;
const ACCURATE_RND = SWS_ACCURATE_RND; const ACCURATE_RND = SWS_ACCURATE_RND;
const BITEXACT = SWS_BITEXACT; const BITEXACT = SWS_BITEXACT;
const ERROR_DIFFUSION = SWS_ERROR_DIFFUSION; const ERROR_DIFFUSION = SWS_ERROR_DIFFUSION;
} }
} }

View File

@ -23,19 +23,13 @@ use std::str::from_utf8_unchecked;
use ffi::*; use ffi::*;
pub fn version() -> u32 { pub fn version() -> u32 {
unsafe { unsafe { swscale_version() }
swscale_version()
}
} }
pub fn configuration() -> &'static str { pub fn configuration() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(swscale_configuration()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(swscale_configuration()).to_bytes())
}
} }
pub fn license() -> &'static str { pub fn license() -> &'static str {
unsafe { unsafe { from_utf8_unchecked(CStr::from_ptr(swscale_license()).to_bytes()) }
from_utf8_unchecked(CStr::from_ptr(swscale_license()).to_bytes())
}
} }

View File

@ -1,20 +1,14 @@
use ffi::*; use ffi::*;
use ::util::format; use util::format;
pub fn input(format: format::Pixel) -> bool { pub fn input(format: format::Pixel) -> bool {
unsafe { unsafe { sws_isSupportedInput(format.into()) != 0 }
sws_isSupportedInput(format.into()) != 0
}
} }
pub fn output(format: format::Pixel) -> bool { pub fn output(format: format::Pixel) -> bool {
unsafe { unsafe { sws_isSupportedOutput(format.into()) != 0 }
sws_isSupportedOutput(format.into()) != 0
}
} }
pub fn endianness_conversion(format: format::Pixel) -> bool { pub fn endianness_conversion(format: format::Pixel) -> bool {
unsafe { unsafe { sws_isSupportedEndiannessConversion(format.into()) != 0 }
sws_isSupportedEndiannessConversion(format.into()) != 0
}
} }

View File

@ -1,120 +1,140 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use std::slice; use std::slice;
use libc::{c_int, c_double};
use ffi::*; use ffi::*;
use libc::{c_double, c_int};
pub struct Vector<'a> { pub struct Vector<'a> {
ptr: *mut SwsVector, ptr: *mut SwsVector,
_own: bool, _own: bool,
_marker: PhantomData<&'a ()>, _marker: PhantomData<&'a ()>,
} }
impl<'a> Vector<'a> { impl<'a> Vector<'a> {
pub unsafe fn wrap(ptr: *mut SwsVector) -> Self { pub unsafe fn wrap(ptr: *mut SwsVector) -> Self {
Vector { ptr: ptr, _own: false, _marker: PhantomData } Vector {
} ptr: ptr,
_own: false,
_marker: PhantomData,
}
}
pub unsafe fn as_ptr(&self) -> *const SwsVector { pub unsafe fn as_ptr(&self) -> *const SwsVector {
self.ptr as *const _ self.ptr as *const _
} }
pub unsafe fn as_mut_ptr(&mut self) -> *mut SwsVector { pub unsafe fn as_mut_ptr(&mut self) -> *mut SwsVector {
self.ptr self.ptr
} }
} }
impl<'a> Vector<'a> { impl<'a> Vector<'a> {
pub fn new(length: usize) -> Self { pub fn new(length: usize) -> Self {
unsafe { unsafe {
Vector { ptr: sws_allocVec(length as c_int), _own: true, _marker: PhantomData } Vector {
} ptr: sws_allocVec(length as c_int),
} _own: true,
_marker: PhantomData,
}
}
}
pub fn gaussian(variance: f64, quality: f64) -> Self { pub fn gaussian(variance: f64, quality: f64) -> Self {
unsafe { unsafe {
Vector { ptr: sws_getGaussianVec(variance as c_double, quality as c_double), _own: true, _marker: PhantomData } Vector {
} ptr: sws_getGaussianVec(variance as c_double, quality as c_double),
} _own: true,
_marker: PhantomData,
}
}
}
pub fn value(value: f64, length: usize) -> Self { pub fn value(value: f64, length: usize) -> Self {
unsafe { unsafe {
Vector { ptr: sws_getConstVec(value as c_double, length as c_int), _own: true, _marker: PhantomData } Vector {
} ptr: sws_getConstVec(value as c_double, length as c_int),
} _own: true,
_marker: PhantomData,
}
}
}
pub fn identity() -> Self { pub fn identity() -> Self {
unsafe { unsafe {
Vector { ptr: sws_getIdentityVec(), _own: true, _marker: PhantomData } Vector {
} ptr: sws_getIdentityVec(),
} _own: true,
_marker: PhantomData,
}
}
}
pub fn scale(&mut self, scalar: f64) { pub fn scale(&mut self, scalar: f64) {
unsafe { unsafe {
sws_scaleVec(self.as_mut_ptr(), scalar as c_double); sws_scaleVec(self.as_mut_ptr(), scalar as c_double);
} }
} }
pub fn normalize(&mut self, height: f64) { pub fn normalize(&mut self, height: f64) {
unsafe { unsafe {
sws_normalizeVec(self.as_mut_ptr(), height as c_double); sws_normalizeVec(self.as_mut_ptr(), height as c_double);
} }
} }
pub fn conv(&mut self, other: &Vector) { pub fn conv(&mut self, other: &Vector) {
unsafe { unsafe {
sws_convVec(self.as_mut_ptr(), other.as_ptr() as *mut _); sws_convVec(self.as_mut_ptr(), other.as_ptr() as *mut _);
} }
} }
pub fn add(&mut self, other: &Vector) { pub fn add(&mut self, other: &Vector) {
unsafe { unsafe {
sws_addVec(self.as_mut_ptr(), other.as_ptr() as *mut _); sws_addVec(self.as_mut_ptr(), other.as_ptr() as *mut _);
} }
} }
pub fn sub(&mut self, other: &Vector) { pub fn sub(&mut self, other: &Vector) {
unsafe { unsafe {
sws_subVec(self.as_mut_ptr(), other.as_ptr() as *mut _); sws_subVec(self.as_mut_ptr(), other.as_ptr() as *mut _);
} }
} }
pub fn shift(&mut self, value: usize) { pub fn shift(&mut self, value: usize) {
unsafe { unsafe {
sws_shiftVec(self.as_mut_ptr(), value as c_int); sws_shiftVec(self.as_mut_ptr(), value as c_int);
} }
} }
pub fn coefficients(&self) -> &[f64] { pub fn coefficients(&self) -> &[f64] {
unsafe { unsafe { slice::from_raw_parts((*self.as_ptr()).coeff, (*self.as_ptr()).length as usize) }
slice::from_raw_parts((*self.as_ptr()).coeff, }
(*self.as_ptr()).length as usize)
}
}
pub fn coefficients_mut(&self) -> &[f64] { pub fn coefficients_mut(&self) -> &[f64] {
unsafe { unsafe {
slice::from_raw_parts_mut((*self.as_ptr()).coeff, slice::from_raw_parts_mut((*self.as_ptr()).coeff, (*self.as_ptr()).length as usize)
(*self.as_ptr()).length as usize) }
} }
}
} }
impl<'a> Clone for Vector<'a> { impl<'a> Clone for Vector<'a> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
unsafe { unsafe {
Vector { ptr: sws_cloneVec(self.as_ptr() as *mut _), _own: true, _marker: PhantomData } Vector {
} ptr: sws_cloneVec(self.as_ptr() as *mut _),
} _own: true,
_marker: PhantomData,
}
}
}
} }
impl<'a> Drop for Vector<'a> { impl<'a> Drop for Vector<'a> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
if self._own { if self._own {
sws_freeVec(self.as_mut_ptr()); sws_freeVec(self.as_mut_ptr());
} }
} }
} }
} }

View File

@ -1,77 +1,75 @@
use libc::c_ulonglong;
use ffi::*; use ffi::*;
use libc::c_ulonglong;
bitflags! { bitflags! {
pub struct ChannelLayout: c_ulonglong { pub struct ChannelLayout: c_ulonglong {
const FRONT_LEFT = AV_CH_FRONT_LEFT; const FRONT_LEFT = AV_CH_FRONT_LEFT;
const FRONT_RIGHT = AV_CH_FRONT_RIGHT; const FRONT_RIGHT = AV_CH_FRONT_RIGHT;
const FRONT_CENTER = AV_CH_FRONT_CENTER; const FRONT_CENTER = AV_CH_FRONT_CENTER;
const LOW_FREQUENCY = AV_CH_LOW_FREQUENCY; const LOW_FREQUENCY = AV_CH_LOW_FREQUENCY;
const BACK_LEFT = AV_CH_BACK_LEFT; const BACK_LEFT = AV_CH_BACK_LEFT;
const BACK_RIGHT = AV_CH_BACK_RIGHT; const BACK_RIGHT = AV_CH_BACK_RIGHT;
const FRONT_LEFT_OF_CENTER = AV_CH_FRONT_LEFT_OF_CENTER; const FRONT_LEFT_OF_CENTER = AV_CH_FRONT_LEFT_OF_CENTER;
const FRONT_RIGHT_OF_CENTER = AV_CH_FRONT_RIGHT_OF_CENTER; const FRONT_RIGHT_OF_CENTER = AV_CH_FRONT_RIGHT_OF_CENTER;
const BACK_CENTER = AV_CH_BACK_CENTER; const BACK_CENTER = AV_CH_BACK_CENTER;
const SIDE_LEFT = AV_CH_SIDE_LEFT; const SIDE_LEFT = AV_CH_SIDE_LEFT;
const SIDE_RIGHT = AV_CH_SIDE_RIGHT; const SIDE_RIGHT = AV_CH_SIDE_RIGHT;
const TOP_CENTER = AV_CH_TOP_CENTER; const TOP_CENTER = AV_CH_TOP_CENTER;
const TOP_FRONT_LEFT = AV_CH_TOP_FRONT_LEFT; const TOP_FRONT_LEFT = AV_CH_TOP_FRONT_LEFT;
const TOP_FRONT_CENTER = AV_CH_TOP_FRONT_CENTER; const TOP_FRONT_CENTER = AV_CH_TOP_FRONT_CENTER;
const TOP_FRONT_RIGHT = AV_CH_TOP_FRONT_RIGHT; const TOP_FRONT_RIGHT = AV_CH_TOP_FRONT_RIGHT;
const TOP_BACK_LEFT = AV_CH_TOP_BACK_LEFT; const TOP_BACK_LEFT = AV_CH_TOP_BACK_LEFT;
const TOP_BACK_CENTER = AV_CH_TOP_BACK_CENTER; const TOP_BACK_CENTER = AV_CH_TOP_BACK_CENTER;
const TOP_BACK_RIGHT = AV_CH_TOP_BACK_RIGHT; const TOP_BACK_RIGHT = AV_CH_TOP_BACK_RIGHT;
const STEREO_LEFT = AV_CH_STEREO_LEFT; const STEREO_LEFT = AV_CH_STEREO_LEFT;
const STEREO_RIGHT = AV_CH_STEREO_RIGHT; const STEREO_RIGHT = AV_CH_STEREO_RIGHT;
const WIDE_LEFT = AV_CH_WIDE_LEFT; const WIDE_LEFT = AV_CH_WIDE_LEFT;
const WIDE_RIGHT = AV_CH_WIDE_RIGHT; const WIDE_RIGHT = AV_CH_WIDE_RIGHT;
const SURROUND_DIRECT_LEFT = AV_CH_SURROUND_DIRECT_LEFT; const SURROUND_DIRECT_LEFT = AV_CH_SURROUND_DIRECT_LEFT;
const SURROUND_DIRECT_RIGHT = AV_CH_SURROUND_DIRECT_RIGHT; const SURROUND_DIRECT_RIGHT = AV_CH_SURROUND_DIRECT_RIGHT;
const LOW_FREQUENCY_2 = AV_CH_LOW_FREQUENCY_2; const LOW_FREQUENCY_2 = AV_CH_LOW_FREQUENCY_2;
const NATIVE = AV_CH_LAYOUT_NATIVE; const NATIVE = AV_CH_LAYOUT_NATIVE;
const MONO = AV_CH_LAYOUT_MONO; const MONO = AV_CH_LAYOUT_MONO;
const STEREO = AV_CH_LAYOUT_STEREO; const STEREO = AV_CH_LAYOUT_STEREO;
const _2POINT1 = AV_CH_LAYOUT_2POINT1; const _2POINT1 = AV_CH_LAYOUT_2POINT1;
const _2_1 = AV_CH_LAYOUT_2_1; const _2_1 = AV_CH_LAYOUT_2_1;
const SURROUND = AV_CH_LAYOUT_SURROUND; const SURROUND = AV_CH_LAYOUT_SURROUND;
const _3POINT1 = AV_CH_LAYOUT_3POINT1; const _3POINT1 = AV_CH_LAYOUT_3POINT1;
const _4POINT0 = AV_CH_LAYOUT_4POINT0; const _4POINT0 = AV_CH_LAYOUT_4POINT0;
const _4POINT1 = AV_CH_LAYOUT_4POINT1; const _4POINT1 = AV_CH_LAYOUT_4POINT1;
const _2_2 = AV_CH_LAYOUT_2_2; const _2_2 = AV_CH_LAYOUT_2_2;
const QUAD = AV_CH_LAYOUT_QUAD; const QUAD = AV_CH_LAYOUT_QUAD;
const _5POINT0 = AV_CH_LAYOUT_5POINT0; const _5POINT0 = AV_CH_LAYOUT_5POINT0;
const _5POINT1 = AV_CH_LAYOUT_5POINT1; const _5POINT1 = AV_CH_LAYOUT_5POINT1;
const _5POINT0_BACK = AV_CH_LAYOUT_5POINT0_BACK; const _5POINT0_BACK = AV_CH_LAYOUT_5POINT0_BACK;
const _5POINT1_BACK = AV_CH_LAYOUT_5POINT1_BACK; const _5POINT1_BACK = AV_CH_LAYOUT_5POINT1_BACK;
const _6POINT0 = AV_CH_LAYOUT_6POINT0; const _6POINT0 = AV_CH_LAYOUT_6POINT0;
const _6POINT0_FRONT = AV_CH_LAYOUT_6POINT0_FRONT; const _6POINT0_FRONT = AV_CH_LAYOUT_6POINT0_FRONT;
const HEXAGONAL = AV_CH_LAYOUT_HEXAGONAL; const HEXAGONAL = AV_CH_LAYOUT_HEXAGONAL;
const _6POINT1 = AV_CH_LAYOUT_6POINT1; const _6POINT1 = AV_CH_LAYOUT_6POINT1;
const _6POINT1_BACK = AV_CH_LAYOUT_6POINT1_BACK; const _6POINT1_BACK = AV_CH_LAYOUT_6POINT1_BACK;
const _6POINT1_FRONT = AV_CH_LAYOUT_6POINT1_FRONT; const _6POINT1_FRONT = AV_CH_LAYOUT_6POINT1_FRONT;
const _7POINT0 = AV_CH_LAYOUT_7POINT0; const _7POINT0 = AV_CH_LAYOUT_7POINT0;
const _7POINT0_FRONT = AV_CH_LAYOUT_7POINT0_FRONT; const _7POINT0_FRONT = AV_CH_LAYOUT_7POINT0_FRONT;
const _7POINT1 = AV_CH_LAYOUT_7POINT1; const _7POINT1 = AV_CH_LAYOUT_7POINT1;
const _7POINT1_WIDE = AV_CH_LAYOUT_7POINT1_WIDE; const _7POINT1_WIDE = AV_CH_LAYOUT_7POINT1_WIDE;
const _7POINT1_WIDE_BACK = AV_CH_LAYOUT_7POINT1_WIDE_BACK; const _7POINT1_WIDE_BACK = AV_CH_LAYOUT_7POINT1_WIDE_BACK;
const OCTAGONAL = AV_CH_LAYOUT_OCTAGONAL; const OCTAGONAL = AV_CH_LAYOUT_OCTAGONAL;
const HEXADECAGONAL = AV_CH_LAYOUT_HEXADECAGONAL; const HEXADECAGONAL = AV_CH_LAYOUT_HEXADECAGONAL;
const STEREO_DOWNMIX = AV_CH_LAYOUT_STEREO_DOWNMIX; const STEREO_DOWNMIX = AV_CH_LAYOUT_STEREO_DOWNMIX;
} }
} }
impl ChannelLayout { impl ChannelLayout {
#[inline] #[inline]
pub fn channels(&self) -> i32 { pub fn channels(&self) -> i32 {
unsafe { unsafe { av_get_channel_layout_nb_channels(self.bits()) }
av_get_channel_layout_nb_channels(self.bits()) }
}
}
pub fn default(number: i32) -> ChannelLayout { pub fn default(number: i32) -> ChannelLayout {
unsafe { unsafe {
ChannelLayout::from_bits_truncate(av_get_default_channel_layout(number) as c_ulonglong) ChannelLayout::from_bits_truncate(av_get_default_channel_layout(number) as c_ulonglong)
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More