1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "a2dp_codec_thread.h"
17 #include <sys/time.h>
18 #include "a2dp_decoder_aac.h"
19 #include "a2dp_encoder_aac.h"
20 #include "a2dp_decoder_sbc.h"
21 #include "a2dp_encoder_sbc.h"
22 #include "log.h"
23
24 namespace bluetooth {
25 A2dpCodecThread *A2dpCodecThread::g_instance = nullptr;
26 std::recursive_mutex g_codecMutex {};
A2dpCodecThread(const std::string & name)27 A2dpCodecThread::A2dpCodecThread(const std::string &name) : name_(name)
28 {
29 LOG_INFO("[A2dpCodecThread]%{public}s\n", __func__);
30 dispatcher_ = std::make_unique<Dispatcher>(name);
31 }
32
~A2dpCodecThread()33 A2dpCodecThread::~A2dpCodecThread()
34 {
35 encoder_ = nullptr;
36 decoder_ = nullptr;
37 dispatcher_ = nullptr;
38 g_instance = nullptr;
39 isSbc_ = false;
40 }
41
PostMessage(const utility::Message msg,const A2dpEncoderInitPeerParams & peerParams,A2dpCodecConfig * config,A2dpEncoderObserver * observer,A2dpDecoderObserver * decObserver) const42 bool A2dpCodecThread::PostMessage(const utility::Message msg, const A2dpEncoderInitPeerParams &peerParams,
43 A2dpCodecConfig *config, A2dpEncoderObserver *observer, A2dpDecoderObserver *decObserver) const
44 {
45 dispatcher_->PostTask(
46 std::bind(&A2dpCodecThread::ProcessMessage, g_instance, msg, peerParams, config, observer, decObserver));
47
48 return true;
49 }
50
GetInstance()51 A2dpCodecThread *A2dpCodecThread::GetInstance()
52 {
53 std::lock_guard<std::recursive_mutex> lock(g_codecMutex);
54 if (g_instance == nullptr) {
55 auto instance = std::make_unique<A2dpCodecThread>("a2dpCodec");
56 g_instance = instance.release();
57 }
58 return g_instance;
59 }
60
StartA2dpCodecThread()61 void A2dpCodecThread::StartA2dpCodecThread()
62 {
63 dispatcher_->Initialize();
64 threadInit = true;
65 }
66
StopA2dpCodecThread()67 void A2dpCodecThread::StopA2dpCodecThread()
68 {
69 LOG_INFO("[A2dpCodecThread]%{public}s\n", __func__);
70
71 dispatcher_->Uninitialize();
72 threadInit = false;
73 }
74
ProcessMessage(utility::Message msg,const A2dpEncoderInitPeerParams & peerParams,A2dpCodecConfig * config,A2dpEncoderObserver * observer,A2dpDecoderObserver * decObserver)75 void A2dpCodecThread::ProcessMessage(utility::Message msg, const A2dpEncoderInitPeerParams &peerParams,
76 A2dpCodecConfig *config, A2dpEncoderObserver *observer, A2dpDecoderObserver *decObserver)
77 {
78 struct timeval tv = {};
79 struct timezone tz = {};
80 gettimeofday(&tv, &tz);
81 std::lock_guard<std::recursive_mutex> lock(g_codecMutex);
82 switch (msg.what_) {
83 case A2DP_AUDIO_RECONFIGURE:
84 if (encoder_ != nullptr) {
85 encoder_->UpdateEncoderParam();
86 }
87 break;
88 case A2DP_PCM_PUSH:
89 if (encoder_ != nullptr) {
90 encoder_->SendFrames(tv.tv_usec);
91 }
92 break;
93 case A2DP_FRAME_READY:
94 if (msg.arg2_ != nullptr && decoder_ != nullptr) {
95 decoder_->DecodePacket((uint8_t *)msg.arg2_, msg.arg1_);
96 }
97 if (msg.arg2_ != nullptr) {
98 free((uint8_t *)msg.arg2_);
99 }
100 break;
101 case A2DP_PCM_ENCODED:
102 if (config == nullptr) {
103 return;
104 }
105 if (encoder_ != nullptr) {
106 A2dpEncoder* encoder = encoder_.release();
107 delete encoder;
108 }
109 SourceEncode(peerParams, *config, *observer);
110 break;
111 case A2DP_FRAME_DECODED:
112 if (config == nullptr) {
113 return;
114 }
115 if (decoder_ != nullptr) {
116 A2dpDecoder* decoder = decoder_.release();
117 delete decoder;
118 }
119 SinkDecode(*config, *decObserver);
120 break;
121 default:
122 break;
123 }
124 }
125
GetInitStatus() const126 bool A2dpCodecThread::GetInitStatus() const
127 {
128 return threadInit;
129 }
130
WriteFrame(const uint8_t * data,uint16_t size) const131 bool A2dpCodecThread::WriteFrame(const uint8_t *data, uint16_t size) const
132 {
133 LOG_INFO("[A2dpCodecThread]%{public}s size:%{public}hu\n", __func__, size);
134 if (encoder_ != nullptr) {
135 if(!encoder_->SetPcmData(data, size)) {
136 return false;
137 }
138 utility::Message msg(A2DP_PCM_PUSH, 0, nullptr);
139 A2dpEncoderInitPeerParams peerParams = {};
140 PostMessage(msg, peerParams, nullptr, nullptr, nullptr);
141 return true;
142 }
143 return false;
144 }
145
GetRenderPosition(uint16_t & delayValue,uint16_t & sendDataSize,uint32_t & timeStamp) const146 void A2dpCodecThread::GetRenderPosition(uint16_t &delayValue, uint16_t &sendDataSize, uint32_t &timeStamp) const
147 {
148 LOG_INFO("[A2dpCodecThread]%{public}s\n", __func__);
149 if (encoder_ != nullptr) {
150 encoder_->GetRenderPosition(delayValue, sendDataSize, timeStamp);
151 }
152 }
153
SourceEncode(const A2dpEncoderInitPeerParams & peerParams,const A2dpCodecConfig & config,const A2dpEncoderObserver & observer)154 void A2dpCodecThread::SourceEncode(
155 const A2dpEncoderInitPeerParams &peerParams, const A2dpCodecConfig &config, const A2dpEncoderObserver &observer)
156 {
157 LOG_INFO("[A2dpCodecThread]%{public}s index:%u\n", __func__, config.GetCodecIndex());
158 switch (config.GetCodecIndex()) {
159 case A2DP_SINK_CODEC_INDEX_SBC:
160 case A2DP_SOURCE_CODEC_INDEX_SBC:
161 isSbc_ = true;
162 encoder_ = std::make_unique<A2dpSbcEncoder>(&const_cast<A2dpEncoderInitPeerParams &>(peerParams),
163 &const_cast<A2dpCodecConfig &>(config),
164 &const_cast<A2dpEncoderObserver &>(observer));
165 break;
166 case A2DP_SOURCE_CODEC_INDEX_AAC:
167 case A2DP_SINK_CODEC_INDEX_AAC:
168 isSbc_ = false;
169 encoder_ = std::make_unique<A2dpAacEncoder>(&const_cast<A2dpEncoderInitPeerParams &>(peerParams),
170 &const_cast<A2dpCodecConfig &>(config),
171 &const_cast<A2dpEncoderObserver &>(observer));
172 break;
173 default:
174 break;
175 }
176 }
177
SinkDecode(const A2dpCodecConfig & config,A2dpDecoderObserver & observer)178 void A2dpCodecThread::SinkDecode(const A2dpCodecConfig &config, A2dpDecoderObserver &observer)
179 {
180 LOG_INFO("[A2dpCodecThread]%{public}s index:%u\n", __func__, config.GetCodecIndex());
181
182 switch (config.GetCodecIndex()) {
183 case A2DP_SINK_CODEC_INDEX_SBC:
184 case A2DP_SOURCE_CODEC_INDEX_SBC:
185 if (decoder_ == nullptr) {
186 decoder_ = std::make_unique<A2dpSbcDecoder>(&observer);
187 }
188 break;
189 case A2DP_SOURCE_CODEC_INDEX_AAC:
190 case A2DP_SINK_CODEC_INDEX_AAC:
191 if (decoder_ == nullptr) {
192 decoder_ = std::make_unique<A2dpAacDecoder>(&observer);
193 }
194
195 break;
196 default:
197 break;
198 }
199 }
200 } // namespace bluetooth
201