1 /*
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #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_volume.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 = 2;
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 const std::string DEVICE_NAME = "primary";
42
ProRendererStreamImpl(AudioProcessConfig processConfig,bool isDirect)43 ProRendererStreamImpl::ProRendererStreamImpl(AudioProcessConfig processConfig, bool isDirect)
44 : isDirect_(isDirect),
45 isNeedResample_(false),
46 isNeedMcr_(false),
47 isBlock_(true),
48 isDrain_(false),
49 isFirstFrame_(true),
50 privacyType_(0),
51 renderRate_(0),
52 streamIndex_(static_cast<uint32_t>(-1)),
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 || processConfig_.streamType == STREAM_VOICE_COMMUNICATION) {
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 if (format == SAMPLE_F32LE) {
116 // Direct VoIP not support SAMPLE_F32LE format.It needs to be converted to S16.
117 return AudioSampleFormat::SAMPLE_S16LE;
118 } else {
119 AUDIO_WARNING_LOG("The format %{public}u is unsupported for direct VoIP. Use 32Bit.", format);
120 return AudioSampleFormat::SAMPLE_S32LE;
121 }
122 }
123
InitParams()124 int32_t ProRendererStreamImpl::InitParams()
125 {
126 Trace trace("ProRendererStreamImpl::InitParams");
127 if (status_ != I_STATUS_INVALID) {
128 return ERR_ILLEGAL_STATE;
129 }
130 AudioStreamInfo streamInfo = processConfig_.streamInfo;
131 AUDIO_INFO_LOG("sampleSpec: channels: %{public}u, formats: %{public}d, rate: %{public}d", streamInfo.channels,
132 streamInfo.format, streamInfo.samplingRate);
133 InitBasicInfo(streamInfo);
134 size_t frameSize = spanSizeInFrame_ * streamInfo.channels;
135 uint32_t desChannels = streamInfo.channels >= STEREO_CHANNEL_COUNT ? STEREO_CHANNEL_COUNT : 1;
136 uint32_t desSpanSize = (desSamplingRate_ * DEFAULT_BUFFER_MILLISECOND) / SECOND_TO_MILLISECOND;
137 if (streamInfo.samplingRate != desSamplingRate_) {
138 Trace::Count("ProRendererStreamImpl::InitParams", streamInfo.samplingRate);
139 AUDIO_INFO_LOG("stream need resample, dest:%{public}d", desSamplingRate_);
140 isNeedResample_ = true;
141 resample_ = std::make_shared<AudioResample>(desChannels, streamInfo.samplingRate, desSamplingRate_,
142 DEFAULT_RESAMPLE_QUANTITY);
143 if (!resample_->IsResampleInit()) {
144 AUDIO_ERR_LOG("resample not supported.");
145 return ERR_INVALID_PARAM;
146 }
147 resampleSrcBuffer.resize(frameSize, 0.f);
148 resampleDesBuffer.resize(desSpanSize * desChannels, 0.f);
149 resample_->ProcessFloatResample(resampleSrcBuffer, resampleDesBuffer);
150 }
151 if (streamInfo.channels > STEREO_CHANNEL_COUNT) {
152 Trace::Count("ProRendererStreamImpl::InitParams", streamInfo.channels);
153 isNeedMcr_ = true;
154 if (!isNeedResample_) {
155 resampleSrcBuffer.resize(frameSize, 0.f);
156 resampleDesBuffer.resize(desSpanSize * desChannels, 0.f);
157 }
158 downMixer_ = std::make_unique<AudioDownMixStereo>();
159 int32_t ret = downMixer_->InitMixer(streamInfo.channelLayout, streamInfo.channels);
160 if (ret != SUCCESS) {
161 AUDIO_ERR_LOG("down mixer not supported.");
162 return ret;
163 }
164 }
165 uint32_t bufferSize = Util::GetSamplePerFrame(desFormat_) * desSpanSize * desChannels;
166 sinkBuffer_.resize(DEFAULT_TOTAL_SPAN_COUNT, std::vector<char>(bufferSize, 0));
167 for (int32_t i = 0; i < DEFAULT_TOTAL_SPAN_COUNT; i++) {
168 writeQueue_.emplace(i);
169 }
170 SetOffloadDisable();
171 DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, DUMP_DIRECT_STREAM_FILE, &dumpFile_);
172 status_ = I_STATUS_IDLE;
173 return SUCCESS;
174 }
175
Start()176 int32_t ProRendererStreamImpl::Start()
177 {
178 Trace trace("ProRendererStreamImpl::Start::" + std::to_string(streamIndex_));
179 isBlock_ = false;
180 AUDIO_INFO_LOG("Enter");
181 if (status_ == I_STATUS_INVALID) {
182 return ERR_ILLEGAL_STATE;
183 }
184 if (status_ == I_STATUS_STARTED) {
185 return SUCCESS;
186 }
187 status_ = I_STATUS_STARTED;
188 isFirstFrame_ = true;
189 isFirstNoUnderrunFrame_ = false;
190 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
191 if (statusCallback != nullptr) {
192 statusCallback->OnStatusUpdate(OPERATION_STARTED);
193 }
194 return SUCCESS;
195 }
196
Pause(bool isStandby)197 int32_t ProRendererStreamImpl::Pause(bool isStandby)
198 {
199 Trace trace("ProRendererStreamImpl::Pause::" + std::to_string(streamIndex_));
200 AUDIO_INFO_LOG("Enter");
201 if (status_ == I_STATUS_STARTED) {
202 status_ = I_STATUS_PAUSED;
203 }
204 if (isFirstFrame_) {
205 firstFrameSync_.notify_all();
206 }
207 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
208 if (statusCallback != nullptr) {
209 statusCallback->OnStatusUpdate(OPERATION_PAUSED);
210 }
211 return SUCCESS;
212 }
213
Flush()214 int32_t ProRendererStreamImpl::Flush()
215 {
216 Trace trace("ProRendererStreamImpl::Flush::" + std::to_string(streamIndex_));
217 AUDIO_INFO_LOG("reset total bytes");
218 {
219 std::lock_guard lock(enqueueMutex);
220 while (!readQueue_.empty()) {
221 int32_t index = readQueue_.front();
222 readQueue_.pop();
223 writeQueue_.emplace(index);
224 }
225 if (isDrain_) {
226 drainSync_.notify_all();
227 }
228 }
229 for (auto &buffer : sinkBuffer_) {
230 memset_s(buffer.data(), buffer.size(), 0, buffer.size());
231 }
232 sinkBytesWritten_ = 0;
233 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
234 if (statusCallback != nullptr) {
235 statusCallback->OnStatusUpdate(OPERATION_FLUSHED);
236 }
237 return SUCCESS;
238 }
239
Drain(bool stopFlag)240 int32_t ProRendererStreamImpl::Drain(bool stopFlag)
241 {
242 Trace trace("ProRendererStreamImpl::Drain::" + std::to_string(streamIndex_));
243 AUDIO_INFO_LOG("Enter");
244 isDrain_ = true;
245 if (!readQueue_.empty()) {
246 std::unique_lock lock(enqueueMutex);
247 drainSync_.wait_for(lock, std::chrono::milliseconds(DRAIN_WAIT_TIMEOUT_TIME),
248 [this] { return readQueue_.empty(); });
249 }
250 isDrain_ = false;
251 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
252 if (statusCallback != nullptr) {
253 statusCallback->OnStatusUpdate(OPERATION_DRAINED);
254 }
255 status_ = I_STATUS_DRAINED;
256 return SUCCESS;
257 }
258
Stop()259 int32_t ProRendererStreamImpl::Stop()
260 {
261 Trace trace("ProRendererStreamImpl::Stop::" + std::to_string(streamIndex_));
262 AUDIO_INFO_LOG("Enter");
263 status_ = I_STATUS_STOPPED;
264 if (isFirstFrame_) {
265 firstFrameSync_.notify_all();
266 }
267 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
268 if (statusCallback != nullptr) {
269 statusCallback->OnStatusUpdate(OPERATION_STOPPED);
270 }
271 return SUCCESS;
272 }
273
Release()274 int32_t ProRendererStreamImpl::Release()
275 {
276 Trace trace("ProRendererStreamImpl::Release::" + std::to_string(streamIndex_));
277 AUDIO_INFO_LOG("Enter");
278 status_ = I_STATUS_INVALID;
279 isBlock_ = true;
280 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
281 if (statusCallback != nullptr) {
282 statusCallback->OnStatusUpdate(OPERATION_RELEASED);
283 }
284 return SUCCESS;
285 }
286
GetStreamFramesWritten(uint64_t & framesWritten)287 int32_t ProRendererStreamImpl::GetStreamFramesWritten(uint64_t &framesWritten)
288 {
289 CHECK_AND_RETURN_RET_LOG(byteSizePerFrame_ != 0, ERR_ILLEGAL_STATE, "Error frame size");
290 framesWritten = totalBytesWritten_ / byteSizePerFrame_;
291 return SUCCESS;
292 }
293
GetCurrentTimeStamp(uint64_t & timestamp)294 int32_t ProRendererStreamImpl::GetCurrentTimeStamp(uint64_t ×tamp)
295 {
296 int64_t timeSec = 0;
297 int64_t timeNsec = 0;
298 uint64_t framePosition;
299 bool ret = GetAudioTime(framePosition, timeSec, timeNsec);
300 CHECK_AND_RETURN_RET_LOG(ret, ERROR, "GetAudioTime error");
301 timestamp = static_cast<uint64_t>(timeSec * AUDIO_NS_PER_S + timeNsec);
302 return SUCCESS;
303 }
304
GetCurrentPosition(uint64_t & framePosition,uint64_t & timestamp,uint64_t & latency)305 int32_t ProRendererStreamImpl::GetCurrentPosition(uint64_t &framePosition, uint64_t ×tamp, uint64_t &latency)
306 {
307 int64_t timeSec = 0;
308 int64_t timeNsec = 0;
309 bool ret = GetAudioTime(framePosition, timeSec, timeNsec);
310 CHECK_AND_RETURN_RET_LOG(ret, ERROR, "GetAudioTime error");
311 timespec tm {};
312 clock_gettime(CLOCK_MONOTONIC, &tm);
313 timestamp = static_cast<uint64_t>(tm.tv_sec) * AUDIO_NS_PER_S + static_cast<uint64_t>(tm.tv_nsec);
314 latency = 0;
315 return SUCCESS;
316 }
317
GetLatency(uint64_t & latency)318 int32_t ProRendererStreamImpl::GetLatency(uint64_t &latency)
319 {
320 CHECK_AND_RETURN_RET_LOG(byteSizePerFrame_ != 0, ERR_ILLEGAL_STATE, "Error frame size");
321 uint64_t framePos = sinkBytesWritten_ / byteSizePerFrame_;
322 latency = ((framePos / byteSizePerFrame_) * AUDIO_US_PER_S) / processConfig_.streamInfo.samplingRate;
323 return SUCCESS;
324 }
325
SetRate(int32_t rate)326 int32_t ProRendererStreamImpl::SetRate(int32_t rate)
327 {
328 uint32_t currentRate = processConfig_.streamInfo.samplingRate;
329 switch (rate) {
330 case RENDER_RATE_NORMAL:
331 break;
332 case RENDER_RATE_DOUBLE:
333 currentRate *= DOUBLE_VALUE;
334 break;
335 case RENDER_RATE_HALF:
336 currentRate /= DOUBLE_VALUE;
337 break;
338 default:
339 return ERR_INVALID_PARAM;
340 }
341 (void)currentRate;
342 renderRate_ = rate;
343 return SUCCESS;
344 }
345
SetAudioEffectMode(int32_t effectMode)346 int32_t ProRendererStreamImpl::SetAudioEffectMode(int32_t effectMode)
347 {
348 return SUCCESS;
349 }
350
GetAudioEffectMode(int32_t & effectMode)351 int32_t ProRendererStreamImpl::GetAudioEffectMode(int32_t &effectMode)
352 {
353 return SUCCESS;
354 }
355
SetPrivacyType(int32_t privacyType)356 int32_t ProRendererStreamImpl::SetPrivacyType(int32_t privacyType)
357 {
358 privacyType_ = privacyType;
359 return SUCCESS;
360 }
361
GetPrivacyType(int32_t & privacyType)362 int32_t ProRendererStreamImpl::GetPrivacyType(int32_t &privacyType)
363 {
364 privacyType = privacyType_;
365 return SUCCESS;
366 }
367
RegisterStatusCallback(const std::weak_ptr<IStatusCallback> & callback)368 void ProRendererStreamImpl::RegisterStatusCallback(const std::weak_ptr<IStatusCallback> &callback)
369 {
370 AUDIO_DEBUG_LOG("enter in");
371 statusCallback_ = callback;
372 }
373
RegisterWriteCallback(const std::weak_ptr<IWriteCallback> & callback)374 void ProRendererStreamImpl::RegisterWriteCallback(const std::weak_ptr<IWriteCallback> &callback)
375 {
376 AUDIO_DEBUG_LOG("enter in");
377 writeCallback_ = callback;
378 }
379
DequeueBuffer(size_t length)380 BufferDesc ProRendererStreamImpl::DequeueBuffer(size_t length)
381 {
382 Trace trace("ProRendererStreamImpl::DequeueBuffer");
383 BufferDesc bufferDesc = {nullptr, 0, 0};
384 if (status_ != I_STATUS_STARTED) {
385 return bufferDesc;
386 }
387 bufferDesc.buffer = reinterpret_cast<uint8_t *>(sinkBuffer_[0].data());
388 bufferDesc.bufLength = sinkBuffer_[0].size();
389 return bufferDesc;
390 }
391
EnqueueBuffer(const BufferDesc & bufferDesc)392 int32_t ProRendererStreamImpl::EnqueueBuffer(const BufferDesc &bufferDesc)
393 {
394 Trace trace("ProRendererStreamImpl::EnqueueBuffer::" + std::to_string(streamIndex_));
395 int32_t writeIndex = PopWriteBufferIndex();
396 if (writeIndex < 0) {
397 AUDIO_ERR_LOG("write index is empty.");
398 return ERR_WRITE_BUFFER;
399 }
400 std::lock_guard lock(peekMutex);
401 GetStreamVolume();
402 if (isNeedMcr_ && !isNeedResample_) {
403 ConvertSrcToFloat(bufferDesc);
404 downMixer_->Apply(spanSizeInFrame_, resampleSrcBuffer.data(), resampleDesBuffer.data());
405 ConvertFloatToDes(writeIndex);
406 } else if (isNeedMcr_ && isNeedResample_) {
407 ConvertSrcToFloat(bufferDesc);
408 downMixer_->Apply(spanSizeInFrame_, resampleSrcBuffer.data(), resampleSrcBuffer.data());
409 }
410 if (isNeedResample_) {
411 if (!isNeedMcr_) {
412 ConvertSrcToFloat(bufferDesc);
413 }
414 resample_->ProcessFloatResample(resampleSrcBuffer, resampleDesBuffer);
415 DumpFileUtil::WriteDumpFile(dumpFile_, resampleDesBuffer.data(), resampleDesBuffer.size() * sizeof(float));
416 ConvertFloatToDes(writeIndex);
417 } else if (!isNeedMcr_) {
418 bufferInfo_.bufLength = bufferDesc.bufLength;
419 bufferInfo_.frameSize = bufferDesc.bufLength / bufferInfo_.samplePerFrame;
420 bufferInfo_.buffer = bufferDesc.buffer;
421 if (desFormat_ == AudioSampleFormat::SAMPLE_S16LE) {
422 AudioCommonConverter::ConvertBufferTo16Bit(bufferInfo_, sinkBuffer_[writeIndex]);
423 } else {
424 AudioCommonConverter::ConvertBufferTo32Bit(bufferInfo_, sinkBuffer_[writeIndex]);
425 }
426 }
427 readQueue_.emplace(writeIndex);
428 if (isFirstFrame_) {
429 firstFrameSync_.notify_all();
430 }
431 AUDIO_DEBUG_LOG("buffer length:%{public}zu ,sink buffer length:%{public}zu", bufferDesc.bufLength,
432 sinkBuffer_[0].size());
433 totalBytesWritten_ += bufferDesc.bufLength;
434 sinkBytesWritten_ += bufferDesc.bufLength;
435 return SUCCESS;
436 }
437
GetMinimumBufferSize(size_t & minBufferSize) const438 int32_t ProRendererStreamImpl::GetMinimumBufferSize(size_t &minBufferSize) const
439 {
440 minBufferSize = minBufferSize_;
441 return SUCCESS;
442 }
443
GetByteSizePerFrame(size_t & byteSizePerFrame) const444 void ProRendererStreamImpl::GetByteSizePerFrame(size_t &byteSizePerFrame) const
445 {
446 byteSizePerFrame = byteSizePerFrame_;
447 }
448
GetSpanSizePerFrame(size_t & spanSizeInFrame) const449 void ProRendererStreamImpl::GetSpanSizePerFrame(size_t &spanSizeInFrame) const
450 {
451 spanSizeInFrame = spanSizeInFrame_;
452 }
453
SetStreamIndex(uint32_t index)454 void ProRendererStreamImpl::SetStreamIndex(uint32_t index)
455 {
456 AUDIO_INFO_LOG("Using index/sessionId %{public}d", index);
457 streamIndex_ = index;
458 }
459
GetStreamIndex()460 uint32_t ProRendererStreamImpl::GetStreamIndex()
461 {
462 return streamIndex_;
463 }
464
465 // offload
SetOffloadMode(int32_t state,bool isAppBack)466 int32_t ProRendererStreamImpl::SetOffloadMode(int32_t state, bool isAppBack)
467 {
468 SetOffloadDisable();
469 return SUCCESS;
470 }
471
UnsetOffloadMode()472 int32_t ProRendererStreamImpl::UnsetOffloadMode()
473 {
474 SetOffloadDisable();
475 return SUCCESS;
476 }
477
GetOffloadApproximatelyCacheTime(uint64_t & timestamp,uint64_t & paWriteIndex,uint64_t & cacheTimeDsp,uint64_t & cacheTimePa)478 int32_t ProRendererStreamImpl::GetOffloadApproximatelyCacheTime(uint64_t ×tamp, uint64_t &paWriteIndex,
479 uint64_t &cacheTimeDsp, uint64_t &cacheTimePa)
480 {
481 return SUCCESS;
482 }
483
OffloadSetVolume(float volume)484 int32_t ProRendererStreamImpl::OffloadSetVolume(float volume)
485 {
486 return SUCCESS;
487 }
488
GetWritableSize()489 size_t ProRendererStreamImpl::GetWritableSize()
490 {
491 return writeQueue_.size() * minBufferSize_;
492 }
493 // offload end
UpdateSpatializationState(bool spatializationEnabled,bool headTrackingEnabled)494 int32_t ProRendererStreamImpl::UpdateSpatializationState(bool spatializationEnabled, bool headTrackingEnabled)
495 {
496 return SUCCESS;
497 }
498
GetAudioProcessConfig() const499 AudioProcessConfig ProRendererStreamImpl::GetAudioProcessConfig() const noexcept
500 {
501 return processConfig_;
502 }
503
GetAudioTime(uint64_t & framePos,int64_t & sec,int64_t & nanoSec)504 bool ProRendererStreamImpl::GetAudioTime(uint64_t &framePos, int64_t &sec, int64_t &nanoSec)
505 {
506 GetStreamFramesWritten(framePos);
507 int64_t time = handleTimeModel_.GetTimeOfPos(framePos);
508 int64_t deltaTime = DEFAULT_BUFFER_MICROSECOND; // note: 20ms
509 time += deltaTime;
510 sec = time / AUDIO_NS_PER_S;
511 nanoSec = time % AUDIO_NS_PER_S;
512 return true;
513 }
514
Peek(std::vector<char> * audioBuffer,int32_t & index)515 int32_t ProRendererStreamImpl::Peek(std::vector<char> *audioBuffer, int32_t &index)
516 {
517 Trace trace("ProRendererStreamImpl::Peek::" + std::to_string(streamIndex_));
518 int32_t result = SUCCESS;
519 if (isBlock_) {
520 return ERR_WRITE_BUFFER;
521 }
522 if (!readQueue_.empty()) {
523 PopSinkBuffer(audioBuffer, index);
524 return result;
525 }
526
527 std::shared_ptr<IWriteCallback> writeCallback = writeCallback_.lock();
528 if (writeCallback != nullptr) {
529 result = writeCallback->OnWriteData(minBufferSize_);
530 switch (result) {
531 // As a low-risk change, temporarily keep the previous behavior
532 // and avoid enterring the err logic on underrun.
533 case ERR_RENDERER_IN_SERVER_UNDERRUN: {
534 auto statusCallback = statusCallback_.lock();
535 if (statusCallback != nullptr && isFirstNoUnderrunFrame_) {
536 statusCallback->OnStatusUpdate(OPERATION_UNDERFLOW);
537 }
538 [[fallthrough]];
539 }
540 case SUCCESS: {
541 PopSinkBuffer(audioBuffer, index);
542 if (result != ERR_RENDERER_IN_SERVER_UNDERRUN) {
543 isFirstNoUnderrunFrame_ = true;
544 result = SUCCESS;
545 }
546 break;
547 }
548 default: {
549 AUDIO_ERR_LOG("Write callback failed,result:%{public}d", result);
550 return result;
551 }
552 }
553 } else {
554 AUDIO_ERR_LOG("Write callback is nullptr");
555 result = ERR_WRITE_BUFFER;
556 }
557 return result;
558 }
559
ReturnIndex(int32_t index)560 int32_t ProRendererStreamImpl::ReturnIndex(int32_t index)
561 {
562 if (index < 0) {
563 return SUCCESS;
564 }
565 std::lock_guard lock(enqueueMutex);
566 writeQueue_.emplace(index);
567 return SUCCESS;
568 }
569
SetClientVolume(float clientVolume)570 int32_t ProRendererStreamImpl::SetClientVolume(float clientVolume)
571 {
572 AUDIO_INFO_LOG("clientVolume: %{public}f", clientVolume);
573 return SUCCESS;
574 }
575
UpdateMaxLength(uint32_t maxLength)576 int32_t ProRendererStreamImpl::UpdateMaxLength(uint32_t maxLength)
577 {
578 return SUCCESS;
579 }
580
PopWriteBufferIndex()581 int32_t ProRendererStreamImpl::PopWriteBufferIndex()
582 {
583 std::lock_guard lock(enqueueMutex);
584 int32_t writeIndex = -1;
585 if (!writeQueue_.empty()) {
586 writeIndex = writeQueue_.front();
587 writeQueue_.pop();
588 }
589 return writeIndex;
590 }
591
PopSinkBuffer(std::vector<char> * audioBuffer,int32_t & index)592 void ProRendererStreamImpl::PopSinkBuffer(std::vector<char> *audioBuffer, int32_t &index)
593 {
594 if (readQueue_.empty() && isFirstFrame_) {
595 std::unique_lock firstFrameLock(firstFrameMutex);
596 firstFrameSync_.wait_for(firstFrameLock, std::chrono::milliseconds(FIRST_FRAME_TIMEOUT_TIME),
597 [this] { return (!readQueue_.empty() || isBlock_); });
598 if (!readQueue_.empty()) {
599 isFirstFrame_ = false;
600 }
601 }
602 std::lock_guard lock(enqueueMutex);
603 if (!readQueue_.empty()) {
604 index = readQueue_.front();
605 readQueue_.pop();
606 *audioBuffer = sinkBuffer_[index];
607 }
608 if (readQueue_.empty() && isDrain_) {
609 drainSync_.notify_all();
610 }
611 }
612
SetOffloadDisable()613 void ProRendererStreamImpl::SetOffloadDisable()
614 {
615 std::shared_ptr<IStatusCallback> statusCallback = statusCallback_.lock();
616 if (statusCallback != nullptr) {
617 statusCallback->OnStatusUpdate(OPERATION_UNSET_OFFLOAD_ENABLE);
618 }
619 }
620
ConvertSrcToFloat(const BufferDesc & bufferDesc)621 void ProRendererStreamImpl::ConvertSrcToFloat(const BufferDesc &bufferDesc)
622 {
623 bufferInfo_.buffer = bufferDesc.buffer;
624 bufferInfo_.bufLength = bufferDesc.bufLength;
625 bufferInfo_.frameSize = bufferDesc.bufLength / bufferInfo_.samplePerFrame;
626
627 if (bufferInfo_.format == AudioSampleFormat::SAMPLE_F32LE) {
628 AudioCommonConverter::ConvertFloatToFloatWithVolume(bufferInfo_, resampleSrcBuffer);
629 return;
630 }
631 AUDIO_DEBUG_LOG("ConvertSrcToFloat resample buffer,samplePerFrame:%{public}d,size:%{public}zu",
632 bufferInfo_.samplePerFrame, resampleSrcBuffer.size());
633 AudioCommonConverter::ConvertBufferToFloat(bufferInfo_, resampleSrcBuffer);
634 }
635
ConvertFloatToDes(int32_t writeIndex)636 void ProRendererStreamImpl::ConvertFloatToDes(int32_t writeIndex)
637 {
638 uint32_t samplePerFrame = Util::GetSamplePerFrame(desFormat_);
639 if (desFormat_ == AudioSampleFormat::SAMPLE_F32LE) {
640 auto error = memcpy_s(sinkBuffer_[writeIndex].data(), sinkBuffer_[writeIndex].size(), resampleDesBuffer.data(),
641 resampleDesBuffer.size() * samplePerFrame);
642 if (error != EOK) {
643 AUDIO_ERR_LOG("copy failed");
644 }
645 return;
646 }
647 AudioCommonConverter::ConvertFloatToAudioBuffer(resampleDesBuffer,
648 reinterpret_cast<uint8_t *>(sinkBuffer_[writeIndex].data()), samplePerFrame);
649 }
650
GetStreamVolume()651 void ProRendererStreamImpl::GetStreamVolume()
652 {
653 if (processConfig_.streamType == STREAM_VOICE_COMMUNICATION) {
654 bufferInfo_.volumeBg = 1;
655 bufferInfo_.volumeEd = 1;
656 return;
657 }
658 AudioVolumeType volumeType = VolumeUtils::GetVolumeTypeFromStreamType(processConfig_.streamType);
659 bufferInfo_.volumeBg = AudioVolume::GetInstance()->GetHistoryVolume(streamIndex_);
660 bufferInfo_.volumeEd = AudioVolume::GetInstance()->GetVolume(streamIndex_, volumeType, DEVICE_NAME);
661 if (bufferInfo_.volumeBg != bufferInfo_.volumeEd) {
662 AudioVolume::GetInstance()->SetHistoryVolume(streamIndex_, bufferInfo_.volumeEd);
663 AudioVolume::GetInstance()->Monitor(streamIndex_, true);
664 AUDIO_INFO_LOG("audio volume begin:%{public}f,end:%{public}f", bufferInfo_.volumeBg, bufferInfo_.volumeEd);
665 }
666 }
667
InitBasicInfo(const AudioStreamInfo & streamInfo)668 void ProRendererStreamImpl::InitBasicInfo(const AudioStreamInfo &streamInfo)
669 {
670 currentRate_ = streamInfo.samplingRate;
671 desSamplingRate_ = GetDirectSampleRate(streamInfo.samplingRate);
672 desFormat_ = GetDirectFormat(streamInfo.format);
673 spanSizeInFrame_ = (streamInfo.samplingRate * DEFAULT_BUFFER_MILLISECOND) / SECOND_TO_MILLISECOND;
674 byteSizePerFrame_ = Util::GetSamplePerFrame(streamInfo.format) * streamInfo.channels;
675 minBufferSize_ = spanSizeInFrame_ * byteSizePerFrame_;
676 handleTimeModel_.ConfigSampleRate(currentRate_);
677 bufferInfo_.channelCount = streamInfo.channels;
678 bufferInfo_.format = streamInfo.format;
679 bufferInfo_.samplePerFrame = Util::GetSamplePerFrame(streamInfo.format);
680 bufferInfo_.frameSize = spanSizeInFrame_;
681 }
682
BlockStream()683 void ProRendererStreamImpl::BlockStream() noexcept
684 {
685 isBlock_ = true;
686 AudioVolume::GetInstance()->SetHistoryVolume(streamIndex_, 0.f);
687 }
688 } // namespace AudioStandard
689 } // namespace OHOS
690