• 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 
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, &param, &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