• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #ifndef LOG_TAG
17 #define LOG_TAG "FastAudioCaptureSource"
18 #endif
19 
20 #include "source/fast_audio_capture_source.h"
21 #include <climits>
22 #include "audio_hdi_log.h"
23 #include "audio_errors.h"
24 #include "audio_utils.h"
25 #include "common/hdi_adapter_info.h"
26 #include "manager/hdi_adapter_manager.h"
27 
28 namespace OHOS {
29 namespace AudioStandard {
~FastAudioCaptureSource()30 FastAudioCaptureSource::~FastAudioCaptureSource()
31 {
32     AUDIO_INFO_LOG("destruction");
33 }
34 
Init(const IAudioSourceAttr & attr)35 int32_t FastAudioCaptureSource::Init(const IAudioSourceAttr &attr)
36 {
37     AUDIO_INFO_LOG("in, flag: %{public}d", attr.audioStreamFlag);
38     attr_ = attr;
39 
40     int32_t ret = CreateCapture();
41     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "create capture fail");
42     ret = PrepareMmapBuffer();
43     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "prepare mmap buffer fail");
44     ret = DoSetInputRoute(static_cast<DeviceType>(attr_.deviceType));
45     if (ret != SUCCESS) {
46         AUDIO_WARNING_LOG("update route fail, ret: %{public}d", ret);
47     }
48     sourceInited_ = true;
49     return SUCCESS;
50 }
51 
DeInit(void)52 void FastAudioCaptureSource::DeInit(void)
53 {
54     AUDIO_INFO_LOG("in, flag: %{public}d, isCheckPositionSuccess: %{public}d", attr_.audioStreamFlag,
55         isCheckPositionSuccess_.load());
56     if (started_ || !isCheckPositionSuccess_) {
57         Stop();
58         started_ = false;
59     }
60     sourceInited_ = false;
61     HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
62     std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
63     CHECK_AND_RETURN(deviceManager != nullptr);
64     deviceManager->DestroyCapture(attr_.adapterName, hdiCaptureId_);
65     audioCapture_ = nullptr;
66 
67     callback_.OnCaptureState(false);
68 }
69 
IsInited(void)70 bool FastAudioCaptureSource::IsInited(void)
71 {
72     return sourceInited_;
73 }
74 
Start(void)75 int32_t FastAudioCaptureSource::Start(void)
76 {
77     std::lock_guard<std::mutex> lock(statusMutex_);
78     AUDIO_INFO_LOG("in");
79 #ifdef FEATURE_POWER_MANAGER
80     if (runningLock_ == nullptr) {
81         WatchTimeout guard("create AudioRunningLock start");
82         runningLock_ = std::make_shared<AudioRunningLock>(std::string(RUNNING_LOCK_NAME));
83         guard.CheckCurrTimeout();
84     }
85     if (runningLock_ != nullptr) {
86         runningLock_->Lock(RUNNING_LOCK_TIMEOUTMS_LASTING);
87     } else {
88         AUDIO_ERR_LOG("running lock is null, playback can not work well");
89     }
90 #endif
91     if (started_) {
92         isCheckPositionSuccess_ = true;
93         return SUCCESS;
94     }
95     callback_.OnCaptureState(true);
96     CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
97     int32_t ret = audioCapture_->Start(audioCapture_);
98     if (ret != SUCCESS) {
99         goto ERR_RET;
100     }
101     ret = CheckPositionTime();
102     if (ret != SUCCESS) {
103         isCheckPositionSuccess_ = false;
104         goto ERR_RET;
105     }
106     isCheckPositionSuccess_ = true;
107     started_ = true;
108     return SUCCESS;
109 
110 ERR_RET:
111     callback_.OnCaptureState(false);
112     return ERR_NOT_STARTED;
113 }
114 
Stop(void)115 int32_t FastAudioCaptureSource::Stop(void)
116 {
117     std::lock_guard<std::mutex> lock(statusMutex_);
118     AUDIO_INFO_LOG("in, isCheckPositionSuccess: %{public}d", isCheckPositionSuccess_.load());
119 
120 #ifdef FEATURE_POWER_MANAGER
121     if (runningLock_ != nullptr) {
122         AUDIO_INFO_LOG("running lock unlock");
123         runningLock_->UnLock();
124     } else {
125         AUDIO_WARNING_LOG("running lock is null, playback can not work well");
126     }
127 #endif
128     if (!started_) {
129         return SUCCESS;
130     }
131     if (isCheckPositionSuccess_) {
132         CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
133         int32_t ret = audioCapture_->Stop(audioCapture_);
134         callback_.OnCaptureState(false);
135         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "stop fail, ret: %{public}d", ret);
136     }
137     started_ = false;
138     return SUCCESS;
139 }
140 
Resume(void)141 int32_t FastAudioCaptureSource::Resume(void)
142 {
143     CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
144 
145     if (!paused_) {
146         return SUCCESS;
147     }
148     int32_t ret = audioCapture_->Resume(audioCapture_);
149     callback_.OnCaptureState(true);
150     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "resume fail");
151     paused_ = false;
152     return SUCCESS;
153 }
154 
Pause(void)155 int32_t FastAudioCaptureSource::Pause(void)
156 {
157     CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
158     CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
159 
160     int32_t ret = audioCapture_->Pause(audioCapture_);
161     callback_.OnCaptureState(false);
162     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "pause fail");
163     paused_ = true;
164     return SUCCESS;
165 }
166 
Flush(void)167 int32_t FastAudioCaptureSource::Flush(void)
168 {
169     CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
170     CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
171 
172     int32_t ret = audioCapture_->Flush(audioCapture_);
173     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "flush fail");
174     return SUCCESS;
175 }
176 
Reset(void)177 int32_t FastAudioCaptureSource::Reset(void)
178 {
179     CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
180     CHECK_AND_RETURN_RET_LOG(started_, ERR_OPERATION_FAILED, "not start, invalid state");
181 
182     int32_t ret = audioCapture_->Flush(audioCapture_);
183     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "reset fail");
184     return SUCCESS;
185 }
186 
CaptureFrame(char * frame,uint64_t requestBytes,uint64_t & replyBytes)187 int32_t FastAudioCaptureSource::CaptureFrame(char *frame, uint64_t requestBytes, uint64_t &replyBytes)
188 {
189     AUDIO_INFO_LOG("not support");
190     return ERR_NOT_SUPPORTED;
191 }
192 
CaptureFrameWithEc(FrameDesc * fdesc,uint64_t & replyBytes,FrameDesc * fdescEc,uint64_t & replyBytesEc)193 int32_t FastAudioCaptureSource::CaptureFrameWithEc(FrameDesc *fdesc, uint64_t &replyBytes, FrameDesc *fdescEc,
194     uint64_t &replyBytesEc)
195 {
196     AUDIO_INFO_LOG("not support");
197     return ERR_NOT_SUPPORTED;
198 }
199 
GetAudioParameter(const AudioParamKey key,const std::string & condition)200 std::string FastAudioCaptureSource::GetAudioParameter(const AudioParamKey key, const std::string &condition)
201 {
202     return "";
203 }
204 
SetVolume(float left,float right)205 int32_t FastAudioCaptureSource::SetVolume(float left, float right)
206 {
207     AUDIO_INFO_LOG("not support");
208     return ERR_NOT_SUPPORTED;
209 }
210 
GetVolume(float & left,float & right)211 int32_t FastAudioCaptureSource::GetVolume(float &left, float &right)
212 {
213     AUDIO_INFO_LOG("not support");
214     return ERR_NOT_SUPPORTED;
215 }
216 
SetMute(bool isMute)217 int32_t FastAudioCaptureSource::SetMute(bool isMute)
218 {
219     AUDIO_INFO_LOG("not support");
220     return ERR_NOT_SUPPORTED;
221 }
222 
GetMute(bool & isMute)223 int32_t FastAudioCaptureSource::GetMute(bool &isMute)
224 {
225     AUDIO_INFO_LOG("not support");
226     return ERR_NOT_SUPPORTED;
227 }
228 
GetTransactionId(void)229 uint64_t FastAudioCaptureSource::GetTransactionId(void)
230 {
231     return reinterpret_cast<uint64_t>(audioCapture_);
232 }
233 
GetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)234 int32_t FastAudioCaptureSource::GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
235 {
236     AUDIO_INFO_LOG("not support");
237     return ERR_NOT_SUPPORTED;
238 }
239 
GetMaxAmplitude(void)240 float FastAudioCaptureSource::GetMaxAmplitude(void)
241 {
242     AUDIO_INFO_LOG("not support");
243     return 0;
244 }
245 
SetAudioScene(AudioScene audioScene,DeviceType activeDevice)246 int32_t FastAudioCaptureSource::SetAudioScene(AudioScene audioScene, DeviceType activeDevice)
247 {
248     CHECK_AND_RETURN_RET_LOG(audioScene >= AUDIO_SCENE_DEFAULT && audioScene < AUDIO_SCENE_MAX, ERR_INVALID_PARAM,
249         "invalid scene");
250     AUDIO_INFO_LOG("scene: %{public}d, device: %{public}d", audioScene, activeDevice);
251 
252     if (audioScene != currentAudioScene_) {
253         struct AudioSceneDescriptor sceneDesc;
254         InitSceneDesc(sceneDesc, audioScene);
255 
256         CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
257         int32_t ret = audioCapture_->SelectScene(audioCapture_, &sceneDesc);
258         CHECK_AND_RETURN_RET_LOG(ret >= 0, ERR_OPERATION_FAILED, "select scene fail, ret: %{public}d", ret);
259         currentAudioScene_ = audioScene;
260     }
261     int32_t ret = DoSetInputRoute(activeDevice);
262     if (ret != SUCCESS) {
263         AUDIO_WARNING_LOG("update route fail, ret: %{public}d", ret);
264     }
265     return SUCCESS;
266 }
267 
UpdateActiveDevice(DeviceType inputDevice)268 int32_t FastAudioCaptureSource::UpdateActiveDevice(DeviceType inputDevice)
269 {
270     return DoSetInputRoute(inputDevice);
271 }
272 
RegistCallback(uint32_t type,std::shared_ptr<IAudioSourceCallback> callback)273 void FastAudioCaptureSource::RegistCallback(uint32_t type, std::shared_ptr<IAudioSourceCallback> callback)
274 {
275     AUDIO_INFO_LOG("in");
276     callback_.RegistCallback(type, callback);
277 }
278 
UpdateAppsUid(const int32_t appsUid[PA_MAX_OUTPUTS_PER_SOURCE],const size_t size)279 int32_t FastAudioCaptureSource::UpdateAppsUid(const int32_t appsUid[PA_MAX_OUTPUTS_PER_SOURCE], const size_t size)
280 {
281 #ifdef FEATURE_POWER_MANAGER
282     CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
283     runningLock_->UpdateAppsUid(appsUid, appsUid + size);
284 #endif
285     return SUCCESS;
286 }
287 
UpdateAppsUid(const std::vector<int32_t> & appsUid)288 int32_t FastAudioCaptureSource::UpdateAppsUid(const std::vector<int32_t> &appsUid)
289 {
290 #ifdef FEATURE_POWER_MANAGER
291     CHECK_AND_RETURN_RET_LOG(runningLock_, ERR_INVALID_HANDLE, "running lock is nullptr");
292     runningLock_->UpdateAppsUid(appsUid.cbegin(), appsUid.cend());
293     runningLock_->UpdateAppsUidToPowerMgr();
294 #endif
295     return SUCCESS;
296 }
297 
DumpInfo(std::string & dumpString)298 void FastAudioCaptureSource::DumpInfo(std::string &dumpString)
299 {
300     dumpString += "type: FastSource\tstarted: " + std::string(started_ ? "true" : "false") + "\n";
301 }
302 
GetMmapBufferInfo(int & fd,uint32_t & totalSizeInframe,uint32_t & spanSizeInframe,uint32_t & byteSizePerFrame)303 int32_t FastAudioCaptureSource::GetMmapBufferInfo(int &fd, uint32_t &totalSizeInframe, uint32_t &spanSizeInframe,
304     uint32_t &byteSizePerFrame)
305 {
306     CHECK_AND_RETURN_RET_LOG(bufferFd_ != INVALID_FD, ERR_INVALID_HANDLE, "buffer fd has been released");
307     fd = bufferFd_;
308     totalSizeInframe = bufferTotalFrameSize_;
309     spanSizeInframe = eachReadFrameSize_;
310     byteSizePerFrame = PcmFormatToBit(attr_.format) * attr_.channel / PCM_8_BIT;
311     return SUCCESS;
312 }
313 
GetMmapHandlePosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)314 int32_t FastAudioCaptureSource::GetMmapHandlePosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
315 {
316     CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
317 
318     struct AudioTimeStamp stamp = {};
319     int32_t ret = audioCapture_->GetMmapPosition(audioCapture_, &frames, &stamp);
320     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "get mmap position fail, ret: %{public}d", ret);
321 
322     int64_t maxSec = 9223372036; // (9223372036 + 1) * 10^9 > INT64_MAX, seconds should not bigger than it
323     CHECK_AND_RETURN_RET_LOG(stamp.tvSec >= 0 && stamp.tvSec <= maxSec && stamp.tvNSec >= 0 &&
324         stamp.tvNSec <= SECOND_TO_NANOSECOND, ERR_OPERATION_FAILED,
325         "get invalid time, second: %{public}" PRId64 ", nanosecond: %{public}" PRId64, stamp.tvSec, stamp.tvNSec);
326     timeSec = stamp.tvSec;
327     timeNanoSec = stamp.tvNSec;
328     return ret;
329 }
330 
PcmFormatToBit(AudioSampleFormat format)331 uint32_t FastAudioCaptureSource::PcmFormatToBit(AudioSampleFormat format)
332 {
333     switch (format) {
334         case SAMPLE_U8:
335             return PCM_8_BIT;
336         case SAMPLE_S16LE:
337             return PCM_16_BIT;
338         case SAMPLE_S24LE:
339             return PCM_24_BIT;
340         case SAMPLE_S32LE:
341             return PCM_32_BIT;
342         case SAMPLE_F32LE:
343             return PCM_32_BIT;
344         default:
345             AUDIO_DEBUG_LOG("unknown format type, set it to default");
346             return PCM_24_BIT;
347     }
348 }
349 
ConvertToHdiFormat(AudioSampleFormat format)350 AudioFormat FastAudioCaptureSource::ConvertToHdiFormat(AudioSampleFormat format)
351 {
352     AudioFormat hdiFormat;
353     switch (format) {
354         case SAMPLE_U8:
355             hdiFormat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
356             break;
357         case SAMPLE_S16LE:
358             hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
359             break;
360         case SAMPLE_S24LE:
361             hdiFormat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
362             break;
363         case SAMPLE_S32LE:
364             hdiFormat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
365             break;
366         default:
367             hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
368             break;
369     }
370     return hdiFormat;
371 }
372 
ConvertToHDIAudioInputType(int32_t sourceType)373 enum AudioInputType FastAudioCaptureSource::ConvertToHDIAudioInputType(int32_t sourceType)
374 {
375     enum AudioInputType hdiAudioInputType;
376     switch (sourceType) {
377         case SOURCE_TYPE_INVALID:
378             hdiAudioInputType = AUDIO_INPUT_DEFAULT_TYPE;
379             break;
380         case SOURCE_TYPE_MIC:
381         case SOURCE_TYPE_PLAYBACK_CAPTURE:
382         case SOURCE_TYPE_ULTRASONIC:
383         case SOURCE_TYPE_UNPROCESSED:
384             hdiAudioInputType = AUDIO_INPUT_MIC_TYPE;
385             break;
386         case SOURCE_TYPE_WAKEUP:
387             hdiAudioInputType = AUDIO_INPUT_SPEECH_WAKEUP_TYPE;
388             break;
389         case SOURCE_TYPE_VOICE_COMMUNICATION:
390             hdiAudioInputType = AUDIO_INPUT_VOICE_COMMUNICATION_TYPE;
391             break;
392         case SOURCE_TYPE_VOICE_RECOGNITION:
393             hdiAudioInputType = AUDIO_INPUT_VOICE_RECOGNITION_TYPE;
394             break;
395         case SOURCE_TYPE_VOICE_CALL:
396             hdiAudioInputType = AUDIO_INPUT_VOICE_CALL_TYPE;
397             break;
398         case SOURCE_TYPE_CAMCORDER:
399             hdiAudioInputType = AUDIO_INPUT_CAMCORDER_TYPE;
400             break;
401         default:
402             hdiAudioInputType = AUDIO_INPUT_MIC_TYPE;
403             break;
404     }
405     return hdiAudioInputType;
406 }
407 
GetAudioCategory(AudioScene audioScene)408 AudioCategory FastAudioCaptureSource::GetAudioCategory(AudioScene audioScene)
409 {
410     AudioCategory audioCategory;
411     switch (audioScene) {
412         case AUDIO_SCENE_DEFAULT:
413             audioCategory = AUDIO_IN_MEDIA;
414             break;
415         case AUDIO_SCENE_RINGING:
416         case AUDIO_SCENE_VOICE_RINGING:
417             audioCategory = AUDIO_IN_RINGTONE;
418             break;
419         case AUDIO_SCENE_PHONE_CALL:
420             audioCategory = AUDIO_IN_CALL;
421             break;
422         case AUDIO_SCENE_PHONE_CHAT:
423             audioCategory = AUDIO_IN_COMMUNICATION;
424             break;
425         default:
426             audioCategory = AUDIO_IN_MEDIA;
427             break;
428     }
429     AUDIO_DEBUG_LOG("audioCategory: %{public}d", audioCategory);
430 
431     return audioCategory;
432 }
433 
InitAudioSampleAttr(struct AudioSampleAttributes & param)434 void FastAudioCaptureSource::InitAudioSampleAttr(struct AudioSampleAttributes &param)
435 {
436     param.format = AUDIO_FORMAT_TYPE_PCM_16_BIT;
437     param.channelCount = AUDIO_CHANNELCOUNT;
438     param.interleaved = true;
439     param.streamId = static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_CAPTURE_ID_BASE, HDI_CAPTURE_OFFSET_FAST));
440     param.period = 0;
441     param.frameSize = PCM_16_BIT * param.channelCount / PCM_8_BIT;
442     param.isBigEndian = false;
443     param.isSignedData = true;
444     param.startThreshold = 0;
445     param.stopThreshold = INT_MAX;
446     param.silenceThreshold = 0;
447 
448     param.sourceType = static_cast<int32_t>(ConvertToHDIAudioInputType(attr_.sourceType));
449     param.type = attr_.audioStreamFlag == AUDIO_FLAG_VOIP_FAST ? AUDIO_MMAP_VOIP : AUDIO_MMAP_NOIRQ; // enable mmap!
450     param.sampleRate = attr_.sampleRate;
451     param.format = ConvertToHdiFormat(attr_.format);
452     param.isBigEndian = attr_.isBigEndian;
453     param.channelCount = attr_.channel;
454     if (param.channelCount == MONO) {
455         param.channelLayout = CH_LAYOUT_MONO;
456     } else if (param.channelCount == STEREO) {
457         param.channelLayout = CH_LAYOUT_STEREO;
458     }
459     param.silenceThreshold = attr_.bufferSize;
460     param.frameSize = param.format * param.channelCount;
461     param.startThreshold = 0;
462 }
463 
InitDeviceDesc(struct AudioDeviceDescriptor & deviceDesc)464 void FastAudioCaptureSource::InitDeviceDesc(struct AudioDeviceDescriptor &deviceDesc)
465 {
466     switch (static_cast<DeviceType>(attr_.deviceType)) {
467         case DEVICE_TYPE_MIC:
468             deviceDesc.pins = PIN_IN_MIC;
469             break;
470         case DEVICE_TYPE_WIRED_HEADSET:
471             deviceDesc.pins = PIN_IN_HS_MIC;
472             break;
473         case DEVICE_TYPE_USB_HEADSET:
474             deviceDesc.pins = PIN_IN_USB_EXT;
475             break;
476         case DEVICE_TYPE_BLUETOOTH_SCO:
477             deviceDesc.pins = PIN_IN_BLUETOOTH_SCO_HEADSET;
478             break;
479         default:
480             AUDIO_WARNING_LOG("unsupport, use default, deviceType: %{public}d", attr_.deviceType);
481             deviceDesc.pins = PIN_IN_MIC;
482             break;
483     }
484     deviceDesc.desc = const_cast<char *>("");
485 }
486 
InitSceneDesc(struct AudioSceneDescriptor & sceneDesc,AudioScene audioScene)487 void FastAudioCaptureSource::InitSceneDesc(struct AudioSceneDescriptor &sceneDesc, AudioScene audioScene)
488 {
489     sceneDesc.scene.id = GetAudioCategory(audioScene);
490     sceneDesc.desc.pins = PIN_IN_BLUETOOTH_SCO_HEADSET;
491     sceneDesc.desc.desc = const_cast<char *>("pin_in_bluetooth_sco_headset");
492 }
493 
CreateCapture(void)494 int32_t FastAudioCaptureSource::CreateCapture(void)
495 {
496     struct AudioSampleAttributes param;
497     struct AudioDeviceDescriptor deviceDesc;
498     InitAudioSampleAttr(param);
499     InitDeviceDesc(deviceDesc);
500 
501     AUDIO_INFO_LOG("create capture, type: %{public}d, rate: %{public}u, channel: %{public}u, format: %{public}u, "
502         "device: %{public}u", param.type, param.sampleRate, param.channelCount, param.format, attr_.deviceType);
503     HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
504     std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
505     CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
506     void *capture = deviceManager->CreateCapture(attr_.adapterName, &param, &deviceDesc, hdiCaptureId_);
507     audioCapture_ = static_cast<struct IAudioCapture *>(capture);
508     CHECK_AND_RETURN_RET(audioCapture_ != nullptr, ERR_NOT_STARTED);
509 
510     return SUCCESS;
511 }
512 
DoSetInputRoute(DeviceType inputDevice)513 int32_t FastAudioCaptureSource::DoSetInputRoute(DeviceType inputDevice)
514 {
515     HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
516     std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
517     CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
518     int32_t streamId = static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_CAPTURE_ID_BASE, HDI_CAPTURE_OFFSET_FAST));
519     int32_t inputType = static_cast<int32_t>(ConvertToHDIAudioInputType(attr_.sourceType));
520     int32_t ret = deviceManager->SetInputRoute(attr_.adapterName, inputDevice, streamId, inputType);
521     return ret;
522 }
523 
PrepareMmapBuffer(void)524 int32_t FastAudioCaptureSource::PrepareMmapBuffer(void)
525 {
526     uint32_t totalBufferInMs = 40; // 40: 5 * (6 + 2 * (1)) = 40ms, the buffer size, not latency
527     uint32_t reqBufferFrameSize = totalBufferInMs * (attr_.sampleRate / SECOND_TO_MILLISECOND);
528     struct AudioMmapBufferDescriptor desc;
529 
530     int32_t ret = audioCapture_->ReqMmapBuffer(audioCapture_, reqBufferFrameSize, &desc);
531     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "request mmap buffer fail, ret: %{public}d", ret);
532     AUDIO_INFO_LOG("memoryFd: [%{public}d], totalBufferFrames: [%{public}d], "
533         "transferFrameSize: [%{public}d], isShareable: [%{public}d], offset: [%{public}d]", desc.memoryFd,
534         desc.totalBufferFrames, desc.transferFrameSize, desc.isShareable, desc.offset);
535 
536     bufferFd_ = desc.memoryFd; // fcntl(fd, 1030, 3) after dup?
537     int32_t periodFrameMaxSize = 1920000; // 192khz * 10s
538     CHECK_AND_RETURN_RET_LOG(desc.totalBufferFrames >= 0 && desc.transferFrameSize >= 0 &&
539         desc.transferFrameSize <= periodFrameMaxSize, ERR_OPERATION_FAILED,
540         "invalid value, totalBufferFrames: [%{public}d], transferFrameSize: [%{public}d]", desc.totalBufferFrames,
541         desc.transferFrameSize);
542 
543     uint32_t frameSizeInByte = PcmFormatToBit(attr_.format) * attr_.channel / PCM_8_BIT;
544     bufferTotalFrameSize_ = static_cast<uint32_t>(desc.totalBufferFrames); // 1440 ~ 3840
545     eachReadFrameSize_ = static_cast<uint32_t>(desc.transferFrameSize); // 240
546     CHECK_AND_RETURN_RET_LOG(frameSizeInByte <= ULLONG_MAX / bufferTotalFrameSize_, ERR_OPERATION_FAILED,
547         "buffer size will overflow");
548 
549     bufferSize_ = bufferTotalFrameSize_ * frameSizeInByte;
550     return SUCCESS;
551 }
552 
CheckPositionTime(void)553 int32_t FastAudioCaptureSource::CheckPositionTime(void)
554 {
555     int32_t tryCount = MAX_GET_POSITION_TRY_COUNT;
556     uint64_t frames = 0;
557     int64_t timeSec = 0;
558     int64_t timeNanoSec = 0;
559     int64_t maxHandleTime = attr_.audioStreamFlag == AUDIO_FLAG_VOIP_FAST ? VOIP_MAX_GET_POSITION_HANDLE_TIME :
560         GENERAL_MAX_GET_POSITION_HANDLE_TIME;
561     while (tryCount-- > 0) {
562         ClockTime::RelativeSleep(MAX_GET_POSITION_WAIT_TIME);
563         int32_t ret = GetMmapHandlePosition(frames, timeSec, timeNanoSec);
564         int64_t curTime = ClockTime::GetCurNano();
565         int64_t curSec = curTime / AUDIO_NS_PER_SECOND;
566         int64_t curNanoSec = curTime - curSec * AUDIO_NS_PER_SECOND;
567         AUDIO_WARNING_LOG("sec: %{public}" PRId64 ", nanoSec: %{public}" PRId64 ", time cost: %{public}" PRId64,
568             timeSec, timeNanoSec, ClockTime::GetCurNano() - curTime);
569         if (ret != SUCCESS || curSec != timeSec || curNanoSec - timeNanoSec > maxHandleTime) {
570             AUDIO_WARNING_LOG("tryCount: %{public}d, ret: %{public}d", tryCount, ret);
571             continue;
572         } else {
573             AUDIO_INFO_LOG("check succ");
574             return SUCCESS;
575         }
576     }
577 #ifdef FEATURE_POWER_MANAGER
578     if (runningLock_ != nullptr) {
579         AUDIO_INFO_LOG("running lock unlock");
580         runningLock_->UnLock();
581     } else {
582         AUDIO_WARNING_LOG("running lock is null, playback can not work well");
583     }
584 #endif
585     AUDIO_ERR_LOG("fail, stop capture");
586     CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
587     int32_t ret = audioCapture_->Stop(audioCapture_);
588     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "stop fail, ret: %{public}d", ret);
589     return ERR_OPERATION_FAILED;
590 }
591 
592 } // namespace AudioStandard
593 } // namespace OHOS
594