1 /*
2 * Copyright (c) 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 "ProRendererStream"
17 #endif
18
19 #include "pro_renderer_stream_impl.h"
20 #include "audio_errors.h"
21 #include "audio_renderer_log.h"
22 #include "audio_utils.h"
23 #include "securec.h"
24 #include "policy_handler.h"
25 #include "audio_common_converter.h"
26
27 namespace OHOS {
28 namespace AudioStandard {
29 constexpr uint64_t AUDIO_US_PER_S = 1000000;
30 constexpr uint64_t AUDIO_NS_PER_S = 1000000000;
31 constexpr int32_t SECOND_TO_MILLISECOND = 1000;
32 constexpr int32_t DEFAULT_BUFFER_MILLISECOND = 20;
33 constexpr int32_t DEFAULT_BUFFER_MICROSECOND = 20000000;
34 constexpr uint32_t DOUBLE_VALUE = 2;
35 constexpr int32_t DEFAULT_RESAMPLE_QUANTITY = 2;
36 constexpr int32_t STEREO_CHANNEL_COUNT = 2;
37 constexpr int32_t DEFAULT_TOTAL_SPAN_COUNT = 4;
38 constexpr int32_t DRAIN_WAIT_TIMEOUT_TIME = 100;
39 constexpr int32_t FIRST_FRAME_TIMEOUT_TIME = 500;
40 const std::string DUMP_DIRECT_STREAM_FILE = "dump_direct_audio_stream.pcm";
41
ProRendererStreamImpl(AudioProcessConfig processConfig,bool isDirect)42 ProRendererStreamImpl::ProRendererStreamImpl(AudioProcessConfig processConfig, bool isDirect)
43 : isDirect_(isDirect),
44 isNeedResample_(false),
45 isNeedMcr_(false),
46 isBlock_(true),
47 isDrain_(false),
48 isFirstFrame_(true),
49 privacyType_(0),
50 renderRate_(0),
51 streamIndex_(static_cast<uint32_t>(-1)),
52 abortFlag_(0),
53 currentRate_(1),
54 desSamplingRate_(0),
55 desFormat_(AudioSampleFormat::SAMPLE_S32LE),
56 byteSizePerFrame_(0),
57 spanSizeInFrame_(0),
58 totalBytesWritten_(0),
59 sinkBytesWritten_(0),
60 minBufferSize_(0),
61 status_(I_STATUS_INVALID),
62 resample_(nullptr),
63 processConfig_(processConfig),
64 downMixer_(nullptr),
65 dumpFile_(nullptr)
66 {
67 AUDIO_DEBUG_LOG("constructor");
68 }
69
~ProRendererStreamImpl()70 ProRendererStreamImpl::~ProRendererStreamImpl()
71 {
72 AUDIO_DEBUG_LOG("deconstructor");
73 status_ = I_STATUS_INVALID;
74 DumpFileUtil::CloseDumpFile(&dumpFile_);
75 }
76
GetDirectSampleRate(AudioSamplingRate sampleRate) const77 AudioSamplingRate ProRendererStreamImpl::GetDirectSampleRate(AudioSamplingRate sampleRate) const noexcept
78 {
79 if (processConfig_.streamType == STREAM_VOICE_CALL) {
80 // VoIP stream type. Return the special sample rate of direct VoIP mode.
81 if (sampleRate <= AudioSamplingRate::SAMPLE_RATE_16000) {
82 return AudioSamplingRate::SAMPLE_RATE_16000;
83 } else {
84 return AudioSamplingRate::SAMPLE_RATE_48000;
85 }
86 }
87 // High resolution for music
88 AudioSamplingRate result = sampleRate;
89 switch (sampleRate) {
90 case AudioSamplingRate::SAMPLE_RATE_44100:
91 result = AudioSamplingRate::SAMPLE_RATE_48000;
92 break;
93 case AudioSamplingRate::SAMPLE_RATE_88200:
94 result = AudioSamplingRate::SAMPLE_RATE_96000;
95 break;
96 case AudioSamplingRate::SAMPLE_RATE_176400:
97 result = AudioSamplingRate::SAMPLE_RATE_192000;
98 break;
99 default:
100 break;
101 }
102 return result;
103 }
104
GetDirectFormat(AudioSampleFormat format) const105 AudioSampleFormat ProRendererStreamImpl::GetDirectFormat(AudioSampleFormat format) const noexcept
106 {
107 if (isDirect_) {
108 // Only SAMPLE_S32LE is supported for high resolution stream.
109 return AudioSampleFormat::SAMPLE_S32LE;
110 }
111
112 // Both SAMPLE_S16LE and SAMPLE_S32LE are supported for direct VoIP stream.
113 if (format == SAMPLE_S16LE || format == SAMPLE_S32LE) {
114 return format;
115 } else {
116 AUDIO_WARNING_LOG("The format %{public}u is unsupported for direct VoIP. Use 32Bit.", format);
117 return AudioSampleFormat::SAMPLE_S32LE;
118 }
119 }
120
InitParams()121 int32_t ProRendererStreamImpl::InitParams()
122 {
123 if (status_ != I_STATUS_INVALID) {
124 return ERR_ILLEGAL_STATE;
125 }
126 AudioStreamInfo streamInfo = processConfig_.streamInfo;
127 AUDIO_INFO_LOG("sampleSpec: channels: %{public}u, formats: %{public}d, rate: %{public}d", streamInfo.channels,
128 streamInfo.format, streamInfo.samplingRate);
129 InitBasicInfo(streamInfo);
130 size_t frameSize = spanSizeInFrame_ * streamInfo.channels;
131 uint32_t desChannels = streamInfo.channels >= STEREO_CHANNEL_COUNT ? STEREO_CHANNEL_COUNT : 1;
132 uint32_t desSpanSize = (desSamplingRate_ * DEFAULT_BUFFER_MILLISECOND) / SECOND_TO_MILLISECOND;
133 if (streamInfo.samplingRate != desSamplingRate_) {
134 AUDIO_INFO_LOG("stream need resample, dest:%{public}d", desSamplingRate_);
135 isNeedResample_ = true;
136 resample_ = std::make_shared<AudioResample>(desChannels, streamInfo.samplingRate, desSamplingRate_,
137 DEFAULT_RESAMPLE_QUANTITY);
138 if (!resample_->IsResampleInit()) {
139 AUDIO_ERR_LOG("resample not supported.");
140 return ERR_INVALID_PARAM;
141 }
142 resampleSrcBuffer.resize(frameSize, 0.f);
143 resampleDesBuffer.resize(desSpanSize * desChannels, 0.f);
144 resample_->ProcessFloatResample(resampleSrcBuffer, resampleDesBuffer);
145 }
146 if (streamInfo.channels > STEREO_CHANNEL_COUNT) {
147 isNeedMcr_ = true;
148 if (!isNeedResample_) {
149 resampleSrcBuffer.resize(frameSize, 0.f);
150 resampleDesBuffer.resize(desSpanSize * desChannels, 0.f);
151 }
152 downMixer_ = std::make_unique<AudioDownMixStereo>();
153 int32_t ret = downMixer_->InitMixer(streamInfo.channelLayout, streamInfo.channels);
154 if (ret != SUCCESS) {
155 AUDIO_ERR_LOG("down mixer not supported.");
156 return ret;
157 }
158 }
159 uint32_t bufferSize = Util::GetSamplePerFrame(desFormat_) * desSpanSize * desChannels;
160 sinkBuffer_.resize(DEFAULT_TOTAL_SPAN_COUNT, std::vector<char>(bufferSize, 0));
161 for (int32_t i = 0; i < DEFAULT_TOTAL_SPAN_COUNT; i++) {
162 writeQueue_.emplace(i);
163 }
164 SetOffloadDisable();
165 DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DIRECT_STREAM_FILE, &dumpFile_);
166 status_ = I_STATUS_IDLE;
167 return SUCCESS;
168 }
169
Start()170 int32_t ProRendererStreamImpl::Start()
171 {
172 isBlock_ = false;
173 AUDIO_INFO_LOG("Enter");
174 if (status_ == I_STATUS_INVALID) {
175 return ERR_ILLEGAL_STATE;
176 }
177 if (status_ == I_STATUS_STARTED) {
178 return SUCCESS;
179 }
180 status_ = I_STATUS_STARTED;
181 isFirstFrame_ = true;
182 isFirstNoUnderrunFrame_ = false;
183 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
184 if (statusCallback != nullptr) {
185 statusCallback->OnStatusUpdate(OPERATION_STARTED);
186 }
187 return SUCCESS;
188 }
189
Pause(bool isStandby)190 int32_t ProRendererStreamImpl::Pause(bool isStandby)
191 {
192 AUDIO_INFO_LOG("Enter");
193 if (status_ == I_STATUS_STARTED) {
194 status_ = I_STATUS_PAUSED;
195 }
196 if (isFirstFrame_) {
197 firstFrameSync_.notify_all();
198 }
199 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
200 if (statusCallback != nullptr) {
201 statusCallback->OnStatusUpdate(OPERATION_PAUSED);
202 }
203 return SUCCESS;
204 }
205
Flush()206 int32_t ProRendererStreamImpl::Flush()
207 {
208 AUDIO_INFO_LOG("Enter");
209 {
210 std::lock_guard lock(enqueueMutex);
211 while (!readQueue_.empty()) {
212 int32_t index = readQueue_.front();
213 readQueue_.pop();
214 writeQueue_.emplace(index);
215 }
216 if (isDrain_) {
217 drainSync_.notify_all();
218 }
219 }
220 for (auto &buffer : sinkBuffer_) {
221 memset_s(buffer.data(), buffer.size(), 0, buffer.size());
222 }
223 sinkBytesWritten_ = 0;
224 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
225 if (statusCallback != nullptr) {
226 statusCallback->OnStatusUpdate(OPERATION_FLUSHED);
227 }
228 return SUCCESS;
229 }
230
Drain()231 int32_t ProRendererStreamImpl::Drain()
232 {
233 AUDIO_INFO_LOG("Enter");
234 isDrain_ = true;
235 if (!readQueue_.empty()) {
236 std::unique_lock lock(enqueueMutex);
237 drainSync_.wait_for(lock, std::chrono::milliseconds(DRAIN_WAIT_TIMEOUT_TIME),
238 [this] { return readQueue_.empty(); });
239 }
240 isDrain_ = false;
241 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
242 if (statusCallback != nullptr) {
243 statusCallback->OnStatusUpdate(OPERATION_DRAINED);
244 }
245 status_ = I_STATUS_DRAINED;
246 return SUCCESS;
247 }
248
Stop()249 int32_t ProRendererStreamImpl::Stop()
250 {
251 AUDIO_INFO_LOG("Enter");
252 status_ = I_STATUS_STOPPED;
253 if (isFirstFrame_) {
254 firstFrameSync_.notify_all();
255 }
256 totalBytesWritten_ = 0;
257 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
258 if (statusCallback != nullptr) {
259 statusCallback->OnStatusUpdate(OPERATION_STOPPED);
260 }
261 return SUCCESS;
262 }
263
Release()264 int32_t ProRendererStreamImpl::Release()
265 {
266 AUDIO_INFO_LOG("Enter");
267 status_ = I_STATUS_INVALID;
268 isBlock_ = true;
269 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
270 if (statusCallback != nullptr) {
271 statusCallback->OnStatusUpdate(OPERATION_RELEASED);
272 }
273 return SUCCESS;
274 }
275
GetStreamFramesWritten(uint64_t & framesWritten)276 int32_t ProRendererStreamImpl::GetStreamFramesWritten(uint64_t &framesWritten)
277 {
278 CHECK_AND_RETURN_RET_LOG(byteSizePerFrame_ != 0, ERR_ILLEGAL_STATE, "Error frame size");
279 framesWritten = totalBytesWritten_ / byteSizePerFrame_;
280 return SUCCESS;
281 }
282
GetCurrentTimeStamp(uint64_t & timestamp)283 int32_t ProRendererStreamImpl::GetCurrentTimeStamp(uint64_t ×tamp)
284 {
285 int64_t timeSec = 0;
286 int64_t timeNsec = 0;
287 uint64_t framePosition;
288 bool ret = GetAudioTime(framePosition, timeSec, timeNsec);
289 CHECK_AND_RETURN_RET_LOG(ret, ERROR, "GetAudioTime error");
290 timestamp = static_cast<uint64_t>(timeSec * AUDIO_NS_PER_S + timeNsec);
291 return SUCCESS;
292 }
GetCurrentPosition(uint64_t & framePosition,uint64_t & timestamp,uint64_t & latency)293 int32_t ProRendererStreamImpl::GetCurrentPosition(uint64_t &framePosition, uint64_t ×tamp, uint64_t &latency)
294 {
295 int64_t timeSec = 0;
296 int64_t timeNsec = 0;
297 bool ret = GetAudioTime(framePosition, timeSec, timeNsec);
298 CHECK_AND_RETURN_RET_LOG(ret, ERROR, "GetAudioTime error");
299 timespec tm {};
300 clock_gettime(CLOCK_MONOTONIC, &tm);
301 timestamp = static_cast<uint64_t>(tm.tv_sec) * AUDIO_NS_PER_S + static_cast<uint64_t>(tm.tv_nsec);
302 latency = 0;
303 return SUCCESS;
304 }
305
GetLatency(uint64_t & latency)306 int32_t ProRendererStreamImpl::GetLatency(uint64_t &latency)
307 {
308 CHECK_AND_RETURN_RET_LOG(byteSizePerFrame_ != 0, ERR_ILLEGAL_STATE, "Error frame size");
309 uint64_t framePos = sinkBytesWritten_ / byteSizePerFrame_;
310 latency = ((framePos / byteSizePerFrame_) * AUDIO_US_PER_S) / processConfig_.streamInfo.samplingRate;
311 return SUCCESS;
312 }
313
SetRate(int32_t rate)314 int32_t ProRendererStreamImpl::SetRate(int32_t rate)
315 {
316 uint32_t currentRate = processConfig_.streamInfo.samplingRate;
317 switch (rate) {
318 case RENDER_RATE_NORMAL:
319 break;
320 case RENDER_RATE_DOUBLE:
321 currentRate *= DOUBLE_VALUE;
322 break;
323 case RENDER_RATE_HALF:
324 currentRate /= DOUBLE_VALUE;
325 break;
326 default:
327 return ERR_INVALID_PARAM;
328 }
329 (void)currentRate;
330 renderRate_ = rate;
331 return SUCCESS;
332 }
333
SetAudioEffectMode(int32_t effectMode)334 int32_t ProRendererStreamImpl::SetAudioEffectMode(int32_t effectMode)
335 {
336 return SUCCESS;
337 }
GetAudioEffectMode(int32_t & effectMode)338 int32_t ProRendererStreamImpl::GetAudioEffectMode(int32_t &effectMode)
339 {
340 return SUCCESS;
341 }
342
SetPrivacyType(int32_t privacyType)343 int32_t ProRendererStreamImpl::SetPrivacyType(int32_t privacyType)
344 {
345 privacyType_ = privacyType;
346 return SUCCESS;
347 }
348
GetPrivacyType(int32_t & privacyType)349 int32_t ProRendererStreamImpl::GetPrivacyType(int32_t &privacyType)
350 {
351 privacyType = privacyType_;
352 return SUCCESS;
353 }
354
RegisterStatusCallback(const std::weak_ptr<IStatusCallback> & callback)355 void ProRendererStreamImpl::RegisterStatusCallback(const std::weak_ptr<IStatusCallback> &callback)
356 {
357 AUDIO_DEBUG_LOG("enter in");
358 statusCallback_ = callback;
359 }
RegisterWriteCallback(const std::weak_ptr<IWriteCallback> & callback)360 void ProRendererStreamImpl::RegisterWriteCallback(const std::weak_ptr<IWriteCallback> &callback)
361 {
362 AUDIO_DEBUG_LOG("enter in");
363 writeCallback_ = callback;
364 }
365
DequeueBuffer(size_t length)366 BufferDesc ProRendererStreamImpl::DequeueBuffer(size_t length)
367 {
368 BufferDesc bufferDesc = {nullptr, 0, 0};
369 if (status_ != I_STATUS_STARTED) {
370 return bufferDesc;
371 }
372 bufferDesc.buffer = reinterpret_cast<uint8_t *>(sinkBuffer_[0].data());
373 bufferDesc.bufLength = sinkBuffer_[0].size();
374 return bufferDesc;
375 }
376
EnqueueBuffer(const BufferDesc & bufferDesc)377 int32_t ProRendererStreamImpl::EnqueueBuffer(const BufferDesc &bufferDesc)
378 {
379 int32_t writeIndex = PopWriteBufferIndex();
380 if (writeIndex < 0) {
381 AUDIO_ERR_LOG("write index is empty.");
382 return ERR_WRITE_BUFFER;
383 }
384 std::lock_guard lock(peekMutex);
385 float volume = GetStreamVolume();
386 if (isNeedMcr_ && !isNeedResample_) {
387 ConvertSrcToFloat(bufferDesc.buffer, bufferDesc.bufLength, volume);
388 downMixer_->Apply(spanSizeInFrame_, resampleSrcBuffer.data(), resampleDesBuffer.data());
389 DumpFileUtil::WriteDumpFile(dumpFile_, resampleDesBuffer.data(), resampleDesBuffer.size() * sizeof(float));
390 ConvertFloatToDes(writeIndex);
391 } else if (isNeedMcr_ && isNeedResample_) {
392 ConvertSrcToFloat(bufferDesc.buffer, bufferDesc.bufLength, volume);
393 downMixer_->Apply(spanSizeInFrame_, resampleSrcBuffer.data(), resampleSrcBuffer.data());
394 }
395 if (isNeedResample_) {
396 if (!isNeedMcr_) {
397 ConvertSrcToFloat(bufferDesc.buffer, bufferDesc.bufLength, volume);
398 }
399 resample_->ProcessFloatResample(resampleSrcBuffer, resampleDesBuffer);
400 DumpFileUtil::WriteDumpFile(dumpFile_, resampleDesBuffer.data(), resampleDesBuffer.size() * sizeof(float));
401 ConvertFloatToDes(writeIndex);
402 } else if (!isNeedMcr_) {
403 auto streamInfo = processConfig_.streamInfo;
404 uint32_t samplePerFrame = Util::GetSamplePerFrame(streamInfo.format);
405 uint32_t frameLength = bufferDesc.bufLength / samplePerFrame;
406 if (desFormat_ == AudioSampleFormat::SAMPLE_S16LE) {
407 AudioCommonConverter::ConvertBufferTo16Bit(bufferDesc.buffer, streamInfo.format,
408 reinterpret_cast<int16_t *>(sinkBuffer_[writeIndex].data()), frameLength, volume);
409 } else {
410 AudioCommonConverter::ConvertBufferTo32Bit(bufferDesc.buffer, streamInfo.format,
411 reinterpret_cast<int32_t *>(sinkBuffer_[writeIndex].data()), frameLength, volume);
412 }
413 }
414 readQueue_.emplace(writeIndex);
415 if (isFirstFrame_) {
416 firstFrameSync_.notify_all();
417 }
418 AUDIO_DEBUG_LOG("buffer length:%{public}zu ,sink buffer length:%{public}zu,volume:%{public}f", bufferDesc.bufLength,
419 sinkBuffer_[0].size(), volume);
420 totalBytesWritten_ += bufferDesc.bufLength;
421 sinkBytesWritten_ += bufferDesc.bufLength;
422 return SUCCESS;
423 }
424
GetMinimumBufferSize(size_t & minBufferSize) const425 int32_t ProRendererStreamImpl::GetMinimumBufferSize(size_t &minBufferSize) const
426 {
427 minBufferSize = minBufferSize_;
428 return SUCCESS;
429 }
430
GetByteSizePerFrame(size_t & byteSizePerFrame) const431 void ProRendererStreamImpl::GetByteSizePerFrame(size_t &byteSizePerFrame) const
432 {
433 byteSizePerFrame = byteSizePerFrame_;
434 }
435
GetSpanSizePerFrame(size_t & spanSizeInFrame) const436 void ProRendererStreamImpl::GetSpanSizePerFrame(size_t &spanSizeInFrame) const
437 {
438 spanSizeInFrame = spanSizeInFrame_;
439 }
440
SetStreamIndex(uint32_t index)441 void ProRendererStreamImpl::SetStreamIndex(uint32_t index)
442 {
443 AUDIO_INFO_LOG("Using index/sessionId %{public}d", index);
444 streamIndex_ = index;
445 }
446
AbortCallback(int32_t abortTimes)447 void ProRendererStreamImpl::AbortCallback(int32_t abortTimes)
448 {
449 abortFlag_ += abortTimes;
450 }
451
GetStreamIndex()452 uint32_t ProRendererStreamImpl::GetStreamIndex()
453 {
454 return streamIndex_;
455 }
456
457 // offload
SetOffloadMode(int32_t state,bool isAppBack)458 int32_t ProRendererStreamImpl::SetOffloadMode(int32_t state, bool isAppBack)
459 {
460 SetOffloadDisable();
461 return SUCCESS;
462 }
463
UnsetOffloadMode()464 int32_t ProRendererStreamImpl::UnsetOffloadMode()
465 {
466 SetOffloadDisable();
467 return SUCCESS;
468 }
469
GetOffloadApproximatelyCacheTime(uint64_t & timestamp,uint64_t & paWriteIndex,uint64_t & cacheTimeDsp,uint64_t & cacheTimePa)470 int32_t ProRendererStreamImpl::GetOffloadApproximatelyCacheTime(uint64_t ×tamp, uint64_t &paWriteIndex,
471 uint64_t &cacheTimeDsp, uint64_t &cacheTimePa)
472 {
473 return SUCCESS;
474 }
OffloadSetVolume(float volume)475 int32_t ProRendererStreamImpl::OffloadSetVolume(float volume)
476 {
477 return SUCCESS;
478 }
479
GetWritableSize()480 size_t ProRendererStreamImpl::GetWritableSize()
481 {
482 return writeQueue_.size() * minBufferSize_;
483 }
484 // offload end
UpdateSpatializationState(bool spatializationEnabled,bool headTrackingEnabled)485 int32_t ProRendererStreamImpl::UpdateSpatializationState(bool spatializationEnabled, bool headTrackingEnabled)
486 {
487 return SUCCESS;
488 }
489
GetAudioProcessConfig() const490 AudioProcessConfig ProRendererStreamImpl::GetAudioProcessConfig() const noexcept
491 {
492 return processConfig_;
493 }
494
GetAudioTime(uint64_t & framePos,int64_t & sec,int64_t & nanoSec)495 bool ProRendererStreamImpl::GetAudioTime(uint64_t &framePos, int64_t &sec, int64_t &nanoSec)
496 {
497 GetStreamFramesWritten(framePos);
498 int64_t time = handleTimeModel_.GetTimeOfPos(framePos);
499 int64_t deltaTime = DEFAULT_BUFFER_MICROSECOND; // note: 20ms
500 time += deltaTime;
501 sec = time / AUDIO_NS_PER_S;
502 nanoSec = time % AUDIO_NS_PER_S;
503 return true;
504 }
505
Peek(std::vector<char> * audioBuffer,int32_t & index)506 int32_t ProRendererStreamImpl::Peek(std::vector<char> *audioBuffer, int32_t &index)
507 {
508 int32_t result = SUCCESS;
509 if (isBlock_) {
510 return ERR_WRITE_BUFFER;
511 }
512 if (!readQueue_.empty()) {
513 PopSinkBuffer(audioBuffer, index);
514 return result;
515 }
516
517 std::shared_ptr<IWriteCallback> writeCallback = writeCallback_.lock();
518 if (writeCallback != nullptr) {
519 result = writeCallback->OnWriteData(minBufferSize_);
520 switch (result) {
521 // As a low-risk change, temporarily keep the previous behavior
522 // and avoid enterring the err logic on underrun.
523 case ERR_RENDERER_IN_SERVER_UNDERRUN: {
524 auto statusCallback = statusCallback_.lock();
525 if (statusCallback != nullptr && isFirstNoUnderrunFrame_) {
526 statusCallback->OnStatusUpdate(OPERATION_UNDERFLOW);
527 }
528 [[fallthrough]];
529 }
530 case SUCCESS: {
531 PopSinkBuffer(audioBuffer, index);
532 if (result != ERR_RENDERER_IN_SERVER_UNDERRUN) {
533 isFirstNoUnderrunFrame_ = true;
534 result = SUCCESS;
535 }
536 break;
537 }
538 default: {
539 AUDIO_ERR_LOG("Write callback failed,result:%{public}d", result);
540 return result;
541 }
542 }
543 } else {
544 AUDIO_ERR_LOG("Write callback is nullptr");
545 result = ERR_WRITE_BUFFER;
546 }
547 return result;
548 }
549
ReturnIndex(int32_t index)550 int32_t ProRendererStreamImpl::ReturnIndex(int32_t index)
551 {
552 Trace::Count("ProRendererStreamImpl::ReturnIndex", index);
553 if (index < 0) {
554 return SUCCESS;
555 }
556 std::lock_guard lock(enqueueMutex);
557 writeQueue_.emplace(index);
558 return SUCCESS;
559 }
560
SetClientVolume(float clientVolume)561 int32_t ProRendererStreamImpl::SetClientVolume(float clientVolume)
562 {
563 AUDIO_INFO_LOG("clientVolume: %{public}f", clientVolume);
564 return SUCCESS;
565 }
566
UpdateMaxLength(uint32_t maxLength)567 int32_t ProRendererStreamImpl::UpdateMaxLength(uint32_t maxLength)
568 {
569 return SUCCESS;
570 }
571
PopWriteBufferIndex()572 int32_t ProRendererStreamImpl::PopWriteBufferIndex()
573 {
574 std::lock_guard lock(enqueueMutex);
575 int32_t writeIndex = -1;
576 if (!writeQueue_.empty()) {
577 writeIndex = writeQueue_.front();
578 writeQueue_.pop();
579 }
580 return writeIndex;
581 }
582
PopSinkBuffer(std::vector<char> * audioBuffer,int32_t & index)583 void ProRendererStreamImpl::PopSinkBuffer(std::vector<char> *audioBuffer, int32_t &index)
584 {
585 if (readQueue_.empty() && isFirstFrame_) {
586 std::unique_lock firstFrameLock(firstFrameMutex);
587 firstFrameSync_.wait_for(firstFrameLock, std::chrono::milliseconds(FIRST_FRAME_TIMEOUT_TIME),
588 [this] { return (!readQueue_.empty() || isBlock_); });
589 if (!readQueue_.empty()) {
590 isFirstFrame_ = false;
591 }
592 }
593 std::lock_guard lock(enqueueMutex);
594 if (!readQueue_.empty()) {
595 index = readQueue_.front();
596 readQueue_.pop();
597 *audioBuffer = sinkBuffer_[index];
598 Trace::Count("ProRendererStreamImpl::PopSinkBuffer", index);
599 }
600 if (readQueue_.empty() && isDrain_) {
601 drainSync_.notify_all();
602 }
603 }
604
SetOffloadDisable()605 void ProRendererStreamImpl::SetOffloadDisable()
606 {
607 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
608 if (statusCallback != nullptr) {
609 statusCallback->OnStatusUpdate(OPERATION_UNSET_OFFLOAD_ENABLE);
610 }
611 }
612
ConvertSrcToFloat(uint8_t * buffer,size_t bufLength,float volume)613 void ProRendererStreamImpl::ConvertSrcToFloat(uint8_t *buffer, size_t bufLength, float volume)
614 {
615 auto streamInfo = processConfig_.streamInfo;
616 uint32_t samplePerFrame = Util::GetSamplePerFrame(streamInfo.format);
617 if (streamInfo.format == AudioSampleFormat::SAMPLE_F32LE) {
618 if (volume >= 1.0f) {
619 auto error =
620 memcpy_s(resampleSrcBuffer.data(), resampleSrcBuffer.size() * samplePerFrame, buffer, bufLength);
621 if (error != EOK) {
622 AUDIO_ERR_LOG("copy failed");
623 }
624 } else {
625 float *tempBuffer = reinterpret_cast<float *>(buffer);
626 for (uint32_t i = 0; i < resampleSrcBuffer.size(); i++) {
627 resampleSrcBuffer[i] = volume * tempBuffer[i];
628 }
629 }
630 return;
631 }
632
633 AUDIO_DEBUG_LOG("ConvertSrcToFloat resample buffer,samplePerFrame:%{public}d,size:%{public}zu", samplePerFrame,
634 resampleSrcBuffer.size());
635 AudioCommonConverter::ConvertBufferToFloat(buffer, samplePerFrame, resampleSrcBuffer, volume);
636 }
637
ConvertFloatToDes(int32_t writeIndex)638 void ProRendererStreamImpl::ConvertFloatToDes(int32_t writeIndex)
639 {
640 uint32_t samplePerFrame = Util::GetSamplePerFrame(desFormat_);
641 if (desFormat_ == AudioSampleFormat::SAMPLE_F32LE) {
642 auto error = memcpy_s(sinkBuffer_[writeIndex].data(), sinkBuffer_[writeIndex].size(), resampleDesBuffer.data(),
643 resampleDesBuffer.size() * samplePerFrame);
644 if (error != EOK) {
645 AUDIO_ERR_LOG("copy failed");
646 }
647 return;
648 }
649 AudioCommonConverter::ConvertFloatToAudioBuffer(resampleDesBuffer,
650 reinterpret_cast<uint8_t *>(sinkBuffer_[writeIndex].data()), samplePerFrame);
651 }
652
GetStreamVolume()653 float ProRendererStreamImpl::GetStreamVolume()
654 {
655 float volume = 1.0f;
656 AudioVolumeType volumeType = VolumeUtils::GetVolumeTypeFromStreamType(processConfig_.streamType);
657 DeviceType currentOutputDevice = PolicyHandler::GetInstance().GetActiveOutPutDevice();
658 Volume vol = {true, 1.0f, 0};
659 if (PolicyHandler::GetInstance().GetSharedVolume(volumeType, currentOutputDevice, vol)) {
660 volume = vol.isMute ? 0 : vol.volumeFloat;
661 }
662 return volume;
663 }
664
InitBasicInfo(const AudioStreamInfo & streamInfo)665 void ProRendererStreamImpl::InitBasicInfo(const AudioStreamInfo &streamInfo)
666 {
667 currentRate_ = streamInfo.samplingRate;
668 desSamplingRate_ = GetDirectSampleRate(streamInfo.samplingRate);
669 desFormat_ = GetDirectFormat(streamInfo.format);
670 spanSizeInFrame_ = (streamInfo.samplingRate * DEFAULT_BUFFER_MILLISECOND) / SECOND_TO_MILLISECOND;
671 byteSizePerFrame_ = Util::GetSamplePerFrame(streamInfo.format) * streamInfo.channels;
672 minBufferSize_ = spanSizeInFrame_ * byteSizePerFrame_;
673 handleTimeModel_.ConfigSampleRate(currentRate_);
674 }
675 } // namespace AudioStandard
676 } // namespace OHOS
677