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#[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#[repr(transparent)]
85pub struct GlobalPropId(pub u32);
86
87#[repr(transparent)]
101pub struct InstancePropId(pub u32);
102
103impl GlobalPropId {
104 #[doc(alias = "kAudioCodecPropertySupportedInputFormats")]
107 pub const SUPPORTED_INPUT_FORMATS: Self = Self(u32::from_be_bytes(*b"ifm#"));
108
109 #[doc(alias = "kAudioCodecPropertySupportedOutputFormats")]
112 pub const SUPPORTED_OUTPUT_FORMATS: Self = Self(u32::from_be_bytes(*b"ofm#"));
113
114 #[doc(alias = "kAudioCodecPropertyAvailableInputSampleRates")]
120 pub const AVAILABLE_INPUT_SAMPLE_RATES: Self = Self(u32::from_be_bytes(*b"aisr"));
121
122 #[doc(alias = "kAudioCodecPropertyAvailableOutputSampleRates")]
127 pub const AVAILABLE_OUTPUT_SAMPLE_RATES: Self = Self(u32::from_be_bytes(*b"aosr"));
128
129 #[doc(alias = "kAudioCodecPropertyAvailableBitRateRange")]
135 pub const AVAILABLE_BIT_RATE_RANGE: Self = Self(u32::from_be_bytes(*b"abrt"));
136
137 #[doc(alias = "kAudioCodecPropertyMinimumNumberInputPackets")]
142 pub const MINIMUM_NUMBER_INPUT_PACKETS: Self = Self(u32::from_be_bytes(*b"mnip"));
143
144 #[doc(alias = "kAudioCodecPropertyMinimumNumberOutputPackets")]
149 pub const MINIMUM_NUMBER_OUTPUT_PACKETS: Self = Self(u32::from_be_bytes(*b"mnop"));
150
151 #[doc(alias = "kAudioCodecPropertyAvailableNumberChannels")]
155 pub const AVAILABLE_NUMBER_CHANNELS: Self = Self(u32::from_be_bytes(*b"cmnc"));
156
157 #[doc(alias = "kAudioCodecPropertyDoesSampleRateConversion")]
161 pub const DOES_SAMPLE_RATE_CONVERSION: Self = Self(u32::from_be_bytes(*b"lmrc"));
162
163 #[doc(alias = "kAudioCodecPropertyAvailableInputChannelLayoutTags")]
166 pub const AVAILABLE_INPUT_CHANNEL_LAYOUT_TAGS: Self = Self(u32::from_be_bytes(*b"aicl"));
167
168 #[doc(alias = "kAudioCodecPropertyAvailableOutputChannelLayoutTags")]
171 pub const AVAILABLE_OUTPUT_CHANNEL_LAYOUT_TAGS: Self = Self(u32::from_be_bytes(*b"aocl"));
172
173 #[doc(alias = "kAudioCodecPropertyInputFormatsForOutputFormat")]
178 pub const INPUT_FORMATS_FOR_OUTPUT_FORMAT: Self = Self(u32::from_be_bytes(*b"if4o"));
179
180 #[doc(alias = "kAudioCodecPropertyOutputFormatsForInputFormat")]
185 pub const OUTPUT_FORMATS_FOR_INPUT_FORMAT: Self = Self(u32::from_be_bytes(*b"of4i"));
186
187 #[doc(alias = "kAudioCodecPropertyFormatInfo")]
191 pub const FORMAT_INFO: Self = Self(u32::from_be_bytes(*b"acfi"));
192}
193
194impl InstancePropId {
195 #[doc(alias = "kAudioCodecPropertyInputBufferSize")]
200 pub const INPUT_BUF_SIZE: Self = Self(u32::from_be_bytes(*b"tbuf"));
201
202 #[doc(alias = "kAudioCodecPropertyPacketFrameSize")]
209 pub const PACKET_FRAME_SIZE: Self = Self(u32::from_be_bytes(*b"pakf"));
210
211 #[doc(alias = "kAudioCodecPropertyHasVariablePacketByteSizes")]
220 pub const HAS_VARIABLE_PACKET_BYTE_SIZES: Self = Self(u32::from_be_bytes(*b"vpk?"));
221
222 #[doc(alias = "kAudioCodecPropertyEmploysDependentPackets")]
226 pub const EMPLOYS_DEPENDENT_PACKETS: Self = Self(u32::from_be_bytes(*b"dpk?"));
227
228 #[doc(alias = "kAudioCodecPropertyMaximumPacketByteSize")]
236 pub const MAXIMUM_PACKET_BYTE_SIZE: Self = Self(u32::from_be_bytes(*b"pakb"));
237
238 #[doc(alias = "kAudioCodecPropertyPacketSizeLimitForVBR")]
246 pub const PACKET_SIZE_LIMIT_FOR_VBR: Self = Self(u32::from_be_bytes(*b"pakl"));
247
248 #[doc(alias = "kAudioCodecPropertyCurrentInputFormat")]
253 pub const CURRENT_INPUT_FORMAT: Self = Self(u32::from_be_bytes(*b"ifmt"));
254
255 #[doc(alias = "kAudioCodecPropertyCurrentOutputFormat")]
260 pub const CURRENT_OUTPUT_FORMAT: Self = Self(u32::from_be_bytes(*b"ofmt"));
261
262 #[doc(alias = "kAudioCodecPropertyMagicCookie")]
269 pub const MAGIC_COOKIE: Self = Self(u32::from_be_bytes(*b"kuki"));
270
271 #[doc(alias = "kAudioCodecPropertyUsedInputBufferSize")]
277 pub const USED_INPUT_BUF_SIZE: Self = Self(u32::from_be_bytes(*b"ubuf"));
278
279 #[doc(alias = "kAudioCodecPropertyIsInitialized")]
283 pub const IS_INITIALIZED: Self = Self(u32::from_be_bytes(*b"init"));
284
285 #[doc(alias = "kAudioCodecPropertyCurrentTargetBitRate")]
291 pub const CURRENT_TARGET_BIT_RATE: Self = Self(u32::from_be_bytes(*b"brat"));
292
293 #[doc(alias = "kAudioCodecPropertyCurrentInputSampleRate")]
296 pub const CURRENT_INPUT_SAMPLE_RATE: Self = Self(u32::from_be_bytes(*b"cisr"));
297
298 #[doc(alias = "kAudioCodecPropertyCurrentOutputSampleRate")]
301 pub const CURRENT_OUTPUT_SAMPLE_RATE: Self = Self(u32::from_be_bytes(*b"cosr"));
302
303 #[doc(alias = "kAudioCodecPropertyQualitySetting")]
308 pub const QUALITY_SETTING: Self = Self(u32::from_be_bytes(*b"srcq"));
309
310 #[doc(alias = "kAudioCodecPropertyApplicableBitRateRange")]
316 pub const APPLICABLE_BIT_RATE_RANGE: Self = Self(u32::from_be_bytes(*b"brta"));
317
318 #[doc(alias = "kAudioCodecPropertyRecommendedBitRateRange")]
323 pub const RECOMMENDED_BIT_RATE_RANGE: Self = Self(u32::from_be_bytes(*b"brtr"));
324
325 #[doc(alias = "kAudioCodecPropertyApplicableInputSampleRates")]
331 pub const APPLICABLE_INPUT_SAMPLE_RATES: Self = Self(u32::from_be_bytes(*b"isra"));
332
333 #[doc(alias = "kAudioCodecPropertyApplicableOutputSampleRates")]
339 pub const APPLICABLE_OUTPUT_SAMPLE_RATES: Self = Self(u32::from_be_bytes(*b"osra"));
340
341 #[doc(alias = "kAudioCodecPropertyPaddedZeros")]
346 pub const PADDED_ZEROS: Self = Self(u32::from_be_bytes(*b"pad0"));
347
348 #[doc(alias = "kAudioCodecPropertyPrimeMethod")]
353 pub const PRIME_METHOD: Self = Self(u32::from_be_bytes(*b"prmm"));
354
355 #[doc(alias = "kAudioCodecPropertyPrimeInfo")]
359 pub const PRIME_INFO: Self = Self(u32::from_be_bytes(*b"prim"));
360
361 #[doc(alias = "kAudioCodecPropertyCurrentInputChannelLayout")]
364 pub const CURRENT_INPUT_CHANNEL_LAYOUT: Self = Self(u32::from_be_bytes(*b"icl "));
365
366 #[doc(alias = "kAudioCodecPropertyCurrentOutputChannelLayout")]
371 pub const CURRENT_OUTPUT_CHANNEL_LAYOUT: Self = Self(u32::from_be_bytes(*b"ocl "));
372
373 #[doc(alias = "kAudioCodecPropertySettings")]
382 pub const SETTINGS: Self = Self(u32::from_be_bytes(*b"acs "));
383
384 #[doc(alias = "kAudioCodecPropertyFormatList")]
395 pub const FORMAT_LIST: Self = Self(u32::from_be_bytes(*b"acfl"));
396
397 #[doc(alias = "kAudioCodecPropertyBitRateControlMode")]
405 pub const BIT_RATE_CONTROL_MODE: Self = Self(u32::from_be_bytes(*b"acbf"));
406
407 #[doc(alias = "kAudioCodecPropertySoundQualityForVBR")]
414 pub const SOUND_QUALITY_FOR_VBR: Self = Self(u32::from_be_bytes(*b"vbrq"));
415
416 #[doc(alias = "kAudioCodecPropertyBitRateForVBR")]
419 pub const BIT_RATE_FOR_VBR: Self = Self(u32::from_be_bytes(*b"vbrb"));
420
421 #[doc(alias = "kAudioCodecPropertyDelayMode")]
424 pub const DELAY_MODE: Self = Self(u32::from_be_bytes(*b"dmod"));
425
426 #[doc(alias = "kAudioCodecPropertyAdjustLocalQuality")]
432 pub const ADJUST_LOCAL_QUALITY: Self = Self(u32::from_be_bytes(*b"^qal"));
433
434 #[doc(alias = "kAudioCodecPropertyProgramTargetLevel")]
441 pub const PROGRAM_TARGET_LEVEL: Self = Self(u32::from_be_bytes(*b"pptl"));
442
443 #[doc(alias = "kAudioCodecPropertyDynamicRangeControlMode")]
448 pub const DYNAMIC_RANGE_CONTROL_MODE: Self = Self(u32::from_be_bytes(*b"mdrc"));
449
450 #[doc(alias = "kAudioCodecPropertyProgramTargetLevelConstant")]
457 pub const PROGRAM_TARGET_LEVEL_CONSTANT: Self = Self(u32::from_be_bytes(*b"ptlc"));
458
459 #[doc(alias = "kAudioCodecPropertyAdjustCompressionProfile")]
464 pub const ADJUST_COMPRESSION_PROFILE: Self = Self(u32::from_be_bytes(*b"^pro"));
465
466 #[doc(alias = "kAudioCodecPropertyAdjustTargetLevel")]
470 pub const ADJUST_TARGET_LEVEL: Self = Self(u32::from_be_bytes(*b"^ptl"));
471
472 #[doc(alias = "kAudioCodecPropertyAdjustTargetLevelConstant")]
477 pub const ADJUST_TARGET_LEVEL_CONSTANT: Self = Self(u32::from_be_bytes(*b"^tlc"));
478}
479
480#[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#[derive(Debug, Copy, Clone, Eq, PartialEq)]
500#[repr(u32)]
501pub enum DynamicRangeCompressionProfile {
502 #[doc(alias = "kDynamicRangeCompressionProfile_None")]
504 None = 0,
505
506 #[doc(alias = "kDynamicRangeCompressionProfile_LateNight")]
508 LateNight = 1,
509
510 #[doc(alias = "kDynamicRangeCompressionProfile_NoisyEnvironment")]
512 NoisyEnvironment = 2,
513
514 #[doc(alias = "kDynamicRangeCompressionProfile_LimitedPlaybackRange")]
516 LimitedPlaybackRange = 3,
517
518 #[doc(alias = "kDynamicRangeCompressionProfile_GeneralCompression")]
520 GeneralCompression = 6,
521}
522
523#[derive(Debug, Copy, Clone, Eq, PartialEq)]
528#[repr(u32)]
529pub enum BitRateControlMode {
530 Constant = 0,
537
538 LongTermAverage = 1,
546
547 VariableConstrained = 2,
551
552 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#[repr(C)]
570pub struct MagicCookieInfo {
571 pub size: u32,
573 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 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 #[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 #[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 #[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 #[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 #[doc(alias = "kAudioCodecProduceOutputPacketFailure")]
1257 Failure = 1,
1258
1259 #[doc(alias = "kAudioCodecProduceOutputPacketSuccess")]
1262 Success = 2,
1263
1264 #[doc(alias = "kAudioCodecProduceOutputPacketSuccessHasMore")]
1267 SuccessHasMore = 3,
1268
1269 #[doc(alias = "kAudioCodecProduceOutputPacketNeedsMoreInputData")]
1273 NeedsMoreInputData = 4,
1274
1275 #[doc(alias = "kAudioCodecProduceOutputPacketAtEOF")]
1281 AtEof = 5,
1282
1283 #[doc(alias = "kAudioCodecProduceOutputPacketSuccessConcealed")]
1286 SuccessConcealed = 6,
1287}
1288
1289pub 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_flags: audio::FormatFlags(41),
1473 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, 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}