• 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 "cJSON.h"
21 
22 #include "daudio_constants.h"
23 #include "daudio_hisysevent.h"
24 #include "daudio_sink_hidumper.h"
25 #include "daudio_sink_manager.h"
26 
27 #undef DH_LOG_TAG
28 #define DH_LOG_TAG "DMicClient"
29 
30 namespace OHOS {
31 namespace DistributedHardware {
~DMicClient()32 DMicClient::~DMicClient()
33 {
34     if (micTrans_ != nullptr) {
35         DHLOGI("Release mic client.");
36         StopCapture();
37     }
38 }
39 
OnEngineTransEvent(const AVTransEvent & event)40 void DMicClient::OnEngineTransEvent(const AVTransEvent &event)
41 {
42     if (event.type == EventType::EVENT_START_SUCCESS) {
43         OnStateChange(DATA_OPENED);
44     } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
45         (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
46         (event.type == EventType::EVENT_START_FAIL)) {
47         OnStateChange(DATA_CLOSED);
48     }
49 }
50 
OnEngineTransMessage(const std::shared_ptr<AVTransMessage> & message)51 void DMicClient::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
52 {
53     CHECK_NULL_VOID(message);
54     DHLOGI("On Engine message, type : %s.", GetEventNameByType(message->type_).c_str());
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_NULLPTR;
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     cJSON *jParam = cJSON_CreateObject();
78     CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
79 
80     cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
81     char *jsonData = cJSON_PrintUnformatted(jParam);
82     if (jsonData == nullptr) {
83         DHLOGE("Failed to create JSON data.");
84         cJSON_Delete(jParam);
85         return ERR_DH_AUDIO_NULLPTR;
86     }
87     event.content = std::string(jsonData);
88     cJSON_Delete(jParam);
89     cJSON_free(jsonData);
90     switch (type) {
91         case AudioEventType::DATA_OPENED: {
92             isBlocking_.store(true);
93             if (audioParam_.captureOpts.capturerFlags != MMAP_MODE) {
94                 isCaptureReady_.store(true);
95                 captureDataThread_ = std::thread(&DMicClient::CaptureThreadRunning, this);
96             }
97             event.type = AudioEventType::MIC_OPENED;
98             break;
99         }
100         case AudioEventType::DATA_CLOSED: {
101             event.type = AudioEventType::MIC_CLOSED;
102             break;
103         }
104         default:
105             DHLOGE("Invalid parameter type: %d.", type);
106             return ERR_DH_AUDIO_NOT_SUPPORT;
107     }
108 
109     std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
110     CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
111     cbObj->NotifyEvent(event);
112     return DH_SUCCESS;
113 }
114 
AudioFwkClientSetUp()115 int32_t DMicClient::AudioFwkClientSetUp()
116 {
117     AudioStandard::AudioCapturerOptions capturerOptions = {
118         {
119             static_cast<AudioStandard::AudioSamplingRate>(audioParam_.comParam.sampleRate),
120             AudioStandard::AudioEncodingType::ENCODING_PCM,
121             static_cast<AudioStandard::AudioSampleFormat>(audioParam_.comParam.bitFormat),
122             static_cast<AudioStandard::AudioChannel>(audioParam_.comParam.channelMask),
123         },
124         {
125             static_cast<AudioStandard::SourceType>(audioParam_.captureOpts.sourceType),
126             audioParam_.captureOpts.capturerFlags == MMAP_MODE ? AudioStandard::STREAM_FLAG_FAST : 0,
127         }
128     };
129     std::lock_guard<std::mutex> lck(devMtx_);
130     audioCapturer_ = AudioStandard::AudioCapturer::Create(capturerOptions);
131     CHECK_NULL_RETURN(audioCapturer_, ERR_DH_AUDIO_CLIENT_CAPTURER_CREATE_FAILED);
132     if (audioParam_.captureOpts.capturerFlags == MMAP_MODE) {
133         int32_t ret = audioCapturer_->SetCapturerReadCallback(shared_from_this());
134         if (ret != DH_SUCCESS) {
135             DHLOGE("Client save read callback failed.");
136             return ERR_DH_AUDIO_CLIENT_CAPTURER_CREATE_FAILED;
137         }
138     }
139     return TransSetUp();
140 }
141 
TransSetUp()142 int32_t DMicClient::TransSetUp()
143 {
144     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
145     int32_t ret = micTrans_->SetUp(audioParam_, audioParam_, shared_from_this(), CAP_MIC);
146     if (ret != DH_SUCCESS) {
147         DHLOGE("Mic trans setup failed.");
148         return ret;
149     }
150     clientStatus_ = AudioStatus::STATUS_READY;
151     return DH_SUCCESS;
152 }
153 
SetUp(const AudioParam & param)154 int32_t DMicClient::SetUp(const AudioParam &param)
155 {
156     DHLOGI("Set up mic client, param: {sampleRate: %d, bitFormat: %d," +
157         "channelMask: %d, sourceType: %d, capturerFlags: %d, frameSize: %d}.",
158         param.comParam.sampleRate, param.comParam.bitFormat, param.comParam.channelMask, param.captureOpts.sourceType,
159         param.captureOpts.capturerFlags, param.comParam.frameSize);
160     audioParam_ = param;
161     return AudioFwkClientSetUp();
162 }
163 
SendMessage(uint32_t type,std::string content,std::string dstDevId)164 int32_t DMicClient::SendMessage(uint32_t type, std::string content, std::string dstDevId)
165 {
166     DHLOGI("Send message to remote.");
167     if (type != static_cast<uint32_t>(NOTIFY_OPEN_MIC_RESULT) &&
168         type != static_cast<uint32_t>(NOTIFY_CLOSE_MIC_RESULT) &&
169         type != static_cast<uint32_t>(CLOSE_MIC)) {
170         DHLOGE("event type is not NOTIFY_OPEN_MIC or NOTIFY_CLOSE_MIC or CLOSE_MIC. type: %u", type);
171         return ERR_DH_AUDIO_NULLPTR;
172     }
173     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
174     micTrans_->SendMessage(type, content, dstDevId);
175     return DH_SUCCESS;
176 }
177 
Release()178 int32_t DMicClient::Release()
179 {
180     DHLOGI("Release mic client.");
181     std::lock_guard<std::mutex> lck(devMtx_);
182     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_SA_STATUS_ERR);
183     if (clientStatus_ != AudioStatus::STATUS_READY && clientStatus_ != AudioStatus::STATUS_STOP) {
184         DHLOGE("Mic status is wrong, %d.", (int32_t)clientStatus_);
185         return ERR_DH_AUDIO_SA_STATUS_ERR;
186     }
187     bool isReleaseError = false;
188     if (audioCapturer_ == nullptr || !audioCapturer_->Release()) {
189         DHLOGE("Audio capturer release failed.");
190         isReleaseError = true;
191     }
192     int32_t ret = micTrans_->Release();
193     if (ret != DH_SUCCESS) {
194         DHLOGE("Mic trans release failed.");
195         isReleaseError = true;
196     }
197     micTrans_ = nullptr;
198     clientStatus_ = AudioStatus::STATUS_IDLE;
199     if (isReleaseError) {
200         return ERR_DH_AUDIO_FAILED;
201     }
202     return DH_SUCCESS;
203 }
204 
StartCapture()205 int32_t DMicClient::StartCapture()
206 {
207     DHLOGI("Start capturer.");
208     std::lock_guard<std::mutex> lck(devMtx_);
209     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_SA_STATUS_ERR);
210     CHECK_NULL_RETURN(audioCapturer_, ERR_DH_AUDIO_NULLPTR);
211 
212     if (clientStatus_ != AudioStatus::STATUS_READY) {
213         DHLOGE("Audio capturer init failed or mic status wrong, status: %d.", (int32_t)clientStatus_);
214         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_SA_STATUS_ERR,
215             "daudio init failed or mic status wrong.");
216         return ERR_DH_AUDIO_SA_STATUS_ERR;
217     }
218     if (!audioCapturer_->Start()) {
219         DHLOGE("Audio capturer start failed.");
220         audioCapturer_->Release();
221         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL,
222             ERR_DH_AUDIO_CLIENT_CAPTURER_START_FAILED, "daudio capturer start failed.");
223         return ERR_DH_AUDIO_CLIENT_CAPTURER_START_FAILED;
224     }
225     int32_t ret = micTrans_->Start();
226     if (ret != DH_SUCCESS) {
227         DHLOGE("Mic trans start failed.");
228         micTrans_->Release();
229         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ret, "daudio mic trans start failed.");
230         return ret;
231     }
232     clientStatus_ = AudioStatus::STATUS_START;
233     return DH_SUCCESS;
234 }
235 
AudioFwkCaptureData()236 void DMicClient::AudioFwkCaptureData()
237 {
238     std::shared_ptr<AudioData> audioData = std::make_shared<AudioData>(audioParam_.comParam.frameSize);
239     size_t bytesRead = 0;
240     bool errorFlag = false;
241     int64_t startTime = GetNowTimeUs();
242     CHECK_NULL_VOID(audioCapturer_);
243 
244     while (bytesRead < audioParam_.comParam.frameSize) {
245         int32_t len = audioCapturer_->Read(*(audioData->Data() + bytesRead),
246             audioParam_.comParam.frameSize - bytesRead, isBlocking_.load());
247         if (len >= 0) {
248             bytesRead += static_cast<size_t>(len);
249         } else {
250             errorFlag = true;
251             break;
252         }
253         int64_t endTime = GetNowTimeUs();
254         if (IsOutDurationRange(startTime, endTime, lastCaptureStartTime_)) {
255             DHLOGE("This time capture spend: %lld us, The interval of capture this time and the last time: %lld us",
256                 endTime - startTime, startTime - lastCaptureStartTime_);
257         }
258         lastCaptureStartTime_ = startTime;
259     }
260     if (errorFlag) {
261         DHLOGE("Bytes read failed.");
262         return;
263     }
264     if (isPauseStatus_.load()) {
265         memset_s(audioData->Data(), audioData->Size(), 0, audioData->Size());
266     }
267 #ifdef DUMP_DMICCLIENT_FILE
268     if (DaudioSinkHidumper::GetInstance().QueryDumpDataFlag()) {
269         SaveFile(MIC_CLIENT_FILENAME, const_cast<uint8_t*>(audioData->Data()), audioData->Size());
270     }
271 #endif
272     int64_t startTransTime = GetNowTimeUs();
273     int32_t ret = micTrans_->FeedAudioData(audioData);
274     if (ret != DH_SUCCESS) {
275         DHLOGE("Failed to send data.");
276     }
277     int64_t endTransTime = GetNowTimeUs();
278     if (IsOutDurationRange(startTransTime, endTransTime, lastTransStartTime_)) {
279         DHLOGE("This time send data spend: %lld us, The interval of send data this time and the last time: %lld us",
280             endTransTime - startTransTime, startTransTime - lastTransStartTime_);
281     }
282     lastTransStartTime_ = startTransTime;
283 }
284 
CaptureThreadRunning()285 void DMicClient::CaptureThreadRunning()
286 {
287     DHLOGD("Start the capturer thread.");
288     if (pthread_setname_np(pthread_self(), CAPTURETHREAD) != DH_SUCCESS) {
289         DHLOGE("Capture data thread setname failed.");
290     }
291     while (isCaptureReady_.load()) {
292         AudioFwkCaptureData();
293     }
294 }
295 
OnDecodeTransDataDone(const std::shared_ptr<AudioData> & audioData)296 int32_t DMicClient::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
297 {
298     (void)audioData;
299     return DH_SUCCESS;
300 }
301 
OnReadData(size_t length)302 void DMicClient::OnReadData(size_t length)
303 {
304     AudioStandard::BufferDesc bufDesc;
305     CHECK_NULL_VOID(audioCapturer_);
306 
307     if (audioCapturer_->GetBufferDesc(bufDesc) != DH_SUCCESS || bufDesc.bufLength == 0) {
308         DHLOGE("Get buffer desc failed.");
309         return;
310     }
311     CHECK_NULL_VOID(bufDesc.buffer);
312 
313     std::shared_ptr<AudioData> audioData = std::make_shared<AudioData>(audioParam_.comParam.frameSize);
314     if (audioData->Capacity() != bufDesc.bufLength) {
315         DHLOGE("Audio data length is not equal to buflength. datalength: %d, bufLength: %d",
316             audioData->Capacity(), bufDesc.bufLength);
317     }
318     if (memcpy_s(audioData->Data(), audioData->Capacity(), bufDesc.buffer, bufDesc.bufLength) != EOK) {
319         DHLOGE("Copy audio data failed.");
320     }
321     audioCapturer_->Enqueue(bufDesc);
322 
323     CHECK_NULL_VOID(micTrans_);
324     if (micTrans_->FeedAudioData(audioData) != DH_SUCCESS) {
325         DHLOGE("Failed to send data.");
326     }
327 }
328 
StopCapture()329 int32_t DMicClient::StopCapture()
330 {
331     DHLOGI("Stop capturer.");
332     std::lock_guard<std::mutex> lck(devMtx_);
333     if (clientStatus_ != AudioStatus::STATUS_START) {
334         DHLOGE("Capturee is not start or mic status wrong, status: %d.", (int32_t)clientStatus_);
335         DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_SA_STATUS_ERR,
336             "daudio capturer is not start or mic status wrong.");
337         return ERR_DH_AUDIO_SA_STATUS_ERR;
338     }
339     CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
340 
341     isBlocking_.store(false);
342     if (audioParam_.captureOpts.capturerFlags != MMAP_MODE && isCaptureReady_.load()) {
343         isCaptureReady_.store(false);
344         if (captureDataThread_.joinable()) {
345             captureDataThread_.join();
346         }
347     }
348 
349     bool status = true;
350     int32_t ret = micTrans_->Stop();
351     if (ret != DH_SUCCESS) {
352         DHLOGE("Mic trans stop failed.");
353         status = false;
354     }
355     if (audioCapturer_ == nullptr || !audioCapturer_->Stop()) {
356         DHLOGE("Audio capturer stop failed.");
357         status = false;
358     }
359     clientStatus_ = AudioStatus::STATUS_STOP;
360     if (!status) {
361         return ERR_DH_AUDIO_FAILED;
362     }
363     return DH_SUCCESS;
364 }
365 
SetAttrs(const std::string & devId,const std::shared_ptr<IAudioEventCallback> & callback)366 void DMicClient::SetAttrs(const std::string &devId, const std::shared_ptr<IAudioEventCallback> &callback)
367 {
368     DHLOGE("Set attrs, not support yet.");
369 }
370 
PauseCapture()371 int32_t DMicClient::PauseCapture()
372 {
373     DHLOGI("Pause capture.");
374     isPauseStatus_.store(true);
375     return DH_SUCCESS;
376 }
377 
ResumeCapture()378 int32_t DMicClient::ResumeCapture()
379 {
380     DHLOGI("Resume capture.");
381     isPauseStatus_.store(false);
382     return DH_SUCCESS;
383 }
384 } // DistributedHardware
385 } // OHOS
386