1 /*
2 * Copyright (c) 2024 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_buffer_cache.h"
17 #include "log.h"
18 #include "monitor_error.h"
19
20 namespace {
21 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FOUNDATION, "HiStreamer"};
22 }
23
24 namespace OHOS {
25 namespace Media {
26 namespace MediaMonitor {
27
AudioBufferCache(std::shared_ptr<DumpBufferWrap> wrap)28 AudioBufferCache::AudioBufferCache(std::shared_ptr<DumpBufferWrap> wrap)
29 {
30 dumpBufferWrap_ = wrap;
31 }
32
~AudioBufferCache()33 AudioBufferCache::~AudioBufferCache()
34 {
35 Clear();
36 dumpBufferWrap_ = nullptr;
37 }
38
RequestBuffer(std::shared_ptr<AudioBuffer> & buffer,int32_t size)39 int32_t AudioBufferCache::RequestBuffer(std::shared_ptr<AudioBuffer> &buffer, int32_t size)
40 {
41 std::unique_lock<std::mutex> lock(mutex_);
42 auto status = RequestCacheBuffer(buffer, size);
43 if (status == SUCCESS && buffer != nullptr) {
44 return SUCCESS;
45 }
46 status = AllocAudioBuffer(buffer, size);
47 if (status != SUCCESS) {
48 return status;
49 }
50 bufferSize_ += 1;
51 return SUCCESS;
52 }
53
ReleaseBuffer(std::shared_ptr<AudioBuffer> & buffer)54 int32_t AudioBufferCache::ReleaseBuffer(std::shared_ptr<AudioBuffer> &buffer)
55 {
56 if (buffer == nullptr || dumpBufferWrap_ == nullptr) {
57 MEDIA_LOG_E("release buffer error");
58 return ERROR;
59 }
60 std::unique_lock<std::mutex> lock(mutex_);
61 auto bufferId = dumpBufferWrap_->GetUniqueId(buffer.get());
62 for (auto it = freeBufferList_.begin(); it != freeBufferList_.end(); it++) {
63 if (*it == bufferId) {
64 return SUCCESS;
65 }
66 }
67 if (bufferMap_.find(bufferId) == bufferMap_.end()) {
68 buffer = nullptr;
69 return ERROR;
70 }
71
72 freeBufferList_.emplace_back(bufferId);
73 return SUCCESS;
74 }
75
Clear()76 int32_t AudioBufferCache::Clear()
77 {
78 std::unique_lock<std::mutex> lock(mutex_);
79 if (freeBufferList_.size() != bufferMap_.size()) {
80 MEDIA_LOG_E("exist buffer not free");
81 }
82
83 for (auto it = freeBufferList_.begin(); it != freeBufferList_.end(); it++) {
84 bufferMap_[*it].buffer = nullptr;
85 }
86 freeBufferList_.clear();
87 bufferMap_.clear();
88 bufferSize_ = 0;
89 return SUCCESS;
90 }
91
GetBufferById(std::shared_ptr<AudioBuffer> & buffer,uint64_t bufferId)92 int32_t AudioBufferCache::GetBufferById(std::shared_ptr<AudioBuffer> &buffer, uint64_t bufferId)
93 {
94 std::unique_lock<std::mutex> lock(mutex_);
95 auto it = bufferMap_.find(bufferId);
96 if (it != bufferMap_.end()) {
97 buffer = bufferMap_[bufferId].buffer;
98 return SUCCESS;
99 }
100 return ERROR;
101 }
102
SetBufferSize(std::shared_ptr<AudioBuffer> & buffer,int32_t size)103 int32_t AudioBufferCache::SetBufferSize(std::shared_ptr<AudioBuffer> &buffer, int32_t size)
104 {
105 if (dumpBufferWrap_ && dumpBufferWrap_->SetSize(buffer.get(), size)) {
106 return SUCCESS;
107 }
108 return ERROR;
109 }
110
RequestCacheBuffer(std::shared_ptr<AudioBuffer> & buffer,int32_t size)111 int32_t AudioBufferCache::RequestCacheBuffer(std::shared_ptr<AudioBuffer> &buffer, int32_t size)
112 {
113 for (auto it = freeBufferList_.begin(); it != freeBufferList_.end(); it++) {
114 if (size <= bufferMap_[*it].size) {
115 buffer = bufferMap_[*it].buffer;
116 freeBufferList_.erase(it);
117 return SUCCESS;
118 }
119 }
120 if (freeBufferList_.empty()) {
121 buffer = nullptr;
122 return ERROR;
123 }
124 int32_t status = DeleteAudioBuffer(freeBufferList_.front(), size);
125 freeBufferList_.pop_front();
126 if (status != SUCCESS) {
127 return status;
128 }
129 status = AllocAudioBuffer(buffer, size);
130 return status;
131 }
132
AllocBuffer(std::shared_ptr<AudioBuffer> & buffer,int32_t size)133 int32_t AudioBufferCache::AllocBuffer(std::shared_ptr<AudioBuffer> &buffer, int32_t size)
134 {
135 AudioBuffer *ptr = dumpBufferWrap_->CreateDumpBuffer(size);
136 buffer = std::shared_ptr<AudioBuffer>(ptr, [this](AudioBuffer* ptr) {
137 dumpBufferWrap_->DestroyDumpBuffer(ptr);
138 });
139 if (buffer == nullptr) {
140 return ERROR;
141 }
142 return SUCCESS;
143 }
144
AllocAudioBuffer(std::shared_ptr<AudioBuffer> & buffer,int32_t size)145 int32_t AudioBufferCache::AllocAudioBuffer(std::shared_ptr<AudioBuffer> &buffer, int32_t size)
146 {
147 int32_t status = AllocBuffer(buffer, size);
148 if (status != SUCCESS || buffer == nullptr) {
149 MEDIA_LOG_E("alloc buffer error");
150 return ERROR;
151 }
152 AudioBufferElement ele = {
153 .size = size,
154 .buffer = buffer
155 };
156 auto bufferId = dumpBufferWrap_->GetUniqueId(buffer.get());
157 bufferMap_[bufferId] = ele;
158 return SUCCESS;
159 }
160
DeleteAudioBuffer(uint64_t bufferId,int32_t size)161 int32_t AudioBufferCache::DeleteAudioBuffer(uint64_t bufferId, int32_t size)
162 {
163 auto it = bufferMap_.find(bufferId);
164 if (it != bufferMap_.end()) {
165 bufferMap_.erase(it);
166 return SUCCESS;
167 }
168 return ERROR;
169 }
170
171 } // namespace MediaMonitor
172 } // namespace Media
173 } // namespace OHOS