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