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