• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2021 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 #include "data_packer.h"
16 #include <cstring>
17 #include "foundation/log.h"
18 #include "plugin/common/plugin_buffer.h"
19 
20 namespace OHOS {
21 namespace Media {
22 #define LOG_WARN_IF_FAIL(errorNo, errorMsg)                                                                            \
23     do {                                                                                                               \
24         if ((errorNo) != EOK) {                                                                                        \
25             MEDIA_LOG_W(errorMsg);                                                                                     \
26         }                                                                                                              \
27     } while (0)
28 
29 #define RETURN_FALSE_IF_NULL(ptr)                                                                                      \
30     do {                                                                                                               \
31         if ((ptr) == nullptr) {                                                                                        \
32             return false;                                                                                              \
33         }                                                                                                              \
34     } while (0)
35 
DataPacker()36 DataPacker::DataPacker() : mutex_(), que_(), assembler_(), size_(0), bufferOffset_(0), pts_(0), dts_(0)
37 {
38     MEDIA_LOG_I("DataPacker ctor...");
39 }
40 
~DataPacker()41 DataPacker::~DataPacker()
42 {
43     MEDIA_LOG_I("DataPacker dtor...");
44 }
45 
AudioBufferSize(AVBufferPtr & ptr)46 inline static size_t AudioBufferSize(AVBufferPtr& ptr)
47 {
48     return ptr->GetMemory()->GetSize();
49 }
50 
AudioBufferWritableData(AVBufferPtr & ptr,size_t size,size_t position=0)51 inline static uint8_t* AudioBufferWritableData(AVBufferPtr& ptr, size_t size, size_t position = 0)
52 {
53     return ptr->GetMemory()->GetWritableAddr(size, position);
54 }
55 
AudioBufferReadOnlyData(AVBufferPtr & ptr)56 inline static const uint8_t* AudioBufferReadOnlyData(AVBufferPtr& ptr)
57 {
58     return ptr->GetMemory()->GetReadOnlyData();
59 }
60 
PushData(AVBufferPtr bufferPtr,uint64_t offset)61 void DataPacker::PushData(AVBufferPtr bufferPtr, uint64_t offset)
62 {
63     MEDIA_LOG_D("DataPacker PushData begin... buffer (offset %" PUBLIC_LOG_U64 ", size %" PUBLIC_LOG_U32 ")",
64                 offset, AudioBufferSize(bufferPtr));
65     OSAL::ScopedLock lock(mutex_);
66     size_ += AudioBufferSize(bufferPtr);
67     if (que_.empty()) {
68         bufferOffset_ = offset;
69         dts_ = bufferPtr->dts;
70         pts_ = bufferPtr->pts;
71     }
72     que_.emplace_back(std::move(bufferPtr));
73     MEDIA_LOG_D("DataPacker PushData end... dataPacker (offset %" PUBLIC_LOG_U64 ", size %" PUBLIC_LOG_U32 ")",
74                 bufferOffset_, size_.load());
75 }
76 
IsDataAvailable(uint64_t offset,uint32_t size,uint64_t & curOffset)77 bool DataPacker::IsDataAvailable(uint64_t offset, uint32_t size, uint64_t &curOffset)
78 {
79     OSAL::ScopedLock lock(mutex_);
80     auto curOffsetTemp = bufferOffset_;
81     if (que_.empty() || offset < curOffsetTemp || offset >= curOffsetTemp + size_) { // 原有数据无法命中, 则删除原有数据
82         curOffset = offset;
83         FlushInternal();
84         MEDIA_LOG_D("IsDataAvailable false, offset not in cached data, clear it.");
85         return false;
86     }
87     int bufCnt = que_.size();
88     auto offsetEnd = offset + size;
89     auto curOffsetEnd = bufferOffset_ + AudioBufferSize(que_.front());
90     if (bufCnt == 1) {
91         curOffset = curOffsetEnd;
92         MEDIA_LOG_D("IsDataAvailable bufCnt == 1, result %" PUBLIC_LOG_D32, offsetEnd <= curOffsetEnd);
93         return offsetEnd <= curOffsetEnd;
94     }
95     auto preOffsetEnd = curOffsetEnd;
96     for (auto i = 1; i < bufCnt; ++i) {
97         curOffsetEnd = preOffsetEnd + AudioBufferSize(que_[i]);
98         if (curOffsetEnd >= offsetEnd) {
99             MEDIA_LOG_D("IsDataAvailable true, last buffer index %" PUBLIC_LOG_U32 ", offsetEnd %" PUBLIC_LOG_U64
100                 ", curOffsetEnd %" PUBLIC_LOG_U64, i, offsetEnd, curOffsetEnd);
101             return true;
102         } else {
103             preOffsetEnd = curOffsetEnd;
104         }
105     }
106     if (preOffsetEnd >= offsetEnd) {
107         MEDIA_LOG_D("IsDataAvailable true, use all buffers, last buffer index %" PUBLIC_LOG_U32 ", offsetEnd %"
108             PUBLIC_LOG_U64 ", curOffsetEnd %" PUBLIC_LOG_U64, bufCnt - 1, offsetEnd, curOffsetEnd);
109         return true;
110     }
111     curOffset = preOffsetEnd;
112     MEDIA_LOG_D("IsDataAvailable false, offsetEnd %" PUBLIC_LOG_U64 ", curOffsetEnd %" PUBLIC_LOG_U64,
113                 offsetEnd, curOffsetEnd);
114     return false;
115 }
116 
PeekRange(uint64_t offset,uint32_t size,AVBufferPtr & bufferPtr)117 bool DataPacker::PeekRange(uint64_t offset, uint32_t size, AVBufferPtr& bufferPtr)
118 {
119     OSAL::ScopedLock lock(mutex_);
120     return PeekRangeInternal(offset, size, bufferPtr);
121 }
122 
123 // 在调用当前接口前需要先调用IsDataAvailable()
124 // offset - 要peek的数据起始位置 在media file文件 中的 offset
125 // size - 要读取的长度
126 // bufferPtr - 出参
PeekRangeInternal(uint64_t offset,uint32_t size,AVBufferPtr & bufferPtr)127 bool DataPacker::PeekRangeInternal(uint64_t offset, uint32_t size, AVBufferPtr& bufferPtr)
128 {
129     MEDIA_LOG_D("DataPacker PeekRange(offset, size) = (%" PUBLIC_LOG PRIu64 ", %"
130                 PUBLIC_LOG PRIu32 ")...", offset, size);
131     FALSE_RETURN_V(bufferPtr != nullptr, false);
132     assembler_.resize(size);
133     uint8_t* dstPtr = assembler_.data();
134     auto offsetEnd = offset + size;
135     auto curOffsetEnd = bufferOffset_ + AudioBufferSize(que_[0]);
136     if (offsetEnd <= curOffsetEnd) { // 0号buffer够用
137         dstPtr = AudioBufferWritableData(bufferPtr, size);
138         RETURN_FALSE_IF_NULL(dstPtr);
139         LOG_WARN_IF_FAIL(memcpy_s(dstPtr, size,
140             AudioBufferReadOnlyData(que_[0]) + offset - bufferOffset_, size), "failed to memcpy");
141     } else { // 0号buffer不够用
142         // 拷贝第一个buffer需要的内容(多数时候是0号buffer)
143         // 找到第一个要拷贝的Buffer
144         size_t index = 0;
145         uint64_t prevOffset = bufferOffset_;
146         do {
147             if (offset >= prevOffset && offset - prevOffset < AudioBufferSize(que_[index])) {
148                 break;
149             }
150             prevOffset += AudioBufferSize(que_[index]);
151             index++;
152         } while (index < que_.size());
153         FALSE_RET_V_MSG_E(index < que_.size(), false, "Can not find first buffer to copy.");
154         auto srcSize = AudioBufferSize(que_[index]) - (offset - prevOffset);
155         dstPtr = AudioBufferWritableData(bufferPtr, srcSize);
156         RETURN_FALSE_IF_NULL(dstPtr);
157         LOG_WARN_IF_FAIL(memcpy_s(dstPtr, srcSize,
158             AudioBufferReadOnlyData(que_[index]) + offset - prevOffset, srcSize),
159             "failed to copy memory");
160 
161         // 数据不足的部分,从后续buffer(多数时候是1/2/3...号)拷贝
162         auto prevMediaOffsetEnd = prevOffset + AudioBufferSize(que_[index]);
163         dstPtr += srcSize;
164         size -= srcSize;
165         for (size_t i = index + 1; i < que_.size(); ++i) {
166             curOffsetEnd = prevMediaOffsetEnd + AudioBufferSize(que_[i]);
167             if (curOffsetEnd >= offsetEnd) {
168                 LOG_WARN_IF_FAIL(memcpy_s(dstPtr, size, AudioBufferReadOnlyData(que_[i]), size),
169                                  "failed to copy memory");
170                 break;
171             } else {
172                 srcSize = AudioBufferSize(que_[i]);
173                 LOG_WARN_IF_FAIL(memcpy_s(dstPtr, srcSize, AudioBufferReadOnlyData(que_[i]), srcSize),
174                                  "failed to copy memory");
175                 dstPtr += srcSize;
176                 size -= srcSize;
177                 prevMediaOffsetEnd += srcSize;
178             }
179         }
180     }
181     FALSE_LOG_MSG_W(curOffsetEnd >= offsetEnd, "Processed all cached buffers, still not meet offsetEnd.");
182     WrapAssemblerBuffer(offset).swap(bufferPtr);
183     return true;
184 }
185 
186 // 单个buffer不足以存储请求的数据,需要合并多个buffer从而组成目标buffer
RepackBuffers(uint64_t offset,uint32_t size,AVBufferPtr & bufferPtr)187 bool DataPacker::RepackBuffers(uint64_t offset, uint32_t size, AVBufferPtr& bufferPtr)
188 {
189     // 可能的改进点: 即使是GetRange, 也会先Peek数据,从而发生拷贝, 有可能可以减少拷贝
190     FALSE_RETURN_V(PeekRangeInternal(offset, size, bufferPtr), false);
191 
192     // 删除已经拿走的数据
193     auto offsetEnd = offset + size;
194     size_ -= size;
195     while (!que_.empty()) {
196         auto& buf = que_.front();
197         auto curOffsetEnd = bufferOffset_ + AudioBufferSize(buf);
198         if (curOffsetEnd < offsetEnd) {
199             que_.pop_front();
200             bufferOffset_ = curOffsetEnd;
201             continue;
202         } else if (curOffsetEnd == offsetEnd) {
203             que_.pop_front();
204             bufferOffset_ = curOffsetEnd;
205             if (!que_.empty()) {
206                 dts_ = que_.front()->dts;
207                 pts_ = que_.front()->pts;
208             }
209         } else {
210             auto removeSize = AudioBufferSize(que_.front()) - (curOffsetEnd - offsetEnd);
211             RemoveBufferContent(que_.front(), removeSize);
212             bufferOffset_ = offsetEnd;
213             dts_ = buf->dts;
214             pts_ = buf->pts;
215         }
216         break;
217     }
218     return true;
219 }
220 
221 // 在调用当前接口前需要先调用IsDataAvailable()
GetRange(uint64_t offset,uint32_t size,AVBufferPtr & bufferPtr)222 bool DataPacker::GetRange(uint64_t offset, uint32_t size, AVBufferPtr& bufferPtr)
223 {
224     MEDIA_LOG_D("DataPacker GetRange(offset, size) = (%" PUBLIC_LOG PRIu64 ", %"
225                 PUBLIC_LOG PRIu32 ")...", offset, size);
226     OSAL::ScopedLock lock(mutex_);
227     if (!bufferPtr) {
228         bufferPtr = std::make_shared<AVBuffer>();
229     }
230     if (RepackBuffers(offset, size, bufferPtr)) {
231         return true;
232     }
233     MEDIA_LOG_E("GetRange peek data failed, have you called IsDataAvailable() first?");
234     return false;
235 }
236 
WrapAssemblerBuffer(uint64_t offset)237 AVBufferPtr DataPacker::WrapAssemblerBuffer(uint64_t offset)
238 {
239     MEDIA_LOG_D("DataPacker WrapAssemblerBuffer, offset = %" PUBLIC_LOG PRIu64, offset);
240     (void)offset;
241     auto bufferPtr = std::make_shared<AVBuffer>();
242     auto dataPtr = std::shared_ptr<uint8_t>(assembler_.data(), [this](void* ptr) { assembler_.resize(0); });
243     auto bufferData = bufferPtr->WrapMemoryPtr(dataPtr, assembler_.size(), assembler_.size());
244     bufferPtr->dts = dts_;
245     bufferPtr->pts = pts_;
246     return bufferPtr;
247 }
248 
Flush()249 void DataPacker::Flush()
250 {
251     MEDIA_LOG_I("DataPacker Flush called.");
252     OSAL::ScopedLock lock(mutex_);
253     FlushInternal();
254 }
255 
FlushInternal()256 void DataPacker::FlushInternal()
257 {
258     MEDIA_LOG_D("DataPacker FlushInternal called.");
259     que_.clear();
260     size_ = 0;
261     bufferOffset_ = 0;
262     dts_ = 0;
263     pts_ = 0;
264 }
265 
RemoveBufferContent(std::shared_ptr<AVBuffer> & buffer,size_t removeSize)266 void DataPacker::RemoveBufferContent(std::shared_ptr<AVBuffer> &buffer, size_t removeSize) {
267     auto memory = buffer->GetMemory();
268     auto copySize = memory->GetSize() - removeSize;
269     FALSE_LOG_MSG_E(memmove_s(memory->GetWritableAddr(copySize), memory->GetCapacity(),
270               memory->GetReadOnlyData(removeSize), copySize) == EOK, "memmove failed.");
271 }
272 } // namespace Media
273 } // namespace OHOS
274