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_AUDIO, "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
~AudioBuffersManager()28 AudioBuffersManager::~AudioBuffersManager() {}
29
AudioBuffersManager(const uint32_t bufferSize,const std::string_view & name,const uint16_t count,const uint32_t metaSize)30 AudioBuffersManager::AudioBuffersManager(const uint32_t bufferSize, const std::string_view &name, const uint16_t count,
31 const uint32_t metaSize)
32 : isRunning_(true),
33 inBufIndexExist(count, false),
34 bufferCount_(count),
35 bufferSize_(bufferSize),
36 metaSize_(metaSize),
37 name_(name),
38 bufferInfo_(count)
39 {
40 initBuffers();
41 }
42
getMemory(const uint32_t & index) const43 std::shared_ptr<AudioBufferInfo> AudioBuffersManager::getMemory(const uint32_t &index) const noexcept
44 {
45 if (index >= bufferInfo_.size()) {
46 return nullptr;
47 }
48 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "start get memory,name:%{public}s,index:%{public}u", name_.data(), index);
49 return bufferInfo_[index];
50 }
51
SetBufferBusy(const uint32_t & index)52 bool AudioBuffersManager::SetBufferBusy(const uint32_t &index)
53 {
54 if (index < bufferInfo_.size()) {
55 bufferInfo_[index]->SetBufferOwned();
56 return true;
57 }
58 return false;
59 }
60
initBuffers()61 void AudioBuffersManager::initBuffers()
62 {
63 std::lock_guard<std::mutex> lock(stateMutex_);
64 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "start allocate %{public}s buffers,each buffer size:%{public}d",
65 name_.data(), bufferSize_);
66 for (size_t i = 0; i < bufferCount_; i++) {
67 bufferInfo_[i] = std::make_shared<AudioBufferInfo>(bufferSize_, name_, metaSize_);
68 inBufIndexQue_.emplace(i);
69 inBufIndexExist[i] = true;
70 }
71 }
72
RequestNewBuffer(uint32_t & index,std::shared_ptr<AudioBufferInfo> & buffer)73 bool AudioBuffersManager::RequestNewBuffer(uint32_t &index, std::shared_ptr<AudioBufferInfo> &buffer)
74 {
75 buffer = createNewBuffer();
76 if (buffer == nullptr) {
77 return false;
78 }
79 index = bufferInfo_.size() - 1;
80 inBufIndexExist.emplace_back(false);
81 return true;
82 }
83
RequestAvailableIndex(uint32_t & index)84 bool AudioBuffersManager::RequestAvailableIndex(uint32_t &index)
85 {
86 while (inBufIndexQue_.empty() && isRunning_) {
87 AVCODEC_LOGD("Request empty %{public}s buffer", name_.data());
88 std::unique_lock aLock(availableMutex_);
89 availableCondition_.wait_for(aLock, std::chrono::milliseconds(DEFAULT_SLEEP_TIME),
90 [this] { return !inBufIndexQue_.empty() || !isRunning_; });
91 }
92
93 if (!isRunning_) {
94 return false;
95 }
96 {
97 std::lock_guard<std::mutex> lock(stateMutex_);
98 index = inBufIndexQue_.front();
99 inBufIndexQue_.pop();
100 }
101 if (index >= bufferInfo_.size()) {
102 AVCODEC_LOGW("Request %{public}s buffer index is invalidate ,index:%{public}u.", name_.data(), index);
103 return false;
104 }
105 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "Request %{public}s buffer successful,index:%{public}u", name_.data(), index);
106 inBufIndexExist[index] = false;
107 bufferInfo_[index]->SetBufferOwned();
108 return true;
109 }
110
ReleaseAll()111 void AudioBuffersManager::ReleaseAll()
112 {
113 {
114 std::lock_guard<std::mutex> lock(stateMutex_);
115 while (!inBufIndexQue_.empty()) {
116 inBufIndexQue_.pop();
117 }
118 }
119 for (uint32_t i = 0; i < bufferInfo_.size(); ++i) {
120 bufferInfo_[i]->ResetBuffer();
121 inBufIndexQue_.emplace(i);
122 inBufIndexExist[i] = true;
123 }
124 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "release all %{public}s buffer.", name_.data());
125 }
126
SetRunning()127 void AudioBuffersManager::SetRunning()
128 {
129 isRunning_ = true;
130 }
131
DisableRunning()132 void AudioBuffersManager::DisableRunning()
133 {
134 isRunning_ = false;
135 availableCondition_.notify_all();
136 }
137
ReleaseBuffer(const uint32_t & index)138 bool AudioBuffersManager::ReleaseBuffer(const uint32_t &index)
139 {
140 if (index < bufferInfo_.size()) {
141 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "ReleaseBuffer %{public}s buffer,index:%{public}u", name_.data(), index);
142 std::lock_guard<std::mutex> lock(stateMutex_);
143 bufferInfo_[index]->ResetBuffer();
144 if (!inBufIndexExist[index]) {
145 inBufIndexQue_.emplace(index);
146 inBufIndexExist[index] = true;
147 }
148 availableCondition_.notify_all();
149 return true;
150 }
151 return false;
152 }
153
createNewBuffer()154 std::shared_ptr<AudioBufferInfo> AudioBuffersManager::createNewBuffer()
155 {
156 std::shared_ptr<AudioBufferInfo> buffer = std::make_shared<AudioBufferInfo>(bufferSize_, name_, metaSize_);
157 bufferInfo_.emplace_back(buffer);
158 return buffer;
159 }
160 } // namespace MediaAVCodec
161 } // namespace OHOS