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