1 /*
2 * Copyright (C) 2023 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 "audio_buffers_manager.h"
17 #include "avcodec_log.h"
18
19 namespace {
20 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AvCodec-AudioBuffersManager"};
21 constexpr uint8_t LOGD_FREQUENCY = 5;
22 } // namespace
23
24 namespace OHOS {
25 namespace MediaAVCodec {
26 constexpr short DEFAULT_SLEEP_TIME = 500;
27 constexpr short MAX_WAIT_TIMES = 20;
28
~AudioBuffersManager()29 AudioBuffersManager::~AudioBuffersManager()
30 {
31 AVCODEC_LOGI("deconstructor called.");
32 }
33
AudioBuffersManager(const uint32_t bufferSize,const std::string_view & name,const uint16_t count,const uint32_t metaSize)34 AudioBuffersManager::AudioBuffersManager(const uint32_t bufferSize, const std::string_view &name, const uint16_t count,
35 const uint32_t metaSize)
36 : isRunning_(true),
37 inBufIndexExist(count, false),
38 bufferCount_(count),
39 bufferSize_(bufferSize),
40 metaSize_(metaSize),
41 name_(name),
42 bufferInfo_(count)
43 {
44 initBuffers();
45 }
46
getMemory(const uint32_t & index) const47 std::shared_ptr<AudioBufferInfo> AudioBuffersManager::getMemory(const uint32_t &index) const noexcept
48 {
49 if (index >= bufferInfo_.size()) {
50 return nullptr;
51 }
52 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "start get memory,name:%{public}s,index:%{public}u", name_.data(), index);
53 std::lock_guard<std::mutex> lock(stateMutex_);
54 return bufferInfo_[index];
55 }
56
SetBufferBusy(const uint32_t & index)57 bool AudioBuffersManager::SetBufferBusy(const uint32_t &index)
58 {
59 if (index < bufferInfo_.size()) {
60 std::lock_guard<std::mutex> lock(stateMutex_);
61 bufferInfo_[index]->SetBufferOwned();
62 return true;
63 }
64 return false;
65 }
66
initBuffers()67 void AudioBuffersManager::initBuffers()
68 {
69 std::lock_guard<std::mutex> lock(stateMutex_);
70 AVCODEC_LOGI("start allocate %{public}s buffers,each buffer size:%{public}d", name_.data(), bufferSize_);
71 for (size_t i = 0; i < bufferCount_; i++) {
72 bufferInfo_[i] = std::make_shared<AudioBufferInfo>(bufferSize_, name_, metaSize_);
73 inBufIndexQue_.emplace(i);
74 inBufIndexExist[i] = true;
75 }
76 AVCODEC_LOGI("end allocate %{public}s buffers", name_.data());
77 }
78
RequestNewBuffer(uint32_t & index,std::shared_ptr<AudioBufferInfo> & buffer)79 bool AudioBuffersManager::RequestNewBuffer(uint32_t &index, std::shared_ptr<AudioBufferInfo> &buffer)
80 {
81 buffer = createNewBuffer();
82 if (buffer == nullptr) {
83 return false;
84 }
85 index = bufferInfo_.size() - 1;
86 inBufIndexExist.emplace_back(false);
87 return true;
88 }
89
RequestAvailableIndex(uint32_t & index)90 bool AudioBuffersManager::RequestAvailableIndex(uint32_t &index)
91 {
92 short waitTimes = 0;
93 bool isTimeOut = false;
94 while (inBufIndexQue_.empty() && isRunning_) {
95 if (waitTimes >= MAX_WAIT_TIMES) {
96 AVCODEC_LOGW("Request empty %{public}s buffer time out.", name_.data());
97 isTimeOut = true;
98 break;
99 }
100 AVCODEC_LOGD("Request empty %{public}s buffer", name_.data());
101 std::unique_lock aLock(availableMutex_);
102 availableCondition_.wait_for(aLock, std::chrono::milliseconds(DEFAULT_SLEEP_TIME),
103 [this] { return !inBufIndexQue_.empty() || !isRunning_; });
104 waitTimes++;
105 }
106
107 if (isTimeOut) {
108 return false;
109 }
110
111 if (!isRunning_) {
112 return false;
113 }
114 {
115 std::lock_guard<std::mutex> lock(stateMutex_);
116 index = inBufIndexQue_.front();
117 inBufIndexQue_.pop();
118 }
119 if (index >= bufferInfo_.size()) {
120 AVCODEC_LOGW("Request %{public}s buffer index is invalidate ,index:%{public}u.", name_.data(), index);
121 return false;
122 }
123 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "Request %{public}s buffer successful,index:%{public}u", name_.data(), index);
124 inBufIndexExist[index] = false;
125 bufferInfo_[index]->SetBufferOwned();
126 return true;
127 }
128
ReleaseAll()129 void AudioBuffersManager::ReleaseAll()
130 {
131 isRunning_ = false;
132 availableCondition_.notify_all();
133 {
134 std::lock_guard<std::mutex> lock(stateMutex_);
135 while (!inBufIndexQue_.empty()) {
136 inBufIndexQue_.pop();
137 }
138 }
139 for (uint32_t i = 0; i < bufferInfo_.size(); ++i) {
140 bufferInfo_[i]->ResetBuffer();
141 inBufIndexQue_.emplace(i);
142 inBufIndexExist[i] = true;
143 }
144 AVCODEC_LOGI("release all %{public}s buffer.", name_.data());
145 }
146
SetRunning()147 void AudioBuffersManager::SetRunning()
148 {
149 isRunning_ = true;
150 }
151
ReleaseBuffer(const uint32_t & index)152 bool AudioBuffersManager::ReleaseBuffer(const uint32_t &index)
153 {
154 if (index < bufferInfo_.size()) {
155 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "ReleaseBuffer %{public}s buffer,index:%{public}u", name_.data(), index);
156 std::lock_guard<std::mutex> lock(stateMutex_);
157 bufferInfo_[index]->ResetBuffer();
158 if (!inBufIndexExist[index]) {
159 inBufIndexQue_.emplace(index);
160 inBufIndexExist[index] = true;
161 }
162 availableCondition_.notify_all();
163 return true;
164 }
165 return false;
166 }
167
createNewBuffer()168 std::shared_ptr<AudioBufferInfo> AudioBuffersManager::createNewBuffer()
169 {
170 std::lock_guard<std::mutex> lock(stateMutex_);
171 std::shared_ptr<AudioBufferInfo> buffer = std::make_shared<AudioBufferInfo>(bufferSize_, name_, metaSize_);
172 bufferInfo_.emplace_back(buffer);
173 return buffer;
174 }
175 } // namespace MediaAVCodec
176 } // namespace OHOS