use bitfield::bitfield;
use bitflags::bitflags;
use bt_avdtp as avdtp;
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SbcSamplingFrequency:u8 {
const FREQ16000HZ = 0b1000;
const FREQ32000HZ = 0b0100;
const FREQ44100HZ = 0b0010;
const FREQ48000HZ = 0b0001;
const MANDATORY_SNK = Self::FREQ44100HZ.bits() | Self::FREQ48000HZ.bits();
}
}
impl SbcSamplingFrequency {
fn best(&self) -> Option<Self> {
let ordered = [Self::FREQ48000HZ, Self::FREQ44100HZ, Self::FREQ32000HZ, Self::FREQ16000HZ];
ordered.iter().find(|freq| self.contains(**freq)).copied()
}
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SbcChannelMode:u8 {
const MONO = 0b1000;
const DUAL_CHANNEL = 0b0100;
const STEREO = 0b0010;
const JOINT_STEREO = 0b0001;
const MANDATORY_SNK = Self::MONO.bits()
| Self::DUAL_CHANNEL.bits()
| Self::STEREO.bits()
| Self::JOINT_STEREO.bits();
}
}
impl SbcChannelMode {
fn best(&self) -> Option<Self> {
let ordered = [Self::JOINT_STEREO, Self::STEREO, Self::DUAL_CHANNEL, Self::MONO];
ordered.iter().find(|mode| self.contains(**mode)).copied()
}
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SbcBlockCount:u8 {
const FOUR = 0b1000;
const EIGHT = 0b0100;
const TWELVE = 0b0010;
const SIXTEEN = 0b0001;
const MANDATORY_SNK = Self::FOUR.bits()
| Self::EIGHT.bits()
| Self::TWELVE.bits()
| Self::SIXTEEN.bits();
const MANDATORY_SRC = Self::FOUR.bits()
| Self::EIGHT.bits()
| Self::TWELVE.bits()
| Self::SIXTEEN.bits();
}
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SbcSubBands:u8 {
const FOUR = 0b0010;
const EIGHT = 0b0001;
const MANDATORY_SNK = Self::FOUR.bits() | Self::EIGHT.bits();
const MANDATORY_SRC = Self::EIGHT.bits();
}
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SbcAllocation:u8 {
const SNR = 0b0010;
const LOUDNESS = 0b0001;
const MANDATORY_SNK = Self::SNR.bits() | Self::LOUDNESS.bits();
const MANDATORY_SRC = Self::LOUDNESS.bits();
}
}
pub const SBC_CODEC_EXTRA_LEN: usize = 4;
bitfield! {
struct SbcCodecInfoBits(u32);
impl Debug;
u8;
maxbitpoolval, set_maxbpv: 7, 0;
minbitpoolval, set_minbpv: 15, 8;
allocation_method, set_allocation_method: 17,16;
sub_bands, set_sub_bands: 19, 18;
block_count, set_block_count: 23, 20;
channel_mode, set_channel_mode: 27, 24;
sampling_frequency, set_sampling_frequency: 31, 28;
}
#[derive(Debug)]
pub struct SbcCodecInfo(SbcCodecInfoBits);
impl SbcCodecInfo {
pub const BITPOOL_MIN: u8 = 2;
pub const BITPOOL_MAX: u8 = 250;
pub fn new(
sampling_frequency: SbcSamplingFrequency,
channel_mode: SbcChannelMode,
block_count: SbcBlockCount,
sub_bands: SbcSubBands,
allocation: SbcAllocation,
min_bpv: u8,
max_bpv: u8,
) -> avdtp::Result<Self> {
if min_bpv > max_bpv {
return Err(avdtp::Error::OutOfRange);
}
if min_bpv < Self::BITPOOL_MIN
|| min_bpv > Self::BITPOOL_MAX
|| max_bpv < Self::BITPOOL_MIN
|| max_bpv > Self::BITPOOL_MAX
{
return Err(avdtp::Error::OutOfRange);
}
let mut res = SbcCodecInfoBits(0);
res.set_maxbpv(max_bpv);
res.set_minbpv(min_bpv);
res.set_allocation_method(allocation.bits());
res.set_sub_bands(sub_bands.bits());
res.set_block_count(block_count.bits());
res.set_channel_mode(channel_mode.bits());
res.set_sampling_frequency(sampling_frequency.bits());
Ok(Self(res))
}
pub fn to_bytes(&self) -> [u8; 4] {
(self.0).0.to_be_bytes()
}
pub fn sub_bands(&self) -> SbcSubBands {
SbcSubBands::from_bits_truncate(self.0.sub_bands())
}
pub fn allocation_method(&self) -> SbcAllocation {
SbcAllocation::from_bits_truncate(self.0.allocation_method())
}
pub fn block_count(&self) -> SbcBlockCount {
SbcBlockCount::from_bits_truncate(self.0.block_count())
}
pub fn channel_mode(&self) -> SbcChannelMode {
SbcChannelMode::from_bits_truncate(self.0.channel_mode())
}
pub fn channel_count(&self) -> avdtp::Result<usize> {
let chan_mode = self.channel_mode();
if chan_mode == SbcChannelMode::MONO {
return Ok(1);
} else if !chan_mode.is_empty() && (chan_mode & SbcChannelMode::MONO).is_empty() {
return Ok(2);
}
Err(avdtp::Error::OutOfRange)
}
pub fn max_bitpool(&self) -> u8 {
self.0.maxbitpoolval()
}
pub fn sampling_frequency(&self) -> avdtp::Result<u32> {
let hz = match SbcSamplingFrequency::from_bits_truncate(self.0.sampling_frequency()) {
SbcSamplingFrequency::FREQ16000HZ => 16000,
SbcSamplingFrequency::FREQ32000HZ => 32000,
SbcSamplingFrequency::FREQ44100HZ => 44100,
SbcSamplingFrequency::FREQ48000HZ => 48000,
_ => return Err(avdtp::Error::OutOfRange),
};
Ok(hz)
}
pub fn supports(&self, other: &Self) -> bool {
let allowed_frequencies =
SbcSamplingFrequency::from_bits_truncate(self.0.sampling_frequency());
let selected_frequencies =
SbcSamplingFrequency::from_bits_truncate(other.0.sampling_frequency());
if !(allowed_frequencies.intersects(selected_frequencies)) {
return false;
}
if !(self.allocation_method().intersects(other.allocation_method())) {
return false;
}
if !(self.channel_mode().intersects(other.channel_mode())) {
return false;
}
if !(self.block_count().intersects(other.block_count())) {
return false;
}
if !(self.sub_bands().intersects(other.sub_bands())) {
return false;
}
if self.0.minbitpoolval() > other.0.minbitpoolval() {
return false;
}
if self.0.maxbitpoolval() < other.0.maxbitpoolval() {
return false;
}
return true;
}
pub fn negotiate(a: &Self, b: &Self) -> Option<Self> {
let min_bitpool = std::cmp::max(a.0.minbitpoolval(), b.0.minbitpoolval());
let max_bitpool = std::cmp::min(a.0.maxbitpoolval(), b.0.maxbitpoolval());
if max_bitpool < min_bitpool {
return None;
}
let available_frequencies = SbcSamplingFrequency::from_bits_truncate(
a.0.sampling_frequency() & b.0.sampling_frequency(),
);
let frequency = match available_frequencies.best() {
None => return None,
Some(freq) => freq,
};
let available_mode = a.channel_mode() & b.channel_mode();
let channel_mode = match available_mode.best() {
None => return None,
Some(mode) => mode,
};
let allocation = SbcAllocation::LOUDNESS;
let block_count = SbcBlockCount::SIXTEEN;
let sub_bands = SbcSubBands::EIGHT;
Some(
SbcCodecInfo::new(
frequency,
channel_mode,
block_count,
sub_bands,
allocation,
min_bitpool,
max_bitpool,
)
.expect("supported options"),
)
}
}
impl TryFrom<&[u8]> for SbcCodecInfo {
type Error = avdtp::Error;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
if value.len() != SBC_CODEC_EXTRA_LEN {
return Err(avdtp::Error::OutOfRange);
}
let mut codec_info_bytes = [0_u8; SBC_CODEC_EXTRA_LEN];
codec_info_bytes.copy_from_slice(&value);
Ok(Self(SbcCodecInfoBits(u32::from_be_bytes(codec_info_bytes))))
}
}
impl From<SbcCodecInfo> for avdtp::ServiceCapability {
fn from(codec_info: SbcCodecInfo) -> Self {
Self::MediaCodec {
media_type: avdtp::MediaType::Audio,
codec_type: avdtp::MediaCodecType::AUDIO_SBC,
codec_extra: codec_info.to_bytes().to_vec(),
}
}
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AacObjectType:u8 {
const MPEG2_AAC_LC = 0b10000000;
const MPEG4_AAC_LC = 0b01000000;
const MPEG4_AAC_LTP = 0b00100000;
const MPEG4_AAC_SCALABLE = 0b00010000;
const MANDATORY_SNK = Self::MPEG2_AAC_LC.bits();
const MANDATORY_SRC = Self::MPEG2_AAC_LC.bits();
}
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AacSamplingFrequency:u16 {
const FREQ8000HZ = 0b100000000000;
const FREQ11025HZ = 0b010000000000;
const FREQ12000HZ = 0b001000000000;
const FREQ16000HZ = 0b000100000000;
const FREQ22050HZ = 0b000010000000;
const FREQ24000HZ = 0b000001000000;
const FREQ32000HZ = 0b000000100000;
const FREQ44100HZ = 0b000000010000;
const FREQ48000HZ = 0b000000001000;
const FREQ64000HZ = 0b000000000100;
const FREQ88200HZ = 0b000000000010;
const FREQ96000HZ = 0b000000000001;
const MANDATORY_SNK = Self::FREQ44100HZ.bits() | Self::FREQ48000HZ.bits();
}
}
impl AacSamplingFrequency {
fn best(&self) -> Option<Self> {
let ordered = [Self::FREQ96000HZ, Self::FREQ48000HZ, Self::FREQ44100HZ];
ordered.iter().find(|freq| self.contains(**freq)).copied()
}
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AacChannels:u8 {
const ONE = 0b10;
const TWO = 0b01;
const MANDATORY_SNK = Self::ONE.bits() | Self::TWO.bits();
}
}
impl AacChannels {
fn best(&self) -> Option<Self> {
let ordered = [Self::TWO, Self::ONE];
ordered.iter().find(|channels| self.contains(**channels)).copied()
}
}
bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct AacVariableBitRate: u8 {
const VBR_SUPPORTED = 0b1;
const MANDATORY_SNK = Self::VBR_SUPPORTED.bits();
}
}
pub const AAC_CODEC_EXTRA_LEN: usize = 6;
bitfield! {
struct AacCodecInfoBits(u64);
impl Debug;
u8;
u32, bitrate, set_bitrate: 22, 0;
vbr, set_vbr: 23, 23;
channels, set_channels: 27,26;
u16, sampling_frequency, set_sampling_frequency: 39, 28;
object_type, set_object_type: 47, 40;
}
#[derive(Debug)]
pub struct AacCodecInfo(AacCodecInfoBits);
impl AacCodecInfo {
pub fn new(
object_type: AacObjectType,
sampling_frequency: AacSamplingFrequency,
channels: AacChannels,
vbr: bool,
bitrate: u32,
) -> avdtp::Result<Self> {
if bitrate > 0x7fffff {
return Err(avdtp::Error::OutOfRange);
}
let mut res = AacCodecInfoBits(0);
res.set_bitrate(bitrate);
if vbr {
res.set_vbr(AacVariableBitRate::VBR_SUPPORTED.bits());
}
res.set_channels(channels.bits());
res.set_sampling_frequency(sampling_frequency.bits());
res.set_object_type(object_type.bits());
Ok(Self(res))
}
pub fn to_bytes(&self) -> [u8; 6] {
let codec_info = (self.0).0.to_be_bytes();
let mut res = [0u8; 6];
res.copy_from_slice(&codec_info[2..8]);
res
}
pub fn variable_bit_rate(&self) -> bool {
self.0.vbr() == 0b1
}
pub fn bitrate(&self) -> u32 {
self.0.bitrate()
}
pub fn channels(&self) -> AacChannels {
AacChannels::from_bits_truncate(self.0.channels())
}
pub fn channel_count(&self) -> avdtp::Result<usize> {
let count = match self.channels() {
AacChannels::ONE => 1,
AacChannels::TWO => 2,
_ => return Err(avdtp::Error::OutOfRange),
};
Ok(count)
}
fn object_type(&self) -> AacObjectType {
AacObjectType::from_bits_truncate(self.0.object_type())
}
pub fn sampling_frequency(&self) -> avdtp::Result<u32> {
let hz = match AacSamplingFrequency::from_bits_truncate(self.0.sampling_frequency()) {
AacSamplingFrequency::FREQ8000HZ => 8000,
AacSamplingFrequency::FREQ11025HZ => 11025,
AacSamplingFrequency::FREQ12000HZ => 12000,
AacSamplingFrequency::FREQ16000HZ => 16000,
AacSamplingFrequency::FREQ22050HZ => 22050,
AacSamplingFrequency::FREQ24000HZ => 24000,
AacSamplingFrequency::FREQ32000HZ => 32000,
AacSamplingFrequency::FREQ44100HZ => 44100,
AacSamplingFrequency::FREQ48000HZ => 48000,
AacSamplingFrequency::FREQ64000HZ => 64000,
AacSamplingFrequency::FREQ88200HZ => 88200,
AacSamplingFrequency::FREQ96000HZ => 96000,
_ => return Err(avdtp::Error::OutOfRange),
};
Ok(hz)
}
pub fn supports(&self, other: &Self) -> bool {
let allowed_frequencies =
AacSamplingFrequency::from_bits_truncate(self.0.sampling_frequency());
let selected_frequencies =
AacSamplingFrequency::from_bits_truncate(other.0.sampling_frequency());
if !(allowed_frequencies.intersects(selected_frequencies)) {
return false;
}
if !(self.channels().intersects(other.channels())) {
return false;
}
if !(self.object_type().intersects(other.object_type())) {
return false;
}
if !self.variable_bit_rate() && other.variable_bit_rate() {
return false;
}
if self.bitrate() != 0 && (self.bitrate() < other.bitrate()) {
return false;
}
return true;
}
pub fn negotiate(a: &Self, b: &Self) -> Option<Self> {
let available_frequencies = AacSamplingFrequency::from_bits_truncate(
a.0.sampling_frequency() & b.0.sampling_frequency(),
);
let sampling_frequency = match available_frequencies.best() {
None => return None,
Some(freq) => freq,
};
let available_channels = a.channels() & b.channels();
let channels = match available_channels.best() {
None => return None,
Some(channels) => channels,
};
let vbr = a.variable_bit_rate() && b.variable_bit_rate();
let bitrate = match (a.bitrate(), b.bitrate()) {
(0, 0) => 128000,
(0, b) => b,
(a, 0) => a,
(a, b) => std::cmp::min(a, b),
};
let object_type = AacObjectType::MPEG2_AAC_LC;
Some(AacCodecInfo::new(object_type, sampling_frequency, channels, vbr, bitrate).unwrap())
}
}
impl TryFrom<&[u8]> for AacCodecInfo {
type Error = avdtp::Error;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
if value.len() != AAC_CODEC_EXTRA_LEN {
return Err(avdtp::Error::OutOfRange);
}
let mut codec_info_bytes = [0_u8; 8];
let codec_info_slice = &mut codec_info_bytes[2..8];
codec_info_slice.copy_from_slice(&value);
Ok(Self(AacCodecInfoBits(u64::from_be_bytes(codec_info_bytes))))
}
}
impl From<AacCodecInfo> for avdtp::ServiceCapability {
fn from(codec_info: AacCodecInfo) -> Self {
Self::MediaCodec {
media_type: avdtp::MediaType::Audio,
codec_type: avdtp::MediaCodecType::AUDIO_AAC,
codec_extra: codec_info.to_bytes().to_vec(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use assert_matches::assert_matches;
#[test]
fn test_sbc_codec_info() {
let sbc_codec_info: SbcCodecInfo = SbcCodecInfo::new(
SbcSamplingFrequency::MANDATORY_SNK,
SbcChannelMode::MANDATORY_SNK,
SbcBlockCount::MANDATORY_SNK,
SbcSubBands::MANDATORY_SNK,
SbcAllocation::MANDATORY_SNK,
2,
250,
)
.expect("Couldn't create sbc media codec info.");
let res = sbc_codec_info.to_bytes();
let codec_extra: Vec<u8> = vec![0x3F, 0xFF, 2, 250];
assert_eq!(codec_extra, res);
let res = SbcCodecInfo::try_from(&codec_extra[..]).expect("created codec info");
assert_eq!((res.0).0, (sbc_codec_info.0).0);
let sbc_codec_info: SbcCodecInfo = SbcCodecInfo::new(
SbcSamplingFrequency::FREQ44100HZ,
SbcChannelMode::MONO | SbcChannelMode::DUAL_CHANNEL,
SbcBlockCount::MANDATORY_SRC,
SbcSubBands::MANDATORY_SRC,
SbcAllocation::MANDATORY_SRC,
2,
250,
)
.expect("Couldn't create sbc media codec info.");
let res = sbc_codec_info.to_bytes();
assert_eq!(vec![0x2C, 0xF5, 2, 250], res);
let sbc_codec_info: SbcCodecInfo = SbcCodecInfo::new(
SbcSamplingFrequency::empty(),
SbcChannelMode::empty(),
SbcBlockCount::empty(),
SbcSubBands::empty(),
SbcAllocation::empty(),
2,
250,
)
.expect("Couldn't create sbc media codec info.");
assert_matches!(sbc_codec_info.channel_count(), Err(avdtp::Error::OutOfRange));
let res = sbc_codec_info.to_bytes();
assert_eq!(vec![0x00, 0x00, 2, 250], res);
let sbc_codec_info: SbcCodecInfo = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::all(),
SbcSubBands::all(),
SbcAllocation::all(),
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
assert_matches!(sbc_codec_info.channel_count(), Err(avdtp::Error::OutOfRange));
let res = sbc_codec_info.to_bytes();
assert_eq!(vec![0xFF, 0xFF, 2, 250], res);
let sbc_codec_info = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::all(),
SbcSubBands::all(),
SbcAllocation::all(),
20,
252, );
assert!(sbc_codec_info.is_err());
let sbc_codec_info = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::all(),
SbcSubBands::all(),
SbcAllocation::all(),
0, 240,
);
assert!(sbc_codec_info.is_err());
let sbc_codec_info = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::all(),
SbcSubBands::all(),
SbcAllocation::all(),
100,
50,
);
assert!(sbc_codec_info.is_err());
let empty = vec![0, 0, 0, 0];
let res = SbcCodecInfo::try_from(&empty[..]).expect("created codec info");
assert_eq!((res.0).0, 0);
let too_big = vec![0, 0, 0, 0, 0];
assert_matches!(SbcCodecInfo::try_from(&too_big[..]), Err(avdtp::Error::OutOfRange));
let sbc_codec_info: SbcCodecInfo = SbcCodecInfo::new(
SbcSamplingFrequency::FREQ44100HZ,
SbcChannelMode::MONO,
SbcBlockCount::MANDATORY_SRC,
SbcSubBands::MANDATORY_SRC,
SbcAllocation::MANDATORY_SRC,
2,
250,
)
.expect("Couldn't create sbc media codec info.");
assert_matches!(sbc_codec_info.channel_count(), Ok(1));
let sbc_codec_info: SbcCodecInfo = SbcCodecInfo::new(
SbcSamplingFrequency::FREQ44100HZ,
SbcChannelMode::JOINT_STEREO,
SbcBlockCount::MANDATORY_SRC,
SbcSubBands::MANDATORY_SRC,
SbcAllocation::MANDATORY_SRC,
2,
250,
)
.expect("Couldn't create sbc media codec info.");
assert_matches!(sbc_codec_info.channel_count(), Ok(2));
}
#[test]
fn test_sbc_codec_supports() {
let sbc_codec_all = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::all(),
SbcSubBands::all(),
SbcAllocation::all(),
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
assert!(sbc_codec_all.supports(&sbc_codec_all));
let sbc_codec_441 = SbcCodecInfo::new(
SbcSamplingFrequency::FREQ44100HZ,
SbcChannelMode::all(),
SbcBlockCount::all(),
SbcSubBands::all(),
SbcAllocation::all(),
53, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
let sbc_codec_48 = SbcCodecInfo::new(
SbcSamplingFrequency::FREQ48000HZ,
SbcChannelMode::all(),
SbcBlockCount::all(),
SbcSubBands::all(),
SbcAllocation::all(),
SbcCodecInfo::BITPOOL_MIN, 53, )
.expect("Couldn't create sbc media codec info.");
assert!(sbc_codec_all.supports(&sbc_codec_441));
assert!(sbc_codec_all.supports(&sbc_codec_48));
assert!(!sbc_codec_48.supports(&sbc_codec_441));
assert!(!sbc_codec_441.supports(&sbc_codec_48));
assert!(!sbc_codec_48.supports(&sbc_codec_all));
assert!(!sbc_codec_441.supports(&sbc_codec_all));
let sbc_codec_mono = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::MONO,
SbcBlockCount::all(),
SbcSubBands::all(),
SbcAllocation::all(),
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
let sbc_codec_stereo = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::JOINT_STEREO,
SbcBlockCount::all(),
SbcSubBands::all(),
SbcAllocation::all(),
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
assert!(sbc_codec_all.supports(&sbc_codec_mono));
assert!(sbc_codec_all.supports(&sbc_codec_stereo));
assert!(!sbc_codec_mono.supports(&sbc_codec_stereo));
assert!(!sbc_codec_stereo.supports(&sbc_codec_mono));
let sbc_codec_blocks_4 = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::FOUR,
SbcSubBands::all(),
SbcAllocation::all(),
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
let sbc_codec_blocks_8 = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::EIGHT,
SbcSubBands::all(),
SbcAllocation::all(),
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
assert!(sbc_codec_all.supports(&sbc_codec_blocks_4));
assert!(sbc_codec_all.supports(&sbc_codec_blocks_8));
assert!(!sbc_codec_blocks_4.supports(&sbc_codec_blocks_8));
assert!(!sbc_codec_blocks_8.supports(&sbc_codec_blocks_4));
let sbc_codec_bands_4 = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::FOUR,
SbcSubBands::FOUR,
SbcAllocation::all(),
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
let sbc_codec_bands_8 = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::FOUR,
SbcSubBands::EIGHT,
SbcAllocation::all(),
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
assert!(sbc_codec_all.supports(&sbc_codec_bands_4));
assert!(sbc_codec_all.supports(&sbc_codec_bands_8));
assert!(!sbc_codec_bands_4.supports(&sbc_codec_bands_8));
assert!(!sbc_codec_bands_8.supports(&sbc_codec_bands_4));
let sbc_codec_snr = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::FOUR,
SbcSubBands::FOUR,
SbcAllocation::SNR,
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
let sbc_codec_loudness = SbcCodecInfo::new(
SbcSamplingFrequency::all(),
SbcChannelMode::all(),
SbcBlockCount::FOUR,
SbcSubBands::FOUR,
SbcAllocation::LOUDNESS,
SbcCodecInfo::BITPOOL_MIN, SbcCodecInfo::BITPOOL_MAX, )
.expect("Couldn't create sbc media codec info.");
assert!(sbc_codec_all.supports(&sbc_codec_snr));
assert!(sbc_codec_all.supports(&sbc_codec_loudness));
assert!(!sbc_codec_snr.supports(&sbc_codec_loudness));
assert!(!sbc_codec_loudness.supports(&sbc_codec_snr));
}
#[test]
fn test_aac_codec_info() {
let aac_codec_info = AacCodecInfo::new(
AacObjectType::empty(),
AacSamplingFrequency::empty(),
AacChannels::empty(),
false,
0,
)
.expect("Error creating aac media codec info.");
let res = aac_codec_info.to_bytes();
assert_eq!(vec![0, 0, 0, 0, 0, 0], res);
let aac_codec_info = AacCodecInfo::new(
AacObjectType::all(),
AacSamplingFrequency::all(),
AacChannels::all(),
true,
8388607, )
.expect("Error creating aac media codec info.");
assert_matches!(aac_codec_info.channel_count(), Err(avdtp::Error::OutOfRange));
let res = aac_codec_info.to_bytes();
assert_eq!(vec![0xF0, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF], res);
let aac_codec_info = AacCodecInfo::new(
AacObjectType::empty(),
AacSamplingFrequency::empty(),
AacChannels::empty(),
true,
0,
)
.expect("Error creating aac media codec info.");
assert_matches!(aac_codec_info.channel_count(), Err(avdtp::Error::OutOfRange));
let res = aac_codec_info.to_bytes();
assert_eq!(vec![0x00, 0x00, 0x00, 0x80, 0x00, 0x00], res);
let aac_codec_info = AacCodecInfo::new(
AacObjectType::MANDATORY_SNK,
AacSamplingFrequency::MANDATORY_SNK,
AacChannels::MANDATORY_SNK,
true,
0xAAFF, )
.expect("Error creating aac media codec info.");
let res = aac_codec_info.to_bytes();
let codec_extra: Vec<u8> = vec![0x80, 0x01, 0x8C, 0x80, 0xAA, 0xFF];
assert_eq!(codec_extra, res);
let res = AacCodecInfo::try_from(&codec_extra[..]).expect("created codec info");
assert_eq!((res.0).0, (aac_codec_info.0).0);
let aac_codec_info = AacCodecInfo::new(
AacObjectType::MANDATORY_SRC,
AacSamplingFrequency::FREQ44100HZ,
AacChannels::ONE,
false, 0xAAFF, )
.expect("Error creating aac media codec info.");
assert_matches!(aac_codec_info.channel_count(), Ok(1));
let res = aac_codec_info.to_bytes();
assert_eq!(vec![0x80, 0x01, 0x08, 0x00, 0xAA, 0xFF], res);
let aac_codec_info = AacCodecInfo::new(
AacObjectType::MANDATORY_SRC,
AacSamplingFrequency::FREQ44100HZ,
AacChannels::TWO,
false, 0xAAFF, )
.expect("Error creating aac media codec info.");
assert_matches!(aac_codec_info.channel_count(), Ok(2));
let aac_codec_info = AacCodecInfo::new(
AacObjectType::MANDATORY_SRC,
AacSamplingFrequency::FREQ44100HZ,
AacChannels::ONE,
false,
0xFFFFFF, );
assert!(aac_codec_info.is_err());
let empty = vec![0, 0, 0, 0, 0, 0];
let res = AacCodecInfo::try_from(&empty[..]).expect("created codec info");
assert_eq!((res.0).0, 0);
let too_big = vec![0, 0, 0, 0, 0, 0, 0];
assert_matches!(AacCodecInfo::try_from(&too_big[..]), Err(avdtp::Error::OutOfRange));
}
#[test]
fn test_aac_codec_supports() {
let aac_codec_all = AacCodecInfo::new(
AacObjectType::all(),
AacSamplingFrequency::all(),
AacChannels::all(),
true,
8388607, )
.expect("Error creating aac media codec info.");
assert!(aac_codec_all.supports(&aac_codec_all));
let aac_codec_441 = AacCodecInfo::new(
AacObjectType::all(),
AacSamplingFrequency::FREQ44100HZ,
AacChannels::all(),
true,
50, )
.expect("Error creating aac media codec info.");
let aac_codec_48 = AacCodecInfo::new(
AacObjectType::all(),
AacSamplingFrequency::FREQ48000HZ,
AacChannels::all(),
true,
8388607, )
.expect("Error creating aac media codec info.");
assert!(aac_codec_all.supports(&aac_codec_441));
assert!(aac_codec_all.supports(&aac_codec_48));
assert!(!aac_codec_441.supports(&aac_codec_48));
assert!(!aac_codec_48.supports(&aac_codec_441));
assert!(!aac_codec_441.supports(&aac_codec_all));
let aac_codec_chan_one = AacCodecInfo::new(
AacObjectType::all(),
AacSamplingFrequency::all(),
AacChannels::ONE,
true,
8388607, )
.expect("Error creating aac media codec info.");
let aac_codec_chan_two = AacCodecInfo::new(
AacObjectType::all(),
AacSamplingFrequency::all(),
AacChannels::TWO,
true,
8388607, )
.expect("Error creating aac media codec info.");
assert!(aac_codec_all.supports(&aac_codec_chan_one));
assert!(aac_codec_all.supports(&aac_codec_chan_two));
assert!(!aac_codec_chan_one.supports(&aac_codec_chan_two));
assert!(!aac_codec_chan_two.supports(&aac_codec_chan_one));
let aac_codec_mpeg2 = AacCodecInfo::new(
AacObjectType::MPEG2_AAC_LC,
AacSamplingFrequency::all(),
AacChannels::ONE,
true,
8388607, )
.expect("Error creating aac media codec info.");
let aac_codec_mpeg4 = AacCodecInfo::new(
AacObjectType::MPEG4_AAC_LC,
AacSamplingFrequency::all(),
AacChannels::ONE,
true,
8388607, )
.expect("Error creating aac media codec info.");
assert!(aac_codec_all.supports(&aac_codec_mpeg2));
assert!(aac_codec_all.supports(&aac_codec_mpeg4));
assert!(!aac_codec_mpeg2.supports(&aac_codec_mpeg4));
assert!(!aac_codec_mpeg4.supports(&aac_codec_mpeg2));
let aac_codec_not_vbr = AacCodecInfo::new(
AacObjectType::MPEG4_AAC_LC,
AacSamplingFrequency::all(),
AacChannels::ONE,
false,
8388607, )
.expect("Error creating aac media codec info.");
assert!(!aac_codec_not_vbr.supports(&aac_codec_mpeg4));
let aac_codec_bitrate_not_known = AacCodecInfo::new(
AacObjectType::MPEG4_AAC_LC,
AacSamplingFrequency::all(),
AacChannels::ONE,
true,
0, )
.expect("Error creating aac media codec info.");
assert!(aac_codec_bitrate_not_known.supports(&aac_codec_not_vbr));
}
}