1 /*
2 * Copyright (c) 2023-2024 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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioProcessInClientInner"
17 #endif
18
19 #include "audio_process_in_client.h"
20
21 #include <atomic>
22 #include <cinttypes>
23 #include <condition_variable>
24 #include <sstream>
25 #include <string>
26 #include <mutex>
27 #include <thread>
28
29 #include "iservice_registry.h"
30 #include "system_ability_definition.h"
31
32 #include "audio_errors.h"
33 #include "audio_capturer_log.h"
34 #include "audio_system_manager.h"
35 #include "audio_utils.h"
36 #include "securec.h"
37
38 #include "audio_manager_base.h"
39 #include "audio_process_cb_stub.h"
40 #include "audio_server_death_recipient.h"
41 #include "i_audio_process.h"
42 #include "linear_pos_time_model.h"
43 #include "audio_log_utils.h"
44
45 namespace OHOS {
46 namespace AudioStandard {
47
48 namespace {
49 static constexpr int32_t VOLUME_SHIFT_NUMBER = 16; // 1 >> 16 = 65536, max volume
50 static const int64_t DELAY_RESYNC_TIME = 10000000000; // 10s
51 static const int32_t HALF_FACTOR = 2;
52 }
53
54 class ProcessCbImpl;
55 class AudioProcessInClientInner : public AudioProcessInClient,
56 public std::enable_shared_from_this<AudioProcessInClientInner> {
57 public:
58 AudioProcessInClientInner(const sptr<IAudioProcess> &ipcProxy, bool isVoipMmap);
59 ~AudioProcessInClientInner();
60
61 int32_t SaveDataCallback(const std::shared_ptr<AudioDataCallback> &dataCallback) override;
62
63 int32_t SaveUnderrunCallback(const std::shared_ptr<ClientUnderrunCallBack> &underrunCallback) override;
64
65 int32_t GetBufferDesc(BufferDesc &bufDesc) const override;
66
67 int32_t Enqueue(const BufferDesc &bufDesc) const override;
68
69 int32_t SetVolume(int32_t vol) override;
70
71 int32_t Start() override;
72
73 int32_t Pause(bool isFlush) override;
74
75 int32_t Resume() override;
76
77 int32_t Stop() override;
78
79 int32_t Release(bool isSwitchStream = false) override;
80
81 // methods for support IAudioStream
82 int32_t GetSessionID(uint32_t &sessionID) override;
83
84 bool GetAudioTime(uint32_t &framePos, int64_t &sec, int64_t &nanoSec) override;
85
86 int32_t GetBufferSize(size_t &bufferSize) override;
87
88 int32_t GetFrameCount(uint32_t &frameCount) override;
89
90 int32_t GetLatency(uint64_t &latency) override;
91
92 int32_t SetVolume(float vol) override;
93
94 float GetVolume() override;
95
96 int32_t SetDuckVolume(float vol) override;
97
98 uint32_t GetUnderflowCount() override;
99
100 uint32_t GetOverflowCount() override;
101
102 void SetUnderflowCount(uint32_t underflowCount) override;
103
104 void SetOverflowCount(uint32_t overflowCount) override;
105
106 int64_t GetFramesWritten() override;
107
108 int64_t GetFramesRead() override;
109
110 void SetApplicationCachePath(const std::string &cachePath) override;
111
112 void SetPreferredFrameSize(int32_t frameSize) override;
113
114 void UpdateLatencyTimestamp(std::string ×tamp, bool isRenderer) override;
115
116 bool Init(const AudioProcessConfig &config);
117
118 int32_t SetSilentModeAndMixWithOthers(bool on) override;
119
120 static const sptr<IStandardAudioService> GetAudioServerProxy();
121 static void AudioServerDied(pid_t pid);
122 static constexpr AudioStreamInfo g_targetStreamInfo = {SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO};
123
124 private:
125 // move it to a common folder
126 static bool ChannelFormatConvert(const AudioStreamData &srcData, const AudioStreamData &dstData);
127
128 bool InitAudioBuffer();
129 void ResetAudioBuffer();
130
131 bool PrepareCurrent(uint64_t curWritePos);
132 void CallClientHandleCurrent();
133 bool FinishHandleCurrent(uint64_t &curWritePos, int64_t &clientWriteCost);
134 int32_t ReadFromProcessClient() const;
135 int32_t RecordReSyncServicePos();
136 int32_t RecordPrepareCurrent(uint64_t curReadPos);
137 int32_t RecordFinishHandleCurrent(uint64_t &curReadPos, int64_t &clientReadCost);
138 bool PrepareCurrentLoop(uint64_t curWritePos);
139 bool FinishHandleCurrentLoop(uint64_t &curWritePos, int64_t &clientWriteCost);
140
141 void UpdateHandleInfo(bool isAysnc = true, bool resetReadWritePos = false);
142 int64_t GetPredictNextHandleTime(uint64_t posInFrame, bool isIndependent = false);
143 bool PrepareNext(uint64_t curHandPos, int64_t &wakeUpTime);
144 bool ClientPrepareNextLoop(uint64_t curWritePos, int64_t &wakeUpTime);
145 bool PrepareNextIndependent(uint64_t curWritePos, int64_t &wakeUpTime);
146
147 std::string GetStatusInfo(StreamStatus status);
148 bool KeepLoopRunning();
149 bool KeepLoopRunningIndependent();
150
151 void CallExitStandBy();
152
153 void ProcessCallbackFuc();
154 void ProcessCallbackFucIndependent();
155 void RecordProcessCallbackFuc();
156 void CopyWithVolume(const BufferDesc &srcDesc, const BufferDesc &dstDesc) const;
157 void ProcessVolume(const AudioStreamData &targetData) const;
158 int32_t ProcessData(const BufferDesc &srcDesc, const BufferDesc &dstDesc) const;
159 void CheckIfWakeUpTooLate(int64_t &curTime, int64_t &wakeUpTime);
160 void CheckIfWakeUpTooLate(int64_t &curTime, int64_t &wakeUpTime, int64_t clientWriteCost);
161 void DfxOperation(BufferDesc &buffer, AudioSampleFormat format, AudioChannel channel) const;
162
163 void DoFadeInOut(uint64_t &curWritePos);
164
165 private:
166 static constexpr int64_t MILLISECOND_PER_SECOND = 1000; // 1000ms
167 static constexpr int64_t ONE_MILLISECOND_DURATION = 1000000; // 1ms
168 static constexpr int64_t THREE_MILLISECOND_DURATION = 3000000; // 3ms
169 static constexpr int64_t MAX_WRITE_COST_DURATION_NANO = 5000000; // 5ms
170 static constexpr int64_t MAX_READ_COST_DURATION_NANO = 5000000; // 5ms
171 static constexpr int64_t WRITE_BEFORE_DURATION_NANO = 2000000; // 2ms
172 static constexpr int64_t RECORD_RESYNC_SLEEP_NANO = 2000000; // 2ms
173 static constexpr int64_t RECORD_HANDLE_DELAY_NANO = 3000000; // 3ms
174 static constexpr size_t MAX_TIMES = 4; // 4 times spanSizeInFrame_
175 static constexpr size_t DIV = 2; // half of span
176 static constexpr int64_t MAX_STOP_FADING_DURATION_NANO = 10000000; // 10ms
177 static constexpr int64_t WAKE_UP_LATE_COUNT = 20; // late for 20 times
178 enum ThreadStatus : uint32_t {
179 WAITTING = 0,
180 SLEEPING,
181 INRUNNING,
182 INVALID
183 };
184 AudioProcessConfig processConfig_;
185 bool needConvert_ = false;
186 size_t clientByteSizePerFrame_ = 0;
187 size_t clientSpanSizeInByte_ = 0;
188 size_t clientSpanSizeInFrame_ = 240;
189 sptr<IAudioProcess> processProxy_ = nullptr;
190 std::shared_ptr<OHAudioBuffer> audioBuffer_ = nullptr;
191 uint32_t sessionId_ = 0;
192 bool isVoipMmap_ = false;
193
194 uint32_t totalSizeInFrame_ = 0;
195 uint32_t spanSizeInFrame_ = 0;
196 uint32_t byteSizePerFrame_ = 0;
197 uint32_t spanSizeInMs_ = 0;
198 size_t spanSizeInByte_ = 0;
199 std::weak_ptr<AudioDataCallback> audioDataCallback_;
200 std::weak_ptr<ClientUnderrunCallBack> underrunCallback_;
201
202 std::unique_ptr<uint8_t[]> callbackBuffer_ = nullptr;
203
204 std::mutex statusSwitchLock_;
205 std::atomic<StreamStatus> *streamStatus_ = nullptr;
206 bool isInited_ = false;
207 bool needReSyncPosition_ = true;
208 int64_t lastPausedTime_ = INT64_MAX;
209
210 float volumeInFloat_ = 1.0f;
211 float duckVolumeInFloat_ = 1.0f;
212 int32_t processVolume_ = PROCESS_VOLUME_MAX; // 0 ~ 65536
213 LinearPosTimeModel handleTimeModel_;
214
215 std::thread callbackLoop_; // thread for callback to client and write.
216 bool isCallbackLoopEnd_ = false;
217 std::atomic<ThreadStatus> threadStatus_ = INVALID;
218 std::mutex loopThreadLock_;
219 std::condition_variable threadStatusCV_;
220
221 std::atomic<uint32_t> underflowCount_ = 0;
222 std::atomic<uint32_t> overflowCount_ = 0;
223
224 std::string cachePath_;
225 FILE *dumpFile_ = nullptr;
226 mutable int64_t volumeDataCount_ = 0;
227 std::string logUtilsTag_ = "";
228
229 std::atomic<bool> startFadein_ = false; // true-fade in when start or resume stream
230 std::atomic<bool> startFadeout_ = false; // true-fade out when pause or stop stream
231
232 sptr<ProcessCbImpl> processCbImpl_ = nullptr;
233 };
234
235 // ProcessCbImpl --> sptr | AudioProcessInClientInner --> shared_ptr
236 class ProcessCbImpl : public ProcessCbStub {
237 public:
238 explicit ProcessCbImpl(std::shared_ptr<AudioProcessInClientInner> processInClientInner);
239 virtual ~ProcessCbImpl() = default;
240
241 int32_t OnEndpointChange(int32_t status) override;
242
243 private:
244 std::weak_ptr<AudioProcessInClientInner> processInClientInner_;
245 };
246
ProcessCbImpl(std::shared_ptr<AudioProcessInClientInner> processInClientInner)247 ProcessCbImpl::ProcessCbImpl(std::shared_ptr<AudioProcessInClientInner> processInClientInner)
248 {
249 if (processInClientInner == nullptr) {
250 AUDIO_ERR_LOG("ProcessCbImpl() find null processInClientInner");
251 }
252 processInClientInner_ = processInClientInner;
253 }
254
OnEndpointChange(int32_t status)255 int32_t ProcessCbImpl::OnEndpointChange(int32_t status)
256 {
257 AUDIO_INFO_LOG("OnEndpointChange: %{public}d", status);
258 return SUCCESS;
259 }
260
261 std::mutex g_audioServerProxyMutex;
262 sptr<IStandardAudioService> gAudioServerProxy = nullptr;
263
AudioProcessInClientInner(const sptr<IAudioProcess> & ipcProxy,bool isVoipMmap)264 AudioProcessInClientInner::AudioProcessInClientInner(const sptr<IAudioProcess> &ipcProxy,
265 bool isVoipMmap) : processProxy_(ipcProxy), isVoipMmap_(isVoipMmap)
266 {
267 processProxy_->GetSessionId(sessionId_);
268 AUDIO_INFO_LOG("Construct with sessionId: %{public}d", sessionId_);
269 }
270
GetAudioServerProxy()271 const sptr<IStandardAudioService> AudioProcessInClientInner::GetAudioServerProxy()
272 {
273 std::lock_guard<std::mutex> lock(g_audioServerProxyMutex);
274 if (gAudioServerProxy == nullptr) {
275 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
276 CHECK_AND_RETURN_RET_LOG(samgr != nullptr, nullptr, "get sa manager failed");
277 sptr<IRemoteObject> object = samgr->GetSystemAbility(AUDIO_DISTRIBUTED_SERVICE_ID);
278 CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "get audio service remote object failed");
279 gAudioServerProxy = iface_cast<IStandardAudioService>(object);
280 CHECK_AND_RETURN_RET_LOG(gAudioServerProxy != nullptr, nullptr, "get audio service proxy failed");
281
282 // register death recipent to restore proxy
283 sptr<AudioServerDeathRecipient> asDeathRecipient = new(std::nothrow) AudioServerDeathRecipient(getpid());
284 if (asDeathRecipient != nullptr) {
285 asDeathRecipient->SetNotifyCb([] (pid_t pid) { AudioServerDied(pid); });
286 bool result = object->AddDeathRecipient(asDeathRecipient);
287 if (!result) {
288 AUDIO_WARNING_LOG("failed to add deathRecipient");
289 }
290 }
291 }
292 sptr<IStandardAudioService> gasp = gAudioServerProxy;
293 return gasp;
294 }
295
296 /**
297 * When AudioServer died, all stream in client should be notified. As they were proxy stream ,the stub stream
298 * has been destoried in server.
299 */
AudioServerDied(pid_t pid)300 void AudioProcessInClientInner::AudioServerDied(pid_t pid)
301 {
302 AUDIO_INFO_LOG("audio server died, will restore proxy in next call");
303 std::lock_guard<std::mutex> lock(g_audioServerProxyMutex);
304 gAudioServerProxy = nullptr;
305 }
306
Create(const AudioProcessConfig & config)307 std::shared_ptr<AudioProcessInClient> AudioProcessInClient::Create(const AudioProcessConfig &config)
308 {
309 AUDIO_INFO_LOG("Create with config: render flag %{public}d, capturer flag %{public}d, streamType %{public}d.",
310 config.rendererInfo.rendererFlags, config.capturerInfo.capturerFlags, config.streamType);
311 bool ret = AudioProcessInClient::CheckIfSupport(config);
312 CHECK_AND_RETURN_RET_LOG(config.audioMode != AUDIO_MODE_PLAYBACK || ret, nullptr,
313 "CheckIfSupport failed!");
314 sptr<IStandardAudioService> gasp = AudioProcessInClientInner::GetAudioServerProxy();
315 CHECK_AND_RETURN_RET_LOG(gasp != nullptr, nullptr, "Create failed, can not get service.");
316 AudioProcessConfig resetConfig = config;
317 bool isVoipMmap = false;
318 if (config.rendererInfo.streamUsage != STREAM_USAGE_VOICE_COMMUNICATION &&
319 config.capturerInfo.sourceType != SOURCE_TYPE_VOICE_COMMUNICATION) {
320 resetConfig.streamInfo = AudioProcessInClientInner::g_targetStreamInfo;
321 } else {
322 isVoipMmap = true;
323 }
324
325 int32_t errorCode = 0;
326 sptr<IRemoteObject> ipcProxy = gasp->CreateAudioProcess(resetConfig, errorCode);
327 CHECK_AND_RETURN_RET_LOG(errorCode == SUCCESS, nullptr, "failed with create audio stream fail.");
328 CHECK_AND_RETURN_RET_LOG(ipcProxy != nullptr, nullptr, "Create failed with null ipcProxy.");
329 sptr<IAudioProcess> iProcessProxy = iface_cast<IAudioProcess>(ipcProxy);
330 CHECK_AND_RETURN_RET_LOG(iProcessProxy != nullptr, nullptr, "Create failed when iface_cast.");
331 std::shared_ptr<AudioProcessInClientInner> process =
332 std::make_shared<AudioProcessInClientInner>(iProcessProxy, isVoipMmap);
333 if (!process->Init(config)) {
334 AUDIO_ERR_LOG("Init failed!");
335 process = nullptr;
336 }
337
338 return process;
339 }
340
~AudioProcessInClientInner()341 AudioProcessInClientInner::~AudioProcessInClientInner()
342 {
343 AUDIO_INFO_LOG("AudioProcessInClient deconstruct.");
344 if (callbackLoop_.joinable()) {
345 std::unique_lock<std::mutex> lock(loopThreadLock_);
346 isCallbackLoopEnd_ = true; // change it with lock to break the loop
347 threadStatusCV_.notify_all();
348 lock.unlock(); // should call unlock before join
349 callbackLoop_.join();
350 }
351 if (isInited_) {
352 AudioProcessInClientInner::Release();
353 }
354 DumpFileUtil::CloseDumpFile(&dumpFile_);
355 AUDIO_INFO_LOG("[%{public}s] volume data counts: %{public}" PRId64, logUtilsTag_.c_str(), volumeDataCount_);
356 }
357
GetSessionID(uint32_t & sessionID)358 int32_t AudioProcessInClientInner::GetSessionID(uint32_t &sessionID)
359 {
360 sessionID = sessionId_;
361 return SUCCESS;
362 }
363
GetAudioTime(uint32_t & framePos,int64_t & sec,int64_t & nanoSec)364 bool AudioProcessInClientInner::GetAudioTime(uint32_t &framePos, int64_t &sec, int64_t &nanoSec)
365 {
366 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, false, "buffer is null, maybe not inited.");
367 uint64_t pos = 0;
368 if (processConfig_.audioMode == AUDIO_MODE_PLAYBACK) {
369 pos = audioBuffer_->GetCurWriteFrame();
370 } else {
371 pos = audioBuffer_->GetCurReadFrame();
372 }
373
374 if (pos > UINT32_MAX) {
375 framePos = pos % UINT32_MAX;
376 } else {
377 framePos = static_cast<uint32_t>(pos);
378 }
379 int64_t time = handleTimeModel_.GetTimeOfPos(pos);
380 int64_t deltaTime = 20000000; // note: 20ms
381 time += deltaTime;
382
383 sec = time / AUDIO_NS_PER_SECOND;
384 nanoSec = time % AUDIO_NS_PER_SECOND;
385 return true;
386 }
387
GetBufferSize(size_t & bufferSize)388 int32_t AudioProcessInClientInner::GetBufferSize(size_t &bufferSize)
389 {
390 bufferSize = clientSpanSizeInByte_;
391 return SUCCESS;
392 }
393
GetFrameCount(uint32_t & frameCount)394 int32_t AudioProcessInClientInner::GetFrameCount(uint32_t &frameCount)
395 {
396 frameCount = static_cast<uint32_t>(clientSpanSizeInFrame_);
397 AUDIO_INFO_LOG ("GetFrameCount successfully, FrameCount: %{public}u", frameCount);
398 return SUCCESS;
399 }
400
GetLatency(uint64_t & latency)401 int32_t AudioProcessInClientInner::GetLatency(uint64_t &latency)
402 {
403 latency = 20; // 20ms for debug
404 return SUCCESS;
405 }
406
SetVolume(float vol)407 int32_t AudioProcessInClientInner::SetVolume(float vol)
408 {
409 float minVol = 0.0f;
410 float maxVol = 1.0f;
411 CHECK_AND_RETURN_RET_LOG(vol >= minVol && vol <= maxVol, ERR_INVALID_PARAM,
412 "SetVolume failed to with invalid volume:%{public}f", vol);
413 int32_t volumeInt = static_cast<int32_t>(vol * PROCESS_VOLUME_MAX);
414 int32_t ret = SetVolume(volumeInt);
415 if (ret == SUCCESS) {
416 volumeInFloat_ = vol;
417 }
418 return ret;
419 }
420
GetVolume()421 float AudioProcessInClientInner::GetVolume()
422 {
423 return volumeInFloat_;
424 }
425
SetDuckVolume(float vol)426 int32_t AudioProcessInClientInner::SetDuckVolume(float vol)
427 {
428 float minVol = 0.0f;
429 float maxVol = 1.0f;
430 CHECK_AND_RETURN_RET_LOG(vol >= minVol && vol <= maxVol, ERR_INVALID_PARAM,
431 "SetDuckVolume failed to with invalid volume:%{public}f", vol);
432 duckVolumeInFloat_ = vol;
433 return SUCCESS;
434 }
435
GetUnderflowCount()436 uint32_t AudioProcessInClientInner::GetUnderflowCount()
437 {
438 return underflowCount_.load();
439 }
440
GetOverflowCount()441 uint32_t AudioProcessInClientInner::GetOverflowCount()
442 {
443 return overflowCount_.load();
444 }
445
SetUnderflowCount(uint32_t underflowCount)446 void AudioProcessInClientInner::SetUnderflowCount(uint32_t underflowCount)
447 {
448 underflowCount_ += underflowCount;
449 }
450
SetOverflowCount(uint32_t overflowCount)451 void AudioProcessInClientInner::SetOverflowCount(uint32_t overflowCount)
452 {
453 overflowCount_ += overflowCount;
454 }
455
GetFramesWritten()456 int64_t AudioProcessInClientInner::GetFramesWritten()
457 {
458 CHECK_AND_RETURN_RET_LOG(processConfig_.audioMode == AUDIO_MODE_PLAYBACK, -1, "Playback not support.");
459 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, -1, "buffer is null, maybe not inited.");
460 return audioBuffer_->GetCurWriteFrame();
461 }
462
GetFramesRead()463 int64_t AudioProcessInClientInner::GetFramesRead()
464 {
465 CHECK_AND_RETURN_RET_LOG(processConfig_.audioMode == AUDIO_MODE_RECORD, -1, "Record not support.");
466 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, -1, "buffer is null, maybe not inited.");
467 return audioBuffer_->GetCurReadFrame();
468 }
469
SetApplicationCachePath(const std::string & cachePath)470 void AudioProcessInClientInner::SetApplicationCachePath(const std::string &cachePath)
471 {
472 AUDIO_INFO_LOG("Using cachePath:%{public}s", cachePath.c_str());
473 cachePath_ = cachePath;
474 }
475
SetPreferredFrameSize(int32_t frameSize)476 void AudioProcessInClientInner::SetPreferredFrameSize(int32_t frameSize)
477 {
478 size_t originalSpanSizeInFrame = static_cast<size_t>(spanSizeInFrame_);
479 size_t tmp = static_cast<size_t>(frameSize);
480 size_t count = static_cast<size_t>(frameSize) / spanSizeInFrame_;
481 size_t rest = static_cast<size_t>(frameSize) % spanSizeInFrame_;
482 if (tmp <= originalSpanSizeInFrame) {
483 clientSpanSizeInFrame_ = originalSpanSizeInFrame;
484 } else if (tmp >= MAX_TIMES * originalSpanSizeInFrame) {
485 clientSpanSizeInFrame_ = MAX_TIMES * originalSpanSizeInFrame;
486 } else {
487 if (rest <= originalSpanSizeInFrame / DIV) {
488 clientSpanSizeInFrame_ = count * spanSizeInFrame_;
489 } else {
490 count++;
491 clientSpanSizeInFrame_ = count * spanSizeInFrame_;
492 }
493 }
494 if (clientByteSizePerFrame_ == 0) {
495 clientSpanSizeInByte_ = count * spanSizeInByte_;
496 } else {
497 clientSpanSizeInByte_ = clientSpanSizeInFrame_ * clientByteSizePerFrame_;
498 }
499 callbackBuffer_ = std::make_unique<uint8_t[]>(clientSpanSizeInByte_);
500 AUDIO_INFO_LOG("Set preferred callbackBuffer size:%{public}zu", clientSpanSizeInByte_);
501 memset_s(callbackBuffer_.get(), clientSpanSizeInByte_, 0, clientSpanSizeInByte_);
502 }
503
UpdateLatencyTimestamp(std::string & timestamp,bool isRenderer)504 void AudioProcessInClientInner::UpdateLatencyTimestamp(std::string ×tamp, bool isRenderer)
505 {
506 sptr<IStandardAudioService> gasp = AudioProcessInClientInner::GetAudioServerProxy();
507 if (gasp == nullptr) {
508 AUDIO_ERR_LOG("LatencyMeas failed to get AudioServerProxy");
509 return;
510 }
511 gasp->UpdateLatencyTimestamp(timestamp, isRenderer);
512 }
513
InitAudioBuffer()514 bool AudioProcessInClientInner::InitAudioBuffer()
515 {
516 CHECK_AND_RETURN_RET_LOG(processProxy_ != nullptr, false, "Init failed with null ipcProxy.");
517 processCbImpl_ = sptr<ProcessCbImpl>::MakeSptr(shared_from_this());
518 CHECK_AND_RETURN_RET_LOG(processProxy_->RegisterProcessCb(processCbImpl_) == SUCCESS, false,
519 "RegisterProcessCb failed.");
520
521 int32_t ret = processProxy_->ResolveBuffer(audioBuffer_);
522 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && audioBuffer_ != nullptr, false,
523 "Init failed to call ResolveBuffer");
524 streamStatus_ = audioBuffer_->GetStreamStatus();
525 CHECK_AND_RETURN_RET_LOG(streamStatus_ != nullptr, false, "Init failed, access buffer failed.");
526
527 audioBuffer_->GetSizeParameter(totalSizeInFrame_, spanSizeInFrame_, byteSizePerFrame_);
528 spanSizeInByte_ = spanSizeInFrame_ * byteSizePerFrame_;
529 spanSizeInMs_ = spanSizeInFrame_ * MILLISECOND_PER_SECOND / processConfig_.streamInfo.samplingRate;
530
531 clientSpanSizeInByte_ = spanSizeInFrame_ * clientByteSizePerFrame_;
532 clientSpanSizeInFrame_ = spanSizeInFrame_;
533 if ((processConfig_.audioMode != AUDIO_MODE_PLAYBACK) && (!isVoipMmap_)) {
534 clientSpanSizeInByte_ = spanSizeInByte_;
535 }
536
537 AUDIO_INFO_LOG("Using totalSizeInFrame_ %{public}d spanSizeInFrame_ %{public}d byteSizePerFrame_ %{public}d "
538 "spanSizeInByte_ %{public}zu, spanSizeInMs_ %{public}u", totalSizeInFrame_, spanSizeInFrame_,
539 byteSizePerFrame_, spanSizeInByte_, spanSizeInMs_);
540
541 callbackBuffer_ = std::make_unique<uint8_t[]>(clientSpanSizeInByte_);
542 CHECK_AND_RETURN_RET_LOG(callbackBuffer_ != nullptr, false, "Init callbackBuffer_ failed.");
543 memset_s(callbackBuffer_.get(), clientSpanSizeInByte_, 0, clientSpanSizeInByte_);
544 AUDIO_INFO_LOG("CallbackBufferSize is %{public}zu", clientSpanSizeInByte_);
545
546 return true;
547 }
548
GetFormatSize(const AudioStreamInfo & info)549 static size_t GetFormatSize(const AudioStreamInfo &info)
550 {
551 size_t result = 0;
552 size_t bitWidthSize = 0;
553 switch (info.format) {
554 case SAMPLE_U8:
555 bitWidthSize = 1; // size is 1
556 break;
557 case SAMPLE_S16LE:
558 bitWidthSize = 2; // size is 2
559 break;
560 case SAMPLE_S24LE:
561 bitWidthSize = 3; // size is 3
562 break;
563 case SAMPLE_S32LE:
564 bitWidthSize = 4; // size is 4
565 break;
566 default:
567 bitWidthSize = 2; // size is 2
568 break;
569 }
570
571 size_t channelSize = 0;
572 switch (info.channels) {
573 case MONO:
574 channelSize = 1; // size is 1
575 break;
576 case STEREO:
577 channelSize = 2; // size is 2
578 break;
579 default:
580 channelSize = 2; // size is 2
581 break;
582 }
583 result = bitWidthSize * channelSize;
584 return result;
585 }
586
Init(const AudioProcessConfig & config)587 bool AudioProcessInClientInner::Init(const AudioProcessConfig &config)
588 {
589 AUDIO_INFO_LOG("Call Init.");
590 processConfig_ = config;
591 if (!isVoipMmap_ && (config.streamInfo.format != g_targetStreamInfo.format ||
592 config.streamInfo.channels != g_targetStreamInfo.channels)) {
593 needConvert_ = true;
594 }
595 clientByteSizePerFrame_ = GetFormatSize(config.streamInfo);
596
597 AUDIO_DEBUG_LOG("Using clientByteSizePerFrame_:%{public}zu", clientByteSizePerFrame_);
598 bool isBufferInited = InitAudioBuffer();
599 CHECK_AND_RETURN_RET_LOG(isBufferInited, isBufferInited, "%{public}s init audio buffer fail.", __func__);
600
601 bool ret = handleTimeModel_.ConfigSampleRate(processConfig_.streamInfo.samplingRate);
602 CHECK_AND_RETURN_RET_LOG(ret != false, false, "Init LinearPosTimeModel failed.");
603 uint64_t handlePos = 0;
604 int64_t handleTime = 0;
605 audioBuffer_->GetHandleInfo(handlePos, handleTime);
606 handleTimeModel_.ResetFrameStamp(handlePos, handleTime);
607
608 streamStatus_->store(StreamStatus::STREAM_IDEL);
609
610 AudioBufferHolder bufferHolder = audioBuffer_->GetBufferHolder();
611 bool isIndependent = bufferHolder == AudioBufferHolder::AUDIO_SERVER_INDEPENDENT;
612 if (config.audioMode == AUDIO_MODE_RECORD) {
613 logUtilsTag_ = "ProcessRec::" + std::to_string(sessionId_);
614 callbackLoop_ = std::thread([this] { this->RecordProcessCallbackFuc(); });
615 pthread_setname_np(callbackLoop_.native_handle(), "OS_AudioRecCb");
616 } else if (isIndependent) {
617 logUtilsTag_ = "ProcessPlay::" + std::to_string(sessionId_);
618 callbackLoop_ = std::thread([this] { this->ProcessCallbackFucIndependent(); });
619 pthread_setname_np(callbackLoop_.native_handle(), "OS_AudioPlayCb");
620 } else {
621 logUtilsTag_ = "ProcessPlay::" + std::to_string(sessionId_);
622 callbackLoop_ = std::thread([this] { this->ProcessCallbackFuc(); });
623 pthread_setname_np(callbackLoop_.native_handle(), "OS_AudioPlayCb");
624 }
625
626 int waitThreadStartTime = 5; // wait for thread start.
627 while (threadStatus_.load() == INVALID) {
628 AUDIO_DEBUG_LOG("%{public}s wait %{public}d ms for %{public}s started...", __func__, waitThreadStartTime,
629 config.audioMode == AUDIO_MODE_RECORD ? "RecordProcessCallbackFuc" : "ProcessCallbackFuc");
630 ClockTime::RelativeSleep(ONE_MILLISECOND_DURATION * waitThreadStartTime);
631 }
632
633 isInited_ = true;
634 return true;
635 }
636
SaveDataCallback(const std::shared_ptr<AudioDataCallback> & dataCallback)637 int32_t AudioProcessInClientInner::SaveDataCallback(const std::shared_ptr<AudioDataCallback> &dataCallback)
638 {
639 AUDIO_INFO_LOG("%{public}s enter.", __func__);
640 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
641
642 CHECK_AND_RETURN_RET_LOG(dataCallback != nullptr, ERR_INVALID_PARAM,
643 "data callback is null.");
644 audioDataCallback_ = dataCallback;
645 return SUCCESS;
646 }
647
SaveUnderrunCallback(const std::shared_ptr<ClientUnderrunCallBack> & underrunCallback)648 int32_t AudioProcessInClientInner::SaveUnderrunCallback(const std::shared_ptr<ClientUnderrunCallBack> &underrunCallback)
649 {
650 AUDIO_INFO_LOG("%{public}s enter.", __func__);
651 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
652
653 CHECK_AND_RETURN_RET_LOG(underrunCallback != nullptr, ERR_INVALID_PARAM,
654 "underrun callback is null.");
655 underrunCallback_ = underrunCallback;
656 return SUCCESS;
657 }
658
ReadFromProcessClient() const659 int32_t AudioProcessInClientInner::ReadFromProcessClient() const
660 {
661 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, ERR_INVALID_HANDLE,
662 "%{public}s audio buffer is null.", __func__);
663 uint64_t curReadPos = audioBuffer_->GetCurReadFrame();
664 Trace trace("AudioProcessInClient::ReadProcessData-<" + std::to_string(curReadPos));
665 BufferDesc readbufDesc = {nullptr, 0, 0};
666 int32_t ret = audioBuffer_->GetReadbuffer(curReadPos, readbufDesc);
667 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && readbufDesc.buffer != nullptr &&
668 readbufDesc.bufLength == spanSizeInByte_ && readbufDesc.dataLength == spanSizeInByte_,
669 ERR_OPERATION_FAILED, "get client mmap read buffer failed, ret %{public}d.", ret);
670 ret = memcpy_s(static_cast<void *>(callbackBuffer_.get()), spanSizeInByte_,
671 static_cast<void *>(readbufDesc.buffer), spanSizeInByte_);
672 CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_OPERATION_FAILED, "%{public}s memcpy fail, ret %{public}d,"
673 " spanSizeInByte %{public}zu.", __func__, ret, spanSizeInByte_);
674 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(readbufDesc.buffer), spanSizeInByte_);
675 DfxOperation(readbufDesc, processConfig_.streamInfo.format, processConfig_.streamInfo.channels);
676
677 ret = memset_s(readbufDesc.buffer, readbufDesc.bufLength, 0, readbufDesc.bufLength);
678 if (ret != EOK) {
679 AUDIO_WARNING_LOG("reset buffer fail, ret %{public}d.", ret);
680 }
681 return SUCCESS;
682 }
683
684 // the buffer will be used by client
GetBufferDesc(BufferDesc & bufDesc) const685 int32_t AudioProcessInClientInner::GetBufferDesc(BufferDesc &bufDesc) const
686 {
687 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "%{public}s not inited!", __func__);
688 Trace trace("AudioProcessInClient::GetBufferDesc");
689
690 if (processConfig_.audioMode == AUDIO_MODE_RECORD) {
691 ReadFromProcessClient();
692 }
693
694 bufDesc.buffer = callbackBuffer_.get();
695 bufDesc.dataLength = clientSpanSizeInByte_;
696 bufDesc.bufLength = clientSpanSizeInByte_;
697 return SUCCESS;
698 }
699
CheckIfSupport(const AudioProcessConfig & config)700 bool AudioProcessInClient::CheckIfSupport(const AudioProcessConfig &config)
701 {
702 if (config.rendererInfo.streamUsage == STREAM_USAGE_VOICE_COMMUNICATION ||
703 config.capturerInfo.sourceType == SOURCE_TYPE_VOICE_COMMUNICATION) {
704 return true;
705 }
706
707 if (config.streamInfo.samplingRate != SAMPLE_RATE_48000) {
708 return false;
709 }
710
711 if (config.streamInfo.encoding != ENCODING_PCM) {
712 return false;
713 }
714
715 if (config.streamInfo.format != SAMPLE_S16LE && config.streamInfo.format != SAMPLE_S32LE) {
716 return false;
717 }
718
719 if (config.streamInfo.channels != MONO && config.streamInfo.channels != STEREO) {
720 return false;
721 }
722 return true;
723 }
724
S16MonoToS16Stereo(const BufferDesc & srcDesc,const BufferDesc & dstDesc)725 inline bool S16MonoToS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc)
726 {
727 size_t half = 2;
728 if (srcDesc.bufLength != dstDesc.bufLength / half || srcDesc.buffer == nullptr || dstDesc.buffer == nullptr) {
729 return false;
730 }
731 int16_t *stcPtr = reinterpret_cast<int16_t *>(srcDesc.buffer);
732 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstDesc.buffer);
733 size_t count = srcDesc.bufLength / half;
734 for (size_t idx = 0; idx < count; idx++) {
735 *(dstPtr++) = *stcPtr;
736 *(dstPtr++) = *stcPtr++;
737 }
738 return true;
739 }
740
S32MonoToS16Stereo(const BufferDesc & srcDesc,const BufferDesc & dstDesc)741 inline bool S32MonoToS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc)
742 {
743 size_t quarter = 4;
744 if (srcDesc.bufLength != dstDesc.bufLength || srcDesc.buffer == nullptr || dstDesc.buffer == nullptr ||
745 srcDesc.bufLength % quarter != 0) {
746 return false;
747 }
748 int32_t *stcPtr = reinterpret_cast<int32_t *>(srcDesc.buffer);
749 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstDesc.buffer);
750 size_t count = srcDesc.bufLength / quarter;
751
752 double maxInt32 = INT32_MAX;
753 double maxInt16 = INT16_MAX;
754 for (size_t idx = 0; idx < count; idx++) {
755 int16_t temp = static_cast<int16_t>((static_cast<double>(*stcPtr) / maxInt32) * maxInt16);
756 stcPtr++;
757 *(dstPtr++) = temp;
758 *(dstPtr++) = temp;
759 }
760 return true;
761 }
762
S32StereoS16Stereo(const BufferDesc & srcDesc,const BufferDesc & dstDesc)763 inline bool S32StereoS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc)
764 {
765 size_t half = 2;
766 if (srcDesc.bufLength / half != dstDesc.bufLength || srcDesc.buffer == nullptr || dstDesc.buffer == nullptr ||
767 dstDesc.bufLength % half != 0) {
768 return false;
769 }
770 int32_t *stcPtr = reinterpret_cast<int32_t *>(srcDesc.buffer);
771 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstDesc.buffer);
772 size_t count = srcDesc.bufLength / half / half;
773 double maxInt32 = INT32_MAX;
774 double maxInt16 = INT16_MAX;
775 for (size_t idx = 0; idx < count; idx++) {
776 int16_t temp = static_cast<int16_t>((static_cast<double>(*stcPtr) / maxInt32) * maxInt16);
777 stcPtr++;
778 *(dstPtr++) = temp;
779 }
780 return true;
781 }
782
783 // only support MONO to STEREO and SAMPLE_S32LE to SAMPLE_S16LE
ChannelFormatConvert(const AudioStreamData & srcData,const AudioStreamData & dstData)784 bool AudioProcessInClientInner::ChannelFormatConvert(const AudioStreamData &srcData, const AudioStreamData &dstData)
785 {
786 if (srcData.streamInfo.samplingRate != dstData.streamInfo.samplingRate ||
787 srcData.streamInfo.encoding != dstData.streamInfo.encoding) {
788 return false;
789 }
790 if (srcData.streamInfo.format == SAMPLE_S16LE && srcData.streamInfo.channels == STEREO) {
791 return true; // no need convert
792 }
793 if (srcData.streamInfo.format == SAMPLE_S16LE && srcData.streamInfo.channels == MONO) {
794 return S16MonoToS16Stereo(srcData.bufferDesc, dstData.bufferDesc);
795 }
796 if (srcData.streamInfo.format == SAMPLE_S32LE && srcData.streamInfo.channels == MONO) {
797 return S32MonoToS16Stereo(srcData.bufferDesc, dstData.bufferDesc);
798 }
799 if (srcData.streamInfo.format == SAMPLE_S32LE && srcData.streamInfo.channels == STEREO) {
800 return S32StereoS16Stereo(srcData.bufferDesc, dstData.bufferDesc);
801 }
802
803 return false;
804 }
805
CopyWithVolume(const BufferDesc & srcDesc,const BufferDesc & dstDesc) const806 void AudioProcessInClientInner::CopyWithVolume(const BufferDesc &srcDesc, const BufferDesc &dstDesc) const
807 {
808 size_t len = dstDesc.dataLength;
809 len /= 2; // SAMPLE_S16LE--> 2 byte
810 int16_t *dstPtr = reinterpret_cast<int16_t *>(dstDesc.buffer);
811 for (size_t pos = 0; len > 0; len--) {
812 int32_t sum = 0;
813 int16_t *srcPtr = reinterpret_cast<int16_t *>(srcDesc.buffer) + pos;
814 sum += (*srcPtr * static_cast<int64_t>(processVolume_ * duckVolumeInFloat_)) >> VOLUME_SHIFT_NUMBER; // 1/65536
815 pos++;
816 *dstPtr++ = sum > INT16_MAX ? INT16_MAX : (sum < INT16_MIN ? INT16_MIN : sum);
817 }
818 }
819
ProcessVolume(const AudioStreamData & targetData) const820 void AudioProcessInClientInner::ProcessVolume(const AudioStreamData &targetData) const
821 {
822 size_t half = 2;
823 size_t len = targetData.bufferDesc.dataLength;
824 len /= half;
825 int16_t *dstPtr = reinterpret_cast<int16_t *>(targetData.bufferDesc.buffer);
826 for (; len > 0; len--) {
827 int32_t sum = 0;
828 sum += (*dstPtr * static_cast<int64_t>(processVolume_ * duckVolumeInFloat_)) >> VOLUME_SHIFT_NUMBER;
829 *dstPtr++ = sum > INT16_MAX ? INT16_MAX : (sum < INT16_MIN ? INT16_MIN : sum);
830 }
831 }
832
ProcessData(const BufferDesc & srcDesc,const BufferDesc & dstDesc) const833 int32_t AudioProcessInClientInner::ProcessData(const BufferDesc &srcDesc, const BufferDesc &dstDesc) const
834 {
835 int32_t ret = 0;
836 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
837 size_t offSet = clientSpanSizeInByte_ / round;
838 if (!needConvert_) {
839 AudioBufferHolder bufferHolder = audioBuffer_->GetBufferHolder();
840 if (bufferHolder == AudioBufferHolder::AUDIO_SERVER_INDEPENDENT) {
841 CopyWithVolume(srcDesc, dstDesc);
842 } else {
843 ret = memcpy_s(static_cast<void *>(dstDesc.buffer), spanSizeInByte_,
844 static_cast<void *>(srcDesc.buffer), offSet);
845 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_OPERATION_FAILED, "Copy data failed!");
846 }
847 } else {
848 Trace traceConvert("APIC::FormatConvert");
849 AudioStreamData srcData = {processConfig_.streamInfo, srcDesc, 0, 0};
850 AudioStreamData dstData = {g_targetStreamInfo, dstDesc, 0, 0};
851 bool succ = ChannelFormatConvert(srcData, dstData);
852 CHECK_AND_RETURN_RET_LOG(succ, ERR_OPERATION_FAILED, "Convert data failed!");
853 AudioBufferHolder bufferHolder = audioBuffer_->GetBufferHolder();
854 if (bufferHolder == AudioBufferHolder::AUDIO_SERVER_INDEPENDENT) {
855 ProcessVolume(dstData);
856 }
857 }
858 return SUCCESS;
859 }
860
Enqueue(const BufferDesc & bufDesc) const861 int32_t AudioProcessInClientInner::Enqueue(const BufferDesc &bufDesc) const
862 {
863 Trace trace("AudioProcessInClient::Enqueue");
864 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
865
866 CHECK_AND_RETURN_RET_LOG(bufDesc.buffer != nullptr && bufDesc.bufLength == clientSpanSizeInByte_ &&
867 bufDesc.dataLength == clientSpanSizeInByte_, ERR_INVALID_PARAM,
868 "bufDesc error, bufLen %{public}zu, dataLen %{public}zu, spanSize %{public}zu.",
869 bufDesc.bufLength, bufDesc.dataLength, clientSpanSizeInByte_);
870 // check if this buffer is form us.
871 if (bufDesc.buffer != callbackBuffer_.get()) {
872 AUDIO_WARNING_LOG("the buffer is not created by client.");
873 }
874
875 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
876 uint64_t curWritePos = audioBuffer_->GetCurWriteFrame();
877 for (size_t count = 0 ; count < round ; count++) {
878 BufferDesc curCallbackBuffer = {nullptr, 0, 0};
879 size_t offSet = clientSpanSizeInByte_ / round;
880 curCallbackBuffer.buffer = bufDesc.buffer + count * offSet;
881 curCallbackBuffer.bufLength = offSet;
882 curCallbackBuffer.dataLength = offSet;
883 uint64_t curPos = curWritePos + count * spanSizeInFrame_;
884 if (processConfig_.audioMode == AUDIO_MODE_PLAYBACK) {
885 BufferDesc curWriteBuffer = {nullptr, 0, 0};
886 Trace writeProcessDataTrace("AudioProcessInClient::WriteProcessData->" + std::to_string(curPos));
887 int32_t ret = audioBuffer_->GetWriteBuffer(curPos, curWriteBuffer);
888 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS && curWriteBuffer.buffer != nullptr &&
889 curWriteBuffer.bufLength == spanSizeInByte_ && curWriteBuffer.dataLength == spanSizeInByte_,
890 ERR_OPERATION_FAILED, "get write buffer fail, ret:%{public}d", ret);
891 ret = ProcessData(curCallbackBuffer, curWriteBuffer);
892 if (ret != SUCCESS) {
893 return ERR_OPERATION_FAILED;
894 }
895 writeProcessDataTrace.End();
896
897 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(curCallbackBuffer.buffer), offSet);
898 DfxOperation(curCallbackBuffer, processConfig_.streamInfo.format, processConfig_.streamInfo.channels);
899 }
900 }
901
902 if (memset_s(callbackBuffer_.get(), clientSpanSizeInByte_, 0, clientSpanSizeInByte_) != EOK) {
903 AUDIO_WARNING_LOG("reset callback buffer fail.");
904 }
905
906 return SUCCESS;
907 }
908
DfxOperation(BufferDesc & buffer,AudioSampleFormat format,AudioChannel channel) const909 void AudioProcessInClientInner::DfxOperation(BufferDesc &buffer, AudioSampleFormat format, AudioChannel channel) const
910 {
911 ChannelVolumes vols = VolumeTools::CountVolumeLevel(buffer, format, channel);
912 if (channel == MONO) {
913 Trace::Count(logUtilsTag_, vols.volStart[0]);
914 } else {
915 Trace::Count(logUtilsTag_, (vols.volStart[0] + vols.volStart[1]) / HALF_FACTOR);
916 }
917 AudioLogUtils::ProcessVolumeData(logUtilsTag_, vols, volumeDataCount_);
918 }
919
SetVolume(int32_t vol)920 int32_t AudioProcessInClientInner::SetVolume(int32_t vol)
921 {
922 AUDIO_INFO_LOG("proc client mode %{public}d to %{public}d.", processConfig_.audioMode, vol);
923 Trace trace("AudioProcessInClient::SetVolume " + std::to_string(vol));
924 CHECK_AND_RETURN_RET_LOG(vol >= 0 && vol <= PROCESS_VOLUME_MAX, ERR_INVALID_PARAM,
925 "SetVolume failed, invalid volume:%{public}d", vol);
926 processVolume_ = vol;
927 return SUCCESS;
928 }
929
Start()930 int32_t AudioProcessInClientInner::Start()
931 {
932 Trace traceStart("AudioProcessInClient::Start");
933 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
934
935 const auto [samplingRate, encoding, format, channels, channelLayout] = processConfig_.streamInfo;
936 // eg: 100005_dump_process_client_audio_48000_2_1.pcm
937 std::string dumpFileName = std::to_string(sessionId_) + "_dump_process_client_audio_" +
938 std::to_string(samplingRate) + '_' + std::to_string(channels) + '_' + std::to_string(format) +
939 ".pcm";
940 DumpFileUtil::OpenDumpFile(DUMP_CLIENT_PARA, dumpFileName, &dumpFile_);
941
942 std::lock_guard<std::mutex> lock(statusSwitchLock_);
943 if (streamStatus_->load() == StreamStatus::STREAM_RUNNING) {
944 AUDIO_INFO_LOG("Start find already started");
945 return SUCCESS;
946 }
947
948 startFadein_.store(true);
949 StreamStatus targetStatus = StreamStatus::STREAM_IDEL;
950 bool ret = streamStatus_->compare_exchange_strong(targetStatus, StreamStatus::STREAM_STARTING);
951 if (!ret) {
952 startFadein_.store(false);
953 }
954 CHECK_AND_RETURN_RET_LOG(
955 ret, ERR_ILLEGAL_STATE, "Start failed, invalid status: %{public}s", GetStatusInfo(targetStatus).c_str());
956
957 if (processProxy_->Start() != SUCCESS) {
958 streamStatus_->store(StreamStatus::STREAM_IDEL);
959 AUDIO_ERR_LOG("Start failed to call process proxy, reset status to IDEL.");
960 startFadein_.store(false);
961 threadStatusCV_.notify_all();
962 return ERR_OPERATION_FAILED;
963 }
964 UpdateHandleInfo();
965 streamStatus_->store(StreamStatus::STREAM_RUNNING);
966 threadStatusCV_.notify_all();
967 return SUCCESS;
968 }
969
Pause(bool isFlush)970 int32_t AudioProcessInClientInner::Pause(bool isFlush)
971 {
972 Trace tracePause("AudioProcessInClient::Pause");
973 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
974
975 std::lock_guard<std::mutex> lock(statusSwitchLock_);
976 if (streamStatus_->load() == StreamStatus::STREAM_PAUSED) {
977 AUDIO_INFO_LOG("Pause find already paused");
978 return SUCCESS;
979 }
980 startFadeout_.store(true);
981 StreamStatus targetStatus = StreamStatus::STREAM_RUNNING;
982 bool ret = streamStatus_->compare_exchange_strong(targetStatus, StreamStatus::STREAM_PAUSING);
983 if (!ret) {
984 startFadeout_.store(false);
985 }
986 CHECK_AND_RETURN_RET_LOG(
987 ret, ERR_ILLEGAL_STATE, "Pause failed, invalid status : %{public}s", GetStatusInfo(targetStatus).c_str());
988 ClockTime::RelativeSleep(MAX_STOP_FADING_DURATION_NANO);
989 if (processProxy_->Pause(isFlush) != SUCCESS) {
990 streamStatus_->store(StreamStatus::STREAM_RUNNING);
991 AUDIO_ERR_LOG("Pause failed to call process proxy, reset status to RUNNING");
992 startFadeout_.store(false);
993 threadStatusCV_.notify_all(); // avoid thread blocking with status PAUSING
994 return ERR_OPERATION_FAILED;
995 }
996 startFadeout_.store(false);
997 streamStatus_->store(StreamStatus::STREAM_PAUSED);
998
999 lastPausedTime_ = ClockTime::GetCurNano();
1000
1001 return SUCCESS;
1002 }
1003
Resume()1004 int32_t AudioProcessInClientInner::Resume()
1005 {
1006 Trace traceResume("AudioProcessInClient::Resume");
1007 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
1008 std::lock_guard<std::mutex> lock(statusSwitchLock_);
1009
1010 if (streamStatus_->load() == StreamStatus::STREAM_RUNNING) {
1011 AUDIO_INFO_LOG("Resume find already running");
1012 return SUCCESS;
1013 }
1014
1015 startFadein_.store(true);
1016
1017 StreamStatus pausedStatus = StreamStatus::STREAM_PAUSED;
1018 StreamStatus stoppedStatus = StreamStatus::STREAM_STOPPED;
1019 if (!streamStatus_->compare_exchange_strong(pausedStatus, StreamStatus::STREAM_STARTING) &&
1020 !streamStatus_->compare_exchange_strong(stoppedStatus, StreamStatus::STREAM_STARTING)) {
1021 startFadein_.store(false);
1022 AUDIO_ERR_LOG("Resume failed, invalid status : %{public}s", GetStatusInfo(stoppedStatus).c_str());
1023 return ERR_ILLEGAL_STATE;
1024 }
1025
1026 if (processProxy_->Resume() != SUCCESS) {
1027 streamStatus_->store(StreamStatus::STREAM_PAUSED);
1028 AUDIO_ERR_LOG("Resume failed to call process proxy, reset status to PAUSED.");
1029 startFadein_.store(false);
1030 threadStatusCV_.notify_all();
1031 return ERR_OPERATION_FAILED;
1032 }
1033
1034 if (ClockTime::GetCurNano() - lastPausedTime_ > DELAY_RESYNC_TIME) {
1035 UpdateHandleInfo(false, true);
1036 lastPausedTime_ = INT64_MAX;
1037 } else {
1038 UpdateHandleInfo();
1039 }
1040
1041 streamStatus_->store(StreamStatus::STREAM_RUNNING);
1042 threadStatusCV_.notify_all();
1043
1044 return SUCCESS;
1045 }
1046
Stop()1047 int32_t AudioProcessInClientInner::Stop()
1048 {
1049 Trace traceStop("AudioProcessInClient::Stop");
1050 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
1051 std::lock_guard<std::mutex> lock(statusSwitchLock_);
1052 if (streamStatus_->load() == StreamStatus::STREAM_STOPPED) {
1053 AUDIO_INFO_LOG("Stop find already stopped");
1054 return SUCCESS;
1055 }
1056
1057 StreamStatus oldStatus = streamStatus_->load();
1058 CHECK_AND_RETURN_RET_LOG(oldStatus != STREAM_IDEL && oldStatus != STREAM_RELEASED && oldStatus != STREAM_INVALID,
1059 ERR_ILLEGAL_STATE, "Stop failed, invalid status : %{public}s", GetStatusInfo(oldStatus).c_str());
1060 if (oldStatus == STREAM_STARTING || oldStatus == STREAM_RUNNING) {
1061 startFadeout_.store(true);
1062 }
1063 streamStatus_->store(StreamStatus::STREAM_STOPPING);
1064
1065 ClockTime::RelativeSleep(MAX_STOP_FADING_DURATION_NANO);
1066
1067 if (processProxy_->Stop() != SUCCESS) {
1068 streamStatus_->store(oldStatus);
1069 AUDIO_ERR_LOG("Stop failed in server, reset status to %{public}s", GetStatusInfo(oldStatus).c_str());
1070 startFadeout_.store(false);
1071 threadStatusCV_.notify_all(); // avoid thread blocking with status RUNNING
1072 return ERR_OPERATION_FAILED;
1073 }
1074 startFadeout_.store(false);
1075 streamStatus_->store(StreamStatus::STREAM_STOPPED);
1076 AUDIO_INFO_LOG("Success stop proc client mode %{public}d form %{public}s.",
1077 processConfig_.audioMode, GetStatusInfo(oldStatus).c_str());
1078 return SUCCESS;
1079 }
1080
Release(bool isSwitchStream)1081 int32_t AudioProcessInClientInner::Release(bool isSwitchStream)
1082 {
1083 Trace traceRelease("AudioProcessInClient::Release");
1084 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
1085 AUDIO_INFO_LOG("AudioProcessInClientInner::Release()");
1086 // not lock as status is already released
1087 if (streamStatus_->load() == StreamStatus::STREAM_RELEASED) {
1088 AUDIO_INFO_LOG("Stream status is already released");
1089 return SUCCESS;
1090 }
1091 Stop();
1092 isCallbackLoopEnd_ = true;
1093 threadStatusCV_.notify_all();
1094 std::lock_guard<std::mutex> lock(statusSwitchLock_);
1095 StreamStatus currentStatus = streamStatus_->load();
1096 if (currentStatus != STREAM_STOPPED) {
1097 AUDIO_WARNING_LOG("Release in currentStatus:%{public}s", GetStatusInfo(currentStatus).c_str());
1098 }
1099
1100 if (processProxy_->Release(isSwitchStream) != SUCCESS) {
1101 AUDIO_ERR_LOG("Release may failed in server");
1102 threadStatusCV_.notify_all(); // avoid thread blocking with status RUNNING
1103 return ERR_OPERATION_FAILED;
1104 }
1105
1106 streamStatus_->store(StreamStatus::STREAM_RELEASED);
1107 AUDIO_INFO_LOG("Success release proc client mode %{public}d.", processConfig_.audioMode);
1108 isInited_ = false;
1109 return SUCCESS;
1110 }
1111
1112 // client should call GetBufferDesc and Enqueue in OnHandleData
CallClientHandleCurrent()1113 void AudioProcessInClientInner::CallClientHandleCurrent()
1114 {
1115 Trace trace("AudioProcessInClient::CallClientHandleCurrent");
1116 std::shared_ptr<AudioDataCallback> cb = audioDataCallback_.lock();
1117 CHECK_AND_RETURN_LOG(cb != nullptr, "audio data callback is null.");
1118
1119 int64_t stamp = ClockTime::GetCurNano();
1120 cb->OnHandleData(clientSpanSizeInByte_);
1121 stamp = ClockTime::GetCurNano() - stamp;
1122 if (stamp > MAX_WRITE_COST_DURATION_NANO) {
1123 AUDIO_PRERELEASE_LOGW("Client write cost too long...");
1124 if (processConfig_.audioMode == AUDIO_MODE_PLAYBACK) {
1125 underflowCount_++;
1126 } else {
1127 overflowCount_++;
1128 }
1129 // todo
1130 // handle write time out: send underrun msg to client, reset time model with latest server handle time.
1131 }
1132 if (stamp > THREE_MILLISECOND_DURATION) {
1133 AUDIO_WARNING_LOG("Client handle callback too slow, cost %{public}" PRId64"us", stamp / AUDIO_MS_PER_SECOND);
1134 return;
1135 }
1136 }
1137
UpdateHandleInfo(bool isAysnc,bool resetReadWritePos)1138 void AudioProcessInClientInner::UpdateHandleInfo(bool isAysnc, bool resetReadWritePos)
1139 {
1140 Trace traceSync("AudioProcessInClient::UpdateHandleInfo");
1141 uint64_t serverHandlePos = 0;
1142 int64_t serverHandleTime = 0;
1143 int32_t ret = processProxy_->RequestHandleInfo(isAysnc);
1144 CHECK_AND_RETURN_LOG(ret == SUCCESS, "RequestHandleInfo failed ret:%{public}d", ret);
1145 audioBuffer_->GetHandleInfo(serverHandlePos, serverHandleTime);
1146
1147 bool isSuccess = handleTimeModel_.UpdataFrameStamp(serverHandlePos, serverHandleTime);
1148 if (!isSuccess) {
1149 handleTimeModel_.ResetFrameStamp(serverHandlePos, serverHandleTime);
1150 }
1151
1152 if (resetReadWritePos) {
1153 uint64_t nextWritePos = serverHandlePos + spanSizeInFrame_;
1154 ResetAudioBuffer();
1155 ret = audioBuffer_->ResetCurReadWritePos(nextWritePos, nextWritePos);
1156 CHECK_AND_RETURN_LOG(ret == SUCCESS, "ResetCurReadWritePos failed ret:%{public}d", ret);
1157 }
1158 }
1159
ResetAudioBuffer()1160 void AudioProcessInClientInner::ResetAudioBuffer()
1161 {
1162 CHECK_AND_RETURN_LOG((audioBuffer_ != nullptr), "%{public}s: audio buffer is null.", __func__);
1163
1164 uint32_t spanCount = audioBuffer_->GetSpanCount();
1165 for (uint32_t i = 0; i < spanCount; i++) {
1166 SpanInfo *spanInfo = audioBuffer_->GetSpanInfoByIndex(i);
1167 if (spanInfo == nullptr) {
1168 AUDIO_ERR_LOG("ResetAudiobuffer failed.");
1169 return;
1170 }
1171 spanInfo->spanStatus = SPAN_READ_DONE;
1172 spanInfo->offsetInFrame = 0;
1173
1174 spanInfo->readStartTime = 0;
1175 spanInfo->readDoneTime = 0;
1176
1177 spanInfo->writeStartTime = 0;
1178 spanInfo->writeDoneTime = 0;
1179
1180 spanInfo->volumeStart = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
1181 spanInfo->volumeEnd = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
1182 spanInfo->isMute = false;
1183 }
1184 return;
1185 }
1186
GetPredictNextHandleTime(uint64_t posInFrame,bool isIndependent)1187 int64_t AudioProcessInClientInner::GetPredictNextHandleTime(uint64_t posInFrame, bool isIndependent)
1188 {
1189 Trace trace("AudioProcessInClient::GetPredictNextRead");
1190 CHECK_AND_RETURN_RET_LOG(spanSizeInFrame_ != 0, 0, "spanSizeInFrame is 0.");
1191 uint64_t handleSpanCnt = 0;
1192 if (spanSizeInFrame_ != 0) {
1193 handleSpanCnt = posInFrame / spanSizeInFrame_;
1194 }
1195 uint32_t startPeriodCnt = 20; // sync each time when start
1196 uint32_t oneBigPeriodCnt = 40; // 200ms
1197 if (isIndependent) {
1198 if (handleSpanCnt % oneBigPeriodCnt == 0) {
1199 UpdateHandleInfo(true);
1200 }
1201 } else {
1202 if (handleSpanCnt < startPeriodCnt || handleSpanCnt % oneBigPeriodCnt == 0) {
1203 UpdateHandleInfo();
1204 }
1205 }
1206
1207 int64_t nextHandleTime = handleTimeModel_.GetTimeOfPos(posInFrame);
1208
1209 return nextHandleTime;
1210 }
1211
PrepareNext(uint64_t curHandPos,int64_t & wakeUpTime)1212 bool AudioProcessInClientInner::PrepareNext(uint64_t curHandPos, int64_t &wakeUpTime)
1213 {
1214 Trace trace("AudioProcessInClient::PrepareNext " + std::to_string(curHandPos));
1215 int64_t handleModifyTime = 0;
1216 if (processConfig_.audioMode == AUDIO_MODE_RECORD) {
1217 handleModifyTime = RECORD_HANDLE_DELAY_NANO;
1218 } else {
1219 handleModifyTime = -WRITE_BEFORE_DURATION_NANO;
1220 }
1221
1222 int64_t nextServerHandleTime = GetPredictNextHandleTime(curHandPos) + handleModifyTime;
1223 if (nextServerHandleTime < ClockTime::GetCurNano()) {
1224 wakeUpTime = ClockTime::GetCurNano() + ONE_MILLISECOND_DURATION; // make sure less than duration
1225 } else {
1226 wakeUpTime = nextServerHandleTime;
1227 }
1228 AUDIO_DEBUG_LOG("%{public}s end, audioMode %{public}d, curReadPos %{public}" PRIu64", nextServerHandleTime "
1229 "%{public}" PRId64" wakeUpTime %{public}" PRId64".", __func__, processConfig_.audioMode, curHandPos,
1230 nextServerHandleTime, wakeUpTime);
1231 return true;
1232 }
1233
ClientPrepareNextLoop(uint64_t curWritePos,int64_t & wakeUpTime)1234 bool AudioProcessInClientInner::ClientPrepareNextLoop(uint64_t curWritePos, int64_t &wakeUpTime)
1235 {
1236 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1237 for (size_t count = 0; count < round; count++) {
1238 bool ret = PrepareNext(curWritePos + count * spanSizeInFrame_, wakeUpTime);
1239 CHECK_AND_RETURN_RET_LOG(ret, false, "PrepareNextLoop in process failed!");
1240 }
1241 return true;
1242 }
1243
CallExitStandBy()1244 void AudioProcessInClientInner::CallExitStandBy()
1245 {
1246 Trace trace("AudioProcessInClient::CallExitStandBy::" + std::to_string(sessionId_));
1247 int32_t result = processProxy_->Start();
1248 StreamStatus targetStatus = StreamStatus::STREAM_STARTING;
1249 bool ret = streamStatus_->compare_exchange_strong(targetStatus, StreamStatus::STREAM_RUNNING);
1250 AUDIO_INFO_LOG("Call start result:%{public}d status change: %{public}s", result, ret ? "success" : "fail");
1251 UpdateHandleInfo();
1252 }
1253
GetStatusInfo(StreamStatus status)1254 std::string AudioProcessInClientInner::GetStatusInfo(StreamStatus status)
1255 {
1256 switch (status) {
1257 case STREAM_IDEL:
1258 return "STREAM_IDEL";
1259 case STREAM_STARTING:
1260 return "STREAM_STARTING";
1261 case STREAM_RUNNING:
1262 return "STREAM_RUNNING";
1263 case STREAM_PAUSING:
1264 return "STREAM_PAUSING";
1265 case STREAM_PAUSED:
1266 return "STREAM_PAUSED";
1267 case STREAM_STOPPING:
1268 return "STREAM_STOPPING";
1269 case STREAM_STOPPED:
1270 return "STREAM_STOPPED";
1271 case STREAM_RELEASED:
1272 return "STREAM_RELEASED";
1273 case STREAM_INVALID:
1274 return "STREAM_INVALID";
1275 default:
1276 break;
1277 }
1278 return "NO_SUCH_STATUS";
1279 }
1280
KeepLoopRunning()1281 bool AudioProcessInClientInner::KeepLoopRunning()
1282 {
1283 StreamStatus targetStatus = STREAM_INVALID;
1284
1285 switch (streamStatus_->load()) {
1286 case STREAM_RUNNING:
1287 return true;
1288 case STREAM_STAND_BY:
1289 AUDIO_INFO_LOG("Status is STAND_BY, let's call exit!");
1290 CallExitStandBy();
1291 return true;
1292 case STREAM_STARTING:
1293 targetStatus = STREAM_RUNNING;
1294 break;
1295 case STREAM_IDEL:
1296 targetStatus = STREAM_STARTING;
1297 break;
1298 case STREAM_PAUSING:
1299 targetStatus = STREAM_PAUSED;
1300 break;
1301 case STREAM_PAUSED:
1302 targetStatus = STREAM_STARTING;
1303 break;
1304 case STREAM_STOPPING:
1305 targetStatus = STREAM_STOPPED;
1306 break;
1307 case STREAM_STOPPED:
1308 targetStatus = STREAM_RELEASED;
1309 break;
1310 default:
1311 break;
1312 }
1313
1314 if (startFadeout_.load() &&
1315 (targetStatus == STREAM_PAUSED || targetStatus == STREAM_STOPPED || targetStatus == STREAM_RELEASED)) {
1316 // do one more time to prepare fade out span buffer
1317 return true;
1318 }
1319
1320 Trace trace("AudioProcessInClient::InWaitStatus");
1321 std::unique_lock<std::mutex> lock(loopThreadLock_);
1322 AUDIO_DEBUG_LOG("Process status is %{public}s now, wait for %{public}s...",
1323 GetStatusInfo(streamStatus_->load()).c_str(), GetStatusInfo(targetStatus).c_str());
1324 threadStatus_ = WAITTING;
1325 threadStatusCV_.wait(lock);
1326 AUDIO_DEBUG_LOG("Process wait end. Cur is %{public}s now, target is %{public}s...",
1327 GetStatusInfo(streamStatus_->load()).c_str(), GetStatusInfo(targetStatus).c_str());
1328
1329 return false;
1330 }
1331
RecordProcessCallbackFuc()1332 void AudioProcessInClientInner::RecordProcessCallbackFuc()
1333 {
1334 AUDIO_INFO_LOG("%{public}s enter.", __func__);
1335 processProxy_->RegisterThreadPriority(gettid(),
1336 AudioSystemManager::GetInstance()->GetSelfBundleName(processConfig_.appInfo.appUid));
1337 uint64_t curReadPos = 0;
1338 int64_t wakeUpTime = ClockTime::GetCurNano();
1339 int64_t clientReadCost = 0;
1340
1341 while (!isCallbackLoopEnd_ && audioBuffer_ != nullptr) {
1342 if (!KeepLoopRunning()) {
1343 continue;
1344 }
1345 threadStatus_ = INRUNNING;
1346 Trace traceLoop("AudioProcessInClient Record InRunning");
1347 if (needReSyncPosition_ && RecordReSyncServicePos() == SUCCESS) {
1348 wakeUpTime = ClockTime::GetCurNano();
1349 needReSyncPosition_ = false;
1350 continue;
1351 }
1352 int64_t curTime = ClockTime::GetCurNano();
1353 int64_t wakeupCost = curTime - wakeUpTime;
1354 if (wakeupCost > ONE_MILLISECOND_DURATION) {
1355 AUDIO_WARNING_LOG("loop wake up too late, cost %{public}" PRId64"us", wakeupCost / AUDIO_MS_PER_SECOND);
1356 wakeUpTime = curTime;
1357 }
1358
1359 curReadPos = audioBuffer_->GetCurReadFrame();
1360 int32_t recordPrepare = RecordPrepareCurrent(curReadPos);
1361 CHECK_AND_CONTINUE_LOG(recordPrepare == SUCCESS, "prepare current fail.");
1362 CallClientHandleCurrent();
1363 int32_t recordFinish = RecordFinishHandleCurrent(curReadPos, clientReadCost);
1364 CHECK_AND_CONTINUE_LOG(recordFinish == SUCCESS, "finish handle current fail.");
1365
1366 bool ret = PrepareNext(curReadPos, wakeUpTime);
1367 CHECK_AND_BREAK_LOG(ret, "prepare next loop in process fail.");
1368
1369 threadStatus_ = SLEEPING;
1370 curTime = ClockTime::GetCurNano();
1371 if (wakeUpTime > curTime && wakeUpTime - curTime < static_cast<int64_t>(spanSizeInMs_) *
1372 ONE_MILLISECOND_DURATION + clientReadCost) {
1373 ClockTime::AbsoluteSleep(wakeUpTime);
1374 } else {
1375 Trace trace("RecordBigWakeUpTime");
1376 AUDIO_WARNING_LOG("%{public}s wakeUpTime is too late...", __func__);
1377 ClockTime::RelativeSleep(spanSizeInMs_ * ONE_MILLISECOND_DURATION);
1378 }
1379 }
1380 }
1381
RecordReSyncServicePos()1382 int32_t AudioProcessInClientInner::RecordReSyncServicePos()
1383 {
1384 CHECK_AND_RETURN_RET_LOG(processProxy_ != nullptr && audioBuffer_ != nullptr, ERR_INVALID_HANDLE,
1385 "%{public}s process proxy or audio buffer is null.", __func__);
1386 uint64_t serverHandlePos = 0;
1387 int64_t serverHandleTime = 0;
1388 int32_t tryTimes = 3;
1389 int32_t ret = 0;
1390 while (tryTimes > 0) {
1391 ret = processProxy_->RequestHandleInfo();
1392 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "%{public}s request handle info fail, ret %{public}d.",
1393 __func__, ret);
1394
1395 CHECK_AND_RETURN_RET_LOG(audioBuffer_->GetHandleInfo(serverHandlePos, serverHandleTime), ERR_OPERATION_FAILED,
1396 "%{public}s get handle info fail.", __func__);
1397 if (serverHandlePos > 0) {
1398 break;
1399 }
1400 ClockTime::RelativeSleep(MAX_READ_COST_DURATION_NANO);
1401 tryTimes--;
1402 }
1403 AUDIO_INFO_LOG("%{public}s get handle info OK, tryTimes %{public}d, serverHandlePos %{public}" PRIu64", "
1404 "serverHandleTime %{public}" PRId64".", __func__, tryTimes, serverHandlePos, serverHandleTime);
1405 ClockTime::AbsoluteSleep(serverHandleTime + RECORD_HANDLE_DELAY_NANO);
1406
1407 ret = audioBuffer_->SetCurReadFrame(serverHandlePos);
1408 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "%{public}s set curReadPos fail, ret %{public}d.", __func__, ret);
1409 return SUCCESS;
1410 }
1411
RecordPrepareCurrent(uint64_t curReadPos)1412 int32_t AudioProcessInClientInner::RecordPrepareCurrent(uint64_t curReadPos)
1413 {
1414 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, ERR_INVALID_HANDLE,
1415 "%{public}s audio buffer is null.", __func__);
1416 SpanInfo *curReadSpan = audioBuffer_->GetSpanInfo(curReadPos);
1417 CHECK_AND_RETURN_RET_LOG(curReadSpan != nullptr, ERR_INVALID_HANDLE,
1418 "%{public}s get read span info of process client fail.", __func__);
1419
1420 int tryCount = 10;
1421 SpanStatus targetStatus = SpanStatus::SPAN_WRITE_DONE;
1422 while (!curReadSpan->spanStatus.compare_exchange_strong(targetStatus, SpanStatus::SPAN_READING)
1423 && tryCount > 0) {
1424 AUDIO_WARNING_LOG("%{public}s unready, curReadSpan %{public}" PRIu64", curSpanStatus %{public}d, wait 2ms.",
1425 __func__, curReadPos, curReadSpan->spanStatus.load());
1426 if (curReadSpan->spanStatus.load() == SpanStatus::SPAN_READING) {
1427 AUDIO_WARNING_LOG("Change status to reading while status is already reading!");
1428 return SUCCESS;
1429 }
1430 targetStatus = SpanStatus::SPAN_WRITE_DONE;
1431 tryCount--;
1432 ClockTime::RelativeSleep(RECORD_RESYNC_SLEEP_NANO);
1433 }
1434 CHECK_AND_RETURN_RET_LOG(tryCount > 0, ERR_INVALID_READ,
1435 "%{public}s wait too long, curReadSpan %{public}" PRIu64".", __func__, curReadPos);
1436
1437 curReadSpan->readStartTime = ClockTime::GetCurNano();
1438 return SUCCESS;
1439 }
1440
RecordFinishHandleCurrent(uint64_t & curReadPos,int64_t & clientReadCost)1441 int32_t AudioProcessInClientInner::RecordFinishHandleCurrent(uint64_t &curReadPos, int64_t &clientReadCost)
1442 {
1443 CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, ERR_INVALID_HANDLE,
1444 "%{public}s audio buffer is null.", __func__);
1445 SpanInfo *curReadSpan = audioBuffer_->GetSpanInfo(curReadPos);
1446 CHECK_AND_RETURN_RET_LOG(curReadSpan != nullptr, ERR_INVALID_HANDLE,
1447 "%{public}s get read span info of process client fail.", __func__);
1448
1449 SpanStatus targetStatus = SpanStatus::SPAN_READING;
1450 if (!curReadSpan->spanStatus.compare_exchange_strong(targetStatus, SpanStatus::SPAN_READ_DONE)) {
1451 AUDIO_ERR_LOG("%{public}s status error, curReadSpan %{public}" PRIu64", curSpanStatus %{public}d.",
1452 __func__, curReadPos, curReadSpan->spanStatus.load());
1453 return ERR_INVALID_OPERATION;
1454 }
1455 curReadSpan->readDoneTime = ClockTime::GetCurNano();
1456
1457 clientReadCost = curReadSpan->readDoneTime - curReadSpan->readStartTime;
1458 if (clientReadCost > MAX_READ_COST_DURATION_NANO) {
1459 AUDIO_WARNING_LOG("Client write cost too long...");
1460 }
1461
1462 uint64_t nextWritePos = curReadPos + spanSizeInFrame_;
1463 int32_t ret = audioBuffer_->SetCurReadFrame(nextWritePos);
1464 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "%{public}s set next hand frame %{public}" PRIu64" fail, "
1465 "ret %{public}d.", __func__, nextWritePos, ret);
1466 curReadPos = nextWritePos;
1467
1468 return SUCCESS;
1469 }
1470
PrepareCurrent(uint64_t curWritePos)1471 bool AudioProcessInClientInner::PrepareCurrent(uint64_t curWritePos)
1472 {
1473 Trace trace("AudioProcessInClient::PrepareCurrent " + std::to_string(curWritePos));
1474 SpanInfo *tempSpan = audioBuffer_->GetSpanInfo(curWritePos);
1475 if (tempSpan == nullptr) {
1476 AUDIO_ERR_LOG("GetSpanInfo failed!");
1477 return false;
1478 }
1479
1480 int tryCount = 50; // try 50 * 2 = 100ms
1481 SpanStatus targetStatus = SpanStatus::SPAN_READ_DONE;
1482 while (!tempSpan->spanStatus.compare_exchange_strong(targetStatus, SpanStatus::SPAN_WRITTING) && tryCount > 0) {
1483 tryCount--;
1484 AUDIO_PRERELEASE_LOGW("span %{public}" PRIu64" not ready, status: %{public}d, wait 2ms.", curWritePos,
1485 targetStatus);
1486 targetStatus = SpanStatus::SPAN_READ_DONE;
1487 ClockTime::RelativeSleep(ONE_MILLISECOND_DURATION + ONE_MILLISECOND_DURATION);
1488 }
1489 // If the last attempt is successful, tryCount will be equal to zero.
1490 CHECK_AND_RETURN_RET_LOG(tryCount >= 0, false,
1491 "wait on current span %{public}" PRIu64" too long...", curWritePos);
1492 tempSpan->writeStartTime = ClockTime::GetCurNano();
1493 return true;
1494 }
1495
PrepareCurrentLoop(uint64_t curWritePos)1496 bool AudioProcessInClientInner::PrepareCurrentLoop(uint64_t curWritePos)
1497 {
1498 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1499 for (size_t count = 0; count < round; count++) {
1500 uint64_t tmp = curWritePos + count * static_cast<uint64_t>(spanSizeInFrame_);
1501 bool ret = PrepareCurrent(tmp);
1502 CHECK_AND_RETURN_RET_LOG(ret, false, "PrepareCurrent failed at %{public}" PRIu64" ", tmp);
1503 }
1504 return true;
1505 }
1506
FinishHandleCurrent(uint64_t & curWritePos,int64_t & clientWriteCost)1507 bool AudioProcessInClientInner::FinishHandleCurrent(uint64_t &curWritePos, int64_t &clientWriteCost)
1508 {
1509 Trace trace("AudioProcessInClient::FinishHandleCurrent " + std::to_string(curWritePos));
1510 SpanInfo *tempSpan = audioBuffer_->GetSpanInfo(curWritePos);
1511 CHECK_AND_RETURN_RET_LOG(tempSpan != nullptr, false, "GetSpanInfo failed!");
1512
1513 int32_t ret = ERROR;
1514 // mark status write-done and then server can read
1515 SpanStatus targetStatus = SpanStatus::SPAN_WRITTING;
1516 if (tempSpan->spanStatus.load() == targetStatus) {
1517 uint64_t nextWritePos = curWritePos + spanSizeInFrame_;
1518 ret = audioBuffer_->SetCurWriteFrame(nextWritePos); // move ahead before writedone
1519 curWritePos = nextWritePos;
1520 tempSpan->spanStatus.store(SpanStatus::SPAN_WRITE_DONE);
1521 }
1522 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false,
1523 "SetCurWriteFrame %{public}" PRIu64" failed, ret:%{public}d", curWritePos, ret);
1524 tempSpan->writeDoneTime = ClockTime::GetCurNano();
1525 tempSpan->volumeStart = static_cast<int32_t>(processVolume_ * duckVolumeInFloat_);
1526 tempSpan->volumeEnd = static_cast<int32_t>(processVolume_ * duckVolumeInFloat_);
1527 clientWriteCost = tempSpan->writeDoneTime - tempSpan->writeStartTime;
1528
1529 return true;
1530 }
1531
FinishHandleCurrentLoop(uint64_t & curWritePos,int64_t & clientWriteCost)1532 bool AudioProcessInClientInner::FinishHandleCurrentLoop(uint64_t &curWritePos, int64_t &clientWriteCost)
1533 {
1534 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1535 for (size_t count = 0; count < round; count++) {
1536 uint64_t tmp = curWritePos + count * static_cast<uint64_t>(spanSizeInFrame_);
1537 bool ret = FinishHandleCurrent(tmp, clientWriteCost);
1538 CHECK_AND_RETURN_RET_LOG(ret, false, "FinishHandleCurrent failed at %{public}" PRIu64" ", tmp);
1539 }
1540 return true;
1541 }
1542
DoFadeInOut(uint64_t & curWritePos)1543 void AudioProcessInClientInner::DoFadeInOut(uint64_t &curWritePos)
1544 {
1545 if (startFadein_.load() || startFadeout_.load()) {
1546 BufferDesc buffDesc;
1547 CHECK_AND_RETURN_LOG(audioBuffer_ != nullptr, "audioBuffer_ is null.");
1548 audioBuffer_->GetWriteBuffer(curWritePos, buffDesc);
1549 CHECK_AND_RETURN_LOG(buffDesc.buffer != nullptr, "audioBuffer_ is null.");
1550 int16_t *dstPtr = reinterpret_cast<int16_t *>(buffDesc.buffer);
1551 uint8_t channels = processConfig_.streamInfo.channels;
1552 size_t dataLength = buffDesc.dataLength / (2 * channels); // SAMPLE_S16LE,2 bytes per frame
1553
1554 bool isFadeOut = startFadeout_.load();
1555 float fadeStep = 1.0f / dataLength;
1556 for (size_t i = 0; i < dataLength; i++) {
1557 float fadeFactor;
1558 if (!isFadeOut) {
1559 fadeFactor = (i + 1) * fadeStep;
1560 } else {
1561 fadeFactor = 1.0f - ((i + 1) * fadeStep);
1562 }
1563 for (uint8_t j = 0; j < channels; j++) {
1564 dstPtr[i * channels + j] *= fadeFactor;
1565 }
1566 }
1567
1568 if (isFadeOut) {
1569 startFadeout_.store(false);
1570 } else {
1571 startFadein_.store(false);
1572 }
1573 }
1574 }
1575
ProcessCallbackFuc()1576 void AudioProcessInClientInner::ProcessCallbackFuc()
1577 {
1578 AUDIO_INFO_LOG("Callback loop start.");
1579 processProxy_->RegisterThreadPriority(gettid(),
1580 AudioSystemManager::GetInstance()->GetSelfBundleName(processConfig_.appInfo.appUid));
1581
1582 uint64_t curWritePos = 0;
1583 int64_t curTime = 0;
1584 int64_t wakeUpTime = ClockTime::GetCurNano();
1585 int64_t clientWriteCost = 0;
1586
1587 while (!isCallbackLoopEnd_ || startFadeout_.load()) {
1588 if (!KeepLoopRunning()) {
1589 continue;
1590 }
1591 threadStatus_ = INRUNNING;
1592 Trace traceLoop("AudioProcessInClient::InRunning");
1593 CheckIfWakeUpTooLate(curTime, wakeUpTime);
1594 curWritePos = audioBuffer_->GetCurWriteFrame();
1595 if (!PrepareCurrentLoop(curWritePos)) {
1596 continue;
1597 }
1598 // call client write
1599 CallClientHandleCurrent();
1600 // client write done, check if time out
1601
1602 DoFadeInOut(curWritePos);
1603
1604 if (!FinishHandleCurrentLoop(curWritePos, clientWriteCost)) {
1605 continue;
1606 }
1607 if (!ClientPrepareNextLoop(curWritePos, wakeUpTime)) {
1608 break;
1609 }
1610 traceLoop.End();
1611 // start safe sleep
1612 threadStatus_ = SLEEPING;
1613 CheckIfWakeUpTooLate(curTime, wakeUpTime, clientWriteCost);
1614 ClockTime::AbsoluteSleep(wakeUpTime);
1615 }
1616 }
1617
ProcessCallbackFucIndependent()1618 void AudioProcessInClientInner::ProcessCallbackFucIndependent()
1619 {
1620 AUDIO_INFO_LOG("multi play loop start");
1621 processProxy_->RegisterThreadPriority(gettid(),
1622 AudioSystemManager::GetInstance()->GetSelfBundleName(processConfig_.appInfo.appUid));
1623 int64_t curTime = 0;
1624 uint64_t curWritePos = 0;
1625 int64_t wakeUpTime = ClockTime::GetCurNano();
1626 while (!isCallbackLoopEnd_) {
1627 if (!KeepLoopRunningIndependent()) {
1628 continue;
1629 }
1630 int32_t ret = 0;
1631 threadStatus_ = INRUNNING;
1632 curTime = ClockTime::GetCurNano();
1633 Trace traceLoop("AudioProcessInClient::InRunning");
1634 if (needReSyncPosition_) {
1635 UpdateHandleInfo(true, true);
1636 wakeUpTime = curTime;
1637 needReSyncPosition_ = false;
1638 continue;
1639 }
1640 curWritePos = audioBuffer_->GetCurWriteFrame();
1641 if (streamStatus_->load() == STREAM_RUNNING) {
1642 CallClientHandleCurrent();
1643 } else {
1644 AudioStreamData writeStreamData;
1645 ret = audioBuffer_->GetWriteBuffer(curWritePos, writeStreamData.bufferDesc);
1646 CHECK_AND_RETURN_LOG(ret == SUCCESS && writeStreamData.bufferDesc.buffer != nullptr,
1647 "ret is fail or buffer is nullptr");
1648 memset_s(writeStreamData.bufferDesc.buffer, writeStreamData.bufferDesc.bufLength,
1649 0, writeStreamData.bufferDesc.bufLength);
1650 }
1651 bool prepared = true;
1652 size_t round = (spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1653 for (size_t count = 0; count < round; count++) {
1654 if (!PrepareNextIndependent(curWritePos + count * spanSizeInFrame_, wakeUpTime)) {
1655 prepared = false;
1656 AUDIO_ERR_LOG("PrepareNextLoop failed!");
1657 break;
1658 }
1659 }
1660 if (!prepared) {
1661 break;
1662 }
1663 traceLoop.End();
1664 // start sleep
1665 threadStatus_ = SLEEPING;
1666
1667 ClockTime::AbsoluteSleep(wakeUpTime);
1668 }
1669 }
1670
KeepLoopRunningIndependent()1671 bool AudioProcessInClientInner::KeepLoopRunningIndependent()
1672 {
1673 switch (streamStatus_->load()) {
1674 case STREAM_RUNNING:
1675 return true;
1676 case STREAM_IDEL:
1677 return true;
1678 case STREAM_PAUSED:
1679 return true;
1680 default:
1681 break;
1682 }
1683
1684 return false;
1685 }
1686
PrepareNextIndependent(uint64_t curWritePos,int64_t & wakeUpTime)1687 bool AudioProcessInClientInner::PrepareNextIndependent(uint64_t curWritePos, int64_t &wakeUpTime)
1688 {
1689 uint64_t nextHandlePos = curWritePos + spanSizeInFrame_;
1690 Trace prepareTrace("AudioEndpoint::PrepareNextLoop " + std::to_string(nextHandlePos));
1691 int64_t nextHdiReadTime = GetPredictNextHandleTime(nextHandlePos, true);
1692 uint64_t aheadTime = spanSizeInFrame_ * AUDIO_NS_PER_SECOND / processConfig_.streamInfo.samplingRate;
1693 int64_t nextServerHandleTime = nextHdiReadTime - static_cast<int64_t>(aheadTime);
1694 if (nextServerHandleTime < ClockTime::GetCurNano()) {
1695 wakeUpTime = ClockTime::GetCurNano() + ONE_MILLISECOND_DURATION; // make sure less than duration
1696 } else {
1697 wakeUpTime = nextServerHandleTime;
1698 }
1699
1700 SpanInfo *nextWriteSpan = audioBuffer_->GetSpanInfo(nextHandlePos);
1701 if (nextWriteSpan == nullptr) {
1702 AUDIO_ERR_LOG("GetSpanInfo failed, can not get next write span");
1703 return false;
1704 }
1705
1706 int32_t ret1 = audioBuffer_->SetCurWriteFrame(nextHandlePos);
1707 int32_t ret2 = audioBuffer_->SetCurReadFrame(nextHandlePos);
1708 if (ret1 != SUCCESS || ret2 != SUCCESS) {
1709 AUDIO_ERR_LOG("SetCurWriteFrame or SetCurReadFrame failed, ret1:%{public}d ret2:%{public}d", ret1, ret2);
1710 return false;
1711 }
1712 return true;
1713 }
1714
CheckIfWakeUpTooLate(int64_t & curTime,int64_t & wakeUpTime)1715 void AudioProcessInClientInner::CheckIfWakeUpTooLate(int64_t &curTime, int64_t &wakeUpTime)
1716 {
1717 curTime = ClockTime::GetCurNano();
1718 int64_t wakeupCost = curTime - wakeUpTime;
1719 if (wakeupCost > ONE_MILLISECOND_DURATION) {
1720 AUDIO_WARNING_LOG("loop wake up too late, cost %{public}" PRId64"us", wakeupCost / AUDIO_MS_PER_SECOND);
1721 wakeUpTime = curTime;
1722 }
1723 }
1724
CheckIfWakeUpTooLate(int64_t & curTime,int64_t & wakeUpTime,int64_t clientWriteCost)1725 void AudioProcessInClientInner::CheckIfWakeUpTooLate(int64_t &curTime, int64_t &wakeUpTime, int64_t clientWriteCost)
1726 {
1727 curTime = ClockTime::GetCurNano();
1728 int64_t round = static_cast<int64_t>(spanSizeInFrame_ == 0 ? 1 : clientSpanSizeInFrame_ / spanSizeInFrame_);
1729 int64_t clientBufferDurationInMs = static_cast<int64_t>(spanSizeInMs_) * ONE_MILLISECOND_DURATION * round;
1730 if (wakeUpTime - curTime > clientBufferDurationInMs + clientWriteCost) {
1731 Trace trace("BigWakeUpTime curTime[" + std::to_string(curTime) + "] target[" + std::to_string(wakeUpTime) +
1732 "] delay " + std::to_string(wakeUpTime - curTime) + "ns");
1733 AUDIO_PRERELEASE_LOGW("wakeUpTime is too late...");
1734 }
1735 }
1736
SetSilentModeAndMixWithOthers(bool on)1737 int32_t AudioProcessInClientInner::SetSilentModeAndMixWithOthers(bool on)
1738 {
1739 CHECK_AND_RETURN_RET_LOG(processProxy_ != nullptr, ERR_OPERATION_FAILED, "ipcProxy is null.");
1740 return processProxy_->SetSilentModeAndMixWithOthers(on);
1741 }
1742 } // namespace AudioStandard
1743 } // namespace OHOS
1744