1 /*
2 * Copyright (c) 2025 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 "lpp_common.h"
16 #include "buffer/avbuffer.h"
17 #include "common/native_mfmagic.h"
18 #include "media_log.h"
19 #include "media_errors.h"
20 #include "native_avbuffer.h"
21 #include "surface_buffer_impl.h"
22 #include "common/log.h"
23 #include <securec.h>
24 #include "param_wrapper.h"
25
26 namespace {
27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "LppDataPacket"};
28 constexpr uint32_t MAX_BUFFER_SIZE = 10 * 1024 * 1024;
29 const std::string DUMP_FILE_DIR_SANDBOX = "/data/storage/el2/base/files/";
30 const std::string DUMP_FILE_DIR_SERVER = "/data/media/pipelinedump/";
31 constexpr size_t DUMP_DATA_UNIT = 1; // data unit is 1 byte
32 const std::string DUMP_PARAM = "a";
33 constexpr int64_t MAX_BUFFER_CNT = 100;
34 } // namespace
35 namespace OHOS {
36 namespace Media {
37
Init(std::string streamerId)38 void LppDataPacket::Init(std::string streamerId)
39 {
40 Init();
41 streamerId_ = streamerId;
42 std::string enableDump;
43 auto ret = OHOS::system::GetStringParameter("debug.media_service.enable_video_lpp_dump", enableDump, "false");
44 dumpBufferNeeded_ = ret == 0 ? enableDump == "true" : false;
45 dumpFileNameInput_ = streamerId_ + "_DUMP_INPUT.bin";
46 }
47
Init()48 void LppDataPacket::Init()
49 {
50 auto allocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
51 buffer_ = AVBuffer::CreateAVBuffer(allocator, MAX_BUFFER_SIZE);
52 CHECK_AND_RETURN_LOG(buffer_ != nullptr, "buffer_ create failed");
53 memory_ = buffer_->memory_;
54 inUser_ = false;
55 }
56
GetRemainedCapacity()57 int32_t LppDataPacket::GetRemainedCapacity()
58 {
59 CHECK_AND_RETURN_RET_LOG(memory_ != nullptr, 0, "local memory is nullptr");
60 int32_t remainedCapacity = memory_->GetCapacity() - dataOffset_;
61 CHECK_AND_RETURN_RET_LOG(remainedCapacity >= 0, 0, "negative remainedCapacity!");
62 return remainedCapacity;
63 }
64
AppendOneBuffer(const std::shared_ptr<AVBuffer> & buffer)65 bool LppDataPacket::AppendOneBuffer(const std::shared_ptr<AVBuffer> &buffer)
66 {
67 CHECK_AND_RETURN_RET_LOG(inUser_, false, "data packet not in user!");
68 CHECK_AND_RETURN_RET_LOG(buffer != nullptr && buffer->memory_, false, "buffer or memory nullptr");
69 CHECK_AND_RETURN_RET_LOG(memory_ != nullptr && memory_->GetAddr() != nullptr, false, "local memory is nullptr");
70 int32_t nextSize = buffer->memory_->GetSize();
71 CHECK_AND_RETURN_RET_LOG(nextSize <= GetRemainedCapacity(), false, "remained capacity not enough");
72 int32_t writeLength = memory_->Write(buffer->memory_->GetAddr(), nextSize, dataOffset_);
73 CHECK_AND_RETURN_RET_LOG(writeLength == nextSize, false, "remained capacity not enough");
74
75 flag_.push_back(buffer->flag_);
76 pts_.push_back(buffer->pts_);
77 size_.push_back(nextSize);
78 dataOffset_ += nextSize;
79 DumpAVBufferToFile(DUMP_PARAM, buffer, true);
80 return true;
81 }
82
WriteVector(MessageParcel & bufferParcel)83 bool LppDataPacket::WriteVector(MessageParcel &bufferParcel)
84 {
85 bufferParcel.WriteInt64(static_cast<int64_t>(flag_.size()));
86 for (const auto &elem : flag_) {
87 bufferParcel.WriteUint32(elem);
88 }
89 bufferParcel.WriteInt64(static_cast<int64_t>(pts_.size()));
90 for (const auto &elem : pts_) {
91 bufferParcel.WriteInt64(elem);
92 }
93 bufferParcel.WriteInt64(static_cast<int64_t>(size_.size()));
94 for (const auto &elem : size_) {
95 bufferParcel.WriteInt32(elem);
96 }
97 return true;
98 }
99
WriteToMessageParcel(MessageParcel & parcel)100 bool LppDataPacket::WriteToMessageParcel(MessageParcel &parcel)
101 {
102 MessageParcel metaParcel;
103 bool ret = WriteVector(metaParcel);
104 CHECK_AND_RETURN_RET_LOG(ret, false, "write meta failed");
105 CHECK_AND_RETURN_RET_LOG(buffer_ != nullptr, false, "buffer is nullptr");
106 MessageParcel dataParcel;
107 ret = buffer_->WriteToMessageParcel(dataParcel);
108
109 CHECK_AND_RETURN_RET_LOG(ret, false, "write data failed");
110 ret = parcel.Append(metaParcel);
111 CHECK_AND_RETURN_RET_LOG(ret, false, "write meta failed");
112 ret = parcel.Append(dataParcel);
113 CHECK_AND_RETURN_RET_LOG(ret, false, "write data failed");
114 return true;
115 }
116
ReadVector(MessageParcel & parcel)117 bool LppDataPacket::ReadVector(MessageParcel &parcel)
118 {
119 int64_t size = 0;
120 parcel.ReadInt64(size);
121 CHECK_AND_RETURN_RET_LOG(size >= 0 && size <= MAX_BUFFER_CNT, false, "invalid buffer cnt");
122 for (int i = 0; i < size; i++) {
123 uint32_t elem = 0;
124 parcel.ReadUint32(elem);
125 flag_.push_back(elem);
126 }
127
128 parcel.ReadInt64(size);
129 std::vector<int64_t> pts;
130 for (int i = 0; i < size; i++) {
131 int64_t elem = 0;
132 parcel.ReadInt64(elem);
133 pts_.push_back(elem);
134 }
135
136 parcel.ReadInt64(size);
137 for (int i = 0; i < size; i++) {
138 int elem = 0;
139 parcel.ReadInt32(elem);
140 size_.push_back(elem);
141 }
142 return true;
143 }
144
ReadFromMessageParcel(MessageParcel & parcel)145 bool LppDataPacket::ReadFromMessageParcel(MessageParcel &parcel)
146 {
147 Clear();
148 bool ret = ReadVector(parcel);
149 CHECK_AND_RETURN_RET_LOG(ret, false, "read meta failed");
150 buffer_ = AVBuffer::CreateAVBuffer();
151 CHECK_AND_RETURN_RET_LOG(buffer_ != nullptr, false, "create avbuffer failed");
152 ret = buffer_->ReadFromMessageParcel(parcel, false);
153 CHECK_AND_RETURN_RET_LOG(ret, false, "read data failed");
154 memory_ = buffer_->memory_;
155 return true;
156 }
157
WriteToByteBuffer(std::shared_ptr<AVBuffer> & avBuffer)158 bool LppDataPacket::WriteToByteBuffer(std::shared_ptr<AVBuffer> &avBuffer)
159 {
160 CHECK_AND_RETURN_RET_LOG(avBuffer != nullptr && avBuffer->memory_ != nullptr, false, "buffer or memory is nullptr");
161 CHECK_AND_RETURN_RET_LOG(!IsEmpty(), false, "LppDataPacket isEmpty..");
162 frameCount_ = 0;
163 if (IsEos()) {
164 avBuffer->flag_ = avBuffer->flag_ | MediaAVCodec::AVCODEC_BUFFER_FLAG_EOS;
165 vectorReadIndex_++;
166 return true;
167 }
168 int offset = 0;
169 offset += sizeof(uint32_t);
170 bool writeContinue = true;
171 while (!IsEmpty() && writeContinue) {
172 writeContinue = WriteOneFrameToAVBuffer(avBuffer, offset);
173 }
174 avBuffer->memory_->SetSize(offset);
175 CHECK_AND_RETURN_RET_LOG(frameCount_ > 0, false, "LppDataPacket isEmpty..");
176 uint8_t *buffer = avBuffer->memory_->GetAddr();
177 int32_t ret = memcpy_s(buffer, sizeof(uint32_t), &frameCount_, sizeof(uint32_t));
178 CHECK_AND_RETURN_RET_LOG(ret == 0, false, "memcopy error");
179 avBuffer->flag_ |= MediaAVCodec::AVCODEC_BUFFER_FLAG_MUL_FRAME;
180 return true;
181 }
182
WriteOneFrameToAVBuffer(std::shared_ptr<AVBuffer> & avbuffer,int & offset)183 bool LppDataPacket::WriteOneFrameToAVBuffer(std::shared_ptr<AVBuffer> &avbuffer, int& offset)
184 {
185 CHECK_AND_RETURN_RET_LOG(avbuffer != nullptr && avbuffer->memory_ != nullptr, false, "buffer or memory is nullptr");
186
187 // EOS和其他数据帧一起,EOS帧只置位,不占用聚包个数
188 if (IsEos()) {
189 MEDIA_LOGD("EOS with others");
190 avbuffer->flag_ = avbuffer->flag_ | MediaAVCodec::AVCODEC_BUFFER_FLAG_EOS;
191 vectorReadIndex_++;
192 return false;
193 }
194
195 int32_t writeLength = sizeof(int64_t) + sizeof(uint32_t) + size_[vectorReadIndex_];
196 CHECK_AND_RETURN_RET_LOG(avbuffer->memory_->GetCapacity() - offset >= writeLength, false, "not enough capacity");
197
198 uint8_t *buffer = avbuffer->memory_->GetAddr();
199 int32_t ret = 0;
200 ret = memcpy_s(buffer + offset, sizeof(int64_t), &pts_[vectorReadIndex_], sizeof(int64_t));
201 CHECK_AND_RETURN_RET_LOG(ret == 0, false, "memcopy error");
202 offset += sizeof(int64_t);
203 ret = memcpy_s(buffer + offset, sizeof(uint32_t), &size_[vectorReadIndex_], sizeof(uint32_t));
204 CHECK_AND_RETURN_RET_LOG(ret == 0, false, "memcopy error");
205 offset += sizeof(uint32_t);
206 ret = memcpy_s(buffer + offset, size_[vectorReadIndex_], memory_->GetAddr() + dataOffset_, size_[vectorReadIndex_]);
207 CHECK_AND_RETURN_RET_LOG(ret == 0, false, "memcopy error");
208 offset += size_[vectorReadIndex_];
209 dataOffset_ += size_[vectorReadIndex_];
210 vectorReadIndex_++;
211 frameCount_++;
212 return true;
213 }
214
IsEmpty()215 bool LppDataPacket::IsEmpty()
216 {
217 return flag_.size() <= vectorReadIndex_ || pts_.size() <= vectorReadIndex_ || size_.size() <= vectorReadIndex_;
218 }
219
WriteOneFrameToAVBuffer(std::shared_ptr<AVBuffer> & buffer)220 bool LppDataPacket::WriteOneFrameToAVBuffer(std::shared_ptr<AVBuffer> &buffer)
221 {
222 if (IsEmpty() || memory_->GetAddr() == nullptr) {
223 MEDIA_LOGW("Current Packet is Empty;");
224 return false;
225 }
226 if (buffer == nullptr || buffer->memory_ == nullptr) {
227 MEDIA_LOGW("buffer or memory is nullptr");
228 return true;
229 }
230 buffer->flag_ = flag_[vectorReadIndex_];
231 buffer->pts_ = pts_[vectorReadIndex_];
232 auto bufferSize = size_[vectorReadIndex_];
233 buffer->memory_->Write(memory_->GetAddr() + dataOffset_, bufferSize, 0);
234 dataOffset_ += bufferSize;
235 vectorReadIndex_++;
236 return true;
237 }
238
Clear()239 void LppDataPacket::Clear()
240 {
241 flag_.clear();
242 pts_.clear();
243 size_.clear();
244 memory_ = nullptr;
245 buffer_ = nullptr;
246 dataOffset_ = 0;
247 vectorReadIndex_ = 0;
248 }
249
Disable()250 void LppDataPacket::Disable()
251 {
252 inUser_ = false;
253 }
254
Enable()255 void LppDataPacket::Enable()
256 {
257 inUser_ = true;
258 flag_.clear();
259 pts_.clear();
260 size_.clear();
261 memory_->SetSize(0);
262 dataOffset_ = 0;
263 vectorReadIndex_ = 0;
264 }
265
IsEnable()266 bool LppDataPacket::IsEnable()
267 {
268 return inUser_;
269 }
270
IsEos()271 bool LppDataPacket::IsEos()
272 {
273 if (IsEmpty() || memory_->GetAddr() == nullptr) {
274 MEDIA_LOGW("Current Packet is Empty;");
275 return false;
276 }
277 return flag_[vectorReadIndex_] & MediaAVCodec::AVCODEC_BUFFER_FLAG_EOS;
278 }
279
DumpAVBufferToFile(const std::string & para,const std::shared_ptr<AVBuffer> & buffer,const bool isClient)280 void LppDataPacket::DumpAVBufferToFile(
281 const std::string ¶, const std::shared_ptr<AVBuffer> &buffer, const bool isClient)
282 {
283 FALSE_RETURN_NOLOG(dumpBufferNeeded_);
284 MEDIA_LOG_D("dump avbuffer to %{public}s", dumpFileNameInput_.c_str());
285 if (buffer == nullptr || buffer->memory_ == nullptr) {
286 MEDIA_LOG_E("buffer or memory is nullptr.");
287 return;
288 }
289 FALSE_RETURN_MSG(
290 (para == "w" || para == "a") && !dumpFileNameInput_.empty(), "para or dumpFileNameInput_ is invalid.");
291 size_t bufferSize = static_cast<size_t>(buffer->memory_->GetSize());
292 FALSE_RETURN((bufferSize != 0) && (buffer->memory_->GetAddr() != nullptr));
293 std::string mode = para + "b+";
294 std::string filePath = (isClient ? DUMP_FILE_DIR_SANDBOX : DUMP_FILE_DIR_SERVER) + dumpFileNameInput_;
295
296 if (filePath == "") {
297 return;
298 }
299 MEDIA_LOG_D("dump avbuffer to %{public}s", filePath.c_str());
300 char path[PATH_MAX] = {0x00};
301 const char *inputPath = filePath.c_str();
302 if (strlen(inputPath) > PATH_MAX || realpath(inputPath, path) == nullptr) {
303 MEDIA_LOG_E("dump buffer failed due to Invalid path");
304 return;
305 }
306 FILE *dumpFile = std::fopen(path, mode.c_str());
307 if (dumpFile == nullptr) {
308 MEDIA_LOG_E("dump buffer to file failed.");
309 return;
310 }
311 size_t ret =
312 fwrite(reinterpret_cast<const char *>(buffer->memory_->GetAddr()), DUMP_DATA_UNIT, bufferSize, dumpFile);
313 if (ret < 0) {
314 MEDIA_LOG_W("dump is fail.");
315 }
316 std::fclose(dumpFile);
317 }
318
319 } // namespace Media
320 } // namespace OHOS