Support FFmpeg 7.0 (#48)
* sys: Run cargo fmt * sys: Add new channel layout consts * sys: Update build script for 7.0 - Add new FF_API flags - Update version_check_info range - Add ffmpeg_7_0 feature entry * sys: Update non-exhaustive match statement * Update enums * Mark old APIs as removed with 7.0 * Make Audio frame work with 7.0 The .unwrap() in clone() is a bit wonky * Add API for swr_alloc_set_opts2 * Use AVFrame::duration field in 7.0+ * Include 7.0 in CI runs * Add fn ChanneLayoutIter::best * Update examples for new API * Add/update Context setter for ch layout
This commit is contained in:
17
.github/workflows/build.yml
vendored
17
.github/workflows/build.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
ffmpeg_version:
|
ffmpeg_version:
|
||||||
["3.4", "4.0", "4.1", "4.2", "4.3", "4.4", "5.0", "5.1", "6.0", "6.1"]
|
["3.4", "4.0", "4.1", "4.2", "4.3", "4.4", "5.0", "5.1", "6.0", "6.1", "7.0"]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@ -45,8 +45,9 @@ jobs:
|
|||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
|
prefix-key: "v2-rust"
|
||||||
# Only save cache for one FFmpeg version
|
# Only save cache for one FFmpeg version
|
||||||
save-if: ${{ matrix.ffmpeg_version == '6.1' }}
|
save-if: ${{ matrix.ffmpeg_version == '7.0' }}
|
||||||
|
|
||||||
- name: Check format
|
- name: Check format
|
||||||
run: cargo fmt -- --check
|
run: cargo fmt -- --check
|
||||||
@ -75,6 +76,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
prefix-key: "v2-rust"
|
||||||
|
|
||||||
- name: Check format
|
- name: Check format
|
||||||
run: cargo fmt -- --check
|
run: cargo fmt -- --check
|
||||||
@ -97,7 +100,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# GyanD builds don't go as far back as the Ubuntu builds
|
# GyanD builds don't go as far back as the Ubuntu builds
|
||||||
ffmpeg_version: ["4.4", "5.0", "5.1", "6.0", "6.1"]
|
ffmpeg_version: ["4.4", "5.0", "5.1", "6.0", "6.1", "7.0"]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@ -127,8 +130,8 @@ jobs:
|
|||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
prefix-key: "v1-rust"
|
prefix-key: "v2-rust"
|
||||||
save-if: ${{ matrix.ffmpeg_version == '6.1' }}
|
save-if: ${{ matrix.ffmpeg_version == '7.0' }}
|
||||||
|
|
||||||
- name: Check format
|
- name: Check format
|
||||||
run: cargo fmt -- --check
|
run: cargo fmt -- --check
|
||||||
@ -147,7 +150,7 @@ jobs:
|
|||||||
|
|
||||||
msrv:
|
msrv:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
container: jrottenberg/ffmpeg:6.1-ubuntu
|
container: jrottenberg/ffmpeg:7.0-ubuntu
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -159,6 +162,8 @@ jobs:
|
|||||||
- name: Install Rust 1.61.0
|
- name: Install Rust 1.61.0
|
||||||
uses: dtolnay/rust-toolchain@1.61.0
|
uses: dtolnay/rust-toolchain@1.61.0
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
prefix-key: "v2-rust"
|
||||||
|
|
||||||
- name: Use predefined lockfile
|
- name: Use predefined lockfile
|
||||||
run: mv Cargo.lock.MSRV Cargo.lock
|
run: mv Cargo.lock.MSRV Cargo.lock
|
||||||
|
@ -47,7 +47,8 @@ fn main() {
|
|||||||
println!("\t formats: any");
|
println!("\t formats: any");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(layouts) = audio.channel_layouts() {
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
if let Some(layouts) = audio.ch_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");
|
||||||
@ -97,7 +98,8 @@ fn main() {
|
|||||||
println!("\t formats: any");
|
println!("\t formats: any");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(layouts) = audio.channel_layouts() {
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
if let Some(layouts) = audio.ch_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");
|
||||||
|
@ -73,10 +73,14 @@ fn main() -> Result<(), ffmpeg::Error> {
|
|||||||
println!("\tmax_rate: {}", audio.max_bit_rate());
|
println!("\tmax_rate: {}", audio.max_bit_rate());
|
||||||
println!("\tdelay: {}", audio.delay());
|
println!("\tdelay: {}", audio.delay());
|
||||||
println!("\taudio.rate: {}", audio.rate());
|
println!("\taudio.rate: {}", audio.rate());
|
||||||
println!("\taudio.channels: {}", audio.channels());
|
|
||||||
println!("\taudio.format: {:?}", audio.format());
|
println!("\taudio.format: {:?}", audio.format());
|
||||||
println!("\taudio.frames: {}", audio.frames());
|
|
||||||
println!("\taudio.align: {}", audio.align());
|
println!("\taudio.align: {}", audio.align());
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
println!("\taudio.ch_layout: {:?}", audio.ch_layout());
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
|
println!("\taudio.channels: {}", audio.channels());
|
||||||
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
println!("\taudio.channel_layout: {:?}", audio.channel_layout());
|
println!("\taudio.channel_layout: {:?}", audio.channel_layout());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,16 @@ fn filter(
|
|||||||
) -> Result<filter::Graph, ffmpeg::Error> {
|
) -> Result<filter::Graph, ffmpeg::Error> {
|
||||||
let mut filter = filter::Graph::new();
|
let mut filter = filter::Graph::new();
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
let channel_layout = decoder.ch_layout().description();
|
||||||
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
|
let channel_layout = format!("0x{:x}", decoder.channel_layout().bits());
|
||||||
|
|
||||||
let args = format!(
|
let args = format!(
|
||||||
"time_base={}:sample_rate={}:sample_fmt={}:channel_layout=0x{:x}",
|
"time_base={}:sample_rate={}:sample_fmt={}:channel_layout={channel_layout}",
|
||||||
decoder.time_base(),
|
decoder.time_base(),
|
||||||
decoder.rate(),
|
decoder.rate(),
|
||||||
decoder.format().name(),
|
decoder.format().name()
|
||||||
decoder.channel_layout().bits()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
filter.add(&filter::find("abuffer").unwrap(), "in", &args)?;
|
filter.add(&filter::find("abuffer").unwrap(), "in", &args)?;
|
||||||
@ -28,7 +32,10 @@ fn filter(
|
|||||||
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());
|
||||||
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
out.set_channel_layout(encoder.channel_layout());
|
out.set_channel_layout(encoder.channel_layout());
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
out.set_ch_layout(encoder.ch_layout());
|
||||||
out.set_sample_rate(encoder.rate());
|
out.set_sample_rate(encoder.rate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,18 +95,31 @@ fn transcoder<P: AsRef<Path>>(
|
|||||||
let context = ffmpeg::codec::context::Context::from_parameters(output.parameters())?;
|
let context = ffmpeg::codec::context::Context::from_parameters(output.parameters())?;
|
||||||
let mut encoder = context.encoder().audio()?;
|
let mut encoder = context.encoder().audio()?;
|
||||||
|
|
||||||
let channel_layout = codec
|
|
||||||
.channel_layouts()
|
|
||||||
.map(|cls| cls.best(decoder.channel_layout().channels()))
|
|
||||||
.unwrap_or(ffmpeg::channel_layout::ChannelLayoutMask::STEREO);
|
|
||||||
|
|
||||||
if global {
|
if global {
|
||||||
encoder.set_flags(ffmpeg::codec::flag::Flags::GLOBAL_HEADER);
|
encoder.set_flags(ffmpeg::codec::flag::Flags::GLOBAL_HEADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
{
|
||||||
|
let ch_layout = codec
|
||||||
|
.ch_layouts()
|
||||||
|
.map(|cls| cls.best(decoder.ch_layout().channels()))
|
||||||
|
.unwrap_or(ffmpeg::channel_layout::ChannelLayout::STEREO);
|
||||||
|
|
||||||
|
encoder.set_ch_layout(ch_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
|
{
|
||||||
|
let channel_layout = codec
|
||||||
|
.channel_layouts()
|
||||||
|
.map(|cls| cls.best(decoder.channel_layout().channels()))
|
||||||
|
.unwrap_or(ffmpeg::channel_layout::ChannelLayoutMask::STEREO);
|
||||||
|
encoder.set_channel_layout(channel_layout);
|
||||||
|
encoder.set_channels(channel_layout.channels());
|
||||||
|
}
|
||||||
|
|
||||||
encoder.set_rate(decoder.rate() as i32);
|
encoder.set_rate(decoder.rate() as i32);
|
||||||
encoder.set_channel_layout(channel_layout);
|
|
||||||
encoder.set_channels(channel_layout.channels());
|
|
||||||
encoder.set_format(
|
encoder.set_format(
|
||||||
codec
|
codec
|
||||||
.formats()
|
.formats()
|
||||||
|
@ -114,6 +114,7 @@ static AVUTIL_FEATURES: &[AVFeature] = &[
|
|||||||
AVFeature::new("FRAME_KEY"),
|
AVFeature::new("FRAME_KEY"),
|
||||||
AVFeature::new("PALETTE_HAS_CHANGED"),
|
AVFeature::new("PALETTE_HAS_CHANGED"),
|
||||||
AVFeature::new("VULKAN_CONTIGUOUS_MEMORY"),
|
AVFeature::new("VULKAN_CONTIGUOUS_MEMORY"),
|
||||||
|
AVFeature::new("H274_FILM_GRAIN_VCS"),
|
||||||
];
|
];
|
||||||
|
|
||||||
static AVCODEC_FEATURES: &[AVFeature] = &[
|
static AVCODEC_FEATURES: &[AVFeature] = &[
|
||||||
@ -199,6 +200,9 @@ static AVCODEC_FEATURES: &[AVFeature] = &[
|
|||||||
AVFeature::new("DROPCHANGED"),
|
AVFeature::new("DROPCHANGED"),
|
||||||
AVFeature::new("AVFFT"),
|
AVFeature::new("AVFFT"),
|
||||||
AVFeature::new("FF_PROFILE_LEVEL"),
|
AVFeature::new("FF_PROFILE_LEVEL"),
|
||||||
|
AVFeature::new("AVCODEC_CLOSE"),
|
||||||
|
AVFeature::new("BUFFER_MIN_SIZE"),
|
||||||
|
AVFeature::new("VDPAU_ALLOC_GET_SET"),
|
||||||
];
|
];
|
||||||
|
|
||||||
static AVFORMAT_FEATURES: &[AVFeature] = &[
|
static AVFORMAT_FEATURES: &[AVFeature] = &[
|
||||||
@ -220,9 +224,16 @@ static AVFORMAT_FEATURES: &[AVFeature] = &[
|
|||||||
AVFeature::new("LAVF_SHORTEST"),
|
AVFeature::new("LAVF_SHORTEST"),
|
||||||
AVFeature::new("ALLOW_FLUSH"),
|
AVFeature::new("ALLOW_FLUSH"),
|
||||||
AVFeature::new("AVSTREAM_SIDE_DATA"),
|
AVFeature::new("AVSTREAM_SIDE_DATA"),
|
||||||
|
AVFeature::new("GET_DUR_ESTIMATE_METHOD"),
|
||||||
|
AVFeature::new("R_FRAME_RATE"),
|
||||||
];
|
];
|
||||||
|
|
||||||
static AVDEVICE_FEATURES: &[AVFeature] = &[AVFeature::new("DEVICE_CAPABILITIES")];
|
static AVDEVICE_FEATURES: &[AVFeature] = &[
|
||||||
|
AVFeature::new("DEVICE_CAPABILITIES"),
|
||||||
|
AVFeature::new("BKTR_DEVICE"),
|
||||||
|
AVFeature::new("OPENGL_DEVICE"),
|
||||||
|
AVFeature::new("SDL2_DEVICE"),
|
||||||
|
];
|
||||||
|
|
||||||
static AVFILTER_FEATURES: &[AVFeature] = &[
|
static AVFILTER_FEATURES: &[AVFeature] = &[
|
||||||
AVFeature::new("AVFILTERPAD_PUBLIC"),
|
AVFeature::new("AVFILTERPAD_PUBLIC"),
|
||||||
@ -237,6 +248,7 @@ static AVFILTER_FEATURES: &[AVFeature] = &[
|
|||||||
AVFeature::new("BUFFERSINK_ALLOC"),
|
AVFeature::new("BUFFERSINK_ALLOC"),
|
||||||
AVFeature::new("PAD_COUNT"),
|
AVFeature::new("PAD_COUNT"),
|
||||||
AVFeature::new("LIBPLACEBO_OPTS"),
|
AVFeature::new("LIBPLACEBO_OPTS"),
|
||||||
|
AVFeature::new("LINK_PUBLIC"),
|
||||||
];
|
];
|
||||||
|
|
||||||
static AVRESAMPLE_FEATURES: &[AVFeature] = &[AVFeature::new("RESAMPLE_CLOSE_OPEN")];
|
static AVRESAMPLE_FEATURES: &[AVFeature] = &[AVFeature::new("RESAMPLE_CLOSE_OPEN")];
|
||||||
@ -736,7 +748,7 @@ fn check_features(include_paths: &[PathBuf]) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let version_check_info = [("avcodec", 56, 61, 0, 108)];
|
let version_check_info = [("avcodec", 56, 62, 0, 108)];
|
||||||
for &(lib, begin_version_major, end_version_major, begin_version_minor, end_version_minor) in
|
for &(lib, begin_version_major, end_version_major, begin_version_minor, end_version_minor) in
|
||||||
version_check_info.iter()
|
version_check_info.iter()
|
||||||
{
|
{
|
||||||
@ -880,6 +892,7 @@ fn check_features(include_paths: &[PathBuf]) {
|
|||||||
("ffmpeg_5_1", 59, 37),
|
("ffmpeg_5_1", 59, 37),
|
||||||
("ffmpeg_6_0", 60, 3),
|
("ffmpeg_6_0", 60, 3),
|
||||||
("ffmpeg_6_1", 60, 31),
|
("ffmpeg_6_1", 60, 31),
|
||||||
|
("ffmpeg_7_0", 61, 3),
|
||||||
];
|
];
|
||||||
for &(ffmpeg_version_flag, lavc_version_major, lavc_version_minor) in
|
for &(ffmpeg_version_flag, lavc_version_major, lavc_version_minor) in
|
||||||
ffmpeg_lavc_versions.iter()
|
ffmpeg_lavc_versions.iter()
|
||||||
|
@ -77,9 +77,10 @@ impl fmt::Debug for AVChannelLayout {
|
|||||||
"map",
|
"map",
|
||||||
&std::slice::from_raw_parts(self.u.map, self.nb_channels as usize),
|
&std::slice::from_raw_parts(self.u.map, self.nb_channels as usize),
|
||||||
);
|
);
|
||||||
} // Starting with FFmpeg 7.0:
|
}
|
||||||
// Not part of public API, but we have to exhaustively match
|
// Not part of public API, but we have to exhaustively match
|
||||||
// AVChannelOrder::FF_CHANNEL_ORDER_NB => {}
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AVChannelOrder::FF_CHANNEL_ORDER_NB => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +185,12 @@ pub const AV_CH_LAYOUT_7POINT1POINT2: u64 =
|
|||||||
AV_CH_LAYOUT_7POINT1 | AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT;
|
AV_CH_LAYOUT_7POINT1 | AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT;
|
||||||
pub const AV_CH_LAYOUT_7POINT1POINT4_BACK: u64 =
|
pub const AV_CH_LAYOUT_7POINT1POINT4_BACK: u64 =
|
||||||
AV_CH_LAYOUT_7POINT1POINT2 | AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT;
|
AV_CH_LAYOUT_7POINT1POINT2 | AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT;
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
pub const AV_CH_LAYOUT_7POINT2POINT3: u64 =
|
||||||
|
AV_CH_LAYOUT_7POINT1POINT2 | AV_CH_TOP_BACK_CENTER | AV_CH_LOW_FREQUENCY_2;
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
pub const AV_CH_LAYOUT_9POINT1POINT4_BACK: u64 =
|
||||||
|
AV_CH_LAYOUT_7POINT1POINT4_BACK | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER;
|
||||||
pub const AV_CH_LAYOUT_HEXADECAGONAL: u64 = AV_CH_LAYOUT_OCTAGONAL
|
pub const AV_CH_LAYOUT_HEXADECAGONAL: u64 = AV_CH_LAYOUT_OCTAGONAL
|
||||||
| AV_CH_WIDE_LEFT
|
| AV_CH_WIDE_LEFT
|
||||||
| AV_CH_WIDE_RIGHT
|
| AV_CH_WIDE_RIGHT
|
||||||
@ -285,6 +292,12 @@ pub const AV_CHANNEL_LAYOUT_7POINT1POINT2: AVChannelLayout =
|
|||||||
AV_CHANNEL_LAYOUT_MASK(10, AV_CH_LAYOUT_7POINT1POINT2);
|
AV_CHANNEL_LAYOUT_MASK(10, AV_CH_LAYOUT_7POINT1POINT2);
|
||||||
pub const AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK: AVChannelLayout =
|
pub const AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK: AVChannelLayout =
|
||||||
AV_CHANNEL_LAYOUT_MASK(12, AV_CH_LAYOUT_7POINT1POINT4_BACK);
|
AV_CHANNEL_LAYOUT_MASK(12, AV_CH_LAYOUT_7POINT1POINT4_BACK);
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
pub const AV_CHANNEL_LAYOUT_7POINT2POINT3: AVChannelLayout =
|
||||||
|
AV_CHANNEL_LAYOUT_MASK(12, AV_CH_LAYOUT_7POINT2POINT3);
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
pub const AV_CHANNEL_LAYOUT_9POINT1POINT4_BACK: AVChannelLayout =
|
||||||
|
AV_CHANNEL_LAYOUT_MASK(14, AV_CH_LAYOUT_9POINT1POINT4_BACK);
|
||||||
pub const AV_CHANNEL_LAYOUT_HEXADECAGONAL: AVChannelLayout =
|
pub const AV_CHANNEL_LAYOUT_HEXADECAGONAL: AVChannelLayout =
|
||||||
AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_HEXADECAGONAL);
|
AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_HEXADECAGONAL);
|
||||||
pub const AV_CHANNEL_LAYOUT_STEREO_DOWNMIX: AVChannelLayout =
|
pub const AV_CHANNEL_LAYOUT_STEREO_DOWNMIX: AVChannelLayout =
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use libc::{c_double, c_int};
|
|
||||||
use crate::AVRational;
|
use crate::AVRational;
|
||||||
|
use libc::{c_double, c_int};
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn av_make_q(num: c_int, den: c_int) -> AVRational {
|
pub unsafe fn av_make_q(num: c_int, den: c_int) -> AVRational {
|
||||||
|
@ -2,7 +2,10 @@ use std::ops::Deref;
|
|||||||
|
|
||||||
use super::codec::Codec;
|
use super::codec::Codec;
|
||||||
use crate::ffi::*;
|
use crate::ffi::*;
|
||||||
use crate::{format, ChannelLayoutMask};
|
use crate::format;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
|
use crate::ChannelLayoutMask;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||||
pub struct Audio {
|
pub struct Audio {
|
||||||
@ -36,6 +39,7 @@ impl Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn channel_layouts(&self) -> Option<ChannelLayoutMaskIter> {
|
pub fn channel_layouts(&self) -> Option<ChannelLayoutMaskIter> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if (*self.codec.as_ptr()).channel_layouts.is_null() {
|
if (*self.codec.as_ptr()).channel_layouts.is_null() {
|
||||||
@ -116,10 +120,12 @@ impl Iterator for FormatIter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub struct ChannelLayoutMaskIter {
|
pub struct ChannelLayoutMaskIter {
|
||||||
ptr: *const u64,
|
ptr: *const u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
impl ChannelLayoutMaskIter {
|
impl ChannelLayoutMaskIter {
|
||||||
pub fn new(ptr: *const u64) -> Self {
|
pub fn new(ptr: *const u64) -> Self {
|
||||||
ChannelLayoutMaskIter { ptr }
|
ChannelLayoutMaskIter { ptr }
|
||||||
@ -136,6 +142,7 @@ impl ChannelLayoutMaskIter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
impl Iterator for ChannelLayoutMaskIter {
|
impl Iterator for ChannelLayoutMaskIter {
|
||||||
type Item = ChannelLayoutMask;
|
type Item = ChannelLayoutMask;
|
||||||
|
|
||||||
@ -171,6 +178,18 @@ mod ch_layout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ChannelLayoutIter<'a> {
|
||||||
|
pub fn best(self, max: u32) -> ChannelLayout<'a> {
|
||||||
|
self.fold(ChannelLayout::MONO, |acc, cur| {
|
||||||
|
if cur.channels() > acc.channels() && cur.channels() <= max {
|
||||||
|
cur
|
||||||
|
} else {
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for ChannelLayoutIter<'a> {
|
impl<'a> Iterator for ChannelLayoutIter<'a> {
|
||||||
type Item = ChannelLayout<'a>;
|
type Item = ChannelLayout<'a>;
|
||||||
|
|
||||||
|
@ -10,13 +10,16 @@ use crate::codec::Context;
|
|||||||
#[cfg(not(feature = "ffmpeg_5_0"))]
|
#[cfg(not(feature = "ffmpeg_5_0"))]
|
||||||
use crate::frame;
|
use crate::frame;
|
||||||
use crate::util::format;
|
use crate::util::format;
|
||||||
|
use crate::AudioService;
|
||||||
#[cfg(not(feature = "ffmpeg_5_0"))]
|
#[cfg(not(feature = "ffmpeg_5_0"))]
|
||||||
use crate::{packet, Error};
|
use crate::{packet, Error};
|
||||||
use crate::{AudioService, ChannelLayoutMask};
|
|
||||||
|
|
||||||
#[cfg(feature = "ffmpeg_5_1")]
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
use crate::ChannelLayout;
|
use crate::ChannelLayout;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
|
use crate::ChannelLayoutMask;
|
||||||
|
|
||||||
pub struct Audio(pub Opened);
|
pub struct Audio(pub Opened);
|
||||||
|
|
||||||
impl Audio {
|
impl Audio {
|
||||||
@ -50,6 +53,7 @@ impl Audio {
|
|||||||
unsafe { (*self.as_ptr()).sample_rate as u32 }
|
unsafe { (*self.as_ptr()).sample_rate as u32 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn channels(&self) -> u16 {
|
pub fn channels(&self) -> u16 {
|
||||||
unsafe { (*self.as_ptr()).channels as u16 }
|
unsafe { (*self.as_ptr()).channels as u16 }
|
||||||
}
|
}
|
||||||
@ -64,6 +68,7 @@ impl Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn frames(&self) -> usize {
|
pub fn frames(&self) -> usize {
|
||||||
unsafe { (*self.as_ptr()).frame_number as usize }
|
unsafe { (*self.as_ptr()).frame_number as usize }
|
||||||
}
|
}
|
||||||
@ -72,16 +77,19 @@ impl Audio {
|
|||||||
unsafe { (*self.as_ptr()).block_align as usize }
|
unsafe { (*self.as_ptr()).block_align as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn channel_layout(&self) -> ChannelLayoutMask {
|
pub fn channel_layout(&self) -> ChannelLayoutMask {
|
||||||
unsafe { ChannelLayoutMask::from_bits_truncate((*self.as_ptr()).channel_layout) }
|
unsafe { ChannelLayoutMask::from_bits_truncate((*self.as_ptr()).channel_layout) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn set_channel_layout(&mut self, value: ChannelLayoutMask) {
|
pub fn set_channel_layout(&mut self, value: ChannelLayoutMask) {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.as_mut_ptr()).channel_layout = value.bits();
|
(*self.as_mut_ptr()).channel_layout = value.bits();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn request_channel_layout(&mut self, value: ChannelLayoutMask) {
|
pub fn request_channel_layout(&mut self, value: ChannelLayoutMask) {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.as_mut_ptr()).request_channel_layout = value.bits();
|
(*self.as_mut_ptr()).request_channel_layout = value.bits();
|
||||||
|
@ -84,6 +84,7 @@ impl Video {
|
|||||||
unsafe { chroma::Location::from((*self.as_ptr()).chroma_sample_location) }
|
unsafe { chroma::Location::from((*self.as_ptr()).chroma_sample_location) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
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;
|
||||||
|
@ -10,11 +10,14 @@ use crate::codec::{traits, Context};
|
|||||||
use crate::util::format;
|
use crate::util::format;
|
||||||
#[cfg(not(feature = "ffmpeg_5_0"))]
|
#[cfg(not(feature = "ffmpeg_5_0"))]
|
||||||
use crate::{frame, packet};
|
use crate::{frame, packet};
|
||||||
use crate::{ChannelLayoutMask, Dictionary, Error};
|
use crate::{Dictionary, Error};
|
||||||
|
|
||||||
#[cfg(feature = "ffmpeg_5_1")]
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
use crate::ChannelLayout;
|
use crate::ChannelLayout;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
|
use crate::ChannelLayoutMask;
|
||||||
|
|
||||||
pub struct Audio(pub Super);
|
pub struct Audio(pub Super);
|
||||||
|
|
||||||
impl Audio {
|
impl Audio {
|
||||||
@ -96,22 +99,26 @@ impl Audio {
|
|||||||
unsafe { format::Sample::from((*self.as_ptr()).sample_fmt) }
|
unsafe { format::Sample::from((*self.as_ptr()).sample_fmt) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn set_channel_layout(&mut self, value: ChannelLayoutMask) {
|
pub fn set_channel_layout(&mut self, value: ChannelLayoutMask) {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.as_mut_ptr()).channel_layout = value.bits();
|
(*self.as_mut_ptr()).channel_layout = value.bits();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn channel_layout(&self) -> ChannelLayoutMask {
|
pub fn channel_layout(&self) -> ChannelLayoutMask {
|
||||||
unsafe { ChannelLayoutMask::from_bits_truncate((*self.as_ptr()).channel_layout) }
|
unsafe { ChannelLayoutMask::from_bits_truncate((*self.as_ptr()).channel_layout) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn channels(&self) -> u16 {
|
pub fn channels(&self) -> u16 {
|
||||||
unsafe { (*self.as_ptr()).channels as u16 }
|
unsafe { (*self.as_ptr()).channels as u16 }
|
||||||
}
|
}
|
||||||
|
@ -214,6 +214,7 @@ pub enum Id {
|
|||||||
AVRP,
|
AVRP,
|
||||||
V012,
|
V012,
|
||||||
AVUI,
|
AVUI,
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
AYUV,
|
AYUV,
|
||||||
TARGA_Y216,
|
TARGA_Y216,
|
||||||
V308,
|
V308,
|
||||||
@ -656,10 +657,14 @@ pub enum Id {
|
|||||||
RTV1,
|
RTV1,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
VMIX,
|
VMIX,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
LEAD,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
AC4,
|
AC4,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
OSQ,
|
OSQ,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
QOA,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
SMPTE_2038,
|
SMPTE_2038,
|
||||||
}
|
}
|
||||||
@ -881,6 +886,7 @@ impl From<AVCodecID> for Id {
|
|||||||
AV_CODEC_ID_AVRP => Id::AVRP,
|
AV_CODEC_ID_AVRP => Id::AVRP,
|
||||||
AV_CODEC_ID_012V => Id::V012,
|
AV_CODEC_ID_012V => Id::V012,
|
||||||
AV_CODEC_ID_AVUI => Id::AVUI,
|
AV_CODEC_ID_AVUI => Id::AVUI,
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
AV_CODEC_ID_AYUV => Id::AYUV,
|
AV_CODEC_ID_AYUV => Id::AYUV,
|
||||||
AV_CODEC_ID_TARGA_Y216 => Id::TARGA_Y216,
|
AV_CODEC_ID_TARGA_Y216 => Id::TARGA_Y216,
|
||||||
AV_CODEC_ID_V308 => Id::V308,
|
AV_CODEC_ID_V308 => Id::V308,
|
||||||
@ -1322,10 +1328,14 @@ impl From<AVCodecID> for Id {
|
|||||||
AV_CODEC_ID_RTV1 => Id::RTV1,
|
AV_CODEC_ID_RTV1 => Id::RTV1,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
AV_CODEC_ID_VMIX => Id::VMIX,
|
AV_CODEC_ID_VMIX => Id::VMIX,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AV_CODEC_ID_LEAD => Id::LEAD,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
AV_CODEC_ID_AC4 => Id::AC4,
|
AV_CODEC_ID_AC4 => Id::AC4,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
AV_CODEC_ID_OSQ => Id::OSQ,
|
AV_CODEC_ID_OSQ => Id::OSQ,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AV_CODEC_ID_QOA => Id::QOA,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
AV_CODEC_ID_SMPTE_2038 => Id::SMPTE_2038,
|
AV_CODEC_ID_SMPTE_2038 => Id::SMPTE_2038,
|
||||||
|
|
||||||
@ -1541,6 +1551,7 @@ impl From<Id> for AVCodecID {
|
|||||||
Id::AVRP => AV_CODEC_ID_AVRP,
|
Id::AVRP => AV_CODEC_ID_AVRP,
|
||||||
Id::V012 => AV_CODEC_ID_012V,
|
Id::V012 => AV_CODEC_ID_012V,
|
||||||
Id::AVUI => AV_CODEC_ID_AVUI,
|
Id::AVUI => AV_CODEC_ID_AVUI,
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
Id::AYUV => AV_CODEC_ID_AYUV,
|
Id::AYUV => AV_CODEC_ID_AYUV,
|
||||||
Id::TARGA_Y216 => AV_CODEC_ID_TARGA_Y216,
|
Id::TARGA_Y216 => AV_CODEC_ID_TARGA_Y216,
|
||||||
Id::V308 => AV_CODEC_ID_V308,
|
Id::V308 => AV_CODEC_ID_V308,
|
||||||
@ -1982,10 +1993,14 @@ impl From<Id> for AVCodecID {
|
|||||||
Id::RTV1 => AV_CODEC_ID_RTV1,
|
Id::RTV1 => AV_CODEC_ID_RTV1,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
Id::VMIX => AV_CODEC_ID_VMIX,
|
Id::VMIX => AV_CODEC_ID_VMIX,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
Id::LEAD => AV_CODEC_ID_LEAD,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
Id::AC4 => AV_CODEC_ID_AC4,
|
Id::AC4 => AV_CODEC_ID_AC4,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
Id::OSQ => AV_CODEC_ID_OSQ,
|
Id::OSQ => AV_CODEC_ID_OSQ,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
Id::QOA => AV_CODEC_ID_QOA,
|
||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
Id::SMPTE_2038 => AV_CODEC_ID_SMPTE_2038,
|
Id::SMPTE_2038 => AV_CODEC_ID_SMPTE_2038,
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,15 @@ pub enum Type {
|
|||||||
|
|
||||||
#[cfg(feature = "ffmpeg_5_0")]
|
#[cfg(feature = "ffmpeg_5_0")]
|
||||||
DYNAMIC_HDR10_PLUS,
|
DYNAMIC_HDR10_PLUS,
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
IAMF_MIX_GAIN_PARAM,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
IAMF_DEMIXING_INFO_PARAM,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
IAMF_RECON_GAIN_INFO_PARAM,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AMBIENT_VIEWING_ENVIRONMENT,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<AVPacketSideDataType> for Type {
|
impl From<AVPacketSideDataType> for Type {
|
||||||
@ -110,6 +119,15 @@ impl From<AVPacketSideDataType> for Type {
|
|||||||
#[cfg(feature = "ffmpeg_5_0")]
|
#[cfg(feature = "ffmpeg_5_0")]
|
||||||
AV_PKT_DATA_DYNAMIC_HDR10_PLUS => Type::DYNAMIC_HDR10_PLUS,
|
AV_PKT_DATA_DYNAMIC_HDR10_PLUS => Type::DYNAMIC_HDR10_PLUS,
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AV_PKT_DATA_IAMF_MIX_GAIN_PARAM => Type::IAMF_MIX_GAIN_PARAM,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AV_PKT_DATA_IAMF_DEMIXING_INFO_PARAM => Type::IAMF_DEMIXING_INFO_PARAM,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AV_PKT_DATA_IAMF_RECON_GAIN_INFO_PARAM => Type::IAMF_RECON_GAIN_INFO_PARAM,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT => Type::AMBIENT_VIEWING_ENVIRONMENT,
|
||||||
|
|
||||||
#[cfg(feature = "non-exhaustive-enums")]
|
#[cfg(feature = "non-exhaustive-enums")]
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
@ -166,6 +184,15 @@ impl From<Type> for AVPacketSideDataType {
|
|||||||
|
|
||||||
#[cfg(feature = "ffmpeg_5_0")]
|
#[cfg(feature = "ffmpeg_5_0")]
|
||||||
Type::DYNAMIC_HDR10_PLUS => AV_PKT_DATA_DYNAMIC_HDR10_PLUS,
|
Type::DYNAMIC_HDR10_PLUS => AV_PKT_DATA_DYNAMIC_HDR10_PLUS,
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
Type::IAMF_MIX_GAIN_PARAM => AV_PKT_DATA_IAMF_MIX_GAIN_PARAM,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
Type::IAMF_DEMIXING_INFO_PARAM => AV_PKT_DATA_IAMF_DEMIXING_INFO_PARAM,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
Type::IAMF_RECON_GAIN_INFO_PARAM => AV_PKT_DATA_IAMF_RECON_GAIN_INFO_PARAM,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
Type::AMBIENT_VIEWING_ENVIRONMENT => AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,15 @@ use std::marker::PhantomData;
|
|||||||
|
|
||||||
use super::{Sink, Source};
|
use super::{Sink, Source};
|
||||||
use crate::ffi::*;
|
use crate::ffi::*;
|
||||||
use crate::{format, option, ChannelLayoutMask};
|
use crate::{format, option};
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
use crate::ChannelLayout;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
|
use crate::ChannelLayoutMask;
|
||||||
|
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
ptr: *mut AVFilterContext,
|
ptr: *mut AVFilterContext,
|
||||||
|
|
||||||
@ -49,9 +55,15 @@ impl<'a> Context<'a> {
|
|||||||
let _ = option::Settable::set(self, "sample_rates", &i64::from(value));
|
let _ = option::Settable::set(self, "sample_rates", &i64::from(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn set_channel_layout(&mut self, value: ChannelLayoutMask) {
|
pub fn set_channel_layout(&mut self, value: ChannelLayoutMask) {
|
||||||
let _ = option::Settable::set(self, "channel_layouts", &value.bits());
|
let _ = option::Settable::set(self, "channel_layouts", &value.bits());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
pub fn set_ch_layout(&mut self, value: ChannelLayout) {
|
||||||
|
let _ = option::Settable::set_str(self, "channel_layouts", &value.description());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<'a> option::Target for Context<'a> {
|
unsafe impl<'a> option::Target for Context<'a> {
|
||||||
|
@ -35,7 +35,7 @@ pub fn converter(
|
|||||||
#[cfg(feature = "software-resampling")]
|
#[cfg(feature = "software-resampling")]
|
||||||
pub mod resampling;
|
pub mod resampling;
|
||||||
|
|
||||||
#[cfg(feature = "software-resampling")]
|
#[cfg(all(feature = "software-resampling", not(feature = "ffmpeg_7_0")))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn resampler(
|
pub fn resampler(
|
||||||
(in_format, in_layout, in_rate): (crate::format::Sample, crate::ChannelLayoutMask, u32),
|
(in_format, in_layout, in_rate): (crate::format::Sample, crate::ChannelLayoutMask, u32),
|
||||||
@ -45,3 +45,14 @@ pub fn resampler(
|
|||||||
in_format, in_layout, in_rate, out_format, out_layout, out_rate,
|
in_format, in_layout, in_rate, out_format, out_layout, out_rate,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "software-resampling", feature = "ffmpeg_5_1"))]
|
||||||
|
#[inline]
|
||||||
|
pub fn resampler2(
|
||||||
|
(in_format, in_layout, in_rate): (crate::format::Sample, crate::ChannelLayout, u32),
|
||||||
|
(out_format, out_layout, out_rate): (crate::format::Sample, crate::ChannelLayout, u32),
|
||||||
|
) -> Result<resampling::Context, crate::Error> {
|
||||||
|
resampling::Context::get2(
|
||||||
|
in_format, in_layout, in_rate, out_format, out_layout, out_rate,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -8,6 +8,9 @@ use crate::{frame, ChannelLayoutMask, Error};
|
|||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
use crate::ChannelLayout;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Copy, Clone)]
|
#[derive(Eq, PartialEq, Copy, Clone)]
|
||||||
pub struct Definition {
|
pub struct Definition {
|
||||||
pub format: format::Sample,
|
pub format: format::Sample,
|
||||||
@ -38,6 +41,7 @@ impl Context {
|
|||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
/// Create a resampler with the given definitions.
|
/// Create a resampler with the given definitions.
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn get(
|
pub fn get(
|
||||||
src_format: format::Sample,
|
src_format: format::Sample,
|
||||||
src_channel_layout: ChannelLayoutMask,
|
src_channel_layout: ChannelLayoutMask,
|
||||||
@ -58,6 +62,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a resampler with the given definitions and custom options dictionary.
|
/// Create a resampler with the given definitions and custom options dictionary.
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
pub fn get_with(
|
pub fn get_with(
|
||||||
src_format: format::Sample,
|
src_format: format::Sample,
|
||||||
src_channel_layout: ChannelLayoutMask,
|
src_channel_layout: ChannelLayoutMask,
|
||||||
@ -114,6 +119,90 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a resampler with the given definitions.
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
pub fn get2(
|
||||||
|
src_format: format::Sample,
|
||||||
|
src_channel_layout: ChannelLayout,
|
||||||
|
src_rate: u32,
|
||||||
|
dst_format: format::Sample,
|
||||||
|
dst_channel_layout: ChannelLayout,
|
||||||
|
dst_rate: u32,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
Self::get_with2(
|
||||||
|
src_format,
|
||||||
|
src_channel_layout,
|
||||||
|
src_rate,
|
||||||
|
dst_format,
|
||||||
|
dst_channel_layout,
|
||||||
|
dst_rate,
|
||||||
|
Dictionary::new(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a resampler with the given definitions and custom options dictionary.
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
pub fn get_with2(
|
||||||
|
src_format: format::Sample,
|
||||||
|
src_channel_layout: ChannelLayout,
|
||||||
|
src_rate: u32,
|
||||||
|
dst_format: format::Sample,
|
||||||
|
dst_channel_layout: ChannelLayout,
|
||||||
|
dst_rate: u32,
|
||||||
|
options: Dictionary,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
unsafe {
|
||||||
|
let mut context_ptr = ptr::null_mut();
|
||||||
|
let res = swr_alloc_set_opts2(
|
||||||
|
ptr::addr_of_mut!(context_ptr),
|
||||||
|
dst_channel_layout.as_ptr() as _,
|
||||||
|
dst_format.into(),
|
||||||
|
dst_rate as c_int,
|
||||||
|
src_channel_layout.as_ptr() as _,
|
||||||
|
src_format.into(),
|
||||||
|
src_rate as c_int,
|
||||||
|
0,
|
||||||
|
ptr::null_mut(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if res < 0 {
|
||||||
|
return Err(Error::from(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut opts = options.disown();
|
||||||
|
let res = av_opt_set_dict(context_ptr as *mut c_void, &mut opts);
|
||||||
|
Dictionary::own(opts);
|
||||||
|
|
||||||
|
if res != 0 {
|
||||||
|
return Err(Error::from(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !context_ptr.is_null() {
|
||||||
|
match swr_init(context_ptr) {
|
||||||
|
e if e < 0 => Err(Error::from(e)),
|
||||||
|
|
||||||
|
_ => Ok(Context {
|
||||||
|
ptr: context_ptr,
|
||||||
|
|
||||||
|
input: Definition {
|
||||||
|
format: src_format,
|
||||||
|
channel_layout: src_channel_layout.mask().unwrap(),
|
||||||
|
rate: src_rate,
|
||||||
|
},
|
||||||
|
|
||||||
|
output: Definition {
|
||||||
|
format: dst_format,
|
||||||
|
channel_layout: dst_channel_layout.mask().unwrap(),
|
||||||
|
rate: dst_rate,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
use super::Context;
|
use super::Context;
|
||||||
use crate::util::format;
|
use crate::util::format;
|
||||||
use crate::{decoder, frame, ChannelLayoutMask, Error};
|
use crate::{decoder, frame, Error};
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
use crate::ChannelLayout;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
|
use crate::ChannelLayoutMask;
|
||||||
|
|
||||||
impl frame::Audio {
|
impl frame::Audio {
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn resampler(
|
pub fn resampler(
|
||||||
&self,
|
&self,
|
||||||
@ -19,9 +26,28 @@ impl frame::Audio {
|
|||||||
rate,
|
rate,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
#[inline]
|
||||||
|
pub fn resampler2(
|
||||||
|
&self,
|
||||||
|
format: format::Sample,
|
||||||
|
ch_layout: ChannelLayout,
|
||||||
|
rate: u32,
|
||||||
|
) -> Result<Context, Error> {
|
||||||
|
Context::get2(
|
||||||
|
self.format(),
|
||||||
|
self.ch_layout(),
|
||||||
|
unsafe { (*self.as_ptr()).sample_rate as u32 },
|
||||||
|
format,
|
||||||
|
ch_layout,
|
||||||
|
rate,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl decoder::Audio {
|
impl decoder::Audio {
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn resampler(
|
pub fn resampler(
|
||||||
&self,
|
&self,
|
||||||
@ -38,4 +64,22 @@ impl decoder::Audio {
|
|||||||
rate,
|
rate,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
#[inline]
|
||||||
|
pub fn resampler2(
|
||||||
|
&self,
|
||||||
|
format: format::Sample,
|
||||||
|
ch_layout: ChannelLayout,
|
||||||
|
rate: u32,
|
||||||
|
) -> Result<Context, Error> {
|
||||||
|
Context::get2(
|
||||||
|
self.format(),
|
||||||
|
self.ch_layout(),
|
||||||
|
self.rate(),
|
||||||
|
format,
|
||||||
|
ch_layout,
|
||||||
|
rate,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,6 +306,11 @@ impl<'a> ChannelLayout<'a> {
|
|||||||
pub const _7POINT1POINT2: Scl = ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_7POINT1POINT2));
|
pub const _7POINT1POINT2: Scl = ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_7POINT1POINT2));
|
||||||
pub const _7POINT1POINT4_BACK: Scl =
|
pub const _7POINT1POINT4_BACK: Scl =
|
||||||
ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK));
|
ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK));
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
pub const _7POINT2POINT3: Scl = ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_7POINT2POINT3));
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
pub const _9POINT1POINT4_BACK: Scl =
|
||||||
|
ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_9POINT1POINT4_BACK));
|
||||||
pub const HEXADECAGONAL: Scl = ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_HEXADECAGONAL));
|
pub const HEXADECAGONAL: Scl = ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_HEXADECAGONAL));
|
||||||
pub const STEREO_DOWNMIX: Scl = ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_STEREO_DOWNMIX));
|
pub const STEREO_DOWNMIX: Scl = ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_STEREO_DOWNMIX));
|
||||||
pub const _22POINT2: Scl = ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_22POINT2));
|
pub const _22POINT2: Scl = ChannelLayout(Cow::Owned(AV_CHANNEL_LAYOUT_22POINT2));
|
||||||
|
@ -28,6 +28,7 @@ bitflags! {
|
|||||||
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;
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
const NATIVE = AV_CH_LAYOUT_NATIVE;
|
const NATIVE = AV_CH_LAYOUT_NATIVE;
|
||||||
|
|
||||||
const MONO = AV_CH_LAYOUT_MONO;
|
const MONO = AV_CH_LAYOUT_MONO;
|
||||||
@ -68,6 +69,10 @@ bitflags! {
|
|||||||
const _7POINT1POINT2 = AV_CH_LAYOUT_7POINT1POINT2;
|
const _7POINT1POINT2 = AV_CH_LAYOUT_7POINT1POINT2;
|
||||||
#[cfg(feature = "ffmpeg_5_1")]
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
const _7POINT1POINT4_BACK = AV_CH_LAYOUT_7POINT1POINT4_BACK;
|
const _7POINT1POINT4_BACK = AV_CH_LAYOUT_7POINT1POINT4_BACK;
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
const _7POINT2POINT3 = AV_CH_LAYOUT_7POINT2POINT3;
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
const _9POINT1POINT4_BACK = AV_CH_LAYOUT_9POINT1POINT4_BACK;
|
||||||
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;
|
||||||
#[cfg(feature = "ffmpeg_5_1")]
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
@ -75,6 +80,7 @@ bitflags! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
impl ChannelLayoutMask {
|
impl ChannelLayoutMask {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn channels(&self) -> i32 {
|
pub fn channels(&self) -> i32 {
|
||||||
|
@ -29,6 +29,9 @@ impl From<AVChannelOrder> for ChannelOrder {
|
|||||||
AV_CHANNEL_ORDER_NATIVE => Native,
|
AV_CHANNEL_ORDER_NATIVE => Native,
|
||||||
AV_CHANNEL_ORDER_CUSTOM => Custom,
|
AV_CHANNEL_ORDER_CUSTOM => Custom,
|
||||||
AV_CHANNEL_ORDER_AMBISONIC => Ambisonic,
|
AV_CHANNEL_ORDER_AMBISONIC => Ambisonic,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
// Not part of the API, should never be used
|
||||||
|
FF_CHANNEL_ORDER_NB => unreachable!(),
|
||||||
#[cfg(feature = "non-exhaustive-enums")]
|
#[cfg(feature = "non-exhaustive-enums")]
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,7 @@ pub enum Pixel {
|
|||||||
VIDEOTOOLBOX,
|
VIDEOTOOLBOX,
|
||||||
|
|
||||||
// --- defaults
|
// --- defaults
|
||||||
#[cfg(feature = "ffmpeg_4_0")]
|
#[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_7_0")))]
|
||||||
XVMC,
|
XVMC,
|
||||||
|
|
||||||
RGB32,
|
RGB32,
|
||||||
@ -417,6 +417,9 @@ pub enum Pixel {
|
|||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
GBRAP14LE,
|
GBRAP14LE,
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
D3D12,
|
||||||
|
|
||||||
#[cfg(feature = "rpi")]
|
#[cfg(feature = "rpi")]
|
||||||
RPI,
|
RPI,
|
||||||
#[cfg(feature = "rpi")]
|
#[cfg(feature = "rpi")]
|
||||||
@ -498,7 +501,7 @@ impl From<AVPixelFormat> for Pixel {
|
|||||||
AV_PIX_FMT_YUVJ420P => Pixel::YUVJ420P,
|
AV_PIX_FMT_YUVJ420P => Pixel::YUVJ420P,
|
||||||
AV_PIX_FMT_YUVJ422P => Pixel::YUVJ422P,
|
AV_PIX_FMT_YUVJ422P => Pixel::YUVJ422P,
|
||||||
AV_PIX_FMT_YUVJ444P => Pixel::YUVJ444P,
|
AV_PIX_FMT_YUVJ444P => Pixel::YUVJ444P,
|
||||||
#[cfg(feature = "ffmpeg_4_0")]
|
#[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_7_0")))]
|
||||||
AV_PIX_FMT_XVMC => Pixel::XVMC,
|
AV_PIX_FMT_XVMC => Pixel::XVMC,
|
||||||
#[cfg(all(feature = "ff_api_xvmc", not(feature = "ffmpeg_5_0")))]
|
#[cfg(all(feature = "ff_api_xvmc", not(feature = "ffmpeg_5_0")))]
|
||||||
AV_PIX_FMT_XVMC_MPEG2_MC => Pixel::XVMC_MPEG2_MC,
|
AV_PIX_FMT_XVMC_MPEG2_MC => Pixel::XVMC_MPEG2_MC,
|
||||||
@ -825,6 +828,9 @@ impl From<AVPixelFormat> for Pixel {
|
|||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
AV_PIX_FMT_GBRAP14LE => Pixel::GBRAP14LE,
|
AV_PIX_FMT_GBRAP14LE => Pixel::GBRAP14LE,
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AV_PIX_FMT_D3D12 => Pixel::D3D12,
|
||||||
|
|
||||||
#[cfg(feature = "rpi")]
|
#[cfg(feature = "rpi")]
|
||||||
AV_PIX_FMT_RPI => Pixel::RPI,
|
AV_PIX_FMT_RPI => Pixel::RPI,
|
||||||
#[cfg(feature = "rpi")]
|
#[cfg(feature = "rpi")]
|
||||||
@ -1062,7 +1068,7 @@ impl From<Pixel> for AVPixelFormat {
|
|||||||
Pixel::VIDEOTOOLBOX => AV_PIX_FMT_VIDEOTOOLBOX,
|
Pixel::VIDEOTOOLBOX => AV_PIX_FMT_VIDEOTOOLBOX,
|
||||||
|
|
||||||
// --- defaults
|
// --- defaults
|
||||||
#[cfg(feature = "ffmpeg_4_0")]
|
#[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_7_0")))]
|
||||||
Pixel::XVMC => AV_PIX_FMT_XVMC,
|
Pixel::XVMC => AV_PIX_FMT_XVMC,
|
||||||
|
|
||||||
Pixel::RGB32 => AV_PIX_FMT_RGB32,
|
Pixel::RGB32 => AV_PIX_FMT_RGB32,
|
||||||
@ -1254,6 +1260,9 @@ impl From<Pixel> for AVPixelFormat {
|
|||||||
#[cfg(feature = "ffmpeg_6_1")]
|
#[cfg(feature = "ffmpeg_6_1")]
|
||||||
Pixel::GBRAP14LE => AV_PIX_FMT_GBRAP14LE,
|
Pixel::GBRAP14LE => AV_PIX_FMT_GBRAP14LE,
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
Pixel::D3D12 => AV_PIX_FMT_D3D12,
|
||||||
|
|
||||||
#[cfg(feature = "rpi")]
|
#[cfg(feature = "rpi")]
|
||||||
Pixel::RPI => AV_PIX_FMT_RPI,
|
Pixel::RPI => AV_PIX_FMT_RPI,
|
||||||
#[cfg(feature = "rpi")]
|
#[cfg(feature = "rpi")]
|
||||||
|
@ -6,11 +6,14 @@ use super::Frame;
|
|||||||
use crate::ffi::*;
|
use crate::ffi::*;
|
||||||
use crate::util::format;
|
use crate::util::format;
|
||||||
use crate::ChannelLayoutMask;
|
use crate::ChannelLayoutMask;
|
||||||
use libc::{c_int, c_ulonglong};
|
use libc::c_int;
|
||||||
|
|
||||||
#[cfg(feature = "ffmpeg_5_1")]
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
use crate::ChannelLayout;
|
use crate::ChannelLayout;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
|
use libc::c_ulonglong;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub struct Audio(Frame);
|
pub struct Audio(Frame);
|
||||||
|
|
||||||
@ -29,7 +32,10 @@ impl Audio {
|
|||||||
) {
|
) {
|
||||||
self.set_format(format);
|
self.set_format(format);
|
||||||
self.set_samples(samples);
|
self.set_samples(samples);
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
self.set_channel_layout(layout);
|
self.set_channel_layout(layout);
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
self.set_ch_layout(ChannelLayout::from_mask(layout).unwrap());
|
||||||
|
|
||||||
av_frame_get_buffer(self.as_mut_ptr(), 0);
|
av_frame_get_buffer(self.as_mut_ptr(), 0);
|
||||||
}
|
}
|
||||||
@ -69,6 +75,7 @@ impl Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn channel_layout(&self) -> ChannelLayoutMask {
|
pub fn channel_layout(&self) -> ChannelLayoutMask {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -76,6 +83,7 @@ impl Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_channel_layout(&mut self, value: ChannelLayoutMask) {
|
pub fn set_channel_layout(&mut self, value: ChannelLayoutMask) {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -97,11 +105,13 @@ impl Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn channels(&self) -> u16 {
|
pub fn channels(&self) -> u16 {
|
||||||
unsafe { (*self.as_ptr()).channels as u16 }
|
unsafe { (*self.as_ptr()).channels as u16 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_channels(&mut self, value: u16) {
|
pub fn set_channels(&mut self, value: u16) {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -154,7 +164,12 @@ impl Audio {
|
|||||||
if self.is_packed() {
|
if self.is_packed() {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
self.channels() as usize
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
|
let channels = self.channels() as usize;
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
let channels = self.ch_layout().channels() as usize;
|
||||||
|
|
||||||
|
channels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +179,12 @@ impl Audio {
|
|||||||
panic!("out of bounds");
|
panic!("out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !<T as Sample>::is_valid(self.format(), self.channels() as u16) {
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
|
let channels = self.channels() as u16;
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
let channels = self.ch_layout().channels() as u16;
|
||||||
|
|
||||||
|
if !<T as Sample>::is_valid(self.format(), channels) {
|
||||||
panic!("unsupported type");
|
panic!("unsupported type");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +197,12 @@ impl Audio {
|
|||||||
panic!("out of bounds");
|
panic!("out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !<T as Sample>::is_valid(self.format(), self.channels() as u16) {
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
|
let channels = self.channels() as u16;
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
let channels = self.ch_layout().channels() as u16;
|
||||||
|
|
||||||
|
if !<T as Sample>::is_valid(self.format(), channels) {
|
||||||
panic!("unsupported type");
|
panic!("unsupported type");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,9 +256,14 @@ impl DerefMut for Audio {
|
|||||||
|
|
||||||
impl ::std::fmt::Debug for Audio {
|
impl ::std::fmt::Debug for Audio {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
||||||
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
|
let channels = self.channels() as u16;
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
let channels = self.ch_layout().channels() as u16;
|
||||||
|
|
||||||
f.write_str("ffmpeg::frame::Audio { ")?;
|
f.write_str("ffmpeg::frame::Audio { ")?;
|
||||||
f.write_str(&format!("format: {:?}, ", self.format()))?;
|
f.write_str(&format!("format: {:?}, ", self.format()))?;
|
||||||
f.write_str(&format!("channels: {:?}, ", self.channels()))?;
|
f.write_str(&format!("channels: {channels}, "))?;
|
||||||
f.write_str(&format!("rate: {:?}, ", self.rate()))?;
|
f.write_str(&format!("rate: {:?}, ", self.rate()))?;
|
||||||
f.write_str(&format!("samples: {:?} ", self.samples()))?;
|
f.write_str(&format!("samples: {:?} ", self.samples()))?;
|
||||||
f.write_str("}")
|
f.write_str("}")
|
||||||
@ -242,7 +272,12 @@ impl ::std::fmt::Debug for Audio {
|
|||||||
|
|
||||||
impl Clone for Audio {
|
impl Clone for Audio {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
let mut cloned = Audio::new(self.format(), self.samples(), self.channel_layout());
|
#[cfg(not(feature = "ffmpeg_5_1"))]
|
||||||
|
let mask = self.channel_layout();
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
let mask = self.ch_layout().mask().unwrap();
|
||||||
|
|
||||||
|
let mut cloned = Audio::new(self.format(), self.samples(), mask);
|
||||||
cloned.clone_from(self);
|
cloned.clone_from(self);
|
||||||
|
|
||||||
cloned
|
cloned
|
||||||
|
@ -89,7 +89,10 @@ impl Frame {
|
|||||||
pub fn packet(&self) -> Packet {
|
pub fn packet(&self) -> Packet {
|
||||||
unsafe {
|
unsafe {
|
||||||
Packet {
|
Packet {
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
duration: (*self.as_ptr()).pkt_duration as i64,
|
duration: (*self.as_ptr()).pkt_duration as i64,
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
duration: (*self.as_ptr()).duration as i64,
|
||||||
position: (*self.as_ptr()).pkt_pos as i64,
|
position: (*self.as_ptr()).pkt_pos as i64,
|
||||||
size: (*self.as_ptr()).pkt_size as usize,
|
size: (*self.as_ptr()).pkt_size as usize,
|
||||||
|
|
||||||
|
@ -173,11 +173,13 @@ impl Video {
|
|||||||
unsafe { Rational::from((*self.as_ptr()).sample_aspect_ratio) }
|
unsafe { Rational::from((*self.as_ptr()).sample_aspect_ratio) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn coded_number(&self) -> usize {
|
pub fn coded_number(&self) -> usize {
|
||||||
unsafe { (*self.as_ptr()).coded_picture_number as usize }
|
unsafe { (*self.as_ptr()).coded_picture_number as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn display_number(&self) -> usize {
|
pub fn display_number(&self) -> usize {
|
||||||
unsafe { (*self.as_ptr()).display_picture_number as usize }
|
unsafe { (*self.as_ptr()).display_picture_number as usize }
|
||||||
|
@ -26,9 +26,18 @@ pub enum Type {
|
|||||||
VideoRate,
|
VideoRate,
|
||||||
Duration,
|
Duration,
|
||||||
Color,
|
Color,
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
ChannelLayout,
|
ChannelLayout,
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
ChLayout,
|
||||||
c_ulong,
|
c_ulong,
|
||||||
bool,
|
bool,
|
||||||
|
|
||||||
|
// FIXME: This is not supported yet. `enum Type` should become a bitflags struct.
|
||||||
|
// FIXME: AVOptionType is also not technically an enum because it may contain
|
||||||
|
// values that are outside the defined enum variants!
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
ArrayFlag = 0x10000,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<AVOptionType> for Type {
|
impl From<AVOptionType> for Type {
|
||||||
@ -53,9 +62,13 @@ impl From<AVOptionType> for Type {
|
|||||||
AV_OPT_TYPE_VIDEO_RATE => Type::VideoRate,
|
AV_OPT_TYPE_VIDEO_RATE => Type::VideoRate,
|
||||||
AV_OPT_TYPE_DURATION => Type::Duration,
|
AV_OPT_TYPE_DURATION => Type::Duration,
|
||||||
AV_OPT_TYPE_COLOR => Type::Color,
|
AV_OPT_TYPE_COLOR => Type::Color,
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
AV_OPT_TYPE_CHANNEL_LAYOUT => Type::ChannelLayout,
|
AV_OPT_TYPE_CHANNEL_LAYOUT => Type::ChannelLayout,
|
||||||
#[cfg(feature = "ffmpeg_5_1")]
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
AV_OPT_TYPE_CHLAYOUT => Type::ChannelLayout,
|
AV_OPT_TYPE_CHLAYOUT => Type::ChLayout,
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
AV_OPT_TYPE_FLAG_ARRAY => Type::ArrayFlag,
|
||||||
|
|
||||||
#[cfg(feature = "non-exhaustive-enums")]
|
#[cfg(feature = "non-exhaustive-enums")]
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
@ -85,7 +98,13 @@ impl From<Type> for AVOptionType {
|
|||||||
Type::VideoRate => AV_OPT_TYPE_VIDEO_RATE,
|
Type::VideoRate => AV_OPT_TYPE_VIDEO_RATE,
|
||||||
Type::Duration => AV_OPT_TYPE_DURATION,
|
Type::Duration => AV_OPT_TYPE_DURATION,
|
||||||
Type::Color => AV_OPT_TYPE_COLOR,
|
Type::Color => AV_OPT_TYPE_COLOR,
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
Type::ChannelLayout => AV_OPT_TYPE_CHANNEL_LAYOUT,
|
Type::ChannelLayout => AV_OPT_TYPE_CHANNEL_LAYOUT,
|
||||||
|
#[cfg(feature = "ffmpeg_5_1")]
|
||||||
|
Type::ChLayout => AV_OPT_TYPE_CHLAYOUT,
|
||||||
|
|
||||||
|
#[cfg(feature = "ffmpeg_7_0")]
|
||||||
|
Type::ArrayFlag => AV_OPT_TYPE_FLAG_ARRAY,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,12 @@ use std::mem;
|
|||||||
|
|
||||||
use crate::ffi::*;
|
use crate::ffi::*;
|
||||||
use crate::util::format;
|
use crate::util::format;
|
||||||
use crate::{ChannelLayoutMask, Error, Rational};
|
use crate::{Error, Rational};
|
||||||
use libc::{c_int, c_void};
|
use libc::{c_int, c_void};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
|
use crate::ChannelLayoutMask;
|
||||||
|
|
||||||
macro_rules! check {
|
macro_rules! check {
|
||||||
($expr:expr) => {
|
($expr:expr) => {
|
||||||
match $expr {
|
match $expr {
|
||||||
@ -130,6 +133,7 @@ pub trait Settable: Target {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
fn set_channel_layout(&mut self, name: &str, layout: ChannelLayoutMask) -> Result<(), Error> {
|
fn set_channel_layout(&mut self, name: &str, layout: ChannelLayoutMask) -> Result<(), Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let name = CString::new(name).unwrap();
|
let name = CString::new(name).unwrap();
|
||||||
|
Reference in New Issue
Block a user