• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &para, 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