1
2 /*
3 * Copyright (C) 2023 Huawei Device Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "cache_buffer.h"
18 #include "media_log.h"
19 #include "media_errors.h"
20
21 namespace OHOS {
22 namespace Media {
CacheBuffer(const MediaAVCodec::Format & trackFormat,const std::deque<std::shared_ptr<AudioBufferEntry>> & cacheData,const size_t & cacheDataTotalSize,const int32_t & soundID,const int32_t & streamID)23 CacheBuffer::CacheBuffer(const MediaAVCodec::Format &trackFormat,
24 const std::deque<std::shared_ptr<AudioBufferEntry>> &cacheData,
25 const size_t &cacheDataTotalSize, const int32_t &soundID, const int32_t &streamID) : trackFormat_(trackFormat),
26 cacheData_(cacheData), cacheDataTotalSize_(cacheDataTotalSize), soundID_(soundID), streamID_(streamID),
27 cacheDataFrameNum_(0), havePlayedCount_(0)
28
29 {
30 MEDIA_INFO_LOG("Construction CacheBuffer");
31 }
32
~CacheBuffer()33 CacheBuffer::~CacheBuffer()
34 {
35 MEDIA_INFO_LOG("Destruction CacheBuffer dec");
36 Release();
37 }
38
CreateAudioRenderer(const int32_t streamID,const AudioStandard::AudioRendererInfo audioRendererInfo,const PlayParams playParams)39 std::unique_ptr<AudioStandard::AudioRenderer> CacheBuffer::CreateAudioRenderer(const int32_t streamID,
40 const AudioStandard::AudioRendererInfo audioRendererInfo, const PlayParams playParams)
41 {
42 CHECK_AND_RETURN_RET_LOG(streamID == streamID_, nullptr,
43 "Invalid streamID, failed to create normal audioRenderer.");
44 int32_t sampleRate;
45 int32_t sampleFormat;
46 int32_t channelCount;
47 AudioStandard::AudioRendererOptions rendererOptions = {};
48 // Set to PCM encoding
49 rendererOptions.streamInfo.encoding = AudioStandard::AudioEncodingType::ENCODING_PCM;
50 // Get sample rate from trackFormat and set it to audiorender.
51 trackFormat_.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_SAMPLE_RATE, sampleRate);
52 rendererOptions.streamInfo.samplingRate = static_cast<AudioStandard::AudioSamplingRate>(sampleRate);
53 // Get sample format from trackFormat and set it to audiorender.
54 trackFormat_.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT, sampleFormat);
55 // Align audiorender capability
56 rendererOptions.streamInfo.format = static_cast<AudioStandard::AudioSampleFormat>(sampleFormat);
57 // Get channel count from trackFormat and set it to audiorender.
58 trackFormat_.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, channelCount);
59 rendererOptions.streamInfo.channels = static_cast<AudioStandard::AudioChannel>(channelCount);
60 // contentType streamUsage rendererFlags come from user.
61 rendererOptions.rendererInfo.contentType = audioRendererInfo.contentType;
62 rendererOptions.rendererInfo.streamUsage = audioRendererInfo.streamUsage;
63 rendererOptions.privacyType = AudioStandard::PRIVACY_TYPE_PUBLIC;
64 std::string cacheDir = "/data/storage/el2/base/temp";
65 if (playParams.cacheDir != "") {
66 cacheDir = playParams.cacheDir;
67 }
68
69 MEDIA_INFO_LOG("CacheBuffer sampleRate:%{public}d, sampleFormat:%{public}d, channelCount:%{public}d.",
70 sampleRate, sampleFormat, channelCount);
71 // low-latency:1, non low-latency:0
72 if ((rendererOptions.streamInfo.samplingRate == AudioStandard::AudioSamplingRate::SAMPLE_RATE_48000) &&
73 (rendererOptions.streamInfo.channels == AudioStandard::AudioChannel::MONO ||
74 rendererOptions.streamInfo.channels == AudioStandard::AudioChannel::STEREO)) {
75 // samplingRate 48KHz, channelCount 1/2
76 MEDIA_INFO_LOG("low latency support this rendererOptions.");
77 rendererFlags_ = audioRendererInfo.rendererFlags;
78 } else {
79 MEDIA_INFO_LOG("low latency didn't support this rendererOptions, force normal play.");
80 rendererFlags_ = NORMAL_PLAY_RENDERER_FLAGS;
81 }
82 rendererOptions.rendererInfo.rendererFlags = rendererFlags_;
83 std::unique_ptr<AudioStandard::AudioRenderer> audioRenderer =
84 AudioStandard::AudioRenderer::Create(cacheDir, rendererOptions);
85 CHECK_AND_RETURN_RET_LOG(audioRenderer != nullptr, nullptr, "Invalid audioRenderer.");
86 audioRenderer->SetRenderMode(AudioStandard::AudioRenderMode::RENDER_MODE_CALLBACK);
87 int32_t ret = audioRenderer->SetRendererWriteCallback(shared_from_this());
88 if (ret != MSERR_OK) {
89 MEDIA_ERR_LOG("audio renderer write callback fail, ret %{public}d.", ret);
90 }
91 return audioRenderer;
92 }
93
PreparePlay(const int32_t streamID,const AudioStandard::AudioRendererInfo audioRendererInfo,const PlayParams playParams)94 int32_t CacheBuffer::PreparePlay(const int32_t streamID, const AudioStandard::AudioRendererInfo audioRendererInfo,
95 const PlayParams playParams)
96 {
97 // create audioRenderer
98 if (audioRenderer_ == nullptr) {
99 audioRenderer_ = CreateAudioRenderer(streamID, audioRendererInfo, playParams);
100 ReCombineCacheData();
101 } else {
102 MEDIA_INFO_LOG("audio render inited.");
103 }
104 // deal play params
105 DealPlayParamsBeforePlay(streamID, playParams);
106 return MSERR_OK;
107 }
108
DoPlay(const int32_t streamID)109 int32_t CacheBuffer::DoPlay(const int32_t streamID)
110 {
111 CHECK_AND_RETURN_RET_LOG(streamID == streamID_, MSERR_INVALID_VAL, "Invalid streamID, failed to DoPlay.");
112 std::lock_guard lock(cacheBufferLock_);
113 if (audioRenderer_ != nullptr) {
114 isRunning_.store(true);
115 cacheDataFrameNum_ = 0;
116 havePlayedCount_ = 0;
117 if (!audioRenderer_->Start()) {
118 MEDIA_ERR_LOG("audioRenderer Start failed");
119 if (callback_ != nullptr) callback_->OnError(MSERR_INVALID_VAL);
120 if (cacheBufferCallback_ != nullptr) cacheBufferCallback_->OnError(MSERR_INVALID_VAL);
121 return MSERR_INVALID_VAL;
122 }
123 return MSERR_OK;
124 }
125 MEDIA_ERR_LOG("Invalid audioRenderer.");
126 return MSERR_INVALID_VAL;
127 }
128
ReCombineCacheData()129 int32_t CacheBuffer::ReCombineCacheData()
130 {
131 std::lock_guard lock(cacheBufferLock_);
132 CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid audioRenderer.");
133 CHECK_AND_RETURN_RET_LOG(!cacheData_.empty(), MSERR_INVALID_VAL, "empty cache data.");
134 size_t bufferSize;
135 audioRenderer_->GetBufferSize(bufferSize);
136 // Prevent data from crossing boundaries, ensure recombine data largest.
137 size_t reCombineCacheDataSize = (cacheDataTotalSize_ + bufferSize - 1) / bufferSize;
138 std::shared_ptr<AudioBufferEntry> preAudioBuffer = cacheData_.front();
139 size_t preAudioBufferIndex = 0;
140 for (size_t reCombineCacheDataNum = 0; reCombineCacheDataNum < reCombineCacheDataSize; reCombineCacheDataNum++) {
141 uint8_t *reCombineBuf = new(std::nothrow) uint8_t[bufferSize];
142 if (reCombineBuf == nullptr) {
143 MEDIA_ERR_LOG("Invalid recombine buffer.");
144 continue;
145 }
146 for (size_t bufferNum = 0; bufferNum < bufferSize; bufferNum++) {
147 if (cacheData_.size() > 1 && (preAudioBufferIndex == static_cast<size_t>(preAudioBuffer->size))) {
148 cacheData_.pop_front();
149 preAudioBuffer = cacheData_.front();
150 preAudioBufferIndex = 0;
151 }
152 if (cacheData_.size() == 1 && (preAudioBufferIndex == static_cast<size_t>(preAudioBuffer->size))) {
153 preAudioBuffer = cacheData_.front();
154 cacheData_.pop_front();
155 preAudioBufferIndex = 0;
156 }
157 if (cacheData_.empty()) {
158 reCombineBuf[bufferNum] = 0;
159 } else {
160 reCombineBuf[bufferNum] = preAudioBuffer->buffer[preAudioBufferIndex];
161 }
162 preAudioBufferIndex++;
163 }
164 reCombineCacheData_.push_back(std::make_shared<AudioBufferEntry>(reCombineBuf, bufferSize));
165 }
166 if (!cacheData_.empty()) {
167 cacheData_.clear();
168 }
169 return MSERR_OK;
170 }
171
DealPlayParamsBeforePlay(const int32_t streamID,const PlayParams playParams)172 int32_t CacheBuffer::DealPlayParamsBeforePlay(const int32_t streamID, const PlayParams playParams)
173 {
174 std::lock_guard lock(cacheBufferLock_);
175 CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, MSERR_INVALID_VAL, "Invalid audioRenderer.");
176 loop_ = playParams.loop;
177 audioRenderer_->SetRenderRate(CheckAndAlignRendererRate(playParams.rate));
178 audioRenderer_->SetVolume(playParams.leftVolume);
179 priority_ = playParams.priority;
180 audioRenderer_->SetParallelPlayFlag(playParams.parallelPlayFlag);
181 return MSERR_OK;
182 }
183
CheckAndAlignRendererRate(const int32_t rate)184 AudioStandard::AudioRendererRate CacheBuffer::CheckAndAlignRendererRate(const int32_t rate)
185 {
186 AudioStandard::AudioRendererRate renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL;
187 switch (rate) {
188 case AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL:
189 renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL;
190 break;
191 case AudioStandard::AudioRendererRate::RENDER_RATE_DOUBLE:
192 renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_DOUBLE;
193 break;
194 case AudioStandard::AudioRendererRate::RENDER_RATE_HALF:
195 renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_HALF;
196 break;
197 default:
198 renderRate = AudioStandard::AudioRendererRate::RENDER_RATE_NORMAL;
199 break;
200 }
201 return renderRate;
202 }
203
OnWriteData(size_t length)204 void CacheBuffer::OnWriteData(size_t length)
205 {
206 AudioStandard::BufferDesc bufDesc;
207 if (audioRenderer_ == nullptr) {
208 MEDIA_ERR_LOG("audioRenderer is nullptr.");
209 return;
210 }
211 if (!isRunning_.load()) {
212 MEDIA_ERR_LOG("audioRenderer is stop.");
213 return;
214 }
215 if (cacheDataFrameNum_ == reCombineCacheData_.size()) {
216 if (havePlayedCount_ == loop_) {
217 MEDIA_INFO_LOG("CacheBuffer stream write finish, cacheDataFrameNum_:%{public}zu,"
218 " havePlayedCount_:%{public}d, loop:%{public}d, try to stop.", cacheDataFrameNum_,
219 havePlayedCount_, loop_);
220 Stop(streamID_);
221 return;
222 }
223 cacheDataFrameNum_ = 0;
224 havePlayedCount_++;
225 }
226 audioRenderer_->GetBufferDesc(bufDesc);
227 std::shared_ptr<AudioBufferEntry> audioBuffer = reCombineCacheData_[cacheDataFrameNum_];
228
229 bufDesc.buffer = audioBuffer->buffer;
230 bufDesc.bufLength = static_cast<size_t>(audioBuffer->size);
231 bufDesc.dataLength = static_cast<size_t>(audioBuffer->size);
232
233 audioRenderer_->Enqueue(bufDesc);
234 cacheDataFrameNum_++;
235 }
236
Stop(const int32_t streamID)237 int32_t CacheBuffer::Stop(const int32_t streamID)
238 {
239 std::lock_guard lock(cacheBufferLock_);
240 if (streamID == streamID_) {
241 if (audioRenderer_ != nullptr && isRunning_.load()) {
242 isRunning_.store(false);
243 if (rendererFlags_ == LOW_LATENCY_PLAY_RENDERER_FLAGS) {
244 audioRenderer_->Pause();
245 audioRenderer_->Flush();
246 } else {
247 audioRenderer_->Stop();
248 }
249 cacheDataFrameNum_ = 0;
250 havePlayedCount_ = 0;
251 if (callback_ != nullptr) callback_->OnPlayFinished();
252 if (cacheBufferCallback_ != nullptr) cacheBufferCallback_->OnPlayFinished();
253 }
254 return MSERR_OK;
255 }
256 return MSERR_INVALID_VAL;
257 }
258
SetVolume(const int32_t streamID,const float leftVolume,const float rightVolume)259 int32_t CacheBuffer::SetVolume(const int32_t streamID, const float leftVolume, const float rightVolume)
260 {
261 std::lock_guard lock(cacheBufferLock_);
262 int32_t ret = MSERR_OK;
263 if (streamID == streamID_) {
264 if (audioRenderer_ != nullptr) {
265 // audio cannot support left & right volume, all use left volume.
266 (void) rightVolume;
267 ret = audioRenderer_->SetVolume(leftVolume);
268 }
269 }
270 return ret;
271 }
272
SetRate(const int32_t streamID,const AudioStandard::AudioRendererRate renderRate)273 int32_t CacheBuffer::SetRate(const int32_t streamID, const AudioStandard::AudioRendererRate renderRate)
274 {
275 std::lock_guard lock(cacheBufferLock_);
276 int32_t ret = MSERR_INVALID_VAL;
277 if (streamID == streamID_) {
278 if (audioRenderer_ != nullptr) {
279 ret = audioRenderer_->SetRenderRate(CheckAndAlignRendererRate(renderRate));
280 }
281 }
282 return ret;
283 }
284
SetPriority(const int32_t streamID,const int32_t priority)285 int32_t CacheBuffer::SetPriority(const int32_t streamID, const int32_t priority)
286 {
287 std::lock_guard lock(cacheBufferLock_);
288 if (streamID == streamID_) {
289 priority_ = priority;
290 }
291 return MSERR_OK;
292 }
293
SetLoop(const int32_t streamID,const int32_t loop)294 int32_t CacheBuffer::SetLoop(const int32_t streamID, const int32_t loop)
295 {
296 std::lock_guard lock(cacheBufferLock_);
297 if (streamID == streamID_) {
298 loop_ = loop;
299 }
300 return MSERR_OK;
301 }
302
SetParallelPlayFlag(const int32_t streamID,const bool parallelPlayFlag)303 int32_t CacheBuffer::SetParallelPlayFlag(const int32_t streamID, const bool parallelPlayFlag)
304 {
305 std::lock_guard lock(cacheBufferLock_);
306 if (streamID == streamID_) {
307 MEDIA_INFO_LOG("CacheBuffer parallelPlayFlag:%{public}d.", parallelPlayFlag);
308 if (audioRenderer_ != nullptr) {
309 audioRenderer_->SetParallelPlayFlag(parallelPlayFlag);
310 }
311 }
312 return MSERR_OK;
313 }
314
Release()315 int32_t CacheBuffer::Release()
316 {
317 std::lock_guard lock(cacheBufferLock_);
318 MEDIA_INFO_LOG("CacheBuffer release, streamID:%{public}d", streamID_);
319 isRunning_.store(false);
320 if (audioRenderer_ != nullptr) {
321 audioRenderer_->Stop();
322 audioRenderer_->Release();
323 audioRenderer_ = nullptr;
324 }
325 if (!cacheData_.empty()) cacheData_.clear();
326 if (!reCombineCacheData_.empty()) reCombineCacheData_.clear();
327 if (callback_ != nullptr) callback_.reset();
328 if (cacheBufferCallback_ != nullptr) cacheBufferCallback_.reset();
329 return MSERR_OK;
330 }
331
SetCallback(const std::shared_ptr<ISoundPoolCallback> & callback)332 int32_t CacheBuffer::SetCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
333 {
334 callback_ = callback;
335 return MSERR_OK;
336 }
337
SetCacheBufferCallback(const std::shared_ptr<ISoundPoolCallback> & callback)338 int32_t CacheBuffer::SetCacheBufferCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
339 {
340 cacheBufferCallback_ = callback;
341 return MSERR_OK;
342 }
343 } // namespace Media
344 } // namespace OHOS
345