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 "RemoteAudioCaptureSource"
18 #endif
19
20 #include "source/remote_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 using namespace OHOS::HDI::DistributedAudio::Audio::V1_0;
29
30 namespace OHOS {
31 namespace AudioStandard {
RemoteAudioCaptureSource(const std::string & deviceNetworkId)32 RemoteAudioCaptureSource::RemoteAudioCaptureSource(const std::string &deviceNetworkId)
33 : deviceNetworkId_(deviceNetworkId)
34 {
35 }
36
~RemoteAudioCaptureSource()37 RemoteAudioCaptureSource::~RemoteAudioCaptureSource()
38 {
39 if (sourceInited_.load()) {
40 DeInit();
41 }
42 }
43
Init(const IAudioSourceAttr & attr)44 int32_t RemoteAudioCaptureSource::Init(const IAudioSourceAttr &attr)
45 {
46 AUDIO_INFO_LOG("in");
47 attr_ = attr;
48 sourceInited_.store(true);
49 SetMute(muteState_);
50 AUDIO_DEBUG_LOG("end");
51 return SUCCESS;
52 }
53
DeInit(void)54 void RemoteAudioCaptureSource::DeInit(void)
55 {
56 AUDIO_INFO_LOG("in");
57 sourceInited_.store(false);
58 captureInited_.store(false);
59 started_.store(false);
60 paused_.store(false);
61
62 DestroyCapture();
63 DumpFileUtil::CloseDumpFile(&dumpFile_);
64 AUDIO_INFO_LOG("end");
65 }
66
IsInited(void)67 bool RemoteAudioCaptureSource::IsInited(void)
68 {
69 return sourceInited_.load();
70 }
71
Start(void)72 int32_t RemoteAudioCaptureSource::Start(void)
73 {
74 AUDIO_INFO_LOG("in");
75 std::lock_guard<std::mutex> lock(createCaptureMutex_);
76 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, DUMP_REMOTE_CAPTURE_SOURCE_FILENAME, &dumpFile_);
77 if (!captureInited_.load()) {
78 int32_t ret = CreateCapture();
79 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "create capture fail");
80 captureInited_.store(true);
81 }
82
83 if (started_.load()) {
84 AUDIO_INFO_LOG("already started");
85 return SUCCESS;
86 }
87 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
88 int32_t ret = audioCapture_->Start();
89 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_NOT_STARTED, "start fail, ret: %{public}d", ret);
90 started_.store(true);
91 return SUCCESS;
92 }
93
Stop(void)94 int32_t RemoteAudioCaptureSource::Stop(void)
95 {
96 AUDIO_INFO_LOG("in");
97 if (!started_.load()) {
98 AUDIO_INFO_LOG("already stopped");
99 return SUCCESS;
100 }
101
102 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
103 int32_t ret = audioCapture_->Stop();
104 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "stop fail, ret: %{public}d", ret);
105 started_.store(false);
106 if (captureInited_.load()) {
107 DestroyCapture();
108 captureInited_.store(false);
109 }
110 return SUCCESS;
111 }
112
Resume(void)113 int32_t RemoteAudioCaptureSource::Resume(void)
114 {
115 AUDIO_INFO_LOG("in");
116 CHECK_AND_RETURN_RET_LOG(started_.load(), ERR_ILLEGAL_STATE, "not start, invalid state");
117
118 if (!paused_.load()) {
119 AUDIO_INFO_LOG("already resumed");
120 return SUCCESS;
121 }
122
123 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
124 int32_t ret = audioCapture_->Resume();
125 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "resume fail, ret: %{public}d", ret);
126 paused_.store(false);
127 return SUCCESS;
128 }
129
Pause(void)130 int32_t RemoteAudioCaptureSource::Pause(void)
131 {
132 AUDIO_INFO_LOG("in");
133 CHECK_AND_RETURN_RET_LOG(started_.load(), ERR_ILLEGAL_STATE, "not start, invalid state");
134
135 if (paused_.load()) {
136 AUDIO_INFO_LOG("already paused");
137 return SUCCESS;
138 }
139
140 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
141 int32_t ret = audioCapture_->Pause();
142 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "pause fail, ret: %{public}d", ret);
143 paused_.store(true);
144 return SUCCESS;
145 }
146
Flush(void)147 int32_t RemoteAudioCaptureSource::Flush(void)
148 {
149 AUDIO_INFO_LOG("in");
150 CHECK_AND_RETURN_RET_LOG(started_.load(), ERR_ILLEGAL_STATE, "not start, invalid state");
151
152 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
153 int32_t ret = audioCapture_->Flush();
154 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "flush fail, ret: %{public}d", ret);
155 return SUCCESS;
156 }
157
Reset(void)158 int32_t RemoteAudioCaptureSource::Reset(void)
159 {
160 AUDIO_INFO_LOG("in");
161 CHECK_AND_RETURN_RET_LOG(started_.load(), ERR_ILLEGAL_STATE, "not start, invalid state");
162
163 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
164 int32_t ret = audioCapture_->Flush();
165 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "reset fail, ret: %{public}d", ret);
166 return SUCCESS;
167 }
168
CaptureFrame(char * frame,uint64_t requestBytes,uint64_t & replyBytes)169 int32_t RemoteAudioCaptureSource::CaptureFrame(char *frame, uint64_t requestBytes, uint64_t &replyBytes)
170 {
171 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
172 if (!started_.load()) {
173 AUDIO_WARNING_LOG("not start, invalid state");
174 return ERR_ILLEGAL_STATE;
175 }
176
177 std::vector<int8_t> bufferVec(requestBytes);
178 int32_t ret = audioCapture_->CaptureFrame(bufferVec, replyBytes);
179 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_READ_FAILED, "fail, ret: %{public}x", ret);
180 ret = memcpy_s(frame, requestBytes, bufferVec.data(), requestBytes);
181 CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_OPERATION_FAILED, "copy fail, error code: %{public}d", ret);
182 replyBytes = requestBytes;
183
184 DumpFileUtil::WriteDumpFile(dumpFile_, frame, requestBytes);
185 CheckUpdateState(frame, requestBytes);
186 return SUCCESS;
187 }
188
CaptureFrameWithEc(FrameDesc * fdesc,uint64_t & replyBytes,FrameDesc * fdescEc,uint64_t & replyBytesEc)189 int32_t RemoteAudioCaptureSource::CaptureFrameWithEc(FrameDesc *fdesc, uint64_t &replyBytes, FrameDesc *fdescEc,
190 uint64_t &replyBytesEc)
191 {
192 AUDIO_INFO_LOG("not support");
193 return ERR_NOT_SUPPORTED;
194 }
195
GetAudioParameter(const AudioParamKey key,const std::string & condition)196 std::string RemoteAudioCaptureSource::GetAudioParameter(const AudioParamKey key, const std::string &condition)
197 {
198 return "";
199 }
200
SetVolume(float left,float right)201 int32_t RemoteAudioCaptureSource::SetVolume(float left, float right)
202 {
203 float leftVolume = left;
204 float rightVolume = right;
205 float volume;
206 if ((leftVolume == 0) && (rightVolume != 0)) {
207 volume = rightVolume;
208 } else if ((leftVolume != 0) && (rightVolume == 0)) {
209 volume = leftVolume;
210 } else {
211 volume = (leftVolume + rightVolume) / HALF_FACTOR;
212 }
213
214 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
215 int32_t ret = audioCapture_->SetVolume(volume);
216 AUDIO_INFO_LOG("left: %{public}f, right: %{public}f, ret: %{public}d", left, right, ret);
217 return SUCCESS;
218 }
219
GetVolume(float & left,float & right)220 int32_t RemoteAudioCaptureSource::GetVolume(float &left, float &right)
221 {
222 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
223
224 float val = 0.0;
225 audioCapture_->GetVolume(val);
226 left = val;
227 right = val;
228 return SUCCESS;
229 }
230
SetMute(bool isMute)231 int32_t RemoteAudioCaptureSource::SetMute(bool isMute)
232 {
233 muteState_ = isMute;
234 if (!sourceInited_.load()) {
235 AUDIO_INFO_LOG("source not init, just save mute state");
236 return SUCCESS;
237 }
238 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
239 int32_t ret = audioCapture_->SetMute(isMute);
240 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "set mute fail");
241 return SUCCESS;
242 }
GetMute(bool & isMute)243 int32_t RemoteAudioCaptureSource::GetMute(bool &isMute)
244 {
245 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
246 bool hdiMuteState = false;
247 int32_t ret = audioCapture_->GetMute(hdiMuteState);
248 if (ret != SUCCESS) {
249 AUDIO_WARNING_LOG("get mute fail");
250 }
251 AUDIO_DEBUG_LOG("hdiMuteState: %{public}d, muteState: %{public}d", hdiMuteState, muteState_);
252 isMute = muteState_;
253 return SUCCESS;
254 }
255
GetTransactionId(void)256 uint64_t RemoteAudioCaptureSource::GetTransactionId(void)
257 {
258 AUDIO_INFO_LOG("not support");
259 return ERR_NOT_SUPPORTED;
260 }
261
GetPresentationPosition(uint64_t & frames,int64_t & timeSec,int64_t & timeNanoSec)262 int32_t RemoteAudioCaptureSource::GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec)
263 {
264 AUDIO_INFO_LOG("not support");
265 return ERR_NOT_SUPPORTED;
266 }
267
GetMaxAmplitude(void)268 float RemoteAudioCaptureSource::GetMaxAmplitude(void)
269 {
270 lastGetMaxAmplitudeTime_ = ClockTime::GetCurNano();
271 startUpdate_ = true;
272 return maxAmplitude_;
273 }
274
SetAudioScene(AudioScene audioScene,DeviceType activeDevice)275 int32_t RemoteAudioCaptureSource::SetAudioScene(AudioScene audioScene, DeviceType activeDevice)
276 {
277 CHECK_AND_RETURN_RET_LOG(audioScene >= AUDIO_SCENE_DEFAULT && audioScene < AUDIO_SCENE_MAX, ERR_INVALID_PARAM,
278 "invalid scene");
279 AUDIO_INFO_LOG("scene: %{public}d, device: %{public}d", audioScene, activeDevice);
280
281 struct AudioSceneDescriptor sceneDesc = {
282 .scene.id = GetAudioCategory(audioScene),
283 .desc.pins = AudioPortPin::PIN_IN_MIC,
284 };
285 AUDIO_INFO_LOG("start");
286 CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE, "capture is nullptr");
287 int32_t ret = audioCapture_->SelectScene(sceneDesc);
288 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "select scene fail, ret: %{public}d", ret);
289 AUDIO_INFO_LOG("end");
290 return SUCCESS;
291 }
292
UpdateActiveDevice(DeviceType inputDevice)293 int32_t RemoteAudioCaptureSource::UpdateActiveDevice(DeviceType inputDevice)
294 {
295 AUDIO_INFO_LOG("not support");
296 return ERR_NOT_SUPPORTED;
297 }
298
RegistCallback(uint32_t type,IAudioSourceCallback * callback)299 void RemoteAudioCaptureSource::RegistCallback(uint32_t type, IAudioSourceCallback *callback)
300 {
301 AUDIO_INFO_LOG("in");
302 callback_.RegistCallback(type, callback);
303 }
304
UpdateAppsUid(const int32_t appsUid[PA_MAX_OUTPUTS_PER_SOURCE],const size_t size)305 int32_t RemoteAudioCaptureSource::UpdateAppsUid(const int32_t appsUid[PA_MAX_OUTPUTS_PER_SOURCE], const size_t size)
306 {
307 return ERR_NOT_SUPPORTED;
308 }
309
UpdateAppsUid(const std::vector<int32_t> & appsUid)310 int32_t RemoteAudioCaptureSource::UpdateAppsUid(const std::vector<int32_t> &appsUid)
311 {
312 return ERR_NOT_SUPPORTED;
313 }
314
DumpInfo(std::string & dumpString)315 void RemoteAudioCaptureSource::DumpInfo(std::string &dumpString)
316 {
317 dumpString += "type: RemoteSource\tstarted: " + std::string(started_.load() ? "true" : "false") +
318 "\tdeviceNetworkId: " + deviceNetworkId_ + "\n";
319 }
320
OnAudioParamChange(const std::string & adapterName,const AudioParamKey key,const std::string & condition,const std::string & value)321 void RemoteAudioCaptureSource::OnAudioParamChange(const std::string &adapterName, const AudioParamKey key,
322 const std::string &condition, const std::string &value)
323 {
324 AUDIO_INFO_LOG("key: %{public}d, condition: %{public}s, value: %{public}s", key, condition.c_str(), value.c_str());
325 if (key == AudioParamKey::PARAM_KEY_STATE) {
326 DeInit();
327 }
328
329 callback_.OnCaptureSourceParamChange(adapterName, key, condition, value);
330 }
331
ConvertToHdiFormat(AudioSampleFormat format)332 AudioFormat RemoteAudioCaptureSource::ConvertToHdiFormat(AudioSampleFormat format)
333 {
334 AudioFormat hdiFormat;
335 switch (format) {
336 case SAMPLE_U8:
337 hdiFormat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
338 break;
339 case SAMPLE_S16LE:
340 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
341 break;
342 case SAMPLE_S24LE:
343 hdiFormat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
344 break;
345 case SAMPLE_S32LE:
346 hdiFormat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
347 break;
348 default:
349 hdiFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
350 break;
351 }
352
353 return hdiFormat;
354 }
355
GetAudioCategory(AudioScene audioScene)356 AudioCategory RemoteAudioCaptureSource::GetAudioCategory(AudioScene audioScene)
357 {
358 AudioCategory audioCategory;
359 switch (audioScene) {
360 case AUDIO_SCENE_DEFAULT:
361 audioCategory = AUDIO_IN_MEDIA;
362 break;
363 case AUDIO_SCENE_RINGING:
364 case AUDIO_SCENE_VOICE_RINGING:
365 audioCategory = AUDIO_IN_RINGTONE;
366 break;
367 case AUDIO_SCENE_PHONE_CALL:
368 audioCategory = AUDIO_IN_CALL;
369 break;
370 case AUDIO_SCENE_PHONE_CHAT:
371 audioCategory = AUDIO_IN_COMMUNICATION;
372 break;
373 default:
374 audioCategory = AUDIO_IN_MEDIA;
375 break;
376 }
377 AUDIO_DEBUG_LOG("audioCategory: %{public}d", audioCategory);
378
379 return audioCategory;
380 }
381
InitAudioSampleAttr(struct AudioSampleAttributes & param)382 void RemoteAudioCaptureSource::InitAudioSampleAttr(struct AudioSampleAttributes ¶m)
383 {
384 param.type = AUDIO_IN_MEDIA;
385 param.period = DEEP_BUFFER_CAPTURE_PERIOD_SIZE;
386 param.streamId = static_cast<int32_t>(GenerateUniqueID(AUDIO_HDI_CAPTURE_ID_BASE, HDI_CAPTURE_OFFSET_REMOTE));
387 param.isSignedData = true;
388 param.stopThreshold = INT_MAX;
389 param.silenceThreshold = AUDIO_BUFFER_SIZE;
390 // user need to set
391 param.sampleRate = attr_.sampleRate;
392 param.format = ConvertToHdiFormat(attr_.format);
393 param.isBigEndian = attr_.isBigEndian;
394 param.channelCount = attr_.channel;
395 param.silenceThreshold = attr_.bufferSize;
396 param.frameSize = param.format * param.channelCount;
397 param.startThreshold = DEEP_BUFFER_CAPTURE_PERIOD_SIZE / (param.frameSize);
398 param.sourceType = attr_.sourceType;
399 }
400
InitDeviceDesc(struct AudioDeviceDescriptor & deviceDesc)401 void RemoteAudioCaptureSource::InitDeviceDesc(struct AudioDeviceDescriptor &deviceDesc)
402 {
403 deviceDesc.pins = AudioPortPin::PIN_IN_MIC;
404 deviceDesc.desc = "";
405 }
406
CreateCapture(void)407 int32_t RemoteAudioCaptureSource::CreateCapture(void)
408 {
409 struct AudioSampleAttributes param;
410 struct AudioDeviceDescriptor deviceDesc;
411 InitAudioSampleAttr(param);
412 InitDeviceDesc(deviceDesc);
413
414 AUDIO_INFO_LOG("create capture, format: %{public}u", param.format);
415 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
416 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_REMOTE);
417 CHECK_AND_RETURN_RET(deviceManager != nullptr, ERR_INVALID_HANDLE);
418 void *capture = deviceManager->CreateCapture(deviceNetworkId_, ¶m, &deviceDesc, hdiCaptureId_);
419 audioCapture_.ForceSetRefPtr(static_cast<IAudioCapture *>(capture));
420 CHECK_AND_RETURN_RET(audioCapture_ != nullptr, ERR_NOT_STARTED, "create capture fail");
421 deviceManager->RegistCaptureSourceCallback(deviceNetworkId_, hdiCaptureId_, this);
422 return SUCCESS;
423 }
424
DestroyCapture(void)425 void RemoteAudioCaptureSource::DestroyCapture(void)
426 {
427 AUDIO_INFO_LOG("destroy capture");
428 HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
429 std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_REMOTE);
430 CHECK_AND_RETURN(deviceManager != nullptr);
431 deviceManager->DestroyCapture(deviceNetworkId_, hdiCaptureId_);
432 deviceManager->UnRegistCaptureSourceCallback(deviceNetworkId_, hdiCaptureId_);
433 audioCapture_.ForceSetRefPtr(nullptr);
434 hdiCaptureId_ = 0;
435 }
436
CheckUpdateState(char * frame,size_t replyBytes)437 void RemoteAudioCaptureSource::CheckUpdateState(char *frame, size_t replyBytes)
438 {
439 if (startUpdate_) {
440 if (captureFrameNum_ == 0) {
441 last10FrameStartTime_ = ClockTime::GetCurNano();
442 }
443 captureFrameNum_++;
444 maxAmplitude_ = UpdateMaxAmplitude(static_cast<ConvertHdiFormat>(attr_.format), frame, replyBytes);
445 if (captureFrameNum_ == GET_MAX_AMPLITUDE_FRAMES_THRESHOLD) {
446 captureFrameNum_ = 0;
447 if (last10FrameStartTime_ > lastGetMaxAmplitudeTime_) {
448 startUpdate_ = false;
449 maxAmplitude_ = 0;
450 }
451 }
452 }
453 }
454
455 } // namespace AudioStandard
456 } // namespace OHOS
457