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 "avcodec_dfx.h"
17 #include "avcodec_errors.h"
18 #include "avcodec_log.h"
19 #include "block_queue_pool.h"
20
21 namespace {
22 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "BlockQueuePool"};
23 }
24
25 namespace OHOS {
26 namespace MediaAVCodec {
~BlockQueuePool()27 BlockQueuePool::~BlockQueuePool()
28 {
29 AVCODEC_LOGD("block queue %{public}s ~BlockQueuePool enter.", name_.c_str());
30 for (auto que : quePool_) {
31 FreeQueue(que.first);
32 }
33 AVCODEC_LOGD("block queue %{public}s ~BlockQueuePool free finish.", name_.c_str());
34 }
35
AddTrackQueue(uint32_t trackIndex)36 int32_t BlockQueuePool::AddTrackQueue(uint32_t trackIndex)
37 {
38 AVCODEC_LOGD("block queue %{public}s AddTrackQueue enter, trackIndex: %{public}u.", name_.c_str(), trackIndex);
39 if (!HasQueue(trackIndex)) {
40 uint32_t queIndex = GetValidQueue();
41 queMap_[trackIndex] = std::vector<uint32_t>({ queIndex });
42 AVCODEC_LOGD("block queue %{public}s AddTrackQueue finish, add track %{public}u, get queue %{public}u",
43 name_.c_str(), trackIndex, queIndex);
44 } else {
45 AVCODEC_LOGD("block queue %{public}s AddTrackQueue finish, track %{public}u is already in queue",
46 name_.c_str(), trackIndex);
47 }
48 return AVCS_ERR_OK;
49 }
50
RemoveTrackQueue(uint32_t trackIndex)51 int32_t BlockQueuePool::RemoveTrackQueue(uint32_t trackIndex)
52 {
53 AVCODEC_LOGD("block queue %{public}s RemoveTrackQueue enter, trackIndex: %{public}u.", name_.c_str(), trackIndex);
54 if (!HasQueue(trackIndex)) {
55 AVCODEC_LOGD("block queue %{public}s RemoveTrackQueue finish, track %{public}u is not in queue",
56 name_.c_str(), trackIndex);
57 } else {
58 for (auto queIndex : queMap_[trackIndex]) {
59 ResetQueue(queIndex);
60 }
61 queMap_[trackIndex].clear();
62 queMap_.erase(trackIndex);
63 }
64 AVCODEC_LOGD("block queue %{public}s RemoveTrackQueue finish", name_.c_str());
65 return AVCS_ERR_OK;
66 }
67
HasCache(uint32_t trackIndex)68 bool BlockQueuePool::HasCache(uint32_t trackIndex)
69 {
70 AVCODEC_LOGD("block queue %{public}s HasCache enter, trackIndex: %{public}u.", name_.c_str(), trackIndex);
71 for (auto queIndex : queMap_[trackIndex]) {
72 if (quePool_[queIndex].blockQue == nullptr) {
73 AVCODEC_LOGD("block queue %{public}d is nullptr, will find next", queIndex);
74 continue;
75 }
76 if (quePool_[queIndex].blockQue->Size() > 0) {
77 AVCODEC_LOGD("block queue %{public}s HasCache finish, result: have cache", name_.c_str());
78 return true;
79 }
80 }
81 AVCODEC_LOGD("block queue %{public}s HasCache finish, result: don't have cache", name_.c_str());
82 return false;
83 }
84
ResetQueue(uint32_t queueIndex)85 void BlockQueuePool::ResetQueue(uint32_t queueIndex)
86 {
87 auto blockQue = quePool_[queueIndex].blockQue;
88 if (blockQue == nullptr) {
89 return;
90 }
91 if (!blockQue->Empty()) {
92 for (auto ele = blockQue->Pop(); ele != nullptr;) {
93 av_packet_free(&(ele->pkt));
94 ele = nullptr;
95 }
96 }
97 blockQue->Clear();
98 quePool_[queueIndex].isValid = true;
99 return;
100 }
101
FreeQueue(uint32_t queueIndex)102 void BlockQueuePool::FreeQueue(uint32_t queueIndex)
103 {
104 ResetQueue(queueIndex);
105 quePool_[queueIndex].blockQue = nullptr;
106 }
107
Push(uint32_t trackIndex,std::shared_ptr<SamplePacket> block)108 bool BlockQueuePool::Push(uint32_t trackIndex, std::shared_ptr<SamplePacket> block)
109 {
110 AVCODEC_LOGD("block queue %{public}s Push enter, trackIndex: %{public}u.", name_.c_str(), trackIndex);
111 int32_t ret;
112 if (!HasQueue(trackIndex)) {
113 AVCODEC_LOGW("trackIndex has not beed added, auto add first");
114 ret = AddTrackQueue(trackIndex);
115 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, false, "add new queue error: %{public}d", ret);
116 }
117 auto& queVector = queMap_[trackIndex];
118 uint32_t pushIndex;
119 if (queVector.size() > 0) {
120 pushIndex = queVector[queVector.size() - 1];
121 } else {
122 pushIndex = GetValidQueue();
123 queMap_[trackIndex].push_back(pushIndex);
124 AVCODEC_LOGD("track has no queue, will get que %{public}d from pool", pushIndex);
125 }
126 if (InnerQueueIsFull(pushIndex)) {
127 pushIndex = GetValidQueue();
128 queMap_[trackIndex].push_back(pushIndex);
129 AVCODEC_LOGD("track que is full, will get que %{public}d from pool", pushIndex);
130 }
131 if (quePool_[pushIndex].blockQue == nullptr) {
132 AVCODEC_LOGD("block queue %{public}d is nullptr, failed to push data", pushIndex);
133 return false;
134 }
135 return quePool_[pushIndex].blockQue->Push(block);
136 }
137
Pop(uint32_t trackIndex)138 std::shared_ptr<SamplePacket> BlockQueuePool::Pop(uint32_t trackIndex)
139 {
140 AVCODEC_LOGD("block queue %{public}s Pop enter, trackIndex: %{public}u.", name_.c_str(), trackIndex);
141 if (!HasQueue(trackIndex)) {
142 AVCODEC_LOGE("trackIndex: %{public}u has not cache queue", trackIndex);
143 return nullptr;
144 }
145 auto& queVector = queMap_[trackIndex];
146 for (auto index = 0; index < static_cast<int32_t>(queVector.size()); ++index) {
147 auto queIndex = queVector[index];
148 if (quePool_[queIndex].blockQue == nullptr) {
149 AVCODEC_LOGD("block queue %{public}d is nullptr, will find next", queIndex);
150 continue;
151 }
152 if (quePool_[queIndex].blockQue->Size() > 0) {
153 auto block = quePool_[queIndex].blockQue->Pop();
154 if (quePool_[queIndex].blockQue->Empty()) {
155 ResetQueue(queIndex);
156 AVCODEC_LOGD("track %{public}u queue %{public}d is empty, will return to pool.", trackIndex, queIndex);
157 queVector.erase(queVector.begin() + index);
158 }
159 AVCODEC_LOGD("block queue %{public}s Pop finish, trackIndex: %{public}u.", name_.c_str(), trackIndex);
160 return block;
161 }
162 }
163 AVCODEC_LOGE("trackIndex: %{public}u has not cache data", trackIndex);
164 return nullptr;
165 }
166
Front(uint32_t trackIndex)167 std::shared_ptr<SamplePacket> BlockQueuePool::Front(uint32_t trackIndex)
168 {
169 AVCODEC_LOGD("block queue %{public}s Pop enter, trackIndex: %{public}u.", name_.c_str(), trackIndex);
170 if (!HasQueue(trackIndex)) {
171 AVCODEC_LOGE("trackIndex: %{public}u has not cache queue", trackIndex);
172 return nullptr;
173 }
174 auto queVector = queMap_[trackIndex];
175 for (int i = 0; i < static_cast<int32_t>(queVector.size()); ++i) {
176 auto queIndex = queVector[i];
177 if (quePool_[queIndex].blockQue == nullptr) {
178 AVCODEC_LOGD("block queue %{public}d is nullptr, will find next", queIndex);
179 continue;
180 }
181 if (quePool_[queIndex].blockQue->Size() > 0) {
182 auto block = quePool_[queIndex].blockQue->Front();
183 return block;
184 }
185 }
186 AVCODEC_LOGE("trackIndex: %{public}u has not cache data", trackIndex);
187 return nullptr;
188 }
189
GetValidQueue()190 uint32_t BlockQueuePool::GetValidQueue()
191 {
192 AVCODEC_LOGD("block queue %{public}s GetValidQueue enter.", name_.c_str());
193 for (auto pair : quePool_) {
194 if (pair.second.isValid && pair.second.blockQue != nullptr && pair.second.blockQue->Empty()) {
195 quePool_[pair.first].isValid = false;
196 return pair.first;
197 }
198 }
199 quePool_[queCount_] = {
200 false,
201 std::make_shared<BlockQueue<std::shared_ptr<SamplePacket>>>("source_que_" + std::to_string(queCount_),
202 singleQueSize_)
203 };
204 AVCODEC_LOGD("block queue %{public}s GetValidQueue finish, valid queue index: %{public}u.",
205 name_.c_str(), queCount_);
206 queCount_++;
207 return (queCount_ - 1);
208 }
209
InnerQueueIsFull(uint32_t queueIndex)210 bool BlockQueuePool::InnerQueueIsFull(uint32_t queueIndex)
211 {
212 AVCODEC_LOGD("block queue %{public}s InnerQueueIsFull enter, queueIndex: %{public}u.", name_.c_str(), queueIndex);
213 if (quePool_[queueIndex].blockQue == nullptr) {
214 AVCODEC_LOGD("block queue %{public}d is nullptr", queueIndex);
215 return true;
216 }
217 return quePool_[queueIndex].blockQue->Size() >= quePool_[queueIndex].blockQue->Capacity();
218 }
219
HasQueue(uint32_t trackIndex)220 bool BlockQueuePool::HasQueue(uint32_t trackIndex)
221 {
222 AVCODEC_LOGD("block queue %{public}s HasQueue enter, trackIndex: %{public}u.", name_.c_str(), trackIndex);
223 return queMap_.count(trackIndex) > 0;
224 }
225 } // namespace MediaAVCodec
226 } // namespace OHOS