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