Skip to main content

ffmpeg_next/util/
channel_layout.rs

1use crate::ffi::*;
2
3#[repr(transparent)]
4#[derive(Copy, Clone)]
5pub struct ChannelLayout(pub AVChannelLayout);
6
7impl PartialEq for ChannelLayout {
8    // TODO this can actually return an error if < 0
9    fn eq(&self, other: &Self) -> bool {
10        unsafe {
11            av_channel_layout_compare(
12                &self.0 as *const AVChannelLayout,
13                &other.0 as *const AVChannelLayout,
14            ) == 0
15        }
16    }
17}
18impl Eq for ChannelLayout {}
19
20impl std::fmt::Debug for ChannelLayout {
21    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
22        let mut s = fmt.debug_struct("ChannelLayout");
23        s.field("is_empty", &self.is_empty());
24        s.field("channels", &self.channels());
25        s.field("u.mask", &unsafe { self.0.u.mask });
26        s.finish()
27    }
28}
29
30macro_rules! define_layout {
31    ($name:ident, $nb:expr, $mask:expr) => {
32        pub const $name: ChannelLayout = ChannelLayout(AVChannelLayout {
33            order: AVChannelOrder::AV_CHANNEL_ORDER_NATIVE,
34            nb_channels: $nb,
35            u: AVChannelLayout__bindgen_ty_1 { mask: $mask },
36            opaque: std::ptr::null_mut(),
37        });
38    };
39}
40
41impl ChannelLayout {
42    define_layout!(MONO, 1, AV_CH_LAYOUT_MONO);
43    define_layout!(STEREO, 2, AV_CH_LAYOUT_STEREO);
44    define_layout!(_2POINT1, 3, AV_CH_LAYOUT_2POINT1);
45    define_layout!(_2_1, 3, AV_CH_LAYOUT_2_1);
46    define_layout!(SURROUND, 3, AV_CH_LAYOUT_SURROUND);
47    define_layout!(_3POINT1, 4, AV_CH_LAYOUT_3POINT1);
48    define_layout!(_4POINT0, 4, AV_CH_LAYOUT_4POINT0);
49    define_layout!(_4POINT1, 5, AV_CH_LAYOUT_4POINT1);
50    define_layout!(_2_2, 4, AV_CH_LAYOUT_2_2);
51    define_layout!(QUAD, 4, AV_CH_LAYOUT_QUAD);
52    define_layout!(_5POINT0, 5, AV_CH_LAYOUT_5POINT0);
53    define_layout!(_5POINT1, 6, AV_CH_LAYOUT_5POINT1);
54    define_layout!(_5POINT0_BACK, 5, AV_CH_LAYOUT_5POINT0_BACK);
55    define_layout!(_5POINT1_BACK, 6, AV_CH_LAYOUT_5POINT1_BACK);
56    define_layout!(_6POINT0, 6, AV_CH_LAYOUT_6POINT0);
57    define_layout!(_6POINT0_FRONT, 6, AV_CH_LAYOUT_6POINT0_FRONT);
58    define_layout!(_3POINT1POINT2, 6, AV_CH_LAYOUT_3POINT1POINT2);
59    define_layout!(HEXAGONAL, 6, AV_CH_LAYOUT_HEXAGONAL);
60    define_layout!(_6POINT1, 7, AV_CH_LAYOUT_6POINT1);
61    define_layout!(_6POINT1_BACK, 7, AV_CH_LAYOUT_6POINT1_BACK);
62    define_layout!(_6POINT1_FRONT, 7, AV_CH_LAYOUT_6POINT1_FRONT);
63    define_layout!(_7POINT0, 7, AV_CH_LAYOUT_7POINT0);
64    define_layout!(_7POINT0_FRONT, 7, AV_CH_LAYOUT_7POINT0_FRONT);
65    define_layout!(_7POINT1, 8, AV_CH_LAYOUT_7POINT1);
66    define_layout!(_7POINT1_WIDE, 8, AV_CH_LAYOUT_7POINT1_WIDE);
67    define_layout!(_7POINT1_WIDE_BACK, 8, AV_CH_LAYOUT_7POINT1_WIDE_BACK);
68    define_layout!(_5POINT1POINT2_BACK, 8, AV_CH_LAYOUT_5POINT1POINT2_BACK);
69    define_layout!(OCTAGONAL, 8, AV_CH_LAYOUT_OCTAGONAL);
70    define_layout!(CUBE, 8, AV_CH_LAYOUT_CUBE);
71    define_layout!(_5POINT1POINT4_BACK, 10, AV_CH_LAYOUT_5POINT1POINT4_BACK);
72    define_layout!(_7POINT1POINT2, 10, AV_CH_LAYOUT_7POINT1POINT2);
73    define_layout!(_7POINT1POINT4_BACK, 12, AV_CH_LAYOUT_7POINT1POINT4_BACK);
74    define_layout!(_7POINT2POINT3, 12, AV_CH_LAYOUT_7POINT2POINT3);
75    define_layout!(_9POINT1POINT4_BACK, 14, AV_CH_LAYOUT_9POINT1POINT4_BACK);
76    define_layout!(HEXADECAGONAL, 16, AV_CH_LAYOUT_HEXADECAGONAL);
77    define_layout!(STEREO_DOWNMIX, 2, AV_CH_LAYOUT_STEREO_DOWNMIX);
78    define_layout!(_22POINT2, 24, AV_CH_LAYOUT_22POINT2);
79    define_layout!(_7POINT1_TOP_BACK, 8, AV_CH_LAYOUT_5POINT1POINT2_BACK);
80
81    #[inline]
82    pub fn channels(&self) -> i32 {
83        self.0.nb_channels
84    }
85
86    #[inline]
87    pub fn bits(&self) -> u64 {
88        unsafe { self.0.u.mask }
89    }
90
91    pub fn default(number: i32) -> ChannelLayout {
92        unsafe {
93            let mut channel_layout = std::mem::zeroed();
94            av_channel_layout_default(&mut channel_layout, number);
95            ChannelLayout(channel_layout)
96        }
97    }
98
99    // See https://ffmpeg.org/doxygen/trunk/group__lavu__audio__channels.html#gaa4a685b5c38835392552a7f96ee24a3e,
100    // AV_CH_UNUSED
101    pub fn is_empty(&self) -> bool {
102        self.0.order == AVChannelOrder::AV_CHANNEL_ORDER_UNSPEC
103    }
104}
105
106impl From<AVChannelLayout> for ChannelLayout {
107    fn from(value: AVChannelLayout) -> Self {
108        Self(value)
109    }
110}
111
112impl From<ChannelLayout> for AVChannelLayout {
113    fn from(value: ChannelLayout) -> Self {
114        value.0
115    }
116}