• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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