Skip to main content

cidre/at/audio/
codec.rs

1use std::{marker::PhantomData, mem::MaybeUninit};
2
3use crate::{
4    arc,
5    at::audio::{
6        self,
7        component::{InitializedState, State, UninitializedState},
8    },
9    cf, os,
10};
11
12/// AudioCodec components translate audio data from one format to another. There
13/// are three kinds of AudioCodec components. Decoder components ('adec')
14/// translate data that isn't in linear PCM into linear PCM formatted data.
15/// Encoder components ('aenc') translate linear PCM data into some other format.
16/// Unity codecs ('acdc') translate between different flavors of the same type
17/// (e.g. 16 bit signed integer linear PCM into 32 bit floating point linear PCM).
18///
19/// AudioCodec components are standard components and are managed by the Component
20/// Manager.
21///
22/// Once an AudioCodec is found that implements the translation in question,
23/// it has to be set up to do the translation. This can be done by setting the
24/// appropriate properties or by calling AudioCodecInitialize. If the translation
25/// is specified by properties, AudioCodecInitialize still needs to be called
26/// prior to appending input data or producing output data.
27
28/// AudioCodecInitialize puts the codec into the "initialized" state. In this state,
29/// the format information for the translation cannot be changed. The codec
30/// has to be in the initialized state for AudioCodecAppendInputData and
31/// AudioCodecProduceOutputData to work. They will return kAudioCodecStateError
32/// if the codec isn't initialized.
33///
34/// AudioCodecUninitialize will return the codec to the uninitialized state and
35/// release any allocated resources. The codec may then be configured freely. It is not
36/// necessary to call AudioCodecUninitialize prior to closing the codec.
37///
38/// Once in the initialized state, the codec is ready to receive input and produce
39/// output using the `append_data` and `produce_data`
40/// routines. Input data can be fed into an encoder and some decoders in any size (even
41/// byte by byte). Input data fed to a decoder should be in terms of whole packets in the
42/// encoded format if the format is variable bit rate and is not self framing (e.g. MPEG-4 AAC).
43/// Output data can only be produced in whole packet sizes. Both routines will return
44/// the amount of data they consume/produce.
45///
46/// AudioCodecProduceOutputData also returns a status code to the caller that
47/// indicates the result of the operation (success or failure) as well as the
48/// state of the input buffer.
49///
50/// The combination of `append_data` and `produce_packets` can be thought of a "push-pull"
51/// model of data handling. First, the input data is pushed into the component and the
52/// resulting output data gets pulled out of that same component.
53///
54/// Basic Workflow
55/// 1. Find the appropriate codec component
56/// 2. Open the codec component
57/// 3. Configure it (AudioCodecGetPropertyInfo, AudioCodecGetProperty, AudioCodecSetProperty)
58/// 4. AudioCodecInitialize
59/// 5. Loop
60///     a. append_data (EOF is signaled by passing a 0-sized buffer)
61///     b. produce_packets
62/// 6. Close the codec component
63#[derive(Debug)]
64#[repr(transparent)]
65pub struct Codec(audio::component::Instance);
66
67#[derive(Debug)]
68pub struct CodecRef<S>(&'static mut Codec, PhantomData<S>)
69where
70    S: State<Codec>;
71
72impl State<Codec> for InitializedState {
73    fn release_resources(instance: &mut Codec) -> os::Result {
74        unsafe { AudioCodecUninitialize(instance).result() }
75    }
76}
77impl State<Codec> for UninitializedState {}
78
79/// These properties reflect the capabilities of the underlying codec.
80/// The values of these properties are independent of the codec's internal
81/// state.
82///
83/// These properties can be read at any time the codec is open.
84#[repr(transparent)]
85pub struct GlobalPropId(pub u32);
86
87/// Properties which can be set or read on an instance of the
88/// underlying audio codec. These properties are dependent on the
89/// codec's current state. A property may be read/write or read
90/// only, depending on the data format of the codec.
91///
92/// These properties may have different values depending on whether the
93/// codec is initialized or not. All properties can be read at any time
94/// the codec is open. However, to ensure the codec is in a valid
95/// operational state and therefore the property value is valid the codec
96/// must be initialized at the time the property is read.
97///
98/// Properties that are writable are only writable when the codec
99/// is not initialized.
100#[repr(transparent)]
101pub struct InstancePropId(pub u32);
102
103impl GlobalPropId {
104    /// An array of audio::StreamBasicDescription structs describing what formats
105    /// the codec supports for input data
106    #[doc(alias = "kAudioCodecPropertySupportedInputFormats")]
107    pub const SUPPORTED_INPUT_FORMATS: Self = Self(u32::from_be_bytes(*b"ifm#"));
108
109    /// An array of audio::StreamBasicDescription structs describing what formats
110    /// the codec supports for output data
111    #[doc(alias = "kAudioCodecPropertySupportedOutputFormats")]
112    pub const SUPPORTED_OUTPUT_FORMATS: Self = Self(u32::from_be_bytes(*b"ofm#"));
113
114    /// An array of audio::ValueRange indicating the valid ranges for the
115    /// output sample rate of the codec for the current bit rate.
116    /// This property is only relevant to encoders.
117    /// See also kAudioCodecPropertyAvailableOutputSampleRates.
118    /// Not writable.
119    #[doc(alias = "kAudioCodecPropertyAvailableInputSampleRates")]
120    pub const AVAILABLE_INPUT_SAMPLE_RATES: Self = Self(u32::from_be_bytes(*b"aisr"));
121
122    /// An array of audio::ValueRange indicating the valid ranges for the
123    /// output sample rate of the codec.
124    /// Required for encoders.
125    /// (see also kAudioCodecPropertyApplicableOutputSampleRates)
126    #[doc(alias = "kAudioCodecPropertyAvailableOutputSampleRates")]
127    pub const AVAILABLE_OUTPUT_SAMPLE_RATES: Self = Self(u32::from_be_bytes(*b"aosr"));
128
129    /// An array of audio::ValueRange that indicate the target bit rates
130    /// supported by the encoder. This can be total bit rate or bit
131    /// rate per channel as appropriate.
132    /// This property is only relevant to encoders.
133    /// (see also kAudioCodecPropertyApplicableBitRateRange)
134    #[doc(alias = "kAudioCodecPropertyAvailableBitRateRange")]
135    pub const AVAILABLE_BIT_RATE_RANGE: Self = Self(u32::from_be_bytes(*b"abrt"));
136
137    /// A u32 indicating the minimum number of input packets
138    /// that need to be supplied to the codec. The actual input the
139    /// codec accepts could be less than this.
140    /// For most codecs this value will be 1.
141    #[doc(alias = "kAudioCodecPropertyMinimumNumberInputPackets")]
142    pub const MINIMUM_NUMBER_INPUT_PACKETS: Self = Self(u32::from_be_bytes(*b"mnip"));
143
144    /// A u32 indicating the minimum number of output packets
145    /// that need to be handled from the codec. The actual output
146    /// might be less than this.
147    /// For most codecs this value will be 1.
148    #[doc(alias = "kAudioCodecPropertyMinimumNumberOutputPackets")]
149    pub const MINIMUM_NUMBER_OUTPUT_PACKETS: Self = Self(u32::from_be_bytes(*b"mnop"));
150
151    /// An array of u32 that specifies the number of channels the codec is
152    /// capable of encoding or decoding to. 0xFFFFFFFF means any number
153    /// of channels.
154    #[doc(alias = "kAudioCodecPropertyAvailableNumberChannels")]
155    pub const AVAILABLE_NUMBER_CHANNELS: Self = Self(u32::from_be_bytes(*b"cmnc"));
156
157    /// A u32 indicating if the codec wants to do a sample rate conversion (if
158    /// necessary) because it can do it in a way that is meaningful for quality.
159    /// Value is 1 if true, 0 otherwise.
160    #[doc(alias = "kAudioCodecPropertyDoesSampleRateConversion")]
161    pub const DOES_SAMPLE_RATE_CONVERSION: Self = Self(u32::from_be_bytes(*b"lmrc"));
162
163    /// An array of audio::ChannelLayoutTag that specifies what channel layouts the codec is
164    /// capable of using on input.
165    #[doc(alias = "kAudioCodecPropertyAvailableInputChannelLayoutTags")]
166    pub const AVAILABLE_INPUT_CHANNEL_LAYOUT_TAGS: Self = Self(u32::from_be_bytes(*b"aicl"));
167
168    /// An array of audio::ChannelLayoutTag that specifies what channel layouts the codec is
169    /// capable of using on output.
170    #[doc(alias = "kAudioCodecPropertyAvailableOutputChannelLayoutTags")]
171    pub const AVAILABLE_OUTPUT_CHANNEL_LAYOUT_TAGS: Self = Self(u32::from_be_bytes(*b"aocl"));
172
173    /// An array of AudioStreamBasicDescription indicating what the codec supports
174    /// for input data given an output format that's passed in as the first member of
175    /// the array (and is overwritten on the reply). Always a subset of
176    /// kAudioCodecPropertySupportedInputFormats
177    #[doc(alias = "kAudioCodecPropertyInputFormatsForOutputFormat")]
178    pub const INPUT_FORMATS_FOR_OUTPUT_FORMAT: Self = Self(u32::from_be_bytes(*b"if4o"));
179
180    /// An array of AudioStreamBasicDescription indicating what the codec supports
181    /// for output data given an input format that's passed in as the first member of
182    /// the array (and is overwritten on the reply). Always a subset of
183    /// kAudioCodecPropertySupportedOutputFormats
184    #[doc(alias = "kAudioCodecPropertyOutputFormatsForInputFormat")]
185    pub const OUTPUT_FORMATS_FOR_INPUT_FORMAT: Self = Self(u32::from_be_bytes(*b"of4i"));
186
187    /// Takes an audio::FormatInfo on input. This audio::FormatInfo is validated either through
188    /// the provided magic cookie or the AudioStreamBasicDescription and where applicable,
189    /// wildcards are overwritten with default values.
190    #[doc(alias = "kAudioCodecPropertyFormatInfo")]
191    pub const FORMAT_INFO: Self = Self(u32::from_be_bytes(*b"acfi"));
192}
193
194impl InstancePropId {
195    /// A u32 indicating the maximum input buffer size for the codec
196    /// in bytes.
197    /// Not writable, but can vary on some codecs depending on the bit stream
198    /// format being handled.
199    #[doc(alias = "kAudioCodecPropertyInputBufferSize")]
200    pub const INPUT_BUF_SIZE: Self = Self(u32::from_be_bytes(*b"tbuf"));
201
202    /// A u32 indicating the number of frames of audio data encapsulated in each
203    /// packet of data in the codec's format. For encoders, this is the
204    /// output format. For decoders this is the input format.
205    /// Formats with variable frames per packet should return a maximum value
206    /// for this property.
207    /// Not writable.
208    #[doc(alias = "kAudioCodecPropertyPacketFrameSize")]
209    pub const PACKET_FRAME_SIZE: Self = Self(u32::from_be_bytes(*b"pakf"));
210
211    /// A u32 where 0 indicates that all packets in the codec's format
212    /// have the same byte size (sometimes referred to as CBR codecs),
213    /// and 1 indicates that they vary in size (sometimes referred to as
214    /// VBR codecs). The maximum size of a variable packet is up to
215    /// the one indicated in kAudioCodecPropertyMaximumPacketByteSize.
216    /// Any codec that reports 1 for this property must be able to handle packet
217    /// descriptions, though it does not have to require them.
218    /// May be writable.
219    #[doc(alias = "kAudioCodecPropertyHasVariablePacketByteSizes")]
220    pub const HAS_VARIABLE_PACKET_BYTE_SIZES: Self = Self(u32::from_be_bytes(*b"vpk?"));
221
222    /// A u32 where 0 indicates that all packets in the codec's format
223    /// are independently decodable, and 1 indicates that some may not be
224    /// independently decodable.
225    #[doc(alias = "kAudioCodecPropertyEmploysDependentPackets")]
226    pub const EMPLOYS_DEPENDENT_PACKETS: Self = Self(u32::from_be_bytes(*b"dpk?"));
227
228    /// A u32 indicating the maximum number of bytes a packet of data
229    /// in the codec's format will be. If the format is constant bit rate,
230    /// all packets will be this size. If it is variable bit rate, the packets
231    /// will never exceed this size.
232    /// This always refers to the encoded data, so for encoders it refers to the
233    /// output data and for decoders the input data.
234    /// Not writable.
235    #[doc(alias = "kAudioCodecPropertyMaximumPacketByteSize")]
236    pub const MAXIMUM_PACKET_BYTE_SIZE: Self = Self(u32::from_be_bytes(*b"pakb"));
237
238    /// A u32 indicating the maximum number of bits in an output packet of an encoder.
239    /// The output packet size will not exceed this number. The size should be smaller
240    /// than kAudioCodecPropertyMaximumPacketByteSize. This property will configure the
241    /// encoder to VBR mode with the highest VBR quality that can maintain the packet
242    /// size limit. kAudioCodecPropertySoundQualityForVBR can be used to retrieve the
243    /// quality setting that will be used given that packet size limit.
244    /// Writeable if supported.
245    #[doc(alias = "kAudioCodecPropertyPacketSizeLimitForVBR")]
246    pub const PACKET_SIZE_LIMIT_FOR_VBR: Self = Self(u32::from_be_bytes(*b"pakl"));
247
248    /// An AudioStreamBasicDescription describing the format the codec
249    /// expects its input data in
250    /// Almost always writable, but if the codec only supports one unique input format
251    /// it does not have to be
252    #[doc(alias = "kAudioCodecPropertyCurrentInputFormat")]
253    pub const CURRENT_INPUT_FORMAT: Self = Self(u32::from_be_bytes(*b"ifmt"));
254
255    /// An audio::StreamBasicDescription describing the format the codec
256    /// provides its output data in
257    /// Almost always writable, but if the codec only supports one unique output format
258    /// it does not have to be
259    #[doc(alias = "kAudioCodecPropertyCurrentOutputFormat")]
260    pub const CURRENT_OUTPUT_FORMAT: Self = Self(u32::from_be_bytes(*b"ofmt"));
261
262    /// An untyped buffer of out of band configuration data the codec
263    /// requires to process the stream of data correctly. The contents
264    /// of this data is private to the codec.
265    /// Not all codecs have magic cookies. If a call to AudioCodecGetPropertyInfo
266    /// returns a size greater than 0 then the codec may take one.
267    /// Writable if present.
268    #[doc(alias = "kAudioCodecPropertyMagicCookie")]
269    pub const MAGIC_COOKIE: Self = Self(u32::from_be_bytes(*b"kuki"));
270
271    /// A u32 indicating the number of bytes in the codec's input
272    /// buffer. The amount of available buffer space is simply the
273    /// answer from kAudioCodecPropertyInputBufferSize minus the answer
274    /// from this property.
275    /// Not writable.
276    #[doc(alias = "kAudioCodecPropertyUsedInputBufferSize")]
277    pub const USED_INPUT_BUF_SIZE: Self = Self(u32::from_be_bytes(*b"ubuf"));
278
279    /// A u32 where 0 means the codec is uninitialized and anything
280    /// else means the codec is initialized. This should never be settable directly.
281    /// Must be set by AudioCodecInitialize and AudioCodecUninitialize.
282    #[doc(alias = "kAudioCodecPropertyIsInitialized")]
283    pub const IS_INITIALIZED: Self = Self(u32::from_be_bytes(*b"init"));
284
285    /// A u32 containing the number of bits per second to aim for when encoding
286    /// data. This property is usually only relevant to encoders, but if a decoder
287    /// can know what bit rate it's set to it may report it.
288    /// This property is irrelevant if the encoder is configured as kAudioCodecBitRateControlMode_Variable.
289    /// Writable on encoders if supported.
290    #[doc(alias = "kAudioCodecPropertyCurrentTargetBitRate")]
291    pub const CURRENT_TARGET_BIT_RATE: Self = Self(u32::from_be_bytes(*b"brat"));
292
293    /// A f64 containing the current input sample rate in Hz. No Default.
294    /// May be writable. If only one sample rate is supported it does not have to be.
295    #[doc(alias = "kAudioCodecPropertyCurrentInputSampleRate")]
296    pub const CURRENT_INPUT_SAMPLE_RATE: Self = Self(u32::from_be_bytes(*b"cisr"));
297
298    /// A f64 containing the current output sample rate in Hz. No Default.
299    /// May be writable. If only one sample rate is supported it does not have to be.
300    #[doc(alias = "kAudioCodecPropertyCurrentOutputSampleRate")]
301    pub const CURRENT_OUTPUT_SAMPLE_RATE: Self = Self(u32::from_be_bytes(*b"cosr"));
302
303    /// A u32 that sets the tradeoff between sound quality and CPU time consumption.
304    /// The property value is between [0 - 0x7F].
305    /// Some enum constants are defined below for convenience.
306    /// Writable if supported.
307    #[doc(alias = "kAudioCodecPropertyQualitySetting")]
308    pub const QUALITY_SETTING: Self = Self(u32::from_be_bytes(*b"srcq"));
309
310    /// An array of audio::ValueRange indicating the target bit rates
311    /// supported by the encoder in its current configuration.
312    /// This property is only relevant to encoders.
313    /// See also kAudioCodecPropertyAvailableBitRateRange.
314    /// Not writable.
315    #[doc(alias = "kAudioCodecPropertyApplicableBitRateRange")]
316    pub const APPLICABLE_BIT_RATE_RANGE: Self = Self(u32::from_be_bytes(*b"brta"));
317
318    /// An array of AudioValueRange indicating the recommended bit rates
319    /// at given sample rate.
320    /// This property is only relevant to encoders.
321    /// Not writable.
322    #[doc(alias = "kAudioCodecPropertyRecommendedBitRateRange")]
323    pub const RECOMMENDED_BIT_RATE_RANGE: Self = Self(u32::from_be_bytes(*b"brtr"));
324
325    /// An array of audio::ValueRange indicating the valid ranges for the
326    /// input sample rate of the codec for the current bit rate.
327    /// This property is only relevant to encoders.
328    /// See also kAudioCodecPropertyAvailableInputSampleRates.
329    /// Not writable.
330    #[doc(alias = "kAudioCodecPropertyApplicableInputSampleRates")]
331    pub const APPLICABLE_INPUT_SAMPLE_RATES: Self = Self(u32::from_be_bytes(*b"isra"));
332
333    /// An array of audio::ValueRange indicating the valid ranges for the
334    /// output sample rate of the codec for the current bit rate.
335    /// This property is only relevant to encoders.
336    /// See also kAudioCodecPropertyAvailableOutputSampleRates.
337    /// Not writable.
338    #[doc(alias = "kAudioCodecPropertyApplicableOutputSampleRates")]
339    pub const APPLICABLE_OUTPUT_SAMPLE_RATES: Self = Self(u32::from_be_bytes(*b"osra"));
340
341    /// A u32 indicating the number of zeros (samples) that were appended
342    /// to the last packet of input data to make a complete packet encoding.
343    /// Encoders only. No default.
344    /// Not writable.
345    #[doc(alias = "kAudioCodecPropertyPaddedZeros")]
346    pub const PADDED_ZEROS: Self = Self(u32::from_be_bytes(*b"pad0"));
347
348    /// A u32 specifying priming method.
349    /// See enum below.
350    /// May be writable. Some encoders offer the option of padding out the last packet, and this
351    /// may be set here.
352    #[doc(alias = "kAudioCodecPropertyPrimeMethod")]
353    pub const PRIME_METHOD: Self = Self(u32::from_be_bytes(*b"prmm"));
354
355    /// A pointer to an audio::CodecPrimeInfo struct.
356    /// Not writable on encoders. On decoders this may be writable, telling the decoder to trim the
357    /// first and/or last packet.
358    #[doc(alias = "kAudioCodecPropertyPrimeInfo")]
359    pub const PRIME_INFO: Self = Self(u32::from_be_bytes(*b"prim"));
360
361    /// An audio::ChannelLayout that specifies the channel layout that the codec is using for input.
362    /// May be writable. If only one channel layout is supported it does not have to be.
363    #[doc(alias = "kAudioCodecPropertyCurrentInputChannelLayout")]
364    pub const CURRENT_INPUT_CHANNEL_LAYOUT: Self = Self(u32::from_be_bytes(*b"icl "));
365
366    /// An audio::ChannelLayout that specifies the channel layout that the codec is using for output.
367    /// If settable on a encoder, it means the encoder can re-map channels
368    /// May be writable. If only one channel layout is supported or the codec does no channel remapping
369    /// (ie, output channel layout always equals the input channel layout) it does not have to be.
370    #[doc(alias = "kAudioCodecPropertyCurrentOutputChannelLayout")]
371    pub const CURRENT_OUTPUT_CHANNEL_LAYOUT: Self = Self(u32::from_be_bytes(*b"ocl "));
372
373    /// A cf::Dictionary that lists both the settable codec settings and their values.
374    /// Encoders only.
375    /// Obviously this will be linked to many of the other properties listed herein and as such
376    /// it potentially will cause synchronization problems. Therefore, when setting this property
377    /// on an encoder a GetProperty should be done first to retrieve the current dictionary,
378    /// and only one setting within the dictionary should change with each SetProperty call,
379    /// as it is not guaranteed that changing one property will not have side effects.
380    /// Writable if supported.
381    #[doc(alias = "kAudioCodecPropertySettings")]
382    pub const SETTINGS: Self = Self(u32::from_be_bytes(*b"acs "));
383
384    /// An array of audio::FormatListItem structs list all formats that can be handled by the decoder
385    /// For decoders, takes a Magic Cookie that gets passed in on the GetProperty call. No default.
386    /// On input, the outPropertyData parameter passed to GetProperty should begin with a
387    /// audio::CodecMagicCookieInfo struct which will be overwritten by the AudioFormatListItems
388    /// returned from the property. For encoders, returns a list of formats which will be in the
389    /// bitstream. No input data required.
390    /// Important note: this encoder property is only applicable to audio formats which are made of
391    /// two or more layers where the base layers(s) can be decoded by systems which aren't capable of
392    /// handling the enhancement layers. For example, a High Efficiency AAC bitstream which contains
393    /// an AAC Low Complexity base layer can be decoded by any AAC decoder.
394    #[doc(alias = "kAudioCodecPropertyFormatList")]
395    pub const FORMAT_LIST: Self = Self(u32::from_be_bytes(*b"acfl"));
396
397    /// A u32 indicating which bit rate control mode will be applied to encoders that
398    /// can produce variable packet sizes (sometimes referred to as VBR encoders).
399    /// Although the packet size may be variable, a constant bit rate can be maintained
400    /// over a transmission channel when decoding in real-time with a fixed end-to-end audio delay.
401    /// E.g., MP3 and MPEG-AAC use a bit reservoir mechanism to meet that constraint.
402    /// See enum below.
403    /// Only needs to be settable if the codec supports multiple bit rate control strategies.
404    #[doc(alias = "kAudioCodecPropertyBitRateControlMode")]
405    pub const BIT_RATE_CONTROL_MODE: Self = Self(u32::from_be_bytes(*b"acbf"));
406
407    /// A u32 that sets a target sound quality level.
408    /// Unlike kAudioCodecPropertyQualitySetting which is relevant to all BitRate Control Modes,
409    /// this property only needs to be set by an encoder configured at kAudioCodecBitRateControlMode_Variable.
410    /// The property value is between [0 - 0x7F].
411    /// See also kAudioCodecPropertyQualitySetting
412    /// Writable if supported.
413    #[doc(alias = "kAudioCodecPropertySoundQualityForVBR")]
414    pub const SOUND_QUALITY_FOR_VBR: Self = Self(u32::from_be_bytes(*b"vbrq"));
415
416    /// A u32 that can be used to set the target bit rate when the encoder is configured
417    /// for VBR mode (kAudioCodecBitRateControlMode_Variable). Writable if supported.
418    #[doc(alias = "kAudioCodecPropertyBitRateForVBR")]
419    pub const BIT_RATE_FOR_VBR: Self = Self(u32::from_be_bytes(*b"vbrb"));
420
421    /// A u32 specifying the delay mode. See enum below.
422    /// Writable if supported.
423    #[doc(alias = "kAudioCodecPropertyDelayMode")]
424    pub const DELAY_MODE: Self = Self(u32::from_be_bytes(*b"dmod"));
425
426    /// An i32 number in the range [-128, 127] to allow encoding quality adjustements on a packet by packet basis.
427    /// This property can be set on an initialized encoder object without having to uninitialize and re-intialize it
428    /// and allows to adjust the encoder quality level for every packet. This is useful for packets streamed over
429    /// unreliable IP networks where the encoder needs to adapt immediately to network condition changes.
430    /// Escape property ID's start with a '^' symbol as the first char code. This bypasses the initilization check.
431    #[doc(alias = "kAudioCodecPropertyAdjustLocalQuality")]
432    pub const ADJUST_LOCAL_QUALITY: Self = Self(u32::from_be_bytes(*b"^qal"));
433
434    /// A f32 specifying the program target level in dB FS for decoders.
435    /// Supported target levels are in the range of -31.0 to -20.0dB.
436    /// This property controls the decoding of broadcast loudness
437    /// normalization metadata with goal of achieving consistent loudness across various
438    /// programs. The property complies with the target level defined in the MPEG Audio
439    /// standard ISO/IEC 14496-3. It will override kAudioCodecPropertyProgramTargetLevelConstant.
440    #[doc(alias = "kAudioCodecPropertyProgramTargetLevel")]
441    pub const PROGRAM_TARGET_LEVEL: Self = Self(u32::from_be_bytes(*b"pptl"));
442
443    /// A u32 specifying the DRC mode. Supported modes are defined as enum with the
444    /// prefix kDynamicRangeControlMode (see below). This property controls which
445    /// dynamic range compression scheme is applied if the information is present in
446    /// the bitstream. The default is kDynamicRangeControlMode_None.
447    #[doc(alias = "kAudioCodecPropertyDynamicRangeControlMode")]
448    pub const DYNAMIC_RANGE_CONTROL_MODE: Self = Self(u32::from_be_bytes(*b"mdrc"));
449
450    /// A u32 specifying the program target level constant in dB FS (Full Scale) for decoders.
451    /// Supported target levels are defined as enum with the prefix kProgramTargetLevel
452    /// (see below). This property controls the decoding of broadcast loudness
453    /// normalization metadata with the goal of achieving consistent loudness across various
454    /// programs. The property complies with the target level defined in the MPEG Audio
455    /// standard ISO/IEC 14496-3. The default is kProgramTargetLevel_None.
456    #[doc(alias = "kAudioCodecPropertyProgramTargetLevelConstant")]
457    pub const PROGRAM_TARGET_LEVEL_CONSTANT: Self = Self(u32::from_be_bytes(*b"ptlc"));
458
459    /// A u32 specifying the dynamic range compression profile to be applied in the decoder. Profiles are
460    /// based on the DRC Effect Types in ISO/IEC 23003-4. Supported profiles are defined as DynamicRangeCompressionProfile
461    /// enum (see below). The default profile is DynamicRangeCompressionProfile::None.
462    /// This property can also be set on an initialized decoder object. It will be applied immediately, if supported.
463    #[doc(alias = "kAudioCodecPropertyAdjustCompressionProfile")]
464    pub const ADJUST_COMPRESSION_PROFILE: Self = Self(u32::from_be_bytes(*b"^pro"));
465
466    /// A f32 specifying the program target loudness in LKFS for decoders. It has the same effect
467    /// as kAudioCodecPropertyProgramTargetLevel, but this property can also be set on an initialized decoder
468    /// object. It will be applied immediately, if supported.
469    #[doc(alias = "kAudioCodecPropertyAdjustTargetLevel")]
470    pub const ADJUST_TARGET_LEVEL: Self = Self(u32::from_be_bytes(*b"^ptl"));
471
472    /// A u32 specifying the program target loudness in LKFS for decoders. It has the same effect
473    /// as kAudioCodecPropertyProgramTargetLevelConstant, but this property can also be set on an
474    /// initialized decoder object. It will be applied immediately, if supported.
475    /// A value of kProgramTargetLevel_None removes a prior target level setting.
476    #[doc(alias = "kAudioCodecPropertyAdjustTargetLevelConstant")]
477    pub const ADJUST_TARGET_LEVEL_CONSTANT: Self = Self(u32::from_be_bytes(*b"^tlc"));
478}
479
480/// Constants to be used with kAudioCodecPropertyProgramTargetLevelConstant to set the target loudness
481#[derive(Debug, Copy, Clone, Eq, PartialEq)]
482#[repr(u32)]
483pub enum ProgramTargetLevel {
484    #[doc(alias = "kProgramTargetLevel_None")]
485    None = 0,
486
487    #[doc(alias = "kProgramTargetLevel_Minus31dB")]
488    Minus31dB = 1,
489
490    #[doc(alias = "kProgramTargetLevel_Minus23dB")]
491    Minus23dB = 2,
492
493    #[doc(alias = "kProgramTargetLevel_Minus20dB")]
494    Minus20dB = 3,
495}
496
497/// Constants to be used with kAudioCodecPropertyAdjustCompressionProfile to control
498/// the DRC Effect Type based on ISO/IEC 23003-4
499#[derive(Debug, Copy, Clone, Eq, PartialEq)]
500#[repr(u32)]
501pub enum DynamicRangeCompressionProfile {
502    /// No compression
503    #[doc(alias = "kDynamicRangeCompressionProfile_None")]
504    None = 0,
505
506    /// Compression to avoid disturbing others and listening at lower volume
507    #[doc(alias = "kDynamicRangeCompressionProfile_LateNight")]
508    LateNight = 1,
509
510    /// Compression suitable for listening in noisy environments
511    #[doc(alias = "kDynamicRangeCompressionProfile_NoisyEnvironment")]
512    NoisyEnvironment = 2,
513
514    /// Compression for transducers with limited dynamic range
515    #[doc(alias = "kDynamicRangeCompressionProfile_LimitedPlaybackRange")]
516    LimitedPlaybackRange = 3,
517
518    /// General purpose compression
519    #[doc(alias = "kDynamicRangeCompressionProfile_GeneralCompression")]
520    GeneralCompression = 6,
521}
522
523/// Constants defining various bit rate control modes
524/// to be used with kAudioCodecPropertyBitRateControlMode.
525/// These modes are only applicable to encoders that can produce
526/// variable packet sizes, such as AAC.
527#[derive(Debug, Copy, Clone, Eq, PartialEq)]
528#[repr(u32)]
529pub enum BitRateControlMode {
530    /// The encoder maintains a constant bit rate suitable for use over a transmission
531    /// channel when decoding in real-time with a fixed end-to-end audio delay.  
532    /// Note that while a constant bit rate is maintained in this mode, the number of bits
533    /// allocated to encode each fixed length of audio data may be variable
534    /// (ie. packet sizes are variable).
535    /// E.g., MP3 and MPEG-AAC use a bit reservoir mechanism to meet that constraint.
536    Constant = 0,
537
538    ///  The provided target bit rate is achieved over a long term average
539    ///  (typically after the first 1000 packets). This mode is similar to
540    ///  BitRateControlMode::Constant in the sense that the
541    ///  target bit rate will be maintained in a long term average. However, it does not
542    ///  provide constant delay when using constant bit rate transmission. This mode offers
543    ///  a better sound quality than BitRateControlMode::Constant
544    ///  can, that is, a more efficient encoding is performed.
545    LongTermAverage = 1,
546
547    /// Encoder dynamically allocates the bit resources according to the characteristics
548    /// of the underlying signal. However, some constraints are applied in order to limit
549    /// the variation of the bit rate.
550    VariableConstrained = 2,
551
552    /// Similar to the VBR constrained mode, however the packet size is virtually unconstrained.
553    /// The coding process targets constant sound quality, and the sound quality level is
554    /// set by kAudioCodecPropertySoundQualityForVBR.
555    /// This mode usually provides the best tradeoff between quality and bit rate.
556    Variable = 3,
557}
558
559#[doc(alias = "kAudioDecoderComponentType")]
560pub const DECODER_COMPONENT_TYPE: os::Type = u32::from_be_bytes(*b"adec");
561
562#[doc(alias = "kAudioEncoderComponentType")]
563pub const ENCODER_COMPONENT_TYPE: os::Type = u32::from_be_bytes(*b"aenc");
564
565#[doc(alias = "kAudioUnityCodecComponentType")]
566pub const UNITY_CODEC_COMPONENT_TYPE: os::Type = u32::from_be_bytes(*b"acdc");
567
568/// Structure holding the magic cookie information.
569#[repr(C)]
570pub struct MagicCookieInfo {
571    /// The size of the magic cookie
572    pub size: u32,
573    /// Generic const pointer to magic cookie
574    /// usually it is esds
575    pub value: *const u8,
576}
577
578#[derive(Debug)]
579pub struct Consumed {
580    pub bytes: u32,
581    pub packets: u32,
582}
583
584#[derive(Debug)]
585pub struct Produced {
586    pub bytes: u32,
587    pub packets: u32,
588    pub status: ProduceOutputPacketStatus,
589}
590
591impl CodecRef<UninitializedState> {
592    pub fn new_apple_aac_encoder() -> os::Result<Self> {
593        let desc = audio::ComponentDesc {
594            type_: audio::ENCODER_COMPONENT_TYPE,
595            sub_type: audio::Format::MPEG4_AAC.0,
596            manufacturer: audio::unit::Manufacturer::APPLE.0,
597            ..Default::default()
598        };
599
600        let comp = desc
601            .into_iter()
602            .next()
603            .ok_or(audio::unit::component_err::UNSUPPORTED_TYPE)?;
604        comp.open_codec()
605    }
606
607    pub fn new_apple_opus_encoder() -> os::Result<Self> {
608        let desc = audio::ComponentDesc {
609            type_: audio::ENCODER_COMPONENT_TYPE,
610            sub_type: audio::Format::OPUS.0,
611            manufacturer: audio::unit::Manufacturer::APPLE.0,
612            ..Default::default()
613        };
614
615        let comp = desc
616            .into_iter()
617            .next()
618            .ok_or(audio::unit::component_err::UNSUPPORTED_TYPE)?;
619        comp.open_codec()
620    }
621
622    pub fn initialize(
623        self,
624        input_format: *const audio::StreamBasicDesc,
625        output_format: *const audio::StreamBasicDesc,
626        magic_cookie: Option<&[u8]>,
627    ) -> os::Result<CodecRef<InitializedState>> {
628        unsafe {
629            self.0
630                .init_codec(input_format, output_format, magic_cookie)?;
631            Ok(CodecRef(std::mem::transmute(self), PhantomData))
632        }
633    }
634
635    #[inline]
636    pub fn set_quality(&mut self, val: u32) -> os::Result {
637        self.0.set_quality(val)
638    }
639
640    #[inline]
641    pub fn set_bit_rate_control_mode(&mut self, val: BitRateControlMode) -> os::Result {
642        self.0.set_bit_rate_control_mode(val)
643    }
644
645    #[inline]
646    pub fn set_current_target_bit_rate(&mut self, val: u32) -> os::Result {
647        self.0.set_current_target_bit_rate(val)
648    }
649
650    pub fn input_formats_for_output_format(
651        &self,
652        output_format: &audio::StreamBasicDesc,
653    ) -> os::Result<Vec<audio::StreamBasicDesc>> {
654        self.0.input_formats_for_output_format(output_format)
655    }
656
657    pub fn output_formats_for_input_format(
658        &self,
659        input_format: &audio::StreamBasicDesc,
660    ) -> os::Result<Vec<audio::StreamBasicDesc>> {
661        self.0.output_formats_for_input_format(input_format)
662    }
663}
664
665impl<S: State<Codec>> Drop for CodecRef<S> {
666    #[inline]
667    fn drop(&mut self) {
668        let res = S::release_resources(self.0);
669        debug_assert!(res.is_ok());
670        let res = unsafe { self.0.0.dispose() };
671        debug_assert!(res.is_ok());
672    }
673}
674
675impl CodecRef<InitializedState> {
676    /// This call will move the codec from the initialized state back to the
677    /// uninitialized state. The codec will release any resources it allocated
678    /// or claimed in AudioCodecInitialize.
679    pub fn uninitialize(mut self) -> os::Result<CodecRef<UninitializedState>> {
680        Ok(unsafe {
681            AudioCodecUninitialize(&mut self.0).result()?;
682            std::mem::transmute(self)
683        })
684    }
685
686    #[doc(alias = "AudioCodecAppendInputData")]
687    #[inline]
688    pub fn append(&mut self, data: &[u8]) -> os::Result<u32> {
689        let mut data_len: u32 = data.len() as _;
690        unsafe {
691            AudioCodecAppendInputData(
692                &mut self.0,
693                data.as_ptr(),
694                &mut data_len,
695                std::ptr::null_mut(),
696                std::ptr::null(),
697            )
698            .result()?;
699        }
700        Ok(data_len)
701    }
702
703    #[doc(alias = "AudioCodecAppendInputData")]
704    #[inline]
705    pub unsafe fn append_input(&mut self, data_ptr: *const u8, data_len: &mut u32) -> os::Result {
706        unsafe {
707            AudioCodecAppendInputData(
708                &mut self.0,
709                data_ptr,
710                data_len,
711                std::ptr::null_mut(),
712                std::ptr::null(),
713            )
714            .result()
715        }
716    }
717
718    /// Append as much of the given data to the codec's input buffer as possible
719    /// and return in (data_len, packets_len) the amount of data and packets used.
720    #[doc(alias = "AudioCodecAppendInputData")]
721    #[inline]
722    pub fn append_data(
723        &mut self,
724        data: &[u8],
725        packets: &[audio::StreamPacketDesc],
726    ) -> os::Result<Consumed> {
727        let mut data_len: u32 = data.len() as _;
728        let mut packets_len: u32 = packets.len() as _;
729        unsafe {
730            AudioCodecAppendInputData(
731                &mut self.0,
732                data.as_ptr(),
733                &mut data_len,
734                &mut packets_len,
735                packets.as_ptr(),
736            )
737            .result()?;
738        }
739
740        Ok(Consumed {
741            bytes: data_len,
742            packets: packets_len,
743        })
744    }
745
746    #[doc(alias = "AudioCodecProduceOutputPackets")]
747    #[inline]
748    pub fn produce_packet(
749        &mut self,
750        data: &mut [u8],
751    ) -> os::Result<(u32, ProduceOutputPacketStatus)> {
752        let mut data_len: u32 = data.len() as _;
753        let mut packets_n: u32 = 1;
754        let mut status = MaybeUninit::uninit();
755
756        unsafe {
757            AudioCodecProduceOutputPackets(
758                &mut self.0,
759                data.as_mut_ptr(),
760                &mut data_len,
761                &mut packets_n,
762                std::ptr::null_mut(),
763                status.as_mut_ptr(),
764            )
765            .result()?;
766        }
767
768        Ok((data_len, unsafe { status.assume_init() }))
769    }
770
771    #[doc(alias = "AudioCodecProduceOutputPackets")]
772    #[inline]
773    pub fn produce_packets(
774        &mut self,
775        data: &mut [u8],
776        out_packet_descriptions: &mut [audio::StreamPacketDesc],
777    ) -> os::Result<Produced> {
778        let mut data_len: u32 = data.len() as _;
779        let mut packets_len: u32 = out_packet_descriptions.len() as _;
780        let mut status = ProduceOutputPacketStatus::Failure;
781
782        unsafe {
783            AudioCodecProduceOutputPackets(
784                &mut self.0,
785                data.as_mut_ptr(),
786                &mut data_len,
787                &mut packets_len,
788                out_packet_descriptions.as_mut_ptr(),
789                &mut status,
790            )
791            .result()?;
792        }
793        Ok(Produced {
794            bytes: data_len,
795            packets: packets_len,
796            status,
797        })
798    }
799
800    #[doc(alias = "AudioCodecAppendInputBufferList")]
801    #[inline]
802    pub fn append_buf_list(
803        &mut self,
804        in_buf_list: &audio::BufList,
805        packet_descriptions: &mut [audio::StreamPacketDesc],
806    ) -> os::Result<Consumed> {
807        let mut bytes_consumed: u32 = 0;
808        let mut packets_len: u32 = packet_descriptions.len() as _;
809        unsafe {
810            AudioCodecAppendInputBufferList(
811                &mut self.0,
812                in_buf_list,
813                &mut packets_len,
814                packet_descriptions.as_ptr(),
815                &mut bytes_consumed,
816            )
817            .result()?;
818        }
819
820        Ok(Consumed {
821            bytes: bytes_consumed,
822            packets: packets_len,
823        })
824    }
825
826    #[doc(alias = "AudioCodecProduceOutputBufferList")]
827    #[inline]
828    pub fn produce_buf_list(
829        &mut self,
830        buf_list: &mut audio::BufList,
831        number_of_packets: &mut u32,
832    ) -> os::Result<os::Status> {
833        let mut status = os::Status::NO_ERR;
834        unsafe {
835            AudioCodecProduceOutputBufferList(
836                &mut self.0,
837                buf_list,
838                number_of_packets,
839                std::ptr::null_mut(),
840                &mut status,
841            )
842            .result()?;
843        }
844
845        Ok(status)
846    }
847
848    #[doc(alias = "AudioCodecProduceOutputBufferList")]
849    #[inline]
850    pub fn produce_buf_list_with_descs(
851        &mut self,
852        buf_list: &mut audio::BufList,
853        packet_descriptions: &mut [audio::StreamPacketDesc],
854    ) -> os::Result<(u32, os::Status)> {
855        let mut number_packets: u32 = packet_descriptions.len() as _;
856        let mut status = os::Status::NO_ERR;
857        unsafe {
858            AudioCodecProduceOutputBufferList(
859                &mut self.0,
860                buf_list,
861                &mut number_packets,
862                packet_descriptions.as_mut_ptr(),
863                &mut status,
864            )
865            .result()?;
866        }
867
868        Ok((number_packets, status))
869    }
870}
871
872impl Codec {
873    pub unsafe fn init_codec(
874        &mut self,
875        input_format: *const audio::StreamBasicDesc,
876        output_format: *const audio::StreamBasicDesc,
877        magic_cookie: Option<&[u8]>,
878    ) -> os::Result {
879        unsafe {
880            match magic_cookie {
881                Some(cookie) => AudioCodecInitialize(
882                    self,
883                    input_format,
884                    output_format,
885                    cookie.as_ptr(),
886                    cookie.len() as _,
887                )
888                .result(),
889                None => {
890                    AudioCodecInitialize(self, input_format, output_format, std::ptr::null(), 0)
891                        .result()
892                }
893            }
894        }
895    }
896
897    #[doc(alias = "AudioCodecGetPropertyInfo")]
898    #[inline]
899    pub fn prop_info(&self, prop_id: u32) -> os::Result<(u32, bool)> {
900        let (mut size, mut writable) = (0u32, false);
901        unsafe { AudioCodecGetPropertyInfo(&self, prop_id, &mut size, &mut writable).result()? };
902        Ok((size, writable))
903    }
904
905    #[doc(alias = "AudioCodecGetProperty")]
906    #[inline]
907    pub unsafe fn prop_vec<T: Sized + Default + Clone>(&self, prop_id: u32) -> os::Result<Vec<T>> {
908        let (mut size, _) = self.prop_info(prop_id)?;
909        if size == 0 {
910            return Ok(vec![]);
911        }
912        let mut vec = vec![T::default(); size as usize / std::mem::size_of::<T>()];
913        unsafe {
914            AudioCodecGetProperty(self, prop_id, &mut size, vec.as_mut_ptr() as _).result()?;
915        }
916        Ok(vec)
917    }
918
919    pub fn cf_prop<T: arc::Release>(&self, prop_id: u32) -> os::Result<arc::R<T>> {
920        let mut size = std::mem::size_of::<arc::R<T>>() as u32;
921        os::result_init(|res| unsafe {
922            AudioCodecGetProperty(self, prop_id, &mut size, res as *mut u8)
923        })
924    }
925
926    #[doc(alias = "AudioCodecGetProperty")]
927    pub fn prop<T: Sized>(&self, prop_id: u32) -> os::Result<T> {
928        let mut size = std::mem::size_of::<T>() as u32;
929        unsafe {
930            let mut value = MaybeUninit::<T>::uninit();
931            AudioCodecGetProperty(self, prop_id, &mut size, value.as_mut_ptr() as _).result()?;
932            Ok(value.assume_init())
933        }
934    }
935
936    pub unsafe fn set_prop<T: Sized>(&mut self, property_id: u32, val: &T) -> os::Result {
937        let size = std::mem::size_of::<T>() as u32;
938        unsafe { AudioCodecSetProperty(self, property_id, size, val as *const _ as _).result() }
939    }
940
941    #[inline]
942    pub fn quality(&self) -> os::Result<u32> {
943        self.prop(InstancePropId::QUALITY_SETTING.0)
944    }
945
946    pub fn settings(&self) -> os::Result<arc::R<cf::DictionaryOf<cf::String, cf::Type>>> {
947        self.cf_prop(InstancePropId::SETTINGS.0)
948    }
949
950    #[inline]
951    pub fn set_quality(&mut self, val: u32) -> os::Result {
952        unsafe { self.set_prop(InstancePropId::QUALITY_SETTING.0, &val) }
953    }
954    #[inline]
955    pub fn bit_rate_control_mode(&self) -> os::Result<BitRateControlMode> {
956        self.prop(InstancePropId::BIT_RATE_CONTROL_MODE.0)
957    }
958
959    #[inline]
960    pub fn set_bit_rate_control_mode(&mut self, val: BitRateControlMode) -> os::Result {
961        unsafe { self.set_prop(InstancePropId::BIT_RATE_CONTROL_MODE.0, &val) }
962    }
963
964    #[inline]
965    pub fn current_target_bit_rate(&self) -> os::Result<u32> {
966        self.prop(InstancePropId::CURRENT_TARGET_BIT_RATE.0)
967    }
968
969    #[inline]
970    pub fn set_current_target_bit_rate(&mut self, val: u32) -> os::Result {
971        unsafe { self.set_prop(InstancePropId::CURRENT_TARGET_BIT_RATE.0, &val) }
972    }
973
974    #[inline]
975    pub fn current_input_sample_rate(&self) -> os::Result<f64> {
976        self.prop(InstancePropId::CURRENT_INPUT_SAMPLE_RATE.0)
977    }
978
979    /// A f64 containing the current input sample rate in Hz. No Default.
980    /// May be writable. If only one sample rate is supported it does not have to be.
981    #[inline]
982    pub fn set_current_input_sample_rate(&mut self, val: f64) -> os::Result {
983        unsafe { self.set_prop(InstancePropId::CURRENT_INPUT_SAMPLE_RATE.0, &val) }
984    }
985
986    /// A f64 containing the current output sample rate in Hz. No Default.
987    /// May be writable. If only one sample rate is supported it does not have to be.
988    #[inline]
989    pub fn current_output_sample_rate(&self) -> os::Result<f64> {
990        self.prop(InstancePropId::CURRENT_OUTPUT_SAMPLE_RATE.0)
991    }
992
993    #[inline]
994    pub fn set_current_output_sample_rate(&mut self, val: f64) -> os::Result {
995        unsafe { self.set_prop(InstancePropId::CURRENT_OUTPUT_SAMPLE_RATE.0, &val) }
996    }
997
998    #[inline]
999    pub fn set_current_input_channel_layout<const N: usize>(
1000        &mut self,
1001        val: &audio::ChannelLayout<N>,
1002    ) -> os::Result {
1003        unsafe { self.set_prop(InstancePropId::CURRENT_INPUT_CHANNEL_LAYOUT.0, val) }
1004    }
1005
1006    #[inline]
1007    pub fn current_input_channel_layout<const N: usize>(
1008        &self,
1009    ) -> os::Result<audio::ChannelLayout<N>> {
1010        self.prop(InstancePropId::CURRENT_INPUT_CHANNEL_LAYOUT.0)
1011    }
1012
1013    #[inline]
1014    pub fn set_current_output_channel_layout<const N: usize>(
1015        &mut self,
1016        val: &audio::ChannelLayout<N>,
1017    ) -> os::Result {
1018        unsafe { self.set_prop(InstancePropId::CURRENT_OUTPUT_CHANNEL_LAYOUT.0, val) }
1019    }
1020
1021    #[inline]
1022    pub fn current_output_channel_layout<const N: usize>(
1023        &self,
1024    ) -> os::Result<audio::ChannelLayout<N>> {
1025        self.prop(InstancePropId::CURRENT_OUTPUT_CHANNEL_LAYOUT.0)
1026    }
1027
1028    #[inline]
1029    pub fn applicable_input_sample_rates(&self) -> os::Result<Vec<audio::ValueRange>> {
1030        unsafe { self.prop_vec(InstancePropId::APPLICABLE_INPUT_SAMPLE_RATES.0) }
1031    }
1032
1033    #[inline]
1034    pub fn applicable_output_sample_rates(&self) -> os::Result<Vec<audio::ValueRange>> {
1035        unsafe { self.prop_vec(InstancePropId::APPLICABLE_OUTPUT_SAMPLE_RATES.0) }
1036    }
1037
1038    #[inline]
1039    pub fn recommended_bit_rate_range(&self) -> os::Result<Vec<audio::ValueRange>> {
1040        unsafe { self.prop_vec(InstancePropId::RECOMMENDED_BIT_RATE_RANGE.0) }
1041    }
1042
1043    #[inline]
1044    pub fn applicable_bit_rate_range(&self) -> os::Result<Vec<audio::ValueRange>> {
1045        unsafe { self.prop_vec(InstancePropId::APPLICABLE_BIT_RATE_RANGE.0) }
1046    }
1047
1048    #[inline]
1049    pub fn supported_input_formats(&self) -> os::Result<Vec<audio::StreamBasicDesc>> {
1050        unsafe { self.prop_vec(GlobalPropId::SUPPORTED_INPUT_FORMATS.0) }
1051    }
1052
1053    pub fn input_formats_for_output_format(
1054        &self,
1055        output_format: &audio::StreamBasicDesc,
1056    ) -> os::Result<Vec<audio::StreamBasicDesc>> {
1057        let prop_id = GlobalPropId::INPUT_FORMATS_FOR_OUTPUT_FORMAT.0;
1058
1059        let (mut size, _) = self.prop_info(prop_id)?;
1060        if size == 0 {
1061            return Ok(vec![]);
1062        }
1063        let mut vec = vec![
1064            audio::StreamBasicDesc::default();
1065            size as usize / std::mem::size_of::<audio::StreamBasicDesc>()
1066        ];
1067        vec[0] = *output_format;
1068        unsafe {
1069            AudioCodecGetProperty(self, prop_id, &mut size, vec.as_mut_ptr() as _).result()?;
1070        }
1071        Ok(vec)
1072    }
1073
1074    #[inline]
1075    pub fn supported_output_formats(&self) -> os::Result<Vec<audio::StreamBasicDesc>> {
1076        unsafe { self.prop_vec(GlobalPropId::SUPPORTED_OUTPUT_FORMATS.0) }
1077    }
1078
1079    pub fn output_formats_for_input_format(
1080        &self,
1081        input_format: &audio::StreamBasicDesc,
1082    ) -> os::Result<Vec<audio::StreamBasicDesc>> {
1083        let prop_id = GlobalPropId::OUTPUT_FORMATS_FOR_INPUT_FORMAT.0;
1084
1085        let (mut size, _) = self.prop_info(prop_id)?;
1086        if size == 0 {
1087            return Ok(vec![]);
1088        }
1089        let mut vec = vec![
1090            audio::StreamBasicDesc::default();
1091            size as usize / std::mem::size_of::<audio::StreamBasicDesc>()
1092        ];
1093        vec[0] = *input_format;
1094        unsafe {
1095            AudioCodecGetProperty(self, prop_id, &mut size, vec.as_mut_ptr() as _).result()?;
1096        }
1097        Ok(vec)
1098    }
1099
1100    /// Flushes all the data in the codec and clears the input buffer. Note that
1101    /// the formats, and magic cookie will be retained so they won't need to be
1102    /// set up again to decode the same data.
1103    #[doc(alias = "AudioCodecReset")]
1104    pub fn reset(&mut self) -> os::Result {
1105        unsafe { AudioCodecReset(self).result() }
1106    }
1107}
1108
1109impl<S> CodecRef<S>
1110where
1111    S: State<Codec>,
1112{
1113    #[inline]
1114    pub fn supported_input_formats(&self) -> os::Result<Vec<audio::StreamBasicDesc>> {
1115        self.0.supported_input_formats()
1116    }
1117
1118    #[inline]
1119    pub fn supported_output_formats(&self) -> os::Result<Vec<audio::StreamBasicDesc>> {
1120        self.0.supported_output_formats()
1121    }
1122
1123    #[inline]
1124    pub fn bit_rate_control_mode(&self) -> os::Result<BitRateControlMode> {
1125        self.0.bit_rate_control_mode()
1126    }
1127
1128    #[inline]
1129    pub fn recommended_bit_rate_range(&self) -> os::Result<Vec<audio::ValueRange>> {
1130        self.0.recommended_bit_rate_range()
1131    }
1132
1133    #[inline]
1134    pub fn applicable_output_sample_rates(&self) -> os::Result<Vec<audio::ValueRange>> {
1135        self.0.applicable_output_sample_rates()
1136    }
1137
1138    #[inline]
1139    pub fn applicable_input_sample_rates(&self) -> os::Result<Vec<audio::ValueRange>> {
1140        self.0.applicable_input_sample_rates()
1141    }
1142
1143    #[inline]
1144    pub fn applicable_bit_rate_range(&self) -> os::Result<Vec<audio::ValueRange>> {
1145        self.0.applicable_bit_rate_range()
1146    }
1147
1148    #[inline]
1149    pub fn current_target_bit_rate(&self) -> os::Result<u32> {
1150        self.0.current_target_bit_rate()
1151    }
1152
1153    #[inline]
1154    pub fn magic_cookie(&self) -> os::Result<Vec<u8>> {
1155        unsafe { self.0.prop_vec(InstancePropId::MAGIC_COOKIE.0) }
1156    }
1157
1158    #[inline]
1159    pub fn current_output_format(&self) -> os::Result<audio::StreamBasicDesc> {
1160        let mut value = audio::StreamBasicDesc::default();
1161        let mut size = std::mem::size_of::<audio::StreamBasicDesc>() as u32;
1162        unsafe {
1163            AudioCodecGetProperty(
1164                &self.0,
1165                InstancePropId::CURRENT_OUTPUT_FORMAT.0,
1166                &mut size,
1167                &mut value as *mut _ as _,
1168            )
1169            .result()?;
1170        }
1171        Ok(value)
1172    }
1173
1174    #[inline]
1175    pub fn current_input_format(&self) -> os::Result<audio::StreamBasicDesc> {
1176        let mut value = audio::StreamBasicDesc::default();
1177        let mut size = std::mem::size_of::<audio::StreamBasicDesc>() as u32;
1178        unsafe {
1179            AudioCodecGetProperty(
1180                &self.0,
1181                InstancePropId::CURRENT_INPUT_FORMAT.0,
1182                &mut size,
1183                &mut value as *mut _ as _,
1184            )
1185            .result()?;
1186        }
1187        Ok(value)
1188    }
1189
1190    #[inline]
1191    pub fn set_current_input_format(&mut self, val: &audio::StreamBasicDesc) -> os::Result {
1192        unsafe {
1193            AudioCodecSetProperty(
1194                &mut self.0,
1195                InstancePropId::CURRENT_INPUT_FORMAT.0,
1196                std::mem::size_of::<audio::StreamBasicDesc>() as u32,
1197                val as *const audio::StreamBasicDesc as _,
1198            )
1199            .result()
1200        }
1201    }
1202
1203    #[inline]
1204    pub fn max_packet_byte_size(&self) -> os::Result<u32> {
1205        let (mut value, mut size) = (0u32, 4u32);
1206        unsafe {
1207            AudioCodecGetProperty(
1208                &self.0,
1209                InstancePropId::MAXIMUM_PACKET_BYTE_SIZE.0,
1210                &mut size,
1211                &mut value as *mut u32 as *mut u8,
1212            )
1213            .result()?;
1214        }
1215        Ok(value)
1216    }
1217
1218    #[inline]
1219    pub fn input_buf_size(&self) -> os::Result<u32> {
1220        let (mut value, mut size) = (0u32, 4u32);
1221        unsafe {
1222            AudioCodecGetProperty(
1223                &self.0,
1224                InstancePropId::INPUT_BUF_SIZE.0,
1225                &mut size,
1226                &mut value as *mut u32 as *mut u8,
1227            )
1228            .result()?;
1229        }
1230        Ok(value)
1231    }
1232
1233    #[inline]
1234    pub fn quality(&self) -> os::Result<u32> {
1235        self.0.quality()
1236    }
1237
1238    pub fn settings(&self) -> os::Result<arc::R<cf::DictionaryOf<cf::String, cf::Type>>> {
1239        self.0.settings()
1240    }
1241}
1242
1243impl audio::Component {
1244    pub fn open_codec(&self) -> os::Result<CodecRef<UninitializedState>> {
1245        Ok(unsafe { std::mem::transmute(self.open()?) })
1246    }
1247}
1248
1249#[doc(alias = "AudioCodecProduceOutputPacketStatus")]
1250#[derive(Debug, Clone, Copy, Eq, PartialEq)]
1251#[repr(u32)]
1252pub enum ProduceOutputPacketStatus {
1253    /// Couldn't complete the request due to an error. It is possible
1254    /// that some output data was produced. This is reflected in the value
1255    /// returned in ioNumberPackets.
1256    #[doc(alias = "kAudioCodecProduceOutputPacketFailure")]
1257    Failure = 1,
1258
1259    /// The number of requested output packets was produced without incident
1260    /// and there isn't any more input data to process
1261    #[doc(alias = "kAudioCodecProduceOutputPacketSuccess")]
1262    Success = 2,
1263
1264    /// The number of requested output packets was produced and there is
1265    /// enough input data to produce at least one more packet of output data
1266    #[doc(alias = "kAudioCodecProduceOutputPacketSuccessHasMore")]
1267    SuccessHasMore = 3,
1268
1269    /// There was insufficient input data to produce the requested
1270    /// number of output packets, The value returned in ioNumberPackets
1271    /// holds the number of output packets produced.
1272    #[doc(alias = "kAudioCodecProduceOutputPacketNeedsMoreInputData")]
1273    NeedsMoreInputData = 4,
1274
1275    /// The end-of-file marker was hit during the processing. Fewer
1276    /// than the requested number of output packets may have been
1277    /// produced. Check the value returned in ioNumberPackets for the
1278    /// actual number produced. Note that not all formats have EOF
1279    /// markers in them.    
1280    #[doc(alias = "kAudioCodecProduceOutputPacketAtEOF")]
1281    AtEof = 5,
1282
1283    /// No input packets were provided, but the decoder supports packet
1284    /// loss concealment, so output packets were still created.
1285    #[doc(alias = "kAudioCodecProduceOutputPacketSuccessConcealed")]
1286    SuccessConcealed = 6,
1287}
1288
1289/// Constants to be used with kAudioCodecPropertyQualitySetting
1290pub mod quality {
1291    #[doc(alias = "kAudioCodecQuality_Max")]
1292    pub const MAX: u32 = 0x7F;
1293
1294    #[doc(alias = "kAudioCodecQuality_High")]
1295    pub const HIGH: u32 = 0x60;
1296
1297    #[doc(alias = "kAudioCodecQuality_Medium")]
1298    pub const MEDIUM: u32 = 0x40;
1299
1300    #[doc(alias = "kAudioCodecQuality_Low")]
1301    pub const LOW: u32 = 0x20;
1302
1303    #[doc(alias = "kAudioCodecQuality_Min")]
1304    pub const MIN: u32 = 0x00;
1305}
1306
1307unsafe extern "C-unwind" {
1308    fn AudioCodecReset(in_codec: &mut Codec) -> os::Status;
1309
1310    fn AudioCodecInitialize(
1311        in_codec: &mut Codec,
1312        in_input_format: *const audio::StreamBasicDesc,
1313        in_output_format: *const audio::StreamBasicDesc,
1314        in_magic_cookie: *const u8,
1315        in_magic_cookie_size: u32,
1316    ) -> os::Status;
1317
1318    fn AudioCodecUninitialize(in_codec: &mut Codec) -> os::Status;
1319
1320    fn AudioCodecAppendInputData(
1321        in_codec: &mut Codec,
1322        in_input_data: *const u8,
1323        io_input_data_byte_size: *mut u32,
1324        io_number_packets: *mut u32,
1325        in_packet_description: *const audio::StreamPacketDesc,
1326    ) -> os::Status;
1327
1328    fn AudioCodecProduceOutputPackets(
1329        in_codec: &mut Codec,
1330        out_output_data: *mut u8,
1331        io_output_data_byte_size: &mut u32,
1332        io_number_packets: *mut u32,
1333        out_packet_description: *mut audio::StreamPacketDesc,
1334        out_status: *mut ProduceOutputPacketStatus,
1335    ) -> os::Status;
1336
1337    fn AudioCodecAppendInputBufferList(
1338        in_codec: &mut Codec,
1339        in_buffer_list: *const audio::BufList,
1340        io_number_packets: &mut u32,
1341        in_packet_descriptions: *const audio::StreamPacketDesc,
1342        out_bytes_consumed: &mut u32,
1343    ) -> os::Status;
1344
1345    fn AudioCodecProduceOutputBufferList(
1346        in_codec: &mut Codec,
1347        io_buffer_list: &mut audio::BufList,
1348        io_number_packets: &mut u32,
1349        out_packet_description: *mut audio::StreamPacketDesc,
1350        out_status: &mut os::Status,
1351    ) -> os::Status;
1352
1353    fn AudioCodecSetProperty(
1354        in_codec: &mut Codec,
1355        in_property_id: u32,
1356        in_property_size: u32,
1357        in_property_data: *const u8,
1358    ) -> os::Status;
1359
1360    fn AudioCodecGetProperty(
1361        in_codec: &Codec,
1362        in_property_id: u32,
1363        io_property_data_size: &mut u32,
1364        out_property_data: *mut u8,
1365    ) -> os::Status;
1366
1367    fn AudioCodecGetPropertyInfo(
1368        in_codec: &Codec,
1369        in_property_id: u32,
1370        out_size: *mut u32,
1371        out_writable: *mut bool,
1372    ) -> os::Status;
1373
1374}
1375
1376#[cfg(test)]
1377mod tests {
1378    use audio::CodecRef;
1379
1380    use crate::{at::audio, four_cc_to_str};
1381
1382    #[test]
1383    fn basics() {
1384        let channels_per_frame = 2;
1385        let sample_rate = 44_100.0;
1386        let src_asbd = audio::StreamBasicDesc {
1387            sample_rate,
1388            channels_per_frame,
1389            format: audio::Format::LINEAR_PCM,
1390            format_flags: audio::FormatFlags::IS_FLOAT | audio::FormatFlags::IS_PACKED,
1391            bytes_per_packet: 4 * channels_per_frame,
1392            frames_per_packet: 1,
1393            bytes_per_frame: 4 * channels_per_frame,
1394            bits_per_channel: 32,
1395            ..Default::default()
1396        };
1397
1398        let dst_asbd = audio::StreamBasicDesc {
1399            sample_rate,
1400            channels_per_frame,
1401            format: audio::Format::MPEG4_AAC,
1402            format_flags: audio::FormatFlags::ALL_CLEAR,
1403            frames_per_packet: 1024,
1404            ..Default::default()
1405        };
1406
1407        let desc = audio::ComponentDesc {
1408            type_: audio::ENCODER_COMPONENT_TYPE,
1409            sub_type: u32::from_be_bytes(*b"aac "),
1410            ..Default::default()
1411        };
1412
1413        let inst = desc.into_iter().last().unwrap();
1414
1415        let codec = inst.open_codec().unwrap();
1416
1417        let recommended_bit_rate_range = codec.recommended_bit_rate_range().unwrap();
1418        println!("{recommended_bit_rate_range:?}");
1419        assert!(!recommended_bit_rate_range.is_empty());
1420
1421        let applicable_output_sample_rates = codec.applicable_output_sample_rates().unwrap();
1422        println!("{applicable_output_sample_rates:?}");
1423        assert!(!applicable_output_sample_rates.is_empty());
1424
1425        let supported_input_formats = codec.supported_input_formats().unwrap();
1426        println!("{supported_input_formats:?}");
1427        assert!(!supported_input_formats.is_empty());
1428
1429        let applicable_output_sample_rates = codec.applicable_output_sample_rates().unwrap();
1430        println!("{applicable_output_sample_rates:?}");
1431        assert!(!applicable_output_sample_rates.is_empty());
1432
1433        let mode = codec.bit_rate_control_mode().unwrap();
1434        assert_eq!(audio::CodecBitRateControlMode::LongTermAverage, mode);
1435
1436        let codec = codec.initialize(&src_asbd, &dst_asbd, None).unwrap();
1437        let cookie_info = codec.magic_cookie().unwrap();
1438        assert!(!cookie_info.is_empty());
1439        let max_packet_size = codec.max_packet_byte_size().unwrap();
1440        assert_eq!(max_packet_size, 1536);
1441
1442        let quality = codec.quality().unwrap();
1443        assert_eq!(quality, audio::codec_quality::MEDIUM);
1444    }
1445
1446    #[test]
1447    fn encoder_list() {
1448        let desc = audio::ComponentDesc {
1449            type_: audio::ENCODER_COMPONENT_TYPE,
1450            manufacturer: audio::UnitManufacturer::APPLE.0,
1451            ..Default::default()
1452        };
1453
1454        for comp in desc.into_iter() {
1455            println!(
1456                "desc {:?} {:?} {}",
1457                comp.name(),
1458                comp.desc(),
1459                four_cc_to_str(&mut comp.desc().unwrap().sub_type.to_be_bytes())
1460            );
1461        }
1462    }
1463
1464    #[test]
1465    fn codec_init() {
1466        let sample_rate = 48000.0;
1467        let channels_per_frame = 2;
1468        let src_asbd = audio::StreamBasicDesc {
1469            sample_rate,
1470            format: audio::Format(1819304813),
1471            // format: audio::FormatID::LINEAR_PCM,
1472            format_flags: audio::FormatFlags(41),
1473            // format_flags: audio::FormatFlags(0),
1474            bytes_per_packet: 4,
1475            frames_per_packet: 1,
1476            bytes_per_frame: 4,
1477            channels_per_frame,
1478            bits_per_channel: 32,
1479            reserved: 0,
1480        };
1481
1482        let src_asbd2 = audio::StreamBasicDesc {
1483            sample_rate,
1484            channels_per_frame,
1485            format: audio::Format::LINEAR_PCM,
1486            format_flags: audio::FormatFlags::NATIVE_FLOAT_PACKED, //audio::FormatFlags::IS_FLOAT | audio::FormatFlags::IS_PACKED,
1487            bytes_per_packet: 4 * channels_per_frame,
1488            frames_per_packet: 1,
1489            bytes_per_frame: 4 * channels_per_frame,
1490            bits_per_channel: 32,
1491            ..Default::default()
1492        };
1493
1494        println!(
1495            "
1496                {src_asbd:#?}
1497                {src_asbd2:#?}
1498            "
1499        );
1500
1501        let dst_asbd = audio::StreamBasicDesc {
1502            sample_rate,
1503            channels_per_frame,
1504            format: audio::Format::MPEG4_AAC,
1505            format_flags: audio::FormatFlags::ALL_CLEAR,
1506            frames_per_packet: 1024,
1507            ..Default::default()
1508        };
1509
1510        let encoder = CodecRef::new_apple_aac_encoder().unwrap();
1511        let _encoder = encoder.initialize(&src_asbd2, &dst_asbd, None).unwrap();
1512    }
1513}