1 /*
2 * Copyright (c) 2023-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 #define HST_LOG_TAG "DataPacker"
16
17 #include <cstring>
18 #include "common/log.h"
19 #include "osal/task/autolock.h"
20 #include "securec.h"
21 #include "data_packer.h"
22
23 namespace OHOS {
24 namespace Media {
25 using namespace Plugins;
26 using AVBufferPtr = std::shared_ptr<Buffer>;
27 #define EXEC_WHEN_GET(isGet, exec) \
28 do { \
29 if (isGet) { \
30 exec; \
31 } \
32 } while (0)
33
34 static const DataPacker::Position DATA_PACKER_INVALID_POSITION = DataPacker::Position(-1, 0, 0);
35 static constexpr size_t MIN_BUFFER_NUMBER_IN_DATA_PACKER = 30;
36 static constexpr size_t MAX_BUFFER_NUMBER_IN_DATA_PACKER = 10 * 1024 * 1024 / 4096;
37
DataPacker()38 DataPacker::DataPacker() : mutex_(), que_(), size_(0), mediaOffset_(0), pts_(0), dts_(0),
39 prevGet_(DATA_PACKER_INVALID_POSITION), currentGet_(DATA_PACKER_INVALID_POSITION),
40 capacity_(MAX_BUFFER_NUMBER_IN_DATA_PACKER)
41 {
42 MEDIA_LOG_I("DataPacker ctor...");
43 }
44
~DataPacker()45 DataPacker::~DataPacker()
46 {
47 MEDIA_LOG_I("DataPacker dtor...");
48 cvEmpty_.NotifyAll();
49 cvFull_.NotifyAll();
50 cvAllowRead_.NotifyAll();
51 }
52
GetBufferSize(AVBufferPtr & ptr)53 inline static size_t GetBufferSize(AVBufferPtr& ptr)
54 {
55 return ptr->GetMemory()->GetSize();
56 }
57
GetBufferWritableData(AVBufferPtr & ptr,size_t size,size_t position=0)58 inline static uint8_t* GetBufferWritableData(AVBufferPtr& ptr, size_t size, size_t position = 0)
59 {
60 return ptr->GetMemory()->GetWritableAddr(size, position);
61 }
62
GetBufferReadOnlyData(AVBufferPtr & ptr)63 inline static const uint8_t* GetBufferReadOnlyData(AVBufferPtr& ptr)
64 {
65 return ptr->GetMemory()->GetReadOnlyData();
66 }
67
PushData(AVBufferPtr & bufferPtr,uint64_t offset)68 void DataPacker::PushData(AVBufferPtr& bufferPtr, uint64_t offset)
69 {
70 size_t bufferSize = GetBufferSize(bufferPtr);
71 MEDIA_LOG_D("DataPacker PushData begin... buffer (offset " PUBLIC_LOG_U64 ", size " PUBLIC_LOG_ZU ")",
72 offset, bufferSize);
73 FALSE_RETURN_MSG(bufferSize > 0, "Can not push zero length buffer.");
74
75 AutoLock lock(mutex_);
76 if (que_.size() >= capacity_) {
77 MEDIA_LOG_D("DataPacker is full, waiting for pop.");
78 do {
79 cvFull_.WaitFor(lock, 1000, // 1000 ms
80 [this] { return que_.size() < capacity_ || stopped_.load(); });
81 if (stopped_.load()) {
82 MEDIA_LOG_D("DataPacker stopped, so return.");
83 return;
84 }
85 } while (que_.size() >= capacity_);
86 }
87
88 size_ += GetBufferSize(bufferPtr);
89 if (que_.empty()) {
90 MEDIA_LOG_D("DataPacker que_ is empty.");
91 mediaOffset_ = offset;
92 dts_ = bufferPtr->dts;
93 pts_ = bufferPtr->pts;
94 }
95 que_.emplace_back(std::move(bufferPtr));
96 cvEmpty_.NotifyAll();
97 MEDIA_LOG_D("DataPacker PushData end. " PUBLIC_LOG_S, ToString().c_str());
98 }
99
IsDataAvailable(uint64_t offset,uint32_t size)100 bool DataPacker::IsDataAvailable(uint64_t offset, uint32_t size)
101 {
102 AutoLock lock(mutex_);
103 return IsDataAvailableInternal(offset, size);
104 }
105
IsDataAvailableInternal(uint64_t offset,uint32_t size)106 bool DataPacker::IsDataAvailableInternal(uint64_t offset, uint32_t size)
107 {
108 MEDIA_LOG_D("dataPacker (offset " PUBLIC_LOG_U64 ", size " PUBLIC_LOG_U32 "), curOffsetEnd is " PUBLIC_LOG_U64
109 ", income offset: " PUBLIC_LOG_U64 ", income size: " PUBLIC_LOG_U32,
110 mediaOffset_, size_.load(), mediaOffset_ + size_.load(), offset, size);
111 auto curOffsetTemp = mediaOffset_;
112 if (que_.empty() || offset < curOffsetTemp || offset > curOffsetTemp + size_) {
113 FlushInternal();
114 MEDIA_LOG_D("IsDataAvailable false, offset not in cached data, clear it.");
115 return false;
116 }
117 size_t bufCnt = que_.size();
118 uint64_t offsetEnd = offset + size;
119 uint64_t curOffsetEnd = mediaOffset_ + GetBufferSize(que_.front());
120 if (bufCnt == 1) {
121 MEDIA_LOG_D("IsDataAvailable bufCnt == 1, result " PUBLIC_LOG_D32, offsetEnd <= curOffsetEnd);
122 return offsetEnd <= curOffsetEnd;
123 }
124 auto preOffsetEnd = curOffsetEnd;
125 for (size_t i = 1; i < bufCnt; ++i) {
126 curOffsetEnd = preOffsetEnd + GetBufferSize(que_[i]);
127 if (curOffsetEnd >= offsetEnd) {
128 MEDIA_LOG_D("IsDataAvailable true, last buffer index " PUBLIC_LOG_ZU ", offsetEnd " PUBLIC_LOG_U64
129 ", curOffsetEnd " PUBLIC_LOG_U64, i, offsetEnd, curOffsetEnd);
130 return true;
131 } else {
132 preOffsetEnd = curOffsetEnd;
133 }
134 }
135 if (preOffsetEnd >= offsetEnd || isEos_) {
136 MEDIA_LOG_D("IsDataAvailable true, use all buffers, last buffer index " PUBLIC_LOG_ZU ", offsetEnd "
137 PUBLIC_LOG_U64 ", curOffsetEnd " PUBLIC_LOG_U64, bufCnt - 1, offsetEnd, curOffsetEnd);
138 return true;
139 }
140 MEDIA_LOG_D("IsDataAvailable false, offsetEnd " PUBLIC_LOG_U64 ", curOffsetEnd " PUBLIC_LOG_U64,
141 offsetEnd, preOffsetEnd);
142 return false;
143 }
144
PeekRange(uint64_t offset,uint32_t size,AVBufferPtr & bufferPtr)145 bool DataPacker::PeekRange(uint64_t offset, uint32_t size, AVBufferPtr& bufferPtr)
146 {
147 AutoLock lock(mutex_);
148 if (que_.empty()) {
149 MEDIA_LOG_D("DataPacker is empty, waiting for push.");
150 cvEmpty_.Wait(lock, [this] { return !que_.empty(); });
151 }
152
153 return PeekRangeInternal(offset, size, bufferPtr, false);
154 }
155
PeekRangeInternal(uint64_t offset,uint32_t size,AVBufferPtr & bufferPtr,bool isGet)156 bool DataPacker::PeekRangeInternal(uint64_t offset, uint32_t size, AVBufferPtr &bufferPtr, bool isGet)
157 {
158 MEDIA_LOG_D("PeekRangeInternal (offset, size) = (" PUBLIC_LOG_U64 ", " PUBLIC_LOG_U32 ")...", offset, size);
159 int32_t startIndex = 0; // The index of buffer that we first use
160 size_t copySize = 0;
161 uint32_t needCopySize = size;
162 uint32_t firstBufferOffset = 0;
163 uint8_t* dstPtr = GetBufferWritableData(bufferPtr, needCopySize);
164 FALSE_RETURN_V(dstPtr != nullptr, false);
165
166 auto offsetEnd = offset + needCopySize;
167 auto curOffsetEnd = mediaOffset_ + GetBufferSize(que_[startIndex]);
168 if (offsetEnd <= curOffsetEnd) { // first buffer is enough
169 auto bufferOffset = static_cast<int32_t>(offset - mediaOffset_);
170 FALSE_RETURN_V_MSG_E(bufferOffset >= 0, false, "Copy buffer start position error.");
171 firstBufferOffset = bufferOffset;
172 copySize = CopyFirstBuffer(size, startIndex, dstPtr, bufferPtr, bufferOffset);
173 needCopySize -= copySize;
174 FALSE_LOG_MSG(needCopySize == 0, "First buffer is enough, but copySize is not enough");
175 EXEC_WHEN_GET(isGet, currentGet_ = Position(startIndex, firstBufferOffset, offset));
176 return true;
177 } else { // first buffer not enough
178 // Find the first buffer that should copy
179 uint64_t prevOffset; // The media offset of the startIndex buffer start byte
180 FALSE_RETURN_V_MSG_E(FindFirstBufferToCopy(offset, startIndex, prevOffset), false,
181 "Read offset(" PUBLIC_LOG_D64 ") size(" PUBLIC_LOG_D32 ") from " PUBLIC_LOG_S,
182 offset, size, ToString().c_str());
183 auto bufferOffset = static_cast<int32_t>(offset - prevOffset);
184 FALSE_RETURN_V_MSG_E(bufferOffset >= 0, false, "Copy buffer start position error.");
185 firstBufferOffset = bufferOffset;
186 copySize = CopyFirstBuffer(size, startIndex, dstPtr, bufferPtr, bufferOffset);
187
188 needCopySize -= copySize;
189 if (needCopySize == 0) { // First buffer is enough
190 EXEC_WHEN_GET(isGet, currentGet_ = Position(startIndex, firstBufferOffset, offset));
191 return true;
192 }
193 dstPtr += copySize;
194
195 // First buffer is not enough, copy from successive buffers
196 (void)CopyFromSuccessiveBuffer(prevOffset, offsetEnd, startIndex, dstPtr, needCopySize);
197 }
198 EXEC_WHEN_GET(isGet, currentGet_ = Position(startIndex, firstBufferOffset, offset));
199
200 // Update to the real size, especially at the end.
201 bufferPtr->GetMemory()->UpdateDataSize(size - needCopySize);
202 return true;
203 }
204
205 // Call IsDataAvailable() first before call GetRange
GetRange(uint64_t offset,uint32_t size,AVBufferPtr & bufferPtr)206 bool DataPacker::GetRange(uint64_t offset, uint32_t size, AVBufferPtr& bufferPtr)
207 {
208 MEDIA_LOG_D("DataPacker GetRange(offset, size) = (" PUBLIC_LOG_U64 ", "
209 PUBLIC_LOG_U32 ")...", offset, size);
210 FALSE_RETURN_V_MSG_E(bufferPtr && (!bufferPtr->IsEmpty()) && bufferPtr->GetMemory()->GetCapacity() >= size, false,
211 "GetRange input bufferPtr empty or capacity not enough.");
212
213 AutoLock lock(mutex_);
214 if (que_.empty()) {
215 MEDIA_LOG_D("DataPacker is empty, waiting for push");
216 cvEmpty_.Wait(lock, [this] { return !que_.empty(); });
217 }
218
219 FALSE_RETURN_V(!que_.empty(), false);
220 prevGet_ = currentGet_; // store last get position to prevGet_
221
222 FALSE_RETURN_V(PeekRangeInternal(offset, size, bufferPtr, true), false);
223 if (isEos_ && size_ <= size) { // Is EOS, and this time get all the data.
224 FlushInternal();
225 } else {
226 if (prevGet_ < currentGet_) {
227 RemoveOldData(currentGet_);
228 }
229 }
230
231 if (que_.size() < capacity_) {
232 cvFull_.NotifyOne();
233 }
234 return true;
235 }
236
PreRemove(uint64_t preRemoveOffset,bool isPreRemove)237 void DataPacker::PreRemove(uint64_t preRemoveOffset, bool isPreRemove)
238 {
239 if (!isPreRemove) {
240 return;
241 }
242 int32_t index = 0;
243 uint32_t bufferOffset = 0;
244 uint64_t mediaOffset = preRemoveOffset;
245 uint64_t sum = 0;
246 for (index = 0; index < static_cast<int32_t>(que_.size()); index++) {
247 if (sum < preRemoveOffset && sum + GetBufferSize(que_[index]) >= preRemoveOffset) {
248 bufferOffset = preRemoveOffset - sum;
249 break;
250 }
251 sum += GetBufferSize(que_[index]);
252 }
253 MEDIA_LOG_D("DataPacker PreRemove, index: " PUBLIC_LOG_D32 ", bufferOffset: " PUBLIC_LOG_U32
254 ", mediaOffset: " PUBLIC_LOG_U64, index, bufferOffset, mediaOffset);
255 auto endPosition = Position(index, bufferOffset, mediaOffset);
256 RemoveOldData(endPosition);
257 MEDIA_LOG_D("DataPacker PreRemove, size: " PUBLIC_LOG_D32, static_cast<int32_t>(que_.size()));
258 }
259
260 // GetRange in live play mode
261 // 1. not use offset
262 // 2. remove the data have been read
GetRange(uint32_t size,AVBufferPtr & bufferPtr,uint64_t preRemoveOffset,bool isPreRemove)263 bool DataPacker::GetRange(uint32_t size, AVBufferPtr& bufferPtr, uint64_t preRemoveOffset, bool isPreRemove)
264 {
265 MEDIA_LOG_D("GetRange(size) = (" PUBLIC_LOG_U32 "), preRemoveOffset: " PUBLIC_LOG_U64, size, preRemoveOffset);
266 FALSE_RETURN_V_MSG_E(bufferPtr && (!bufferPtr->IsEmpty()) && bufferPtr->GetMemory()->GetCapacity() >= size, false,
267 "Live play GetRange input bufferPtr empty or capacity not enough.");
268 AutoLock lock(mutex_);
269 if (que_.empty()) {
270 FALSE_RETURN_V_W(!isEos_, false);
271 MEDIA_LOG_D("DataPacker is empty, live play GetRange waiting for push");
272 cvEmpty_.Wait(lock, [this] { return !que_.empty() || isEos_; });
273 if (isEos_) {
274 MEDIA_LOG_D("Eos wakeup the cvEmpty ConditionVariable");
275 return false;
276 }
277 }
278 PreRemove(preRemoveOffset, isPreRemove);
279 FALSE_RETURN_V_MSG_W(!que_.empty(), false, "que_ is empty");
280 int32_t needCopySize = static_cast<int32_t>(size);
281 int32_t index = 0;
282 uint32_t lastBufferOffsetEnd = 0;
283 uint8_t* dstPtr = GetBufferWritableData(bufferPtr, size);
284 FALSE_RETURN_V_MSG_E(dstPtr != nullptr, false, "dstPtr is nullptr");
285 while (static_cast<uint32_t>(index) < que_.size()) {
286 AVBufferPtr& buffer = que_[index];
287 size_t bufferSize = GetBufferSize(buffer);
288 int32_t currCopySize = std::min(static_cast<int32_t>(bufferSize), needCopySize);
289 currCopySize = CopyFirstBuffer(currCopySize, index, dstPtr, bufferPtr, 0);
290 lastBufferOffsetEnd = currCopySize;
291 dstPtr += currCopySize;
292 needCopySize -= currCopySize;
293 if (needCopySize <= 0) { // it is enough
294 break;
295 }
296 index++;
297 lastBufferOffsetEnd = 0;
298 }
299 FALSE_LOG(needCopySize >= 0);
300 needCopySize = needCopySize < 0 ? 0 : needCopySize;
301 bufferPtr->GetMemory()->UpdateDataSize(size - needCopySize);
302 MEDIA_LOG_D("GetRange before remove, size: " PUBLIC_LOG_D32 ", index: " PUBLIC_LOG_D32 ", lastBufferOffsetEnd: "
303 PUBLIC_LOG_U32 ", mediaOffset: " PUBLIC_LOG_U64, static_cast<int32_t>(que_.size()),
304 index, lastBufferOffsetEnd, mediaOffset_ + size - needCopySize);
305 auto endPosition = Position(index, lastBufferOffsetEnd, mediaOffset_ + size - needCopySize);
306 RemoveOldData(endPosition); // Live play, remove the got data
307 MEDIA_LOG_D("GetRange after remove, size: " PUBLIC_LOG_D32, static_cast<int32_t>(que_.size()));
308 if (que_.size() < capacity_) {
309 cvFull_.NotifyOne();
310 }
311 return true;
312 }
313
GetOrWaitDataAvailable(uint64_t offset,uint32_t size)314 bool DataPacker::GetOrWaitDataAvailable(uint64_t offset, uint32_t size)
315 {
316 MEDIA_LOG_D("GetOrWaitDataAvailable, offset: " PUBLIC_LOG_U64 ", size: " PUBLIC_LOG_U32 ", mediaOffset_: "
317 PUBLIC_LOG_U64 ", size_: " PUBLIC_LOG_U32, offset, size, mediaOffset_, size_.load());
318 AutoLock lock(mutex_);
319 if (!IsDataAvailableInternal(offset, size)) {
320 MEDIA_LOG_D("GetOrWaitDataAvailable, data is not available, start to wait.");
321 do {
322 auto ret = cvEmpty_.WaitFor(lock, 1000, [this, offset, size] () {
323 return IsDataAvailableInternal(offset, size) || stopped_.load();
324 });
325 if (!ret) {
326 MEDIA_LOG_E("GetOrWaitDataAvailable wait for data, time out");
327 return false;
328 }
329 if (stopped_.load()) {
330 MEDIA_LOG_D("DataPacker stopped, so return.");
331 return false;
332 }
333 } while (!IsDataAvailableInternal(offset, size));
334 }
335 MEDIA_LOG_D("GetOrWaitDataAvailable get data success after wait.");
336 return true;
337 }
338
Flush()339 void DataPacker::Flush()
340 {
341 MEDIA_LOG_I("DataPacker Flush called.");
342 AutoLock lock(mutex_);
343 FlushInternal();
344 }
345
SetEos()346 void DataPacker::SetEos()
347 {
348 MEDIA_LOG_I("DataPacker SetEos called.");
349 AutoLock lock(mutex_);
350 isEos_ = true;
351 cvEmpty_.NotifyOne();
352 cvAllowRead_.NotifyOne();
353 }
354
IsSupportPreDownload(bool isSupport)355 void DataPacker::IsSupportPreDownload(bool isSupport)
356 {
357 isSupportPreDownload_ = isSupport;
358 capacity_ = isSupportPreDownload_ ? MAX_BUFFER_NUMBER_IN_DATA_PACKER : MIN_BUFFER_NUMBER_IN_DATA_PACKER;
359 }
360
IsEmpty()361 bool DataPacker::IsEmpty()
362 {
363 AutoLock lock(mutex_);
364 cvAllowRead_.NotifyOne();
365 return size_ > 0;
366 }
367
Start()368 void DataPacker::Start()
369 {
370 MEDIA_LOG_I("DataPacker Start called.");
371 stopped_.store(false);
372 }
373
Stop()374 void DataPacker::Stop()
375 {
376 MEDIA_LOG_I("DataPacker Stop called.");
377 FlushInternal();
378 stopped_.store(true);
379 cvEmpty_.NotifyAll(); // avoid some thread can not exit
380 cvFull_.NotifyAll();
381 }
382
FlushInternal()383 void DataPacker::FlushInternal()
384 {
385 MEDIA_LOG_D("DataPacker FlushInternal called, que_ size: " PUBLIC_LOG_D32 ", capacity_: " PUBLIC_LOG_ZU,
386 static_cast<int32_t>(que_.size()), capacity_);
387 que_.clear();
388 size_ = 0;
389 mediaOffset_ = 0;
390 dts_ = 0;
391 pts_ = 0;
392 isEos_ = false;
393 prevGet_ = DATA_PACKER_INVALID_POSITION;
394 currentGet_ = DATA_PACKER_INVALID_POSITION;
395 }
396
397 // Remove first removeSize data in the buffer
RemoveBufferContent(AVBufferPtr & buffer,size_t removeSize)398 void DataPacker::RemoveBufferContent(AVBufferPtr &buffer, size_t removeSize)
399 {
400 if (removeSize == 0) {
401 return;
402 }
403 auto memory = buffer->GetMemory();
404 FALSE_RETURN(removeSize < memory->GetSize());
405 auto copySize = memory->GetSize() - removeSize;
406 FALSE_LOG_MSG(memmove_s(memory->GetWritableAddr(copySize), memory->GetCapacity(),
407 memory->GetReadOnlyData(removeSize), copySize) == EOK, "memmove failed.");
408 FALSE_RETURN(UpdateWhenFrontDataRemoved(removeSize));
409 }
410
411 // Remove consumed data, and make the remaining data continuous
412 // Consumed data - between prevGet_.first and currentGet_.first
413 // In order to make remaining data continuous, also remove the data before prevGet_.first
414 // Update to support live play mode, Remove the data before position
RemoveOldData(const Position & position)415 void DataPacker::RemoveOldData(const Position& position)
416 {
417 MEDIA_LOG_D("Before RemoveOldData " PUBLIC_LOG_S, ToString().c_str());
418 FALSE_LOG(RemoveTo(position));
419 if (que_.empty()) {
420 mediaOffset_ = 0;
421 size_ = 0;
422 pts_ = 0;
423 dts_ = 0;
424 } else {
425 pts_ = que_.front()->pts;
426 dts_ = que_.front()->dts;
427 }
428 MEDIA_LOG_D("After RemoveOldData " PUBLIC_LOG_S, ToString().c_str());
429 }
430
RemoveTo(const Position & position)431 bool DataPacker::RemoveTo(const Position& position)
432 {
433 MEDIA_LOG_D("Remove to " PUBLIC_LOG_S, position.ToString().c_str());
434 size_t removeSize;
435 int32_t i = 0;
436 while (i < position.index && !que_.empty()) { // Remove all whole buffer before position.index
437 removeSize = GetBufferSize(que_.front());
438 FALSE_RETURN_V(UpdateWhenFrontDataRemoved(removeSize), false);
439 que_.pop_front();
440 i++;
441 }
442 FALSE_RETURN_V_W(!que_.empty(), true);
443
444 // The last buffer
445 removeSize = GetBufferSize(que_.front());
446 // 1. If whole buffer should be removed
447 if (position.bufferOffset >= removeSize) {
448 FALSE_RETURN_V(UpdateWhenFrontDataRemoved(removeSize), false);
449 que_.pop_front();
450 return true;
451 }
452 // 2. Remove the front part of the buffer data
453 RemoveBufferContent(que_.front(), position.bufferOffset);
454 return true;
455 }
456
UpdateWhenFrontDataRemoved(size_t removeSize)457 bool DataPacker::UpdateWhenFrontDataRemoved(size_t removeSize)
458 {
459 mediaOffset_ += removeSize;
460 FALSE_RETURN_V_MSG_E(size_.load() >= removeSize, false, "Total size(size_ " PUBLIC_LOG_U32
461 ") smaller than removeSize(" PUBLIC_LOG_ZU ")", size_.load(), removeSize);
462 size_ -= removeSize;
463 return true;
464 }
465
466 // offset : from GetRange(offset, size)
467 // startIndex : out, find the first buffer should copy
468 // prevOffset : the first copied buffer's media offset.
FindFirstBufferToCopy(uint64_t offset,int32_t & startIndex,uint64_t & prevOffset)469 bool DataPacker::FindFirstBufferToCopy(uint64_t offset, int32_t &startIndex, uint64_t &prevOffset)
470 {
471 startIndex = 0;
472 prevOffset = mediaOffset_;
473 do {
474 if (offset >= prevOffset && offset - prevOffset < GetBufferSize(que_[startIndex])) {
475 return true;
476 }
477 prevOffset += GetBufferSize(que_[startIndex]);
478 startIndex++;
479 } while (static_cast<size_t>(startIndex) < que_.size());
480 return false;
481 }
482
483 // size : the GetRange size
484 // dstPtr : copy data to here
485 // dstBufferPtr : the Buffer contains dstPtr, pass this parameter to update pts / dts.
486 // bufferOffset : the buffer offset that we start copy
CopyFirstBuffer(size_t size,int32_t index,uint8_t * dstPtr,AVBufferPtr & dstBufferPtr,int32_t bufferOffset)487 size_t DataPacker::CopyFirstBuffer(size_t size, int32_t index, uint8_t *dstPtr, AVBufferPtr& dstBufferPtr,
488 int32_t bufferOffset)
489 {
490 auto remainSize = static_cast<int32_t>(GetBufferSize(que_[index]) - bufferOffset);
491 FALSE_RETURN_V_MSG_E(remainSize > 0, 0, "Copy size can not be negative.");
492 size_t copySize = std::min(static_cast<size_t>(remainSize), size);
493 NZERO_LOG(memcpy_s(dstPtr, copySize,
494 GetBufferReadOnlyData(que_[index]) + bufferOffset, copySize));
495
496 dstBufferPtr->pts = que_[index]->pts;
497 dstBufferPtr->dts = que_[index]->dts;
498 return copySize;
499 }
500
501 // prevOffset : the media offset of the first byte in the startIndex + 1 buffer
502 // offsetEnd : calculate from GetRange(offset, size), offsetEnd = offset + size.
503 // startIndex : the index start copy data for this GetRange. CopyFromSuccessiveBuffer process from startIndex + 1.
504 // dstPtr : copy data to here
505 // needCopySize : in and out, indicate how many bytes still need to copy.
CopyFromSuccessiveBuffer(uint64_t prevOffset,uint64_t offsetEnd,int32_t startIndex,uint8_t * dstPtr,uint32_t & needCopySize)506 int32_t DataPacker::CopyFromSuccessiveBuffer(uint64_t prevOffset, uint64_t offsetEnd, int32_t startIndex,
507 uint8_t *dstPtr, uint32_t &needCopySize)
508 {
509 size_t copySize;
510 int32_t usedCount = 0;
511 prevOffset = prevOffset + GetBufferSize(que_[startIndex]);
512 for (size_t i = startIndex + 1; i < que_.size(); ++i) {
513 usedCount++;
514 uint64_t curOffsetEnd = prevOffset + GetBufferSize(que_[i]);
515 if (curOffsetEnd >= offsetEnd) { // This buffer is enough
516 NZERO_LOG(memcpy_s(dstPtr, needCopySize, GetBufferReadOnlyData(que_[i]), needCopySize));
517 needCopySize = 0;
518 return usedCount; // Finished copy buffer
519 } else {
520 copySize = GetBufferSize(que_[i]);
521 NZERO_LOG(memcpy_s(dstPtr, copySize, GetBufferReadOnlyData(que_[i]), copySize));
522 dstPtr += copySize;
523 needCopySize -= copySize;
524 prevOffset += copySize;
525 }
526 }
527 MEDIA_LOG_W("Processed all cached buffers, still not meet offsetEnd, maybe EOS reached.");
528 return usedCount;
529 }
530
ToString() const531 std::string DataPacker::ToString() const
532 {
533 return "DataPacker (offset " + std::to_string(mediaOffset_) + ", size " + std::to_string(size_) +
534 ", buffer count " + std::to_string(que_.size()) + ")";
535 }
536 } // namespace Media
537 } // namespace OHOS
538