1 /*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "stack/include/a2dp_aac.h"
18
19 #include <bluetooth/log.h>
20 #include <gtest/gtest.h>
21
22 #include <cstdint>
23 #include <string>
24
25 #include "common/time_util.h"
26 #include "osi/include/allocator.h"
27 #include "stack/include/a2dp_aac_decoder.h"
28 #include "stack/include/a2dp_aac_encoder.h"
29 #include "stack/include/avdt_api.h"
30 #include "stack/include/bt_hdr.h"
31 #include "test_util.h"
32 #include "wav_reader.h"
33
34 namespace {
35 constexpr uint32_t kAacReadSize = 1024 * 2 * 2;
36 constexpr uint32_t kA2dpTickUs = 23 * 1000;
37 constexpr uint16_t kPeerMtu = 1000;
38 constexpr char kWavFile[] = "test/a2dp/raw_data/pcm1644s.wav";
39 constexpr uint8_t kCodecInfoAacCapability[AVDT_CODEC_SIZE] = {
40 8, // Length (A2DP_AAC_INFO_LEN)
41 0, // Media Type: AVDT_MEDIA_TYPE_AUDIO
42 2, // Media Codec Type: A2DP_MEDIA_CT_AAC
43 0x80, // Object Type: A2DP_AAC_OBJECT_TYPE_MPEG2_LC
44 0x01, // Sampling Frequency: A2DP_AAC_SAMPLING_FREQ_44100
45 0x04, // Channels: A2DP_AAC_CHANNEL_MODE_STEREO
46 0x00 | 0x4, // Variable Bit Rate:
47 // A2DP_AAC_VARIABLE_BIT_RATE_DISABLED
48 // Bit Rate: 320000 = 0x4e200
49 0xe2, // Bit Rate: 320000 = 0x4e200
50 0x00, // Bit Rate: 320000 = 0x4e200
51 7, // Unused
52 8, // Unused
53 9 // Unused
54 };
Data(BT_HDR * packet)55 uint8_t* Data(BT_HDR* packet) { return packet->data + packet->offset; }
56 } // namespace
57
58 namespace bluetooth {
59 namespace testing {
60
61 static BT_HDR* packet = nullptr;
62 static WavReader wav_reader = WavReader(GetWavFilePath(kWavFile).c_str());
63
64 class A2dpAacTest : public ::testing::Test {
65 protected:
SetUp()66 void SetUp() override {
67 SetCodecConfig();
68 encoder_iface_ = const_cast<tA2DP_ENCODER_INTERFACE*>(
69 A2DP_GetEncoderInterfaceAac(kCodecInfoAacCapability));
70 ASSERT_NE(encoder_iface_, nullptr);
71 decoder_iface_ = const_cast<tA2DP_DECODER_INTERFACE*>(
72 A2DP_GetDecoderInterfaceAac(kCodecInfoAacCapability));
73 ASSERT_NE(decoder_iface_, nullptr);
74 }
75
TearDown()76 void TearDown() override {
77 if (a2dp_codecs_ != nullptr) {
78 delete a2dp_codecs_;
79 }
80 if (encoder_iface_ != nullptr) {
81 encoder_iface_->encoder_cleanup();
82 }
83 A2DP_UnloadEncoderAac();
84 if (decoder_iface_ != nullptr) {
85 decoder_iface_->decoder_cleanup();
86 }
87 A2DP_UnloadDecoderAac();
88 }
89
SetCodecConfig()90 void SetCodecConfig() {
91 uint8_t codec_info_result[AVDT_CODEC_SIZE];
92 btav_a2dp_codec_index_t peer_codec_index;
93 a2dp_codecs_ = new A2dpCodecs(std::vector<btav_a2dp_codec_config_t>());
94
95 ASSERT_TRUE(a2dp_codecs_->init());
96
97 // Create the codec capability - AAC Sink
98 memset(codec_info_result, 0, sizeof(codec_info_result));
99 ASSERT_EQ(A2DP_IsSinkCodecSupportedAac(kCodecInfoAacCapability), A2DP_SUCCESS);
100 peer_codec_index = A2DP_SinkCodecIndex(kCodecInfoAacCapability);
101 ASSERT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
102 sink_codec_config_ = a2dp_codecs_->findSinkCodecConfig(kCodecInfoAacCapability);
103 ASSERT_NE(sink_codec_config_, nullptr);
104 ASSERT_TRUE(a2dp_codecs_->setSinkCodecConfig(kCodecInfoAacCapability, true, codec_info_result,
105 true));
106 ASSERT_TRUE(a2dp_codecs_->setPeerSinkCodecCapabilities(kCodecInfoAacCapability));
107 // Compare the result codec with the local test codec info
108 for (size_t i = 0; i < kCodecInfoAacCapability[0] + 1; i++) {
109 ASSERT_EQ(codec_info_result[i], kCodecInfoAacCapability[i]);
110 }
111 ASSERT_TRUE(
112 a2dp_codecs_->setCodecConfig(kCodecInfoAacCapability, true, codec_info_result, true));
113 source_codec_config_ = a2dp_codecs_->getCurrentCodecConfig();
114 }
115
InitializeEncoder(bool peer_supports_3mbps,a2dp_source_read_callback_t read_cb,a2dp_source_enqueue_callback_t enqueue_cb)116 void InitializeEncoder(bool peer_supports_3mbps, a2dp_source_read_callback_t read_cb,
117 a2dp_source_enqueue_callback_t enqueue_cb) {
118 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params = {true, peer_supports_3mbps, kPeerMtu};
119 encoder_iface_->encoder_init(&peer_params, sink_codec_config_, read_cb, enqueue_cb);
120 }
121
InitializeDecoder(decoded_data_callback_t data_cb)122 void InitializeDecoder(decoded_data_callback_t data_cb) { decoder_iface_->decoder_init(data_cb); }
123
AllocateL2capPacket(const std::vector<uint8_t> data) const124 BT_HDR* AllocateL2capPacket(const std::vector<uint8_t> data) const {
125 auto packet = AllocatePacket(data.size());
126 std::copy(data.cbegin(), data.cend(), Data(packet));
127 return packet;
128 }
129
AllocatePacket(size_t packet_length) const130 BT_HDR* AllocatePacket(size_t packet_length) const {
131 BT_HDR* packet = static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length));
132 packet->len = packet_length;
133 return packet;
134 }
135 A2dpCodecConfig* sink_codec_config_;
136 A2dpCodecConfig* source_codec_config_;
137 A2dpCodecs* a2dp_codecs_;
138 tA2DP_ENCODER_INTERFACE* encoder_iface_;
139 tA2DP_DECODER_INTERFACE* decoder_iface_;
140 };
141
TEST_F(A2dpAacTest,a2dp_source_read_underflow)142 TEST_F(A2dpAacTest, a2dp_source_read_underflow) {
143 static int enqueue_cb_invoked = 0;
144
145 auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) -> uint32_t { return 0; };
146
147 auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool {
148 enqueue_cb_invoked += 1;
149 osi_free(p_buf);
150 return false;
151 };
152
153 InitializeEncoder(true, read_cb, enqueue_cb);
154 uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
155 encoder_iface_->send_frames(timestamp_us);
156 encoder_iface_->send_frames(timestamp_us + kA2dpTickUs);
157
158 ASSERT_EQ(enqueue_cb_invoked, 0);
159 }
160
TEST_F(A2dpAacTest,a2dp_enqueue_cb_is_invoked)161 TEST_F(A2dpAacTest, a2dp_enqueue_cb_is_invoked) {
162 static int enqueue_cb_invoked = 0;
163
164 auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t { return len; };
165
166 auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool {
167 enqueue_cb_invoked += 1;
168 osi_free(p_buf);
169 return false;
170 };
171
172 InitializeEncoder(true, read_cb, enqueue_cb);
173 uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
174 encoder_iface_->send_frames(timestamp_us);
175 encoder_iface_->send_frames(timestamp_us + kA2dpTickUs);
176
177 ASSERT_EQ(enqueue_cb_invoked, 1);
178 }
179
TEST_F(A2dpAacTest,decoded_data_cb_not_invoked_when_empty_packet)180 TEST_F(A2dpAacTest, decoded_data_cb_not_invoked_when_empty_packet) {
181 auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) { FAIL(); };
182 InitializeDecoder(data_cb);
183 std::vector<uint8_t> data;
184 BT_HDR* packet = AllocateL2capPacket(data);
185 decoder_iface_->decode_packet(packet);
186 osi_free(packet);
187 }
188
TEST_F(A2dpAacTest,decoded_data_cb_invoked)189 TEST_F(A2dpAacTest, decoded_data_cb_invoked) {
190 static int data_cb_invoked = 0;
191 static int enqueue_cb_invoked = 0;
192
193 auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) { data_cb_invoked += 1; };
194
195 InitializeDecoder(data_cb);
196
197 auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t {
198 static uint32_t counter = 0;
199 memcpy(p_buf, wav_reader.GetSamples() + counter, len);
200 counter += len;
201 return len;
202 };
203
204 auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool {
205 enqueue_cb_invoked += 1;
206 packet = p_buf;
207 return false;
208 };
209
210 InitializeEncoder(true, read_cb, enqueue_cb);
211
212 uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
213 encoder_iface_->send_frames(timestamp_us);
214 encoder_iface_->send_frames(timestamp_us + kA2dpTickUs);
215
216 ASSERT_EQ(enqueue_cb_invoked, 1);
217 decoder_iface_->decode_packet(packet);
218 osi_free(packet);
219 ASSERT_EQ(data_cb_invoked, 1);
220 }
221
TEST_F(A2dpAacTest,set_source_codec_config_works)222 TEST_F(A2dpAacTest, set_source_codec_config_works) {
223 uint8_t codec_info_result[AVDT_CODEC_SIZE];
224 ASSERT_TRUE(a2dp_codecs_->setCodecConfig(kCodecInfoAacCapability, true, codec_info_result, true));
225 ASSERT_TRUE(A2DP_CodecTypeEqualsAac(codec_info_result, kCodecInfoAacCapability));
226 ASSERT_TRUE(A2DP_CodecEqualsAac(codec_info_result, kCodecInfoAacCapability));
227 auto* codec_config = a2dp_codecs_->findSourceCodecConfig(kCodecInfoAacCapability);
228 ASSERT_EQ(codec_config->name(), source_codec_config_->name());
229 ASSERT_EQ(codec_config->getAudioBitsPerSample(), source_codec_config_->getAudioBitsPerSample());
230 }
231
TEST_F(A2dpAacTest,sink_supports_aac)232 TEST_F(A2dpAacTest, sink_supports_aac) {
233 ASSERT_EQ(A2DP_IsSinkCodecSupportedAac(kCodecInfoAacCapability), A2DP_SUCCESS);
234 }
235
TEST_F(A2dpAacTest,effective_mtu_when_peer_supports_3mbps)236 TEST_F(A2dpAacTest, effective_mtu_when_peer_supports_3mbps) {
237 auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t {
238 log::assert_that(kAacReadSize == len, "assert failed: kAacReadSize == len");
239 return len;
240 };
241 auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool {
242 osi_free(p_buf);
243 return false;
244 };
245 InitializeEncoder(true, read_cb, enqueue_cb);
246 ASSERT_EQ(a2dp_aac_get_effective_frame_size(), kPeerMtu);
247 }
248
TEST_F(A2dpAacTest,effective_mtu_when_peer_does_not_support_3mbps)249 TEST_F(A2dpAacTest, effective_mtu_when_peer_does_not_support_3mbps) {
250 auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t {
251 log::assert_that(kAacReadSize == len, "assert failed: kAacReadSize == len");
252 return len;
253 };
254 auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool {
255 osi_free(p_buf);
256 return false;
257 };
258 InitializeEncoder(false, read_cb, enqueue_cb);
259 ASSERT_EQ(a2dp_aac_get_effective_frame_size(), 663 /* MAX_2MBPS_AVDTP_MTU */);
260 }
261
TEST_F(A2dpAacTest,codec_info_string)262 TEST_F(A2dpAacTest, codec_info_string) {
263 auto codec_info = A2DP_CodecInfoString(kCodecInfoAacCapability);
264 ASSERT_NE(codec_info.find("samp_freq: 44100"), std::string::npos);
265 ASSERT_NE(codec_info.find("ch_mode: Stereo"), std::string::npos);
266 }
267
TEST_F(A2dpAacTest,get_track_bits_per_sample)268 TEST_F(A2dpAacTest, get_track_bits_per_sample) {
269 ASSERT_EQ(A2DP_GetTrackBitsPerSampleAac(kCodecInfoAacCapability), 16);
270 }
271
272 } // namespace testing
273 } // namespace bluetooth
274