• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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