*: 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:
parent
20c7ef399a
commit
0bcd4550b8
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,2 +1,8 @@
|
|||||||
|
# Rust files
|
||||||
target
|
target
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*.swn
|
||||||
|
14
build.rs
14
build.rs
@ -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()
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2748
src/codec/id.rs
2748
src/codec/id.rs
File diff suppressed because it is too large
Load Diff
@ -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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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> {}
|
||||||
|
@ -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)
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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> {}
|
||||||
|
@ -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())
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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> {}
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
@ -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> {}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()))
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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))
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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()
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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> {}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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)
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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> {}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
75
src/lib.rs
75
src/lib.rs
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user