1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <chrono>
17 #include <thread>
18 #include <vector>
19
20 #include "audio_errors.h"
21 #include "audio_info.h"
22 #include "media_log.h"
23
24 #include "audio_stream.h"
25
26 using namespace std;
27
28 namespace OHOS {
29 namespace AudioStandard {
30 const unsigned long long TIME_CONVERSION_US_S = 1000000ULL; /* us to s */
31 const unsigned long long TIME_CONVERSION_NS_US = 1000ULL; /* ns to us */
32 const unsigned long long TIME_CONVERSION_NS_S = 1000000000ULL; /* ns to s */
33 constexpr int32_t WRITE_RETRY_DELAY_IN_US = 500;
34 constexpr int32_t READ_WRITE_WAIT_TIME_IN_US = 500;
35 constexpr int32_t CB_WRITE_BUFFERS_WAIT_IN_US = 500;
36
37 const map<pair<ContentType, StreamUsage>, AudioStreamType> AudioStream::streamTypeMap_ = AudioStream::CreateStreamMap();
38
CreateStreamMap()39 map<pair<ContentType, StreamUsage>, AudioStreamType> AudioStream::CreateStreamMap()
40 {
41 map<pair<ContentType, StreamUsage>, AudioStreamType> streamMap;
42
43 streamMap[make_pair(CONTENT_TYPE_UNKNOWN, STREAM_USAGE_UNKNOWN)] = STREAM_MUSIC;
44 streamMap[make_pair(CONTENT_TYPE_UNKNOWN, STREAM_USAGE_MEDIA)] = STREAM_MUSIC;
45 streamMap[make_pair(CONTENT_TYPE_UNKNOWN, STREAM_USAGE_VOICE_COMMUNICATION)] = STREAM_MUSIC;
46 streamMap[make_pair(CONTENT_TYPE_UNKNOWN, STREAM_USAGE_VOICE_ASSISTANT)] = STREAM_MUSIC;
47 streamMap[make_pair(CONTENT_TYPE_UNKNOWN, STREAM_USAGE_NOTIFICATION_RINGTONE)] = STREAM_MUSIC;
48
49 streamMap[make_pair(CONTENT_TYPE_SPEECH, STREAM_USAGE_UNKNOWN)] = STREAM_MUSIC;
50 streamMap[make_pair(CONTENT_TYPE_SPEECH, STREAM_USAGE_MEDIA)] = STREAM_VOICE_ASSISTANT;
51 streamMap[make_pair(CONTENT_TYPE_SPEECH, STREAM_USAGE_VOICE_COMMUNICATION)] = STREAM_VOICE_CALL;
52 streamMap[make_pair(CONTENT_TYPE_SPEECH, STREAM_USAGE_VOICE_ASSISTANT)] = STREAM_VOICE_ASSISTANT;
53 streamMap[make_pair(CONTENT_TYPE_SPEECH, STREAM_USAGE_NOTIFICATION_RINGTONE)] = STREAM_MUSIC;
54
55 streamMap[make_pair(CONTENT_TYPE_MUSIC, STREAM_USAGE_UNKNOWN)] = STREAM_MUSIC;
56 streamMap[make_pair(CONTENT_TYPE_MUSIC, STREAM_USAGE_MEDIA)] = STREAM_MUSIC;
57 streamMap[make_pair(CONTENT_TYPE_MUSIC, STREAM_USAGE_VOICE_COMMUNICATION)] = STREAM_MUSIC;
58 streamMap[make_pair(CONTENT_TYPE_MUSIC, STREAM_USAGE_VOICE_ASSISTANT)] = STREAM_VOICE_ASSISTANT;
59 streamMap[make_pair(CONTENT_TYPE_MUSIC, STREAM_USAGE_NOTIFICATION_RINGTONE)] = STREAM_RING;
60
61 streamMap[make_pair(CONTENT_TYPE_MOVIE, STREAM_USAGE_UNKNOWN)] = STREAM_MEDIA;
62 streamMap[make_pair(CONTENT_TYPE_MOVIE, STREAM_USAGE_MEDIA)] = STREAM_MEDIA;
63 streamMap[make_pair(CONTENT_TYPE_MOVIE, STREAM_USAGE_VOICE_COMMUNICATION)] = STREAM_MUSIC;
64 streamMap[make_pair(CONTENT_TYPE_MOVIE, STREAM_USAGE_VOICE_ASSISTANT)] = STREAM_MUSIC;
65 streamMap[make_pair(CONTENT_TYPE_MOVIE, STREAM_USAGE_NOTIFICATION_RINGTONE)] = STREAM_MUSIC;
66
67 streamMap[make_pair(CONTENT_TYPE_SONIFICATION, STREAM_USAGE_UNKNOWN)] = STREAM_NOTIFICATION;
68 streamMap[make_pair(CONTENT_TYPE_SONIFICATION, STREAM_USAGE_MEDIA)] = STREAM_NOTIFICATION;
69 streamMap[make_pair(CONTENT_TYPE_SONIFICATION, STREAM_USAGE_VOICE_COMMUNICATION)] = STREAM_MUSIC;
70 streamMap[make_pair(CONTENT_TYPE_SONIFICATION, STREAM_USAGE_VOICE_ASSISTANT)] = STREAM_MUSIC;
71 streamMap[make_pair(CONTENT_TYPE_SONIFICATION, STREAM_USAGE_NOTIFICATION_RINGTONE)] = STREAM_MUSIC;
72
73 streamMap[make_pair(CONTENT_TYPE_RINGTONE, STREAM_USAGE_UNKNOWN)] = STREAM_RING;
74 streamMap[make_pair(CONTENT_TYPE_RINGTONE, STREAM_USAGE_MEDIA)] = STREAM_RING;
75 streamMap[make_pair(CONTENT_TYPE_RINGTONE, STREAM_USAGE_VOICE_COMMUNICATION)] = STREAM_MUSIC;
76 streamMap[make_pair(CONTENT_TYPE_RINGTONE, STREAM_USAGE_VOICE_ASSISTANT)] = STREAM_MUSIC;
77 streamMap[make_pair(CONTENT_TYPE_RINGTONE, STREAM_USAGE_NOTIFICATION_RINGTONE)] = STREAM_RING;
78
79 return streamMap;
80 }
81
AudioStream(AudioStreamType eStreamType,AudioMode eMode)82 AudioStream::AudioStream(AudioStreamType eStreamType, AudioMode eMode) : eStreamType_(eStreamType),
83 eMode_(eMode),
84 state_(NEW),
85 isReadInProgress_(false),
86 isWriteInProgress_(false),
87 resetTime_(false),
88 resetTimestamp_(0),
89 renderMode_(RENDER_MODE_NORMAL),
90 isReadyToWrite_(false),
91 isFirstRead_(false)
92 {
93 MEDIA_DEBUG_LOG("AudioStream ctor");
94 }
95
~AudioStream()96 AudioStream::~AudioStream()
97 {
98 isReadyToWrite_ = false;
99 if (writeThread_ && writeThread_->joinable()) {
100 writeThread_->join();
101 }
102
103 if (state_ != RELEASED && state_ != NEW) {
104 ReleaseAudioStream();
105 }
106 }
107
GetState()108 State AudioStream::GetState()
109 {
110 return state_;
111 }
112
GetAudioSessionID(uint32_t & sessionID) const113 int32_t AudioStream::GetAudioSessionID(uint32_t &sessionID) const
114 {
115 if ((state_ == RELEASED) || (state_ == NEW)) {
116 return ERR_ILLEGAL_STATE;
117 }
118
119 if (GetSessionID(sessionID) != 0) {
120 return ERR_INVALID_INDEX;
121 }
122
123 return SUCCESS;
124 }
125
GetAudioTime(Timestamp & timestamp,Timestamp::Timestampbase base)126 bool AudioStream::GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base)
127 {
128 uint64_t paTimeStamp = 0;
129 if (GetCurrentTimeStamp(paTimeStamp) == SUCCESS) {
130 if (resetTime_) {
131 MEDIA_INFO_LOG("AudioStream::GetAudioTime resetTime_ %{public}d", resetTime_);
132 resetTime_ = false;
133 resetTimestamp_ = paTimeStamp;
134 }
135
136 timestamp.time.tv_sec = static_cast<time_t>((paTimeStamp - resetTimestamp_) / TIME_CONVERSION_US_S);
137 timestamp.time.tv_nsec
138 = static_cast<time_t>(((paTimeStamp - resetTimestamp_) - (timestamp.time.tv_sec * TIME_CONVERSION_US_S))
139 * TIME_CONVERSION_NS_US);
140 timestamp.time.tv_sec += baseTimestamp_.tv_sec;
141 timestamp.time.tv_nsec += baseTimestamp_.tv_nsec;
142 timestamp.time.tv_sec += (timestamp.time.tv_nsec / TIME_CONVERSION_NS_S);
143 timestamp.time.tv_nsec = (timestamp.time.tv_nsec % TIME_CONVERSION_NS_S);
144
145 return true;
146 }
147 return false;
148 }
149
GetBufferSize(size_t & bufferSize) const150 int32_t AudioStream::GetBufferSize(size_t &bufferSize) const
151 {
152 MEDIA_INFO_LOG("AudioStream: Get Buffer size");
153 if (GetMinimumBufferSize(bufferSize) != 0) {
154 return ERR_OPERATION_FAILED;
155 }
156
157 return SUCCESS;
158 }
159
GetFrameCount(uint32_t & frameCount) const160 int32_t AudioStream::GetFrameCount(uint32_t &frameCount) const
161 {
162 MEDIA_INFO_LOG("AudioStream: Get frame count");
163 if (GetMinimumFrameCount(frameCount) != 0) {
164 return ERR_OPERATION_FAILED;
165 }
166
167 return SUCCESS;
168 }
169
GetLatency(uint64_t & latency) const170 int32_t AudioStream::GetLatency(uint64_t &latency) const
171 {
172 if (GetAudioLatency(latency) != SUCCESS) {
173 return ERR_OPERATION_FAILED;
174 } else {
175 return SUCCESS;
176 }
177 }
178
GetSupportedFormats() const179 vector<AudioSampleFormat> AudioStream::GetSupportedFormats() const
180 {
181 return AUDIO_SUPPORTED_FORMATS;
182 }
183
GetSupportedChannels() const184 vector<AudioChannel> AudioStream::GetSupportedChannels() const
185 {
186 return AUDIO_SUPPORTED_CHANNELS;
187 }
188
GetSupportedEncodingTypes() const189 vector<AudioEncodingType> AudioStream::GetSupportedEncodingTypes() const
190 {
191 return AUDIO_SUPPORTED_ENCODING_TYPES;
192 }
193
GetSupportedSamplingRates() const194 vector<AudioSamplingRate> AudioStream::GetSupportedSamplingRates() const
195 {
196 return AUDIO_SUPPORTED_SAMPLING_RATES;
197 }
198
IsFormatValid(uint8_t format)199 bool IsFormatValid(uint8_t format)
200 {
201 bool isValidFormat = (find(AUDIO_SUPPORTED_FORMATS.begin(), AUDIO_SUPPORTED_FORMATS.end(), format)
202 != AUDIO_SUPPORTED_FORMATS.end());
203 MEDIA_DEBUG_LOG("AudioStream: IsFormatValid: %{public}s", isValidFormat ? "true" : "false");
204 return isValidFormat;
205 }
206
IsChannelValid(uint8_t channel)207 bool IsChannelValid(uint8_t channel)
208 {
209 bool isValidChannel = (find(AUDIO_SUPPORTED_CHANNELS.begin(), AUDIO_SUPPORTED_CHANNELS.end(), channel)
210 != AUDIO_SUPPORTED_CHANNELS.end());
211 MEDIA_DEBUG_LOG("AudioStream: IsChannelValid: %{public}s", isValidChannel ? "true" : "false");
212 return isValidChannel;
213 }
214
IsEncodingTypeValid(uint8_t encodingType)215 bool IsEncodingTypeValid(uint8_t encodingType)
216 {
217 bool isValidEncodingType
218 = (find(AUDIO_SUPPORTED_ENCODING_TYPES.begin(), AUDIO_SUPPORTED_ENCODING_TYPES.end(), encodingType)
219 != AUDIO_SUPPORTED_ENCODING_TYPES.end());
220 MEDIA_DEBUG_LOG("AudioStream: IsEncodingTypeValid: %{public}s",
221 isValidEncodingType ? "true" : "false");
222 return isValidEncodingType;
223 }
224
IsSamplingRateValid(uint32_t samplingRate)225 bool IsSamplingRateValid(uint32_t samplingRate)
226 {
227 bool isValidSamplingRate
228 = (find(AUDIO_SUPPORTED_SAMPLING_RATES.begin(), AUDIO_SUPPORTED_SAMPLING_RATES.end(), samplingRate)
229 != AUDIO_SUPPORTED_SAMPLING_RATES.end());
230 MEDIA_DEBUG_LOG("AudioStream: IsSamplingRateValid: %{public}s",
231 isValidSamplingRate ? "true" : "false");
232 return isValidSamplingRate;
233 }
234
GetAudioStreamInfo(AudioStreamParams & audioStreamInfo)235 int32_t AudioStream::GetAudioStreamInfo(AudioStreamParams &audioStreamInfo)
236 {
237 MEDIA_INFO_LOG("AudioStream: GetAudioStreamInfo");
238 if (GetAudioStreamParams(audioStreamInfo) != 0) {
239 return ERR_OPERATION_FAILED;
240 }
241
242 return SUCCESS;
243 }
244
SetAudioStreamInfo(const AudioStreamParams info)245 int32_t AudioStream::SetAudioStreamInfo(const AudioStreamParams info)
246 {
247 MEDIA_INFO_LOG("AudioStream: SetAudioParams");
248
249 MEDIA_DEBUG_LOG("AudioStream: Sampling rate: %{public}d", info.samplingRate);
250 MEDIA_DEBUG_LOG("AudioStream: channels: %{public}d", info.channels);
251 MEDIA_DEBUG_LOG("AudioStream: format: %{public}d", info.format);
252 MEDIA_DEBUG_LOG("AudioStream: stream type: %{public}d", eStreamType_);
253
254 if (!IsFormatValid(info.format) || !IsChannelValid(info.channels)
255 || !IsSamplingRateValid(info.samplingRate) || !IsEncodingTypeValid(info.encoding)) {
256 MEDIA_ERR_LOG("AudioStream: Unsupported audio parameter");
257 return ERR_NOT_SUPPORTED;
258 }
259 if (state_ != NEW) {
260 MEDIA_DEBUG_LOG("AudioStream: State is not new, release existing stream");
261 StopAudioStream();
262 ReleaseAudioStream();
263 }
264
265 int32_t ret = 0;
266 switch (eMode_) {
267 case AUDIO_MODE_PLAYBACK:
268 MEDIA_DEBUG_LOG("AudioStream: Initialize playback");
269 ret = Initialize(AUDIO_SERVICE_CLIENT_PLAYBACK);
270 break;
271 case AUDIO_MODE_RECORD:
272 MEDIA_DEBUG_LOG("AudioStream: Initialize recording");
273 ret = Initialize(AUDIO_SERVICE_CLIENT_RECORD);
274 break;
275 default:
276 return ERR_INVALID_OPERATION;
277 }
278
279 if (ret) {
280 MEDIA_DEBUG_LOG("AudioStream: Error initializing!");
281 return ret;
282 }
283
284 if (CreateStream(info, eStreamType_) != SUCCESS) {
285 MEDIA_ERR_LOG("AudioStream:Create stream failed");
286 return ERROR;
287 }
288
289 state_ = PREPARED;
290 MEDIA_INFO_LOG("AudioStream:Set stream Info SUCCESS");
291 return SUCCESS;
292 }
293
StartAudioStream()294 bool AudioStream::StartAudioStream()
295 {
296 if ((state_ != PREPARED) && (state_ != STOPPED) && (state_ != PAUSED)) {
297 MEDIA_ERR_LOG("StartAudioStream Illegal state:%{public}u", state_);
298 return false;
299 }
300
301 int32_t ret = StartStream();
302 if (ret != SUCCESS) {
303 MEDIA_ERR_LOG("StartStream Start failed:%{public}d", ret);
304 return false;
305 }
306
307 resetTime_ = true;
308 int32_t retCode = clock_gettime(CLOCK_MONOTONIC, &baseTimestamp_);
309 if (retCode != 0) {
310 MEDIA_ERR_LOG("AudioStream::StartAudioStream get system elapsed time failed: %d", retCode);
311 }
312
313 if (renderMode_ == RENDER_MODE_CALLBACK) {
314 isReadyToWrite_ = true;
315 writeThread_ = std::make_unique<std::thread>(&AudioStream::WriteBuffers, this);
316 }
317
318 isFirstRead_ = true;
319 state_ = RUNNING;
320 MEDIA_INFO_LOG("StartAudioStream SUCCESS");
321 return true;
322 }
323
Read(uint8_t & buffer,size_t userSize,bool isBlockingRead)324 int32_t AudioStream::Read(uint8_t &buffer, size_t userSize, bool isBlockingRead)
325 {
326 if (userSize <= 0) {
327 MEDIA_ERR_LOG("Invalid userSize:%{public}zu", userSize);
328 return ERR_INVALID_PARAM;
329 }
330
331 if (state_ != RUNNING) {
332 MEDIA_ERR_LOG("Read: State is not RUNNNIG. Illegal state:%{public}u", state_);
333 return ERR_ILLEGAL_STATE;
334 }
335
336 if (isFirstRead_) {
337 FlushAudioStream();
338 isFirstRead_ = false;
339 }
340
341 StreamBuffer stream;
342 stream.buffer = &buffer;
343 stream.bufferLen = userSize;
344 isReadInProgress_ = true;
345 int32_t readLen = ReadStream(stream, isBlockingRead);
346 isReadInProgress_ = false;
347 if (readLen < 0) {
348 MEDIA_ERR_LOG("ReadStream fail,ret:%{public}d", readLen);
349 return ERR_INVALID_READ;
350 }
351
352 return readLen;
353 }
354
Write(uint8_t * buffer,size_t buffer_size)355 size_t AudioStream::Write(uint8_t *buffer, size_t buffer_size)
356 {
357 if (renderMode_ == RENDER_MODE_CALLBACK) {
358 MEDIA_ERR_LOG("AudioStream::Write not supported. RenderMode is callback");
359 return ERR_INCORRECT_MODE;
360 }
361
362 if ((buffer == nullptr) || (buffer_size <= 0)) {
363 MEDIA_ERR_LOG("Invalid buffer size:%{public}zu", buffer_size);
364 return ERR_INVALID_PARAM;
365 }
366
367 if (state_ != RUNNING) {
368 MEDIA_ERR_LOG("Write: Illegal state:%{public}u", state_);
369 // To allow context switch for APIs running in different thread contexts
370 std::this_thread::sleep_for(std::chrono::microseconds(WRITE_RETRY_DELAY_IN_US));
371 return ERR_ILLEGAL_STATE;
372 }
373
374 int32_t writeError;
375 StreamBuffer stream;
376 stream.buffer = buffer;
377 stream.bufferLen = buffer_size;
378 isWriteInProgress_ = true;
379 size_t bytesWritten = WriteStream(stream, writeError);
380 isWriteInProgress_ = false;
381 if (writeError != 0) {
382 MEDIA_ERR_LOG("WriteStream fail,writeError:%{public}d", writeError);
383 return ERR_WRITE_FAILED;
384 }
385 if (bytesWritten < 0) {
386 MEDIA_ERR_LOG("WriteStream fail,bytesWritten:%{public}zu", bytesWritten);
387 return ERR_INVALID_WRITE;
388 }
389
390 return bytesWritten;
391 }
392
PauseAudioStream()393 bool AudioStream::PauseAudioStream()
394 {
395 if (state_ != RUNNING) {
396 MEDIA_ERR_LOG("PauseAudioStream: State is not RUNNING. Illegal state:%{public}u", state_);
397 return false;
398 }
399 State oldState = state_;
400 state_ = PAUSED; // Set it before stopping as Read/Write and Stop can be called from different threads
401 while (isReadInProgress_ || isWriteInProgress_) {
402 std::this_thread::sleep_for(std::chrono::microseconds(READ_WRITE_WAIT_TIME_IN_US));
403 }
404
405 int32_t ret = PauseStream();
406 if (ret != SUCCESS) {
407 MEDIA_DEBUG_LOG("StreamPause fail,ret:%{public}d", ret);
408 state_ = oldState;
409 return false;
410 }
411
412 // Ends the WriteBuffers thread
413 if (renderMode_ == RENDER_MODE_CALLBACK) {
414 isReadyToWrite_ = false;
415 }
416
417 MEDIA_INFO_LOG("PauseAudioStream SUCCESS");
418
419 return true;
420 }
421
StopAudioStream()422 bool AudioStream::StopAudioStream()
423 {
424 MEDIA_INFO_LOG("AudioStream: StopAudioStream begin");
425 if (state_ == PAUSED) {
426 state_ = STOPPED;
427 MEDIA_INFO_LOG("StopAudioStream SUCCESS");
428 return true;
429 }
430
431 if (state_ != RUNNING) {
432 MEDIA_ERR_LOG("StopAudioStream: State is not RUNNING. Illegal state:%{public}u", state_);
433 return false;
434 }
435 State oldState = state_;
436 state_ = STOPPED; // Set it before stopping as Read/Write and Stop can be called from different threads
437 while (isReadInProgress_ || isWriteInProgress_) {
438 std::this_thread::sleep_for(std::chrono::microseconds(READ_WRITE_WAIT_TIME_IN_US));
439 }
440
441 int32_t ret = StopStream();
442 if (ret != SUCCESS) {
443 MEDIA_DEBUG_LOG("StreamStop fail,ret:%{public}d", ret);
444 state_ = oldState;
445 return false;
446 }
447
448 // Ends the WriteBuffers thread
449 if (renderMode_ == RENDER_MODE_CALLBACK) {
450 isReadyToWrite_ = false;
451 }
452
453 MEDIA_INFO_LOG("StopAudioStream SUCCESS");
454
455 return true;
456 }
457
FlushAudioStream()458 bool AudioStream::FlushAudioStream()
459 {
460 if ((state_ != RUNNING) && (state_ != PAUSED) && (state_ != STOPPED)) {
461 MEDIA_ERR_LOG("FlushAudioStream: State is not RUNNING. Illegal state:%{public}u", state_);
462 return false;
463 }
464
465 int32_t ret = FlushStream();
466 if (ret != SUCCESS) {
467 MEDIA_DEBUG_LOG("Flush stream fail,ret:%{public}d", ret);
468 return false;
469 }
470
471 MEDIA_INFO_LOG("Flush stream SUCCESS");
472 return true;
473 }
474
DrainAudioStream()475 bool AudioStream::DrainAudioStream()
476 {
477 if (state_ != RUNNING) {
478 MEDIA_ERR_LOG("DrainAudioStream: State is not RUNNING. Illegal state:%{public}u", state_);
479 return false;
480 }
481
482 int32_t ret = DrainStream();
483 if (ret != SUCCESS) {
484 MEDIA_DEBUG_LOG("Drain stream fail,ret:%{public}d", ret);
485 return false;
486 }
487
488 MEDIA_INFO_LOG("Drain stream SUCCESS");
489 return true;
490 }
491
ReleaseAudioStream()492 bool AudioStream::ReleaseAudioStream()
493 {
494 if (state_ == RELEASED || state_ == NEW) {
495 MEDIA_ERR_LOG("Illegal state: state = %{public}u", state_);
496 return false;
497 }
498 // If state_ is RUNNING try to Stop it first and Release
499 if (state_ == RUNNING) {
500 StopAudioStream();
501 }
502
503 ReleaseStream();
504 state_ = RELEASED;
505 MEDIA_INFO_LOG("ReleaseAudiostream SUCCESS");
506
507 return true;
508 }
509
GetStreamType(ContentType contentType,StreamUsage streamUsage)510 AudioStreamType AudioStream::GetStreamType(ContentType contentType, StreamUsage streamUsage)
511 {
512 AudioStreamType streamType = STREAM_MUSIC;
513 auto pos = streamTypeMap_.find(make_pair(contentType, streamUsage));
514 if (pos != streamTypeMap_.end()) {
515 streamType = pos->second;
516 }
517
518 if (streamType == STREAM_MEDIA) {
519 streamType = STREAM_MUSIC;
520 }
521
522 return streamType;
523 }
524
SetAudioStreamType(AudioStreamType audioStreamType)525 int32_t AudioStream::SetAudioStreamType(AudioStreamType audioStreamType)
526 {
527 return SetStreamType(audioStreamType);
528 }
529
SetVolume(float volume)530 int32_t AudioStream::SetVolume(float volume)
531 {
532 return SetStreamVolume(volume);
533 }
534
GetVolume()535 float AudioStream::GetVolume()
536 {
537 return GetStreamVolume();
538 }
539
SetRenderRate(AudioRendererRate renderRate)540 int32_t AudioStream::SetRenderRate(AudioRendererRate renderRate)
541 {
542 return SetStreamRenderRate(renderRate);
543 }
544
GetRenderRate()545 AudioRendererRate AudioStream::GetRenderRate()
546 {
547 return GetStreamRenderRate();
548 }
549
SetStreamCallback(const std::shared_ptr<AudioStreamCallback> & callback)550 int32_t AudioStream::SetStreamCallback(const std::shared_ptr<AudioStreamCallback> &callback)
551 {
552 if (callback == nullptr) {
553 MEDIA_ERR_LOG("AudioStream::SetStreamCallback failed. callback == nullptr");
554 return ERR_INVALID_PARAM;
555 }
556
557 SaveStreamCallback(callback);
558
559 return SUCCESS;
560 }
561
SetRenderMode(AudioRenderMode renderMode)562 int32_t AudioStream::SetRenderMode(AudioRenderMode renderMode)
563 {
564 int32_t ret = SetAudioRenderMode(renderMode);
565 if (ret) {
566 MEDIA_ERR_LOG("AudioStream::SetRenderMode: renderMode: %{public}d failed", renderMode);
567 return ERR_OPERATION_FAILED;
568 }
569 renderMode_ = renderMode;
570
571 for (int32_t i = 0; i < MAX_NUM_BUFFERS; ++i) {
572 size_t length;
573 GetMinimumBufferSize(length);
574 MEDIA_INFO_LOG("AudioServiceClient:: GetMinimumBufferSize: %{public}zu", length);
575
576 bufferPool_[i] = std::make_unique<uint8_t[]>(length);
577 if (bufferPool_[i] == nullptr) {
578 MEDIA_INFO_LOG("AudioServiceClient::GetBufferDescriptor bufferPool_[i]==nullptr. Allocate memory failed.");
579 return ERR_OPERATION_FAILED;
580 }
581
582 BufferDesc bufDesc {};
583 bufDesc.buffer = bufferPool_[i].get();
584 bufDesc.bufLength = length;
585 freeBufferQ_.emplace(bufDesc);
586 }
587
588 return SUCCESS;
589 }
590
GetRenderMode()591 AudioRenderMode AudioStream::GetRenderMode()
592 {
593 return GetAudioRenderMode();
594 }
595
SetRendererWriteCallback(const std::shared_ptr<AudioRendererWriteCallback> & callback)596 int32_t AudioStream::SetRendererWriteCallback(const std::shared_ptr<AudioRendererWriteCallback> &callback)
597 {
598 if (renderMode_ != RENDER_MODE_CALLBACK) {
599 MEDIA_ERR_LOG("AudioStream::SetRendererWriteCallback not supported. Render mode is not callback.");
600 return ERR_INCORRECT_MODE;
601 }
602
603 int32_t ret = SaveWriteCallback(callback);
604 if (ret) {
605 MEDIA_ERR_LOG("AudioStream::SetRendererWriteCallback: failed");
606 return ERR_INVALID_PARAM;
607 }
608
609 return SUCCESS;
610 }
611
GetBufferDesc(BufferDesc & bufDesc)612 int32_t AudioStream::GetBufferDesc(BufferDesc &bufDesc)
613 {
614 if (renderMode_ != RENDER_MODE_CALLBACK) {
615 MEDIA_ERR_LOG("AudioStream::GetBufferDesc not supported. Render mode is not callback.");
616 return ERR_INCORRECT_MODE;
617 }
618
619 MEDIA_INFO_LOG("AudioStream::freeBufferQ_ count %{public}zu", freeBufferQ_.size());
620 MEDIA_INFO_LOG("AudioStream::filledBufferQ_ count %{public}zu", filledBufferQ_.size());
621
622 if (!freeBufferQ_.empty()) {
623 bufDesc.buffer = freeBufferQ_.front().buffer;
624 bufDesc.bufLength = freeBufferQ_.front().bufLength;
625 freeBufferQ_.pop();
626 } else {
627 bufDesc.buffer = nullptr;
628 }
629
630 if (bufDesc.buffer == nullptr) {
631 MEDIA_INFO_LOG("AudioStream::GetBufferDesc freeBufferQ_.empty()");
632 return ERR_OPERATION_FAILED;
633 }
634
635 return SUCCESS;
636 }
637
Enqueue(const BufferDesc & bufDesc)638 int32_t AudioStream::Enqueue(const BufferDesc &bufDesc)
639 {
640 MEDIA_INFO_LOG("AudioStream::Enqueue");
641 if (renderMode_ != RENDER_MODE_CALLBACK) {
642 MEDIA_ERR_LOG("AudioStream::Enqueue not supported. Render mode is not callback.");
643 return ERR_INCORRECT_MODE;
644 }
645
646 if (bufDesc.buffer == nullptr) {
647 MEDIA_ERR_LOG("AudioStream::Enqueue: failed. bufDesc.buffer == nullptr.");
648 return ERR_INVALID_PARAM;
649 }
650 filledBufferQ_.emplace(bufDesc);
651
652 return SUCCESS;
653 }
654
Clear()655 int32_t AudioStream::Clear()
656 {
657 if (renderMode_ != RENDER_MODE_CALLBACK) {
658 MEDIA_ERR_LOG("AudioStream::Clear not supported. Render mode is not callback.");
659 return ERR_INCORRECT_MODE;
660 }
661
662 while (!filledBufferQ_.empty()) {
663 freeBufferQ_.emplace(filledBufferQ_.front());
664 filledBufferQ_.pop();
665 }
666
667 return SUCCESS;
668 }
669
WriteBuffers()670 void AudioStream::WriteBuffers()
671 {
672 MEDIA_INFO_LOG("AudioStream::WriteBuffers thread start");
673 StreamBuffer stream;
674 size_t bytesWritten;
675 int32_t writeError;
676
677 while (isReadyToWrite_) {
678 while (!filledBufferQ_.empty()) {
679 if (state_ != RUNNING) {
680 MEDIA_ERR_LOG("Write: Illegal state:%{public}u", state_);
681 isReadyToWrite_ = false;
682 return;
683 }
684 MEDIA_DEBUG_LOG("AudioStream::WriteBuffers !filledBufferQ_.empty()");
685 stream.buffer = filledBufferQ_.front().buffer;
686 stream.bufferLen = filledBufferQ_.front().dataLength;
687 MEDIA_DEBUG_LOG("AudioStream::WriteBuffers stream.bufferLen:%{public}d", stream.bufferLen);
688 freeBufferQ_.emplace(filledBufferQ_.front());
689 filledBufferQ_.pop();
690 if (stream.buffer == nullptr) {
691 continue;
692 }
693 bytesWritten = WriteStreamInCb(stream, writeError);
694 if (writeError != 0) {
695 MEDIA_ERR_LOG("AudioStream::WriteStreamInCb fail, writeError:%{public}d", writeError);
696 }
697 MEDIA_INFO_LOG("AudioStream::WriteBuffers WriteStream, bytesWritten:%{public}zu", bytesWritten);
698 }
699 std::this_thread::sleep_for(std::chrono::microseconds(CB_WRITE_BUFFERS_WAIT_IN_US));
700 }
701 MEDIA_INFO_LOG("AudioStream::WriteBuffers thread end");
702 }
703 } // namespace AudioStandard
704 } // namespace OHOS
705