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 <gtest/gtest.h>
18
19 #include <chrono>
20 #include <cstdint>
21 #include <future>
22 #include <string>
23
24 #include "common/time_util.h"
25 #include "osi/include/allocator.h"
26 #include "stack/include/a2dp_vendor_opus.h"
27 #include "stack/include/a2dp_vendor_opus_constants.h"
28 #include "stack/include/bt_hdr.h"
29 #include "test_util.h"
30 #include "wav_reader.h"
31
32 namespace {
33 constexpr uint32_t kA2dpTickUs = 23 * 1000;
34 constexpr char kWavFile[] = "test/a2dp/raw_data/pcm1644s.wav";
35 const uint8_t kCodecInfoOpusCapability[AVDT_CODEC_SIZE] = {
36 A2DP_OPUS_CODEC_LEN, // Length
37 AVDT_MEDIA_TYPE_AUDIO << 4, // Media Type
38 A2DP_MEDIA_CT_NON_A2DP, // Media Codec Type Vendor
39 (A2DP_OPUS_VENDOR_ID & 0x000000FF),
40 (A2DP_OPUS_VENDOR_ID & 0x0000FF00) >> 8,
41 (A2DP_OPUS_VENDOR_ID & 0x00FF0000) >> 16,
42 (A2DP_OPUS_VENDOR_ID & 0xFF000000) >> 24,
43 (A2DP_OPUS_CODEC_ID & 0x00FF),
44 (A2DP_OPUS_CODEC_ID & 0xFF00) >> 8,
45 A2DP_OPUS_CHANNEL_MODE_STEREO | A2DP_OPUS_20MS_FRAMESIZE | A2DP_OPUS_SAMPLING_FREQ_48000};
Data(BT_HDR * packet)46 uint8_t* Data(BT_HDR* packet) { return packet->data + packet->offset; }
47
GetReadSize()48 uint32_t GetReadSize() {
49 return A2DP_VendorGetFrameSizeOpus(kCodecInfoOpusCapability) *
50 A2DP_VendorGetTrackChannelCountOpus(kCodecInfoOpusCapability) *
51 (A2DP_VendorGetTrackBitsPerSampleOpus(kCodecInfoOpusCapability) / 8);
52 }
53 } // namespace
54
55 namespace bluetooth {
56 namespace testing {
57
58 static BT_HDR* packet = nullptr;
59 static WavReader wav_reader = WavReader(GetWavFilePath(kWavFile).c_str());
60 static std::promise<void> promise;
61
62 class A2dpOpusTest : public ::testing::Test {
63 protected:
SetUp()64 void SetUp() override {
65 SetCodecConfig();
66 encoder_iface_ = const_cast<tA2DP_ENCODER_INTERFACE*>(
67 A2DP_VendorGetEncoderInterfaceOpus(kCodecInfoOpusCapability));
68 ASSERT_NE(encoder_iface_, nullptr);
69 decoder_iface_ = const_cast<tA2DP_DECODER_INTERFACE*>(
70 A2DP_VendorGetDecoderInterfaceOpus(kCodecInfoOpusCapability));
71 ASSERT_NE(decoder_iface_, nullptr);
72 }
73
TearDown()74 void TearDown() override {
75 if (a2dp_codecs_ != nullptr) {
76 delete a2dp_codecs_;
77 }
78 if (encoder_iface_ != nullptr) {
79 encoder_iface_->encoder_cleanup();
80 }
81 if (decoder_iface_ != nullptr) {
82 decoder_iface_->decoder_cleanup();
83 }
84 }
85
SetCodecConfig()86 void SetCodecConfig() {
87 uint8_t codec_info_result[AVDT_CODEC_SIZE];
88 btav_a2dp_codec_index_t peer_codec_index;
89 a2dp_codecs_ = new A2dpCodecs(std::vector<btav_a2dp_codec_config_t>());
90
91 ASSERT_TRUE(a2dp_codecs_->init());
92
93 // Create the codec capability - SBC Sink
94 memset(codec_info_result, 0, sizeof(codec_info_result));
95 peer_codec_index = A2DP_SinkCodecIndex(kCodecInfoOpusCapability);
96 ASSERT_NE(peer_codec_index, BTAV_A2DP_CODEC_INDEX_MAX);
97 codec_config_ = a2dp_codecs_->findSinkCodecConfig(kCodecInfoOpusCapability);
98 ASSERT_NE(codec_config_, nullptr);
99 ASSERT_TRUE(a2dp_codecs_->setSinkCodecConfig(kCodecInfoOpusCapability, true, codec_info_result,
100 true));
101 ASSERT_EQ(a2dp_codecs_->getCurrentCodecConfig(), codec_config_);
102 // Compare the result codec with the local test codec info
103 for (size_t i = 0; i < kCodecInfoOpusCapability[0] + 1; i++) {
104 ASSERT_EQ(codec_info_result[i], kCodecInfoOpusCapability[i]);
105 }
106 ASSERT_EQ(codec_config_->getAudioBitsPerSample(), 16);
107 }
108
InitializeEncoder(a2dp_source_read_callback_t read_cb,a2dp_source_enqueue_callback_t enqueue_cb)109 void InitializeEncoder(a2dp_source_read_callback_t read_cb,
110 a2dp_source_enqueue_callback_t enqueue_cb) {
111 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params = {true, true, 1000};
112 encoder_iface_->encoder_init(&peer_params, codec_config_, read_cb, enqueue_cb);
113 }
114
InitializeDecoder(decoded_data_callback_t data_cb)115 void InitializeDecoder(decoded_data_callback_t data_cb) { decoder_iface_->decoder_init(data_cb); }
116
AllocateL2capPacket(const std::vector<uint8_t> data) const117 BT_HDR* AllocateL2capPacket(const std::vector<uint8_t> data) const {
118 auto packet = AllocatePacket(data.size());
119 std::copy(data.cbegin(), data.cend(), Data(packet));
120 return packet;
121 }
122
AllocatePacket(size_t packet_length) const123 BT_HDR* AllocatePacket(size_t packet_length) const {
124 BT_HDR* packet = static_cast<BT_HDR*>(osi_calloc(sizeof(BT_HDR) + packet_length));
125 packet->len = packet_length;
126 return packet;
127 }
128 A2dpCodecConfig* codec_config_;
129 A2dpCodecs* a2dp_codecs_;
130 tA2DP_ENCODER_INTERFACE* encoder_iface_;
131 tA2DP_DECODER_INTERFACE* decoder_iface_;
132 };
133
TEST_F(A2dpOpusTest,a2dp_source_read_underflow)134 TEST_F(A2dpOpusTest, a2dp_source_read_underflow) {
135 promise = {};
136 auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) -> uint32_t {
137 // underflow
138 return 0;
139 };
140 auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool {
141 promise.set_value();
142 osi_free(p_buf);
143 return false;
144 };
145 InitializeEncoder(read_cb, enqueue_cb);
146 uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
147 encoder_iface_->send_frames(timestamp_us);
148 usleep(kA2dpTickUs);
149 timestamp_us = bluetooth::common::time_gettimeofday_us();
150 encoder_iface_->send_frames(timestamp_us);
151 ASSERT_EQ(promise.get_future().wait_for(std::chrono::milliseconds(10)),
152 std::future_status::timeout);
153 }
154
TEST_F(A2dpOpusTest,a2dp_enqueue_cb_is_invoked)155 TEST_F(A2dpOpusTest, a2dp_enqueue_cb_is_invoked) {
156 promise = {};
157 auto read_cb = +[](uint8_t* /*p_buf*/, uint32_t len) -> uint32_t {
158 log::assert_that(GetReadSize() == len, "assert failed: GetReadSize() == len");
159 return len;
160 };
161 auto enqueue_cb = +[](BT_HDR* p_buf, size_t /*frames_n*/, uint32_t /*len*/) -> bool {
162 static bool first_invocation = true;
163 if (first_invocation) {
164 promise.set_value();
165 }
166 first_invocation = false;
167 osi_free(p_buf);
168 return false;
169 };
170 InitializeEncoder(read_cb, enqueue_cb);
171 uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
172 encoder_iface_->send_frames(timestamp_us);
173 usleep(kA2dpTickUs);
174 timestamp_us = bluetooth::common::time_gettimeofday_us();
175 encoder_iface_->send_frames(timestamp_us);
176 promise.get_future().wait();
177 }
178
TEST_F(A2dpOpusTest,decoded_data_cb_not_invoked_when_empty_packet)179 TEST_F(A2dpOpusTest, decoded_data_cb_not_invoked_when_empty_packet) {
180 auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) { FAIL(); };
181 InitializeDecoder(data_cb);
182 std::vector<uint8_t> data;
183 BT_HDR* packet = AllocateL2capPacket(data);
184 decoder_iface_->decode_packet(packet);
185 osi_free(packet);
186 }
187
TEST_F(A2dpOpusTest,decoded_data_cb_invoked)188 TEST_F(A2dpOpusTest, decoded_data_cb_invoked) {
189 promise = {};
190 auto data_cb = +[](uint8_t* /*p_buf*/, uint32_t /*len*/) {};
191 InitializeDecoder(data_cb);
192
193 auto read_cb = +[](uint8_t* p_buf, uint32_t len) -> uint32_t {
194 static uint32_t counter = 0;
195 memcpy(p_buf, wav_reader.GetSamples() + counter, len);
196 counter += len;
197 return len;
198 };
199 auto enqueue_cb = +[](BT_HDR* p_buf, size_t frames_n, uint32_t /*len*/) -> bool {
200 static bool first_invocation = true;
201 if (first_invocation) {
202 packet = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(*p_buf) + p_buf->len + 1));
203 memcpy(packet, p_buf, sizeof(*p_buf));
204 packet->offset = 0;
205 memcpy(packet->data + 1, p_buf->data + p_buf->offset, p_buf->len);
206 packet->data[0] = frames_n;
207 p_buf->len += 1;
208 promise.set_value();
209 }
210 first_invocation = false;
211 osi_free(p_buf);
212 return false;
213 };
214 InitializeEncoder(read_cb, enqueue_cb);
215
216 uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
217 encoder_iface_->send_frames(timestamp_us);
218
219 promise.get_future().wait();
220 decoder_iface_->decode_packet(packet);
221 osi_free(packet);
222 }
223
224 } // namespace testing
225 } // namespace bluetooth
226