• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
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 "appsrc_memory.h"
17 #include "avdatasrcmemory.h"
18 #include "media_dfx.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21 #include "securec.h"
22 
23 namespace {
24     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AppSrcMemory"};
25 }
26 
27 namespace OHOS {
28 namespace Media {
29 // Check whether (srcB, endB) belongs to (srcA, endA)
IsInnerRange(uint32_t srcA,uint32_t endA,uint32_t srcB,uint32_t endB)30 static bool IsInnerRange(uint32_t srcA, uint32_t endA, uint32_t srcB, uint32_t endB)
31 {
32     MEDIA_LOGD("srcA is: %{public}u, endA is: %{public}u, srcB is: %{public}u, endB is: %{public}u,",
33         srcA, endA, srcB, endB);
34     if (srcA < endA) {
35         return srcB < endB && srcB >= srcA && endB <= endA;
36     } else {
37         return (srcB < endB && srcB >= srcA && endB >= srcA) || (srcB < endB && srcB <= endA && endB <= endA) ||
38             (srcB >= srcA && endB <= endA);
39     }
40 }
41 
AppsrcMemory()42 AppsrcMemory::AppsrcMemory()
43 {
44     MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
45 }
46 
~AppsrcMemory()47 AppsrcMemory::~AppsrcMemory()
48 {
49     MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
50 }
51 
GetBufferSize() const52 uint32_t AppsrcMemory::GetBufferSize() const
53 {
54     return bufferSize_;
55 }
56 
GetMem()57 std::shared_ptr<AVSharedMemory> AppsrcMemory::GetMem()
58 {
59     return mem_;
60 }
61 
GetFreeSize() const62 uint32_t AppsrcMemory::GetFreeSize() const
63 {
64     MEDIA_LOGD("GetFreeSize, begin is: %{public}u, end is: %{public}u, availableBegin is: %{public}u",
65         begin_, end_, availableBegin_);
66     uint32_t freeSize;
67     if (noFreeBuffer_) {
68         freeSize = 0;
69     } else {
70         uint32_t end = end_;
71         if (!unreturnedBuffers_.empty()) {
72             MEDIA_LOGD("unreturnedBuffers begin: %{public}u - %{public}u",
73                 unreturnedBuffers_.front().first, unreturnedBuffers_.front().second);
74             end = unreturnedBuffers_.front().first;
75         }
76         freeSize = begin_ <= end ? end - begin_ + 1 : bufferSize_ - begin_ + end + 1;
77     }
78     MEDIA_LOGD("GetFreeSize is: %{public}u", freeSize);
79     MediaTrace::CounterTrace("AppsrcMemory::freeSize", freeSize);
80     return freeSize;
81 }
82 
GetAvailableSize() const83 uint32_t AppsrcMemory::GetAvailableSize() const
84 {
85     MEDIA_LOGD("GetAvailableSize, begin is: %{public}u, end is: %{public}u, availableBegin is: %{public}u",
86         begin_, end_, availableBegin_);
87     uint32_t availableSize;
88     if (availableBegin_ == begin_ && noAvailableBuffer_) {
89         availableSize = 0;
90     } else {
91         availableSize = availableBegin_ < begin_ ?
92             begin_ - availableBegin_ :
93             bufferSize_ - availableBegin_ + begin_;
94     }
95     MEDIA_LOGD("GetAvailableSize is: %{public}u", availableSize);
96     MediaTrace::CounterTrace("AppsrcMemory::availableSize", availableSize);
97     return availableSize;
98 }
99 
GetBeginPos() const100 uint32_t AppsrcMemory::GetBeginPos() const
101 {
102     return begin_;
103 }
104 
GetAvailableBeginPos() const105 uint32_t AppsrcMemory::GetAvailableBeginPos() const
106 {
107     return availableBegin_;
108 }
109 
GetPushOffset() const110 uint64_t AppsrcMemory::GetPushOffset() const
111 {
112     return pushOffset_;
113 }
114 
GetFilePos() const115 uint64_t AppsrcMemory::GetFilePos() const
116 {
117     return filePos_;
118 }
119 
SetBufferSize(uint32_t bufferSize)120 void AppsrcMemory::SetBufferSize(uint32_t bufferSize)
121 {
122     bufferSize_ = bufferSize;
123     MEDIA_LOGD("Set bufferSize_ is %{public}u", bufferSize_);
124 }
125 
SetMem(std::shared_ptr<AVSharedMemory> mem)126 void AppsrcMemory::SetMem(std::shared_ptr<AVSharedMemory> mem)
127 {
128     mem_ = mem;
129 }
130 
SetNoFreeBuffer(bool flag)131 void AppsrcMemory::SetNoFreeBuffer(bool flag)
132 {
133     if (noFreeBuffer_ != flag) {
134         noFreeBuffer_ = flag;
135         MEDIA_LOGD("noFreeBuffer_ set to: %{public}u", noFreeBuffer_);
136     }
137 }
138 
SetNoAvailableBuffer(bool flag)139 void AppsrcMemory::SetNoAvailableBuffer(bool flag)
140 {
141     if (noAvailableBuffer_ != flag) {
142         noAvailableBuffer_ = flag;
143         MEDIA_LOGD("noAvailableBuffer_ set to: %{public}u", noAvailableBuffer_);
144     }
145 }
146 
ResetMemParam()147 void AppsrcMemory::ResetMemParam()
148 {
149     filePos_ = 0;
150     begin_ = 0;
151     end_ = bufferSize_ - 1;
152     availableBegin_ = 0;
153     pushOffset_ = 0;
154     noFreeBuffer_ = false;
155     noAvailableBuffer_ = true;
156 }
157 
RestoreMemParam()158 void AppsrcMemory::RestoreMemParam()
159 {
160     availableBegin_ = 0;
161     end_ = bufferSize_ - 1;
162 }
163 
SeekAndChangePos(uint64_t pos)164 void AppsrcMemory::SeekAndChangePos(uint64_t pos)
165 {
166     MEDIA_LOGD("Enter SeekAndChangePos");
167     pushOffset_ = pos;
168     bool hasUnreturnedBuffer = (((end_ + 1) % bufferSize_) != availableBegin_) ? true : false;
169     uint32_t availableSize = GetAvailableSize();
170     // Check availableBuffer is Successive and seek location is cached
171     if ((IsMemSuccessive() || noFreeBuffer_) && filePos_ - availableSize <= pos && filePos_ >= pos) {
172         // if availableBuffer is Successive and seek location is cached, Adjust end_ according to hasUnreturnedBuffer
173         if (hasUnreturnedBuffer) {
174             uint32_t unusedBufferEnd = (availableBegin_ + availableSize - (filePos_ - pos)) % bufferSize_;
175             MEDIA_LOGD("unusedBuffers push begin: %{public}u, end: %{public}u", availableBegin_, unusedBufferEnd);
176             PushUnusedBuffers({availableBegin_, unusedBufferEnd});
177             availableBegin_ = begin_ - (filePos_ - pos);
178         } else {
179             uint32_t pad = noFreeBuffer_ ? bufferSize_ : 0;
180             availableBegin_ = (begin_ + pad) - (filePos_ - pos);
181             end_ = availableBegin_ == 0 ? bufferSize_ - 1 : availableBegin_ - 1;
182         }
183     } else if (filePos_ - availableSize <= pos && filePos_ >= pos) {
184         // seek location is cached
185         if (hasUnreturnedBuffer) {
186             uint32_t unusedBufferEnd = (availableBegin_ + availableSize - (filePos_ - pos)) % bufferSize_;
187             MEDIA_LOGD("unusedBuffers push begin: %{public}u, end: %{public}u", availableBegin_, unusedBufferEnd);
188             PushUnusedBuffers({availableBegin_, unusedBufferEnd});
189             availableBegin_ = ((begin_ + bufferSize_) - (filePos_ - pos)) % bufferSize_;
190         } else {
191             availableBegin_ = ((begin_ + bufferSize_) - (filePos_ - pos)) % bufferSize_;
192             end_ = availableBegin_ == 0 ? bufferSize_ - 1 : availableBegin_ - 1;
193         }
194     } else {
195         // seek location not cached
196         filePos_ = pos;
197         begin_ = availableBegin_;
198         if (!hasUnreturnedBuffer) {
199             end_ = availableBegin_ == 0 ? bufferSize_ - 1 : availableBegin_ - 1;
200         }
201         SetNoAvailableBuffer(true);
202     }
203     availableSize = GetAvailableSize();
204     if (availableSize != bufferSize_) {
205         SetNoFreeBuffer(false);
206     }
207 }
208 
PullBufferAndChangePos(uint32_t readSize)209 void AppsrcMemory::PullBufferAndChangePos(uint32_t readSize)
210 {
211     MEDIA_LOGD("Enter PullBufferAndChangePos");
212     begin_ = (begin_ + readSize) % bufferSize_;
213     if (begin_ == (end_ + 1) % bufferSize_) {
214         SetNoFreeBuffer(true);
215     }
216     SetNoAvailableBuffer(false);
217     filePos_ += readSize;
218 }
219 
PushBufferAndChangePos(uint32_t pushSize,bool isCopy)220 void AppsrcMemory::PushBufferAndChangePos(uint32_t pushSize, bool isCopy)
221 {
222     MEDIA_LOGD("Enter PushBufferAndChangePos");
223     if (isCopy) {
224         if ((end_ + 1) % bufferSize_ == availableBegin_) {
225             end_ = (end_ + pushSize) % bufferSize_;
226         } else {
227             PushUnusedBuffers({availableBegin_, (availableBegin_ + pushSize) % bufferSize_});
228         }
229     }
230     pushOffset_ += pushSize;
231     availableBegin_ = (availableBegin_ + pushSize) % bufferSize_;
232     if (availableBegin_ == begin_) {
233         SetNoAvailableBuffer(true);
234     }
235 }
236 
FreeBufferAndChangePos(uint32_t offset,uint32_t length,bool isCopymode)237 bool AppsrcMemory::FreeBufferAndChangePos(uint32_t offset, uint32_t length, bool isCopymode)
238 {
239     MEDIA_LOGD("Enter FreeBufferAndChangePos");
240     if ((end_ + 1) % bufferSize_ != offset && !isCopymode) {
241         // Check the buffer after end_ is unusedbuffer, and Re-mark as freeBuffer
242         RemoveUnusedBuffer();
243         // Check the buffer to be returned is unreturnedbuffer and adjust unusedBuffers_ and unreturnedBuffers_
244         bool isProcessed = ProcessBuffer(offset, length);
245         if (isProcessed) {
246             return true;
247         }
248         if ((end_ + 1) % bufferSize_ != offset) {
249             CHECK_AND_RETURN_RET(PushBufferToUnreturnedBuffers(offset, length), false);
250         }
251     }
252     end_ = offset + length - 1;
253     SetNoFreeBuffer(false);
254     return true;
255 }
256 
CopyBufferAndChangePos(std::shared_ptr<AppsrcMemory> & mem)257 bool AppsrcMemory::CopyBufferAndChangePos(std::shared_ptr<AppsrcMemory> &mem)
258 {
259     MEDIA_LOGD("Enter CopyBufferAndChangePos");
260     uint8_t *dstBase = std::static_pointer_cast<AVDataSrcMemory>(mem_)->GetInnerBase();
261     uint8_t *srcBase = std::static_pointer_cast<AVDataSrcMemory>(mem->GetMem())->GetInnerBase();
262     uint32_t size = mem->GetBufferSize();
263     uint32_t copyBegin = mem->GetAvailableBeginPos();
264     uint32_t availableSize = mem->GetAvailableSize();
265     if (availableSize && mem->IsMemSuccessive()) {
266         MEDIA_LOGD("Copy buffer, and buffer size is: %{public}u", availableSize);
267         errno_t rc = memcpy_s(dstBase, availableSize, srcBase + copyBegin, availableSize);
268         CHECK_AND_RETURN_RET_LOG(rc == EOK, false, "get mem is failed");
269     } else if (availableSize) {
270         uint32_t copySize = size - copyBegin;
271         MEDIA_LOGD("Copy buffer, and buffer size is: %{public}u", copySize);
272         errno_t rc = memcpy_s(dstBase, copySize, srcBase + copyBegin, copySize);
273         CHECK_AND_RETURN_RET_LOG(rc == EOK, false, "get mem is failed");
274         dstBase += copySize;
275         copySize = availableSize - (size - copyBegin);
276         if (copySize) {
277             MEDIA_LOGD("Copy buffer, and buffer size is: %{public}u", copySize);
278             rc = memcpy_s(dstBase, copySize, srcBase, copySize);
279             CHECK_AND_RETURN_RET_LOG(rc == EOK, false, "get mem is failed");
280         }
281     }
282     begin_ = availableSize;
283     filePos_ = mem->GetFilePos();
284     pushOffset_ = mem->GetPushOffset();
285     if (availableSize == size) {
286         mem->SetMem(nullptr);
287         mem = nullptr;
288     } else if (availableSize) {
289         mem->PushUnusedBuffers({copyBegin, mem->GetBeginPos()});
290     }
291     PrintCurPos();
292     MEDIA_LOGD("Exit CopyBufferAndChangePos");
293     return true;
294 }
295 
RemoveUnusedBuffer()296 void AppsrcMemory::RemoveUnusedBuffer()
297 {
298     MEDIA_LOGD("Enter RemoveUnusedBuffer");
299     while (!unusedBuffers_.empty() && (end_ + 1) % bufferSize_ == unusedBuffers_.front().first) {
300         end_ = unusedBuffers_.front().second - 1;
301         MEDIA_LOGI("unusedBuffers pop %{public}u - %{public}u",
302             unusedBuffers_.front().first, unusedBuffers_.front().second);
303         unusedBuffers_.pop();
304     }
305 }
306 
ProcessBuffer(uint32_t offset,uint32_t length)307 bool AppsrcMemory::ProcessBuffer(uint32_t offset, uint32_t length)
308 {
309     MEDIA_LOGD("Enter ProcessBuffer");
310     if ((end_ + 1) % bufferSize_ == offset) {
311         return false;
312     }
313     std::deque<std::pair<uint32_t, uint32_t>>::iterator iter;
314     bool flag = IsUnreturnedBuffer(offset, length, iter);
315     if (flag) {
316         while (!unusedBuffers_.empty() && iter != unreturnedBuffers_.end() &&
317             iter->first == unusedBuffers_.front().first) {
318             MEDIA_LOGI("unusedBuffers %{public}u - %{public}u",
319                 unusedBuffers_.front().first, unusedBuffers_.front().second);
320             MEDIA_LOGI("iter %{public}u - %{public}u", iter->first, iter->second);
321             if (iter->second == unusedBuffers_.front().second) {
322                 iter = unreturnedBuffers_.erase(iter);
323                 MEDIA_LOGD("unreturnedBuffers pop");
324             } else {
325                 iter->first = unusedBuffers_.front().second;
326                 MEDIA_LOGD("unreturnedBuffers first change to : %{public}u", iter->first);
327             }
328             unusedBuffers_.pop();
329             MEDIA_LOGD("unusedBuffers pop");
330         }
331         return true;
332     }
333 
334     return false;
335 }
336 
IsUnreturnedBuffer(uint32_t offset,uint32_t length,std::deque<std::pair<uint32_t,uint32_t>>::iterator & iter)337 bool AppsrcMemory::IsUnreturnedBuffer(uint32_t offset, uint32_t length,
338     std::deque<std::pair<uint32_t, uint32_t>>::iterator &iter)
339 {
340     uint32_t pad;
341     for (iter = unreturnedBuffers_.begin(); iter != unreturnedBuffers_.end(); ++iter) {
342         pad = iter->first < iter->second ? 0 : bufferSize_;
343         if (!IsInnerRange(iter->first, iter->second + pad, offset, offset + length)) {
344             continue;
345         }
346         if (offset == iter->first && offset + length == iter->second + pad) {
347             iter = unreturnedBuffers_.erase(iter);
348             MEDIA_LOGD("unreturnedBuffers pop");
349         } else if (offset == iter->first) {
350             iter->first = (offset + length) % bufferSize_;
351             MEDIA_LOGD("unreturnedBuffers first change to : %{public}u", iter->first);
352         } else if (offset + length == iter->second + pad) {
353             iter->second = offset;
354             MEDIA_LOGD("unreturnedBuffers second change to : %{public}u", iter->second);
355         } else {
356             iter = unreturnedBuffers_.insert(iter, {iter->first, offset});
357             MEDIA_LOGD("unreturnedBuffers insert : %{public}u, %{public}u", iter->first, offset);
358             (iter + 1)->first = (offset + length) % bufferSize_;
359             MEDIA_LOGD("unreturnedBuffers first change to : %{public}u", (iter + 1)->first);
360         }
361         return true;
362     }
363     return false;
364 }
365 
PushBufferToUnreturnedBuffers(uint32_t offset,uint32_t length)366 bool AppsrcMemory::PushBufferToUnreturnedBuffers(uint32_t offset, uint32_t length)
367 {
368     MEDIA_LOGD("Enter PushBufferToUnreturnedBuffers");
369     CHECK_AND_RETURN_RET_LOG(unreturnedBuffers_.empty() || !IsInnerRange(unreturnedBuffers_.begin()->first,
370         unreturnedBuffers_.rbegin()->second, offset, (offset + length) % bufferSize_),
371         false, "mempool error, end_ is %{public}u offset is %{public}u", end_, offset)
372     unreturnedBuffers_.push_back({(end_ + 1) % bufferSize_, offset});
373     MEDIA_LOGD("unreturnedBuffers push begin: %{public}u, end: %{public}u",
374         (end_ + 1) % bufferSize_, offset);
375     return true;
376 }
377 
IsMemSuccessive()378 bool AppsrcMemory::IsMemSuccessive()
379 {
380     return availableBegin_ < begin_;
381 }
382 
IsNeedCopy(uint32_t copySize)383 bool AppsrcMemory::IsNeedCopy(uint32_t copySize)
384 {
385     return copySize > (bufferSize_ - availableBegin_) ? true : false;
386 }
387 
PushUnusedBuffers(std::pair<uint32_t,uint32_t> unusedBuffer)388 void AppsrcMemory::PushUnusedBuffers(std::pair<uint32_t, uint32_t> unusedBuffer)
389 {
390     unusedBuffers_.push(unusedBuffer);
391     MEDIA_LOGI("unusedBuffers push %{public}u - %{public}u", unusedBuffer.first, unusedBuffer.second);
392 }
393 
PrintCurPos()394 void AppsrcMemory::PrintCurPos()
395 {
396     MEDIA_LOGD("free mem begin is: %{public}u, free mem end is: %{public}u,"
397         "available mem begin is: %{public}u, filePos is: %{public}" PRIu64 "",
398         begin_, end_, availableBegin_, filePos_);
399 }
400 
CheckBufferUsage()401 void AppsrcMemory::CheckBufferUsage()
402 {
403     MEDIA_LOGD("Enter CheckBufferUsage");
404     size_t queueSize = unusedBuffers_.size();
405     for (size_t i = 0; i < queueSize; i++) {
406         MEDIA_LOGD("unusedBuffers begin: %{public}u, end: %{public}u",
407             unusedBuffers_.front().first, unusedBuffers_.front().second);
408         unusedBuffers_.push(unusedBuffers_.front());
409         unusedBuffers_.pop();
410     }
411     for (auto i = unreturnedBuffers_.begin(); i != unreturnedBuffers_.end(); ++i) {
412         MEDIA_LOGD("unreturnedBuffers begin: %{public}u, end: %{public}u", i->first, i->second);
413     }
414 }
415 }
416 }