1use std::ops::{Deref, DerefMut};
2
3#[cfg(not(feature = "ffmpeg_5_0"))]
4use ffi::*;
5#[cfg(not(feature = "ffmpeg_5_0"))]
6use libc::c_int;
7
8use super::Opened;
9use codec::Context;
10#[cfg(not(feature = "ffmpeg_5_0"))]
11use frame;
12use util::format;
13#[cfg(not(feature = "ffmpeg_5_0"))]
14use {packet, Error};
15use {AudioService, ChannelLayout};
16
17pub struct Audio(pub Opened);
18
19impl Audio {
20 #[deprecated(
21 since = "4.4.0",
22 note = "Underlying API avcodec_decode_audio4 has been deprecated since FFmpeg 3.1; \
23 consider switching to send_packet() and receive_frame()"
24 )]
25 #[cfg(not(feature = "ffmpeg_5_0"))]
26 pub fn decode<P: packet::Ref>(
27 &mut self,
28 packet: &P,
29 out: &mut frame::Audio,
30 ) -> Result<bool, Error> {
31 unsafe {
32 let mut got: c_int = 0;
33
34 match avcodec_decode_audio4(
35 self.as_mut_ptr(),
36 out.as_mut_ptr(),
37 &mut got,
38 packet.as_ptr(),
39 ) {
40 e if e < 0 => Err(Error::from(e)),
41 _ => Ok(got != 0),
42 }
43 }
44 }
45
46 pub fn rate(&self) -> u32 {
47 unsafe { (*self.as_ptr()).sample_rate as u32 }
48 }
49
50 pub fn channels(&self) -> u16 {
51 #[cfg(not(feature = "ffmpeg_7_0"))]
52 unsafe {
53 (*self.as_ptr()).channels as u16
54 }
55
56 #[cfg(feature = "ffmpeg_7_0")]
57 {
58 self.channel_layout().channels() as u16
59 }
60 }
61
62 pub fn format(&self) -> format::Sample {
63 unsafe { format::Sample::from((*self.as_ptr()).sample_fmt) }
64 }
65
66 pub fn request_format(&mut self, value: format::Sample) {
67 unsafe {
68 (*self.as_mut_ptr()).request_sample_fmt = value.into();
69 }
70 }
71
72 pub fn frames(&self) -> usize {
73 #[cfg(not(feature = "ffmpeg_7_0"))]
74 unsafe {
75 (*self.as_ptr()).frame_number as usize
76 }
77
78 #[cfg(feature = "ffmpeg_7_0")]
79 unsafe {
80 (*self.as_ptr()).frame_num as usize
81 }
82 }
83
84 pub fn align(&self) -> usize {
85 unsafe { (*self.as_ptr()).block_align as usize }
86 }
87
88 pub fn channel_layout(&self) -> ChannelLayout {
89 #[cfg(not(feature = "ffmpeg_7_0"))]
90 unsafe {
91 ChannelLayout::from_bits_truncate((*self.as_ptr()).channel_layout)
92 }
93
94 #[cfg(feature = "ffmpeg_7_0")]
95 unsafe {
96 ChannelLayout::from((*self.as_ptr()).ch_layout)
97 }
98 }
99
100 pub fn set_channel_layout(&mut self, value: ChannelLayout) {
101 unsafe {
102 #[cfg(not(feature = "ffmpeg_7_0"))]
103 {
104 (*self.as_mut_ptr()).channel_layout = value.bits();
105 }
106
107 #[cfg(feature = "ffmpeg_7_0")]
108 {
109 (*self.as_mut_ptr()).ch_layout = value.into();
110 }
111 }
112 }
113
114 #[cfg(not(feature = "ffmpeg_7_0"))]
115 pub fn request_channel_layout(&mut self, value: ChannelLayout) {
116 unsafe {
117 (*self.as_mut_ptr()).request_channel_layout = value.bits();
118 }
119 }
120
121 pub fn audio_service(&mut self) -> AudioService {
122 unsafe { AudioService::from((*self.as_mut_ptr()).audio_service_type) }
123 }
124
125 pub fn max_bit_rate(&self) -> usize {
126 unsafe { (*self.as_ptr()).rc_max_rate as usize }
127 }
128
129 pub fn frame_size(&self) -> u32 {
130 unsafe { (*self.as_ptr()).frame_size as u32 }
131 }
132
133 #[cfg(not(feature = "ffmpeg_5_0"))]
134 pub fn frame_start(&self) -> Option<usize> {
135 unsafe {
136 // Removed in ffmpeg >= 5.0 in favor of using encoder
137 // private options.
138 match (*self.as_ptr()).timecode_frame_start {
139 -1 => None,
140 n => Some(n as usize),
141 }
142 }
143 }
144}
145
146impl Deref for Audio {
147 type Target = Opened;
148
149 fn deref(&self) -> &<Self as Deref>::Target {
150 &self.0
151 }
152}
153
154impl DerefMut for Audio {
155 fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
156 &mut self.0
157 }
158}
159
160impl AsRef<Context> for Audio {
161 fn as_ref(&self) -> &Context {
162 self
163 }
164}
165
166impl AsMut<Context> for Audio {
167 fn as_mut(&mut self) -> &mut Context {
168 &mut self.0
169 }
170}
171