• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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