1 /*
2 * Copyright (c) 2021-2022 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 <cstring>
17 #include <dlfcn.h>
18 #include <string>
19 #include <cinttypes>
20 #include "audio_errors.h"
21 #include "audio_log.h"
22 #include "audio_utils.h"
23 #include "audio_capturer_source.h"
24 #include "power_mgr_client.h"
25
26 using namespace std;
27
28 namespace OHOS {
29 namespace AudioStandard {
30 #ifdef CAPTURE_DUMP
31 const char *g_audioOutTestFilePath = "/data/local/tmp/audio_capture.pcm";
32 #endif // CAPTURE_DUMP
33 bool AudioCapturerSource::micMuteState_ = false;
34
AudioCapturerSource()35 AudioCapturerSource::AudioCapturerSource()
36 : capturerInited_(false), started_(false), paused_(false), leftVolume_(MAX_VOLUME_LEVEL),
37 rightVolume_(MAX_VOLUME_LEVEL), openMic_(0), audioManager_(nullptr), audioAdapter_(nullptr),
38 audioCapture_(nullptr)
39 {
40 attr_ = {};
41 #ifdef CAPTURE_DUMP
42 pfd = nullptr;
43 #endif // CAPTURE_DUMP
44 }
45
~AudioCapturerSource()46 AudioCapturerSource::~AudioCapturerSource()
47 {
48 AUDIO_ERR_LOG("~AudioCapturerSource");
49 }
50
GetInstance()51 AudioCapturerSource *AudioCapturerSource::GetInstance()
52 {
53 static AudioCapturerSource audioCapturer_;
54 return &audioCapturer_;
55 }
56
IsInited(void)57 bool AudioCapturerSource::IsInited(void)
58 {
59 return capturerInited_;
60 }
61
DeInit()62 void AudioCapturerSource::DeInit()
63 {
64 started_ = false;
65 capturerInited_ = false;
66
67 if ((audioCapture_ != nullptr) && (audioAdapter_ != nullptr)) {
68 audioAdapter_->DestroyCapture(audioAdapter_, audioCapture_);
69 }
70 audioCapture_ = nullptr;
71
72 if ((audioManager_ != nullptr) && (audioAdapter_ != nullptr)) {
73 audioManager_->UnloadAdapter(audioManager_, audioAdapter_);
74 }
75 audioAdapter_ = nullptr;
76 audioManager_ = nullptr;
77 #ifdef CAPTURE_DUMP
78 if (pfd) {
79 fclose(pfd);
80 pfd = nullptr;
81 }
82 #endif // CAPTURE_DUMP
83 }
84
InitAttrsCapture(struct AudioSampleAttributes & attrs)85 void InitAttrsCapture(struct AudioSampleAttributes &attrs)
86 {
87 /* Initialization of audio parameters for playback */
88 attrs.format = AUDIO_FORMAT_PCM_16_BIT;
89 attrs.channelCount = AUDIO_CHANNELCOUNT;
90 attrs.sampleRate = AUDIO_SAMPLE_RATE_48K;
91 attrs.interleaved = true;
92 attrs.streamId = INTERNAL_INPUT_STREAM_ID;
93 attrs.type = AUDIO_IN_MEDIA;
94 attrs.period = DEEP_BUFFER_CAPTURE_PERIOD_SIZE;
95 attrs.frameSize = PCM_16_BIT * attrs.channelCount / PCM_8_BIT;
96 attrs.isBigEndian = false;
97 attrs.isSignedData = true;
98 attrs.startThreshold = DEEP_BUFFER_CAPTURE_PERIOD_SIZE / (attrs.frameSize);
99 attrs.stopThreshold = INT_32_MAX;
100 /* 16 * 1024 */
101 attrs.silenceThreshold = AUDIO_BUFF_SIZE;
102 }
103
SwitchAdapterCapture(struct AudioAdapterDescriptor * descs,int32_t size,const std::string & adapterNameCase,enum AudioPortDirection portFlag,struct AudioPort & capturePort)104 int32_t SwitchAdapterCapture(struct AudioAdapterDescriptor *descs, int32_t size, const std::string &adapterNameCase,
105 enum AudioPortDirection portFlag, struct AudioPort &capturePort)
106 {
107 if (descs == nullptr) {
108 return ERROR;
109 }
110
111 for (int32_t index = 0; index < size; index++) {
112 struct AudioAdapterDescriptor *desc = &descs[index];
113 if (desc == nullptr || desc->adapterName == nullptr) {
114 continue;
115 }
116 if (!adapterNameCase.compare(desc->adapterName)) {
117 for (uint32_t port = 0; port < desc->portNum; port++) {
118 // Only find out the port of out in the sound card
119 if (desc->ports[port].dir == portFlag) {
120 capturePort = desc->ports[port];
121 return index;
122 }
123 }
124 }
125 }
126 AUDIO_ERR_LOG("SwitchAdapterCapture Fail");
127
128 return ERR_INVALID_INDEX;
129 }
130
InitAudioManager()131 int32_t AudioCapturerSource::InitAudioManager()
132 {
133 AUDIO_INFO_LOG("AudioCapturerSource: Initialize audio proxy manager");
134
135 audioManager_ = GetAudioManagerFuncs();
136 if (audioManager_ == nullptr) {
137 return ERR_INVALID_HANDLE;
138 }
139
140 return 0;
141 }
142
CreateCapture(struct AudioPort & capturePort)143 int32_t AudioCapturerSource::CreateCapture(struct AudioPort &capturePort)
144 {
145 int32_t ret;
146 struct AudioSampleAttributes param;
147 // User needs to set
148 InitAttrsCapture(param);
149 param.sampleRate = attr_.sampleRate;
150 param.format = attr_.format;
151 param.isBigEndian = attr_.isBigEndian;
152 param.channelCount = attr_.channel;
153 param.silenceThreshold = attr_.bufferSize;
154 param.frameSize = param.format * param.channelCount;
155 param.startThreshold = DEEP_BUFFER_CAPTURE_PERIOD_SIZE / (param.frameSize);
156
157 struct AudioDeviceDescriptor deviceDesc;
158 deviceDesc.portId = capturePort.portId;
159 deviceDesc.pins = PIN_IN_MIC;
160 deviceDesc.desc = nullptr;
161
162 ret = audioAdapter_->CreateCapture(audioAdapter_, &deviceDesc, ¶m, &audioCapture_);
163 if (audioCapture_ == nullptr || ret < 0) {
164 AUDIO_ERR_LOG("Create capture failed");
165 return ERR_NOT_STARTED;
166 }
167
168 return 0;
169 }
170
Init(IAudioSourceAttr & attr)171 int32_t AudioCapturerSource::Init(IAudioSourceAttr &attr)
172 {
173 attr_ = attr;
174 int32_t ret;
175 int32_t index;
176 int32_t size = 0;
177 struct AudioAdapterDescriptor *descs = nullptr;
178 if (InitAudioManager() != 0) {
179 AUDIO_ERR_LOG("Init audio manager Fail");
180 return ERR_INVALID_HANDLE;
181 }
182 ret = audioManager_->GetAllAdapters(audioManager_, &descs, &size);
183 // adapters is 0~3
184 if (size > MAX_AUDIO_ADAPTER_NUM || size == 0 || descs == nullptr || ret != 0) {
185 AUDIO_ERR_LOG("Get adapters Fail");
186 return ERR_NOT_STARTED;
187 }
188 // Get qualified sound card and port
189 adapterNameCase_ = attr_.adapterName;
190 openMic_ = attr_.open_mic_speaker;
191 index = SwitchAdapterCapture(descs, size, adapterNameCase_, PORT_IN, audioPort);
192 if (index < 0) {
193 AUDIO_ERR_LOG("Switch Adapter Capture Fail");
194 return ERR_NOT_STARTED;
195 }
196 struct AudioAdapterDescriptor *desc = &descs[index];
197 if (audioManager_->LoadAdapter(audioManager_, desc, &audioAdapter_) != 0) {
198 AUDIO_ERR_LOG("Load Adapter Fail");
199 return ERR_NOT_STARTED;
200 }
201 if (audioAdapter_ == nullptr) {
202 AUDIO_ERR_LOG("Load audio device failed");
203 return ERR_NOT_STARTED;
204 }
205
206 // Inittialization port information, can fill through mode and other parameters
207 ret = audioAdapter_->InitAllPorts(audioAdapter_);
208 if (ret != 0) {
209 AUDIO_ERR_LOG("InitAllPorts failed");
210 return ERR_DEVICE_INIT;
211 }
212 if (CreateCapture(audioPort) != 0) {
213 AUDIO_ERR_LOG("Create capture failed");
214 return ERR_NOT_STARTED;
215 }
216 if (openMic_) {
217 ret = SetInputRoute(DEVICE_TYPE_MIC);
218 if (ret < 0) {
219 AUDIO_ERR_LOG("AudioCapturerSource:update route FAILED: %{public}d", ret);
220 }
221 }
222 capturerInited_ = true;
223
224 #ifdef CAPTURE_DUMP
225 pfd = fopen(g_audioOutTestFilePath, "wb+");
226 if (pfd == nullptr) {
227 AUDIO_ERR_LOG("Error opening pcm test file!");
228 }
229 #endif // CAPTURE_DUMP
230
231 return SUCCESS;
232 }
233
CaptureFrame(char * frame,uint64_t requestBytes,uint64_t & replyBytes)234 int32_t AudioCapturerSource::CaptureFrame(char *frame, uint64_t requestBytes, uint64_t &replyBytes)
235 {
236 int64_t stamp = GetNowTimeMs();
237 int32_t ret;
238 if (audioCapture_ == nullptr) {
239 AUDIO_ERR_LOG("Audio capture Handle is nullptr!");
240 return ERR_INVALID_HANDLE;
241 }
242
243 ret = audioCapture_->CaptureFrame(audioCapture_, frame, requestBytes, &replyBytes);
244 if (ret < 0) {
245 AUDIO_ERR_LOG("Capture Frame Fail");
246 return ERR_READ_FAILED;
247 }
248
249 #ifdef CAPTURE_DUMP
250 size_t writeResult = fwrite(frame, replyBytes, 1, pfd);
251 if (writeResult != replyBytes) {
252 AUDIO_ERR_LOG("Failed to write the file.");
253 }
254 #endif // CAPTURE_DUMP
255
256 stamp = GetNowTimeMs() - stamp;
257 AUDIO_DEBUG_LOG("RenderFrame len[%{public}" PRIu64 "] cost[%{public}" PRId64 "]ms", requestBytes, stamp);
258 return SUCCESS;
259 }
260
Start(void)261 int32_t AudioCapturerSource::Start(void)
262 {
263 AUDIO_INFO_LOG("Start.");
264
265 if (mKeepRunningLock == nullptr) {
266 mKeepRunningLock = PowerMgr::PowerMgrClient::GetInstance().CreateRunningLock("AudioPrimaryCapturer",
267 PowerMgr::RunningLockType::RUNNINGLOCK_BACKGROUND);
268 }
269
270 if (mKeepRunningLock != nullptr) {
271 AUDIO_INFO_LOG("AudioCapturerSourceInner call KeepRunningLock lock");
272 mKeepRunningLock->Lock(0); // 0 for lasting.
273 } else {
274 AUDIO_ERR_LOG("mKeepRunningLock is null, start can not work well!");
275 }
276
277 int32_t ret;
278 if (!started_) {
279 ret = audioCapture_->control.Start((AudioHandle)audioCapture_);
280 if (ret < 0) {
281 return ERR_NOT_STARTED;
282 }
283 started_ = true;
284 }
285
286 return SUCCESS;
287 }
288
SetVolume(float left,float right)289 int32_t AudioCapturerSource::SetVolume(float left, float right)
290 {
291 float volume;
292 if (audioCapture_ == nullptr) {
293 AUDIO_ERR_LOG("AudioCapturerSource::SetVolume failed audioCapture_ null");
294 return ERR_INVALID_HANDLE;
295 }
296
297 rightVolume_ = right;
298 leftVolume_ = left;
299 if ((leftVolume_ == 0) && (rightVolume_ != 0)) {
300 volume = rightVolume_;
301 } else if ((leftVolume_ != 0) && (rightVolume_ == 0)) {
302 volume = leftVolume_;
303 } else {
304 volume = (leftVolume_ + rightVolume_) / HALF_FACTOR;
305 }
306
307 audioCapture_->volume.SetVolume(reinterpret_cast<AudioHandle>(audioCapture_), volume);
308
309 return SUCCESS;
310 }
311
GetVolume(float & left,float & right)312 int32_t AudioCapturerSource::GetVolume(float &left, float &right)
313 {
314 float val = 0.0;
315 audioCapture_->volume.GetVolume((AudioHandle)audioCapture_, &val);
316 left = val;
317 right = val;
318
319 return SUCCESS;
320 }
321
SetMute(bool isMute)322 int32_t AudioCapturerSource::SetMute(bool isMute)
323 {
324 int32_t ret;
325 if (audioCapture_ == nullptr) {
326 AUDIO_ERR_LOG("AudioCapturerSource::SetMute failed audioCapture_ handle is null!");
327 return ERR_INVALID_HANDLE;
328 }
329
330 ret = audioCapture_->volume.SetMute((AudioHandle)audioCapture_, isMute);
331 if (ret != 0) {
332 AUDIO_ERR_LOG("AudioCapturerSource::SetMute failed from hdi");
333 }
334
335 if (audioAdapter_ != nullptr) {
336 ret = audioAdapter_->SetMicMute(audioAdapter_, isMute);
337 if (ret != 0) {
338 AUDIO_ERR_LOG("AudioCapturerSource::SetMicMute failed from hdi");
339 }
340 }
341
342 micMuteState_ = isMute;
343
344 return SUCCESS;
345 }
346
GetMute(bool & isMute)347 int32_t AudioCapturerSource::GetMute(bool &isMute)
348 {
349 int32_t ret;
350 if (audioCapture_ == nullptr) {
351 AUDIO_ERR_LOG("AudioCapturerSource::GetMute failed audioCapture_ handle is null!");
352 return ERR_INVALID_HANDLE;
353 }
354
355 bool isHdiMute = false;
356 ret = audioCapture_->volume.GetMute((AudioHandle)audioCapture_, &isHdiMute);
357 if (ret != 0) {
358 AUDIO_ERR_LOG("AudioCapturerSource::GetMute failed from hdi");
359 }
360
361 isMute = micMuteState_;
362
363 return SUCCESS;
364 }
365
GetAudioCategory(AudioScene audioScene)366 static AudioCategory GetAudioCategory(AudioScene audioScene)
367 {
368 AudioCategory audioCategory;
369 switch (audioScene) {
370 case AUDIO_SCENE_PHONE_CALL:
371 audioCategory = AUDIO_IN_CALL;
372 break;
373 case AUDIO_SCENE_PHONE_CHAT:
374 audioCategory = AUDIO_IN_COMMUNICATION;
375 break;
376 case AUDIO_SCENE_RINGING:
377 audioCategory = AUDIO_IN_RINGTONE;
378 break;
379 case AUDIO_SCENE_DEFAULT:
380 audioCategory = AUDIO_IN_MEDIA;
381 break;
382 default:
383 audioCategory = AUDIO_IN_MEDIA;
384 break;
385 }
386 AUDIO_DEBUG_LOG("AudioCapturerSource: Audio category returned is: %{public}d", audioCategory);
387
388 return audioCategory;
389 }
390
SetInputPortPin(DeviceType inputDevice,AudioRouteNode & source)391 static int32_t SetInputPortPin(DeviceType inputDevice, AudioRouteNode &source)
392 {
393 int32_t ret = SUCCESS;
394
395 switch (inputDevice) {
396 case DEVICE_TYPE_MIC:
397 case DEVICE_TYPE_SPEAKER:
398 source.ext.device.type = PIN_IN_MIC;
399 source.ext.device.desc = "pin_in_mic";
400 break;
401 case DEVICE_TYPE_WIRED_HEADSET:
402 source.ext.device.type = PIN_IN_HS_MIC;
403 source.ext.device.desc = "pin_in_hs_mic";
404 break;
405 case DEVICE_TYPE_USB_HEADSET:
406 source.ext.device.type = PIN_IN_USB_EXT;
407 source.ext.device.desc = "pin_in_usb_ext";
408 break;
409 case DEVICE_TYPE_BLUETOOTH_SCO:
410 source.ext.device.type = PIN_IN_BLUETOOTH_SCO_HEADSET;
411 source.ext.device.desc = "pin_in_bluetooth_sco_headset";
412 break;
413 default:
414 ret = ERR_NOT_SUPPORTED;
415 break;
416 }
417
418 return ret;
419 }
420
SetInputRoute(DeviceType inputDevice)421 int32_t AudioCapturerSource::SetInputRoute(DeviceType inputDevice)
422 {
423 AudioPortPin inputPortPin = PIN_IN_MIC;
424 return SetInputRoute(inputDevice, inputPortPin);
425 }
426
SetInputRoute(DeviceType inputDevice,AudioPortPin & inputPortPin)427 int32_t AudioCapturerSource::SetInputRoute(DeviceType inputDevice, AudioPortPin &inputPortPin)
428 {
429 AudioRouteNode source = {};
430 AudioRouteNode sink = {};
431
432 int32_t ret = SetInputPortPin(inputDevice, source);
433 if (ret != SUCCESS) {
434 AUDIO_ERR_LOG("AudioCapturerSource: SetOutputRoute FAILED: %{public}d", ret);
435 return ret;
436 }
437
438 inputPortPin = source.ext.device.type;
439 AUDIO_INFO_LOG("AudioCapturerSource: Input PIN is: 0x%{public}X", inputPortPin);
440 source.portId = static_cast<int32_t>(audioPort.portId);
441 source.role = AUDIO_PORT_SOURCE_ROLE;
442 source.type = AUDIO_PORT_DEVICE_TYPE;
443 source.ext.device.moduleId = 0;
444
445 sink.portId = 0;
446 sink.role = AUDIO_PORT_SINK_ROLE;
447 sink.type = AUDIO_PORT_MIX_TYPE;
448 sink.ext.mix.moduleId = 0;
449 sink.ext.mix.streamId = INTERNAL_INPUT_STREAM_ID;
450
451 AudioRoute route = {
452 .sourcesNum = 1,
453 .sources = &source,
454 .sinksNum = 1,
455 .sinks = &sink,
456 };
457
458 if (audioAdapter_ == nullptr) {
459 AUDIO_ERR_LOG("SetInputRoute failed, audioAdapter_ is null");
460 return ERR_INVALID_PARAM;
461 }
462 ret = audioAdapter_->UpdateAudioRoute(audioAdapter_, &route, &routeHandle_);
463 if (ret != 0) {
464 AUDIO_ERR_LOG("UpdateAudioRoute failed");
465 return ERR_OPERATION_FAILED;
466 }
467
468 return SUCCESS;
469 }
470
SetAudioScene(AudioScene audioScene,DeviceType activeDevice)471 int32_t AudioCapturerSource::SetAudioScene(AudioScene audioScene, DeviceType activeDevice)
472 {
473 AUDIO_INFO_LOG("AudioCapturerSource::SetAudioScene scene: %{public}d, device: %{public}d",
474 audioScene, activeDevice);
475 CHECK_AND_RETURN_RET_LOG(audioScene >= AUDIO_SCENE_DEFAULT && audioScene <= AUDIO_SCENE_PHONE_CHAT,
476 ERR_INVALID_PARAM, "invalid audioScene");
477 if (audioCapture_ == nullptr) {
478 AUDIO_ERR_LOG("AudioCapturerSource::SetAudioScene failed audioCapture_ handle is null!");
479 return ERR_INVALID_HANDLE;
480 }
481 if (openMic_) {
482 AudioPortPin audioSceneInPort = PIN_IN_MIC;
483 int32_t ret = SetInputRoute(activeDevice, audioSceneInPort);
484 if (ret < 0) {
485 AUDIO_ERR_LOG("AudioCapturerSource: Update route FAILED: %{public}d", ret);
486 }
487 struct AudioSceneDescriptor scene;
488 scene.scene.id = GetAudioCategory(audioScene);
489 scene.desc.pins = audioSceneInPort;
490 scene.desc.desc = nullptr;
491 if (audioCapture_->scene.SelectScene == nullptr) {
492 AUDIO_ERR_LOG("AudioCapturerSource: Select scene nullptr");
493 return ERR_OPERATION_FAILED;
494 }
495
496 ret = audioCapture_->scene.SelectScene((AudioHandle)audioCapture_, &scene);
497 if (ret < 0) {
498 AUDIO_ERR_LOG("AudioCapturerSource: Select scene FAILED: %{public}d", ret);
499 return ERR_OPERATION_FAILED;
500 }
501 }
502 AUDIO_INFO_LOG("AudioCapturerSource::Select audio scene SUCCESS: %{public}d", audioScene);
503 return SUCCESS;
504 }
505
GetTransactionId()506 uint64_t AudioCapturerSource::GetTransactionId()
507 {
508 AUDIO_INFO_LOG("AudioCapturerSource::GetTransactionId in");
509 return reinterpret_cast<uint64_t>(audioCapture_);
510 }
511
Stop(void)512 int32_t AudioCapturerSource::Stop(void)
513 {
514 AUDIO_INFO_LOG("Stop.");
515
516 if (mKeepRunningLock != nullptr) {
517 AUDIO_INFO_LOG("AudioCapturerSourceInner call KeepRunningLock UnLock");
518 mKeepRunningLock->UnLock();
519 } else {
520 AUDIO_ERR_LOG("mKeepRunningLock is null, stop can not work well!");
521 }
522
523 int32_t ret;
524 if (started_ && audioCapture_ != nullptr) {
525 ret = audioCapture_->control.Stop(reinterpret_cast<AudioHandle>(audioCapture_));
526 if (ret < 0) {
527 AUDIO_ERR_LOG("Stop capture Failed");
528 return ERR_OPERATION_FAILED;
529 }
530 }
531 started_ = false;
532
533 return SUCCESS;
534 }
535
Pause(void)536 int32_t AudioCapturerSource::Pause(void)
537 {
538 int32_t ret;
539 if (started_ && audioCapture_ != nullptr) {
540 ret = audioCapture_->control.Pause(reinterpret_cast<AudioHandle>(audioCapture_));
541 if (ret != 0) {
542 AUDIO_ERR_LOG("pause capture Failed");
543 return ERR_OPERATION_FAILED;
544 }
545 }
546 paused_ = true;
547
548 return SUCCESS;
549 }
550
Resume(void)551 int32_t AudioCapturerSource::Resume(void)
552 {
553 int32_t ret;
554 if (paused_ && audioCapture_ != nullptr) {
555 ret = audioCapture_->control.Resume(reinterpret_cast<AudioHandle>(audioCapture_));
556 if (ret != 0) {
557 AUDIO_ERR_LOG("resume capture Failed");
558 return ERR_OPERATION_FAILED;
559 }
560 }
561 paused_ = false;
562
563 return SUCCESS;
564 }
565
Reset(void)566 int32_t AudioCapturerSource::Reset(void)
567 {
568 if (started_ && audioCapture_ != nullptr) {
569 audioCapture_->control.Flush(reinterpret_cast<AudioHandle>(audioCapture_));
570 }
571
572 return SUCCESS;
573 }
574
Flush(void)575 int32_t AudioCapturerSource::Flush(void)
576 {
577 if (started_ && audioCapture_ != nullptr) {
578 audioCapture_->control.Flush(reinterpret_cast<AudioHandle>(audioCapture_));
579 }
580
581 return SUCCESS;
582 }
583 } // namespace AudioStandard
584 } // namesapce OHOS
585