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