• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "dmic_client.h"
17 
18 #include <chrono>
19 
20 #include "daudio_constants.h"
21 #include "daudio_hisysevent.h"
22 #include "daudio_sink_manager.h"
23 
24 #undef DH_LOG_TAG
25 #define DH_LOG_TAG "DMicClient"
26 
27 namespace OHOS {
28 namespace DistributedHardware {
~DMicClient()29 DMicClient::~DMicClient()
30 {
31     if (micTrans_ != nullptr) {
32         DHLOGI("Release mic client.");
33         StopCapture();
34     }
35 }
36 
OnEngineTransEvent(const AVTransEvent & event)37 void DMicClient::OnEngineTransEvent(const AVTransEvent &event)
38 {
39     if (event.type == EventType::EVENT_START_SUCCESS) {
40         OnStateChange(DATA_OPENED);
41     } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
42         (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
43         (event.type == EventType::EVENT_START_FAIL)) {
44         OnStateChange(DATA_CLOSED);
45     }
46 }
47 
OnEngineTransMessage(const std::shared_ptr<AVTransMessage> & message)48 void DMicClient::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
49 {
50     DHLOGI("On Engine message");
51     if (message == nullptr) {
52         DHLOGE("The parameter is nullptr");
53         return;
54     }
55     DAudioSinkManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
56         static_cast<int32_t>(message->type_), message->content_);
57 }
58 
InitSenderEngine(IAVEngineProvider * providerPtr)59 int32_t DMicClient::InitSenderEngine(IAVEngineProvider *providerPtr)
60 {
61     DHLOGI("Init SenderEngine");
62     if (micTrans_ == nullptr) {
63         micTrans_ = std::make_shared<AVTransSenderTransport>(devId_, shared_from_this());
64     }
65     int32_t ret = micTrans_->InitEngine(providerPtr);
66     if (ret != DH_SUCCESS) {
67         DHLOGE("Mic client initialize av sender adapter failed.");
68         return ERR_DH_AUDIO_TRANS_NULL_VALUE;
69     }
70     return DH_SUCCESS;
71 }
72 
OnStateChange(const AudioEventType type)73 int32_t DMicClient::OnStateChange(const AudioEventType type)
74 {
75     DHLOGD("On state change type: %d.", type);
76     AudioEvent event;
77     event.content = "";
78     switch (type) {
79         case AudioEventType::DATA_OPENED: {
80             isBlocking_.store(true);
81             if (audioParam_.captureOpts.capturerFlags != MMAP_MODE) {
82                 isCaptureReady_.store(true);
83                 captureDataThread_ = std::thread(&DMicClient::CaptureThreadRunning, this);
84             }
85             event.type = AudioEventType::MIC_OPENED;
86             break;
87         }
88         case AudioEventType::DATA_CLOSED: {
89             event.type = AudioEventType::MIC_CLOSED;
90             break;
91         }
92         default:
93             DHLOGE("Invalid parameter type: %d.", type);
94             return ERR_DH_AUDIO_CLIENT_STATE_IS_INVALID;
95     }
96 
97     std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
98     if (cbObj == nullptr) {
99         DHLOGE("Event callback is nullptr.");
100         return ERR_DH_AUDIO_CLIENT_EVENT_CALLBACK_IS_NULL;
101     }
102     cbObj->NotifyEvent(event);
103     return DH_SUCCESS;
104 }
105 
SetUp(const AudioParam & param)106 int32_t DMicClient::SetUp(const AudioParam &param)
107 {
108     DHLOGI("Set up mic client, param: {sampleRate: %d, bitFormat: %d," +
109         "channelMask: %d, sourceType: %d, capturerFlags: %d, frameSize: %d}.",
110         param.comParam.sampleRate, param.comParam.bitFormat, param.comParam.channelMask, param.captureOpts.sourceType,
111         param.captureOpts.capturerFlags, param.comParam.frameSize);
112     audioParam_ = param;
113     AudioStandard::AudioCapturerOptions capturerOptions = {
114         {
115             static_cast<AudioStandard::AudioSamplingRate>(audioParam_.comParam.sampleRate),
116             AudioStandard::AudioEncodingType::ENCODING_PCM,
117             static_cast<AudioStandard::AudioSampleFormat>(audioParam_.comParam.bitFormat),
118             static_cast<AudioStandard::AudioChannel>(audioParam_.comParam.channelMask),
119         },
120         {
121             static_cast<AudioStandard::SourceType>(audioParam_.captureOpts.sourceType),
122             audioParam_.captureOpts.capturerFlags == MMAP_MODE ? AudioStandard::STREAM_FLAG_FAST : 0,
123         }
124     };
125     std::lock_guard<std::mutex> lck(devMtx_);
126     audioCapturer_ = AudioStandard::AudioCapturer::Create(capturerOptions);
127     if (audioCapturer_ == nullptr) {
128         DHLOGE("Audio capturer create failed.");
129         return ERR_DH_AUDIO_CLIENT_CREATE_CAPTURER_FAILED;
130     }
131     if (audioParam_.captureOpts.capturerFlags == MMAP_MODE) {
132         int32_t ret = audioCapturer_->SetCapturerReadCallback(shared_from_this());
133         if (ret != DH_SUCCESS) {
134             DHLOGE("Client save read callback failed.");
135             return ERR_DH_AUDIO_CLIENT_CREATE_CAPTURER_FAILED;
136         }
137     }
138 
139     if (micTrans_ == nullptr) {
140         DHLOGE("mic trans in engine should be init by dev.");
141         return ERR_DH_AUDIO_NULLPTR;
142     }
143     int32_t ret = micTrans_->SetUp(audioParam_, audioParam_, shared_from_this(), CAP_MIC);
144     if (ret != DH_SUCCESS) {
145         DHLOGE("Mic trans setup failed.");
146         return ret;
147     }
148     clientStatus_ = AudioStatus::STATUS_READY;
149     return DH_SUCCESS;
150 }
151 
SendMessage(uint32_t type,std::string content,std::string dstDevId)152 int32_t DMicClient::SendMessage(uint32_t type, std::string content, std::string dstDevId)
153 {
154     DHLOGI("Send message to remote.");
155     if (type != static_cast<uint32_t>(NOTIFY_OPEN_MIC_RESULT) &&
156         type != static_cast<uint32_t>(NOTIFY_CLOSE_MIC_RESULT)) {
157         DHLOGE("event type is not NOTIFY_OPEN_MIC or NOTIFY_CLOSE_MIC. type: %u", type);
158         return ERR_DH_AUDIO_NULLPTR;
159     }
160     if (micTrans_ == nullptr) {
161         DHLOGE("mic trans is null.");
162         return ERR_DH_AUDIO_NULLPTR;
163     }
164     micTrans_->SendMessage(type, content, dstDevId);
165     return DH_SUCCESS;
166 }
167 
Release()168 int32_t DMicClient::Release()
169 {
170     DHLOGI("Release mic client.");
171     std::lock_guard<std::mutex> lck(devMtx_);
172     if ((clientStatus_ != AudioStatus::STATUS_READY && clientStatus_ != AudioStatus::STATUS_STOP) ||
173         micTrans_ == nullptr) {
174         DHLOGE("Mic status is wrong or mic trans is null, %d.", (int32_t)clientStatus_);
175         return ERR_DH_AUDIO_SA_STATUS_ERR;
176     }
177     bool status = true;
178     if (!audioCapturer_->Release()) {
179         DHLOGE("Audio capturer release failed.");
180         status = false;
181     }
182     int32_t ret = micTrans_->Release();
183     if (ret != DH_SUCCESS) {
184         DHLOGE("Mic trans release failed.");
185         status = false;
186     }
187     micTrans_ = nullptr;
188     clientStatus_ = AudioStatus::STATUS_IDLE;
189     if (!status) {
190         return ERR_DH_AUDIO_FAILED;
191     }
192     return DH_SUCCESS;
193 }
194 
StartCapture()195 int32_t DMicClient::StartCapture()
196 {
197     DHLOGI("Start capturer.");
198     std::lock_guard<std::mutex> lck(devMtx_);
199     if (audioCapturer_ == nullptr || micTrans_ == nullptr || clientStatus_ != AudioStatus::STATUS_READY) {
200         DHLOGE("Audio capturer init failed or mic status wrong, status: %d.", (int32_t)clientStatus_);
201         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_SA_STATUS_ERR,
202             "daudio init failed or mic status wrong.");
203         return ERR_DH_AUDIO_SA_STATUS_ERR;
204     }
205 
206     if (!audioCapturer_->Start()) {
207         DHLOGE("Audio capturer start failed.");
208         audioCapturer_->Release();
209         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_CLIENT_CAPTURER_START_FAILED,
210             "daudio capturer start failed.");
211         return ERR_DH_AUDIO_CLIENT_CAPTURER_START_FAILED;
212     }
213     int32_t ret = micTrans_->Start();
214     if (ret != DH_SUCCESS) {
215         DHLOGE("Mic trans start failed.");
216         micTrans_->Release();
217         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ret, "daudio mic trans start failed.");
218         return ret;
219     }
220     clientStatus_ = AudioStatus::STATUS_START;
221     return DH_SUCCESS;
222 }
223 
CaptureThreadRunning()224 void DMicClient::CaptureThreadRunning()
225 {
226     DHLOGD("Start the capturer thread.");
227     if (pthread_setname_np(pthread_self(), CAPTURETHREAD) != DH_SUCCESS) {
228         DHLOGE("Capture data thread setname failed.");
229     }
230     while (isCaptureReady_.load()) {
231         std::shared_ptr<AudioData> audioData = std::make_shared<AudioData>(audioParam_.comParam.frameSize);
232         size_t bytesRead = 0;
233         bool errorFlag = false;
234         while (bytesRead < audioParam_.comParam.frameSize) {
235             int32_t len = audioCapturer_->Read(*(audioData->Data() + bytesRead),
236                 audioParam_.comParam.frameSize - bytesRead, isBlocking_.load());
237             if (len >= 0) {
238                 bytesRead += static_cast<size_t>(len);
239             } else {
240                 errorFlag = true;
241                 break;
242             }
243         }
244         if (errorFlag) {
245             DHLOGE("Bytes read failed.");
246             break;
247         }
248         int32_t ret = micTrans_->FeedAudioData(audioData);
249         if (ret != DH_SUCCESS) {
250             DHLOGE("Failed to send data.");
251         }
252     }
253 }
254 
OnDecodeTransDataDone(const std::shared_ptr<AudioData> & audioData)255 int32_t DMicClient::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
256 {
257     (void)audioData;
258     return DH_SUCCESS;
259 }
260 
OnReadData(size_t length)261 void DMicClient::OnReadData(size_t length)
262 {
263     AudioStandard::BufferDesc bufDesc;
264     if (audioCapturer_ == nullptr) {
265         DHLOGE("audioCapturer is nullptr.");
266         return;
267     }
268     int32_t ret = audioCapturer_->GetBufferDesc(bufDesc);
269     if (ret != DH_SUCCESS || bufDesc.buffer == nullptr || bufDesc.bufLength == 0) {
270         DHLOGE("Get buffer desc failed. On read data.");
271         return;
272     }
273     std::shared_ptr<AudioData> audioData = std::make_shared<AudioData>(audioParam_.comParam.frameSize);
274     if (audioData->Capacity() != bufDesc.bufLength) {
275         DHLOGE("Audio data length is not equal to buflength. datalength: %d, bufLength: %d",
276             audioData->Capacity(), bufDesc.bufLength);
277     }
278     if (memcpy_s(audioData->Data(), audioData->Capacity(), bufDesc.buffer, bufDesc.bufLength) != EOK) {
279         DHLOGE("Copy audio data failed.");
280     }
281     audioCapturer_->Enqueue(bufDesc);
282     if (micTrans_ == nullptr) {
283         DHLOGE("Mic trans is nullptr.");
284         return;
285     }
286     if (micTrans_->FeedAudioData(audioData) != DH_SUCCESS) {
287         DHLOGE("Failed to send data.");
288     }
289 }
290 
StopCapture()291 int32_t DMicClient::StopCapture()
292 {
293     DHLOGI("Stop capturer.");
294     std::lock_guard<std::mutex> lck(devMtx_);
295     if (clientStatus_ != AudioStatus::STATUS_START || !isCaptureReady_.load()) {
296         DHLOGE("Capturee is not start or mic status wrong, status: %d.", (int32_t)clientStatus_);
297         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_SA_STATUS_ERR,
298             "daudio capturer is not start or mic status wrong.");
299         return ERR_DH_AUDIO_SA_STATUS_ERR;
300     }
301     if (audioCapturer_ == nullptr || micTrans_ == nullptr) {
302         DHLOGE("The capturer or mictrans is not instantiated.");
303         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL,
304             ERR_DH_AUDIO_CLIENT_CAPTURER_OR_MICTRANS_INSTANCE, "daudio capturer or mictrans is not instantiated.");
305         return ERR_DH_AUDIO_CLIENT_CAPTURER_OR_MICTRANS_INSTANCE;
306     }
307 
308     isBlocking_.store(false);
309     if (audioParam_.captureOpts.capturerFlags != MMAP_MODE) {
310         isCaptureReady_.store(false);
311         if (captureDataThread_.joinable()) {
312             captureDataThread_.join();
313         }
314     }
315 
316     bool status = true;
317     int32_t ret = micTrans_->Stop();
318     if (ret != DH_SUCCESS) {
319         DHLOGE("Mic trans stop failed.");
320         status = false;
321     }
322     if (!audioCapturer_->Stop()) {
323         DHLOGE("Audio capturer stop failed.");
324         status = false;
325     }
326     clientStatus_ = AudioStatus::STATUS_STOP;
327     if (!status) {
328         return ERR_DH_AUDIO_FAILED;
329     }
330     return DH_SUCCESS;
331 }
332 
SetAttrs(const std::string & devId,const std::shared_ptr<IAudioEventCallback> & callback)333 void DMicClient::SetAttrs(const std::string &devId, const std::shared_ptr<IAudioEventCallback> &callback)
334 {
335     DHLOGE("Set attrs, not support yet.");
336 }
337 } // DistributedHardware
338 } // OHOS
339