1 /*
2 * Copyright (c) 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
16 #include <fstream>
17 #include <sstream>
18 #include "hcodec.h"
19 #include "hcodec_log.h"
20 #include "hcodec_dfx.h"
21 #include "hcodec_utils.h"
22 #include "hisysevent.h"
23
24 namespace OHOS::MediaAVCodec {
25 using namespace std;
26
FuncTracker(std::string value)27 FuncTracker::FuncTracker(std::string value) : value_(std::move(value))
28 {
29 PLOGI("%s >>", value_.c_str());
30 }
31
~FuncTracker()32 FuncTracker::~FuncTracker()
33 {
34 PLOGI("%s <<", value_.c_str());
35 }
36
OnPrintAllBufferOwner(const MsgInfo & msg)37 void HCodec::OnPrintAllBufferOwner(const MsgInfo& msg)
38 {
39 TimePoint lastOwnerChangeTime;
40 msg.param->GetValue(KEY_LAST_OWNER_CHANGE_TIME, lastOwnerChangeTime);
41 if (lastOwnerChangeTime == lastOwnerChangeTime_) {
42 UpdateOwner(); // update all owner count trace in case of systrace is catched too late
43 if (!circulateHasStopped_) {
44 HLOGW("buffer circulate stoped");
45 PrintAllBufferInfo();
46 circulateHasStopped_ = true;
47 }
48 }
49 ParamSP param = make_shared<ParamBundle>();
50 param->SetValue(KEY_LAST_OWNER_CHANGE_TIME, lastOwnerChangeTime_);
51 SendAsyncMsg(MsgWhat::PRINT_ALL_BUFFER_OWNER, param, THREE_SECONDS_IN_US);
52 }
53
PrintAllBufferInfo()54 void HCodec::PrintAllBufferInfo()
55 {
56 auto now = chrono::steady_clock::now();
57 PrintAllBufferInfo(now, OMX_DirInput);
58 PrintAllBufferInfo(now, OMX_DirOutput);
59 }
60
PrintAllBufferInfo(const TimePoint & now,OMX_DIRTYPE port)61 void HCodec::PrintAllBufferInfo(const TimePoint& now, OMX_DIRTYPE port)
62 {
63 const Record& record = record_[port];
64 const char* inOutStr = (port == OMX_DirInput) ? " in" : "out";
65 bool eos = (port == OMX_DirInput) ? inputPortEos_ : outputPortEos_;
66 const std::array<int, OWNER_CNT>& arr = record.currOwner_;
67 const vector<BufferInfo>& pool = (port == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
68
69 std::stringstream s;
70 for (const BufferInfo& info : pool) {
71 int64_t holdMs = chrono::duration_cast<chrono::milliseconds>(now - info.lastOwnerChangeTime).count();
72 s << info.bufferId << ":" << ToString(info.owner) << "(" << holdMs << "), ";
73 }
74 HLOGI("%s: eos=%d, cnt=%" PRIu64 ", pts=%" PRId64 ", %d/%d/%d/%d, %s", inOutStr, eos,
75 record.frameCntTotal_, record.lastPts_,
76 arr[OWNED_BY_US], arr[OWNED_BY_USER], arr[OWNED_BY_OMX], arr[OWNED_BY_SURFACE], s.str().c_str());
77 }
78
OnGetHidumperInfo()79 std::string HCodec::OnGetHidumperInfo()
80 {
81 auto now = chrono::steady_clock::now();
82 std::stringstream s;
83 auto getbufferCapacity = [](const std::vector<BufferInfo> &pool) -> int32_t {
84 IF_TRUE_RETURN_VAL(pool.empty(), 0);
85 IF_TRUE_RETURN_VAL(pool.front().surfaceBuffer, pool.front().surfaceBuffer->GetSize());
86 IF_TRUE_RETURN_VAL(!(pool.front().avBuffer && pool.front().avBuffer->memory_), 0);
87 return pool.front().avBuffer->memory_->GetCapacity();
88 };
89
90 s << " " << "[" << compUniqueStr_ << "][" << currState_->GetName() << "]" << endl;
91 s << " " << "------------INPUT-----------" << endl;
92 s << " " << "eos:" << inputPortEos_ << ", etb:" << record_[OMX_DirInput].frameCntTotal_
93 << ", bufferCapacity:" << getbufferCapacity(inputBufferPool_) << endl;
94 for (const BufferInfo& info : inputBufferPool_) {
95 int64_t holdMs = chrono::duration_cast<chrono::milliseconds>(now - info.lastOwnerChangeTime).count();
96 s << " " << "inBufId = " << info.bufferId << ", owner = " << ToString(info.owner);
97 if (info.hasSwapedOut) {
98 s << ", hasSwapedOut = " << info.hasSwapedOut << ", nextOwner = " << ToString(info.nextStepOwner);
99 }
100 s << ", holdMs = " << holdMs << endl;
101 }
102 s << " " << "----------------------------" << endl;
103 s << " " << "------------OUTPUT----------" << endl;
104 s << " " << "eos:" << outputPortEos_ << ", fbd:" << record_[OMX_DirOutput].frameCntTotal_
105 << ", bufferCapacity:" << getbufferCapacity(outputBufferPool_) << endl;
106 for (const BufferInfo& info : outputBufferPool_) {
107 int fd = info.surfaceBuffer == nullptr ? -1 : info.surfaceBuffer->GetFileDescriptor();
108 int64_t holdMs = chrono::duration_cast<chrono::milliseconds>(now - info.lastOwnerChangeTime).count();
109 s << " " << "outBufId = " << info.bufferId << ", fd = " << fd << ", owner = " << ToString(info.owner);
110 if (info.hasSwapedOut) {
111 s << ", hasSwapedOut = " << info.hasSwapedOut << ", nextOwner = " << ToString(info.nextStepOwner);
112 }
113 s << ", holdMs = " << holdMs << endl;
114 }
115 s << " " << "----------------------------" << endl << endl;
116 return s.str();
117 }
118
UpdateOwner()119 void HCodec::UpdateOwner()
120 {
121 UpdateOwner(OMX_DirInput);
122 UpdateOwner(OMX_DirOutput);
123 }
124
FaultEventWrite(const string & faultType,const std::string & msg)125 void HCodec::FaultEventWrite(const string& faultType, const std::string& msg)
126 {
127 HiSysEventWrite(HISYSEVENT_DOMAIN_HCODEC, "FAULT",
128 OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
129 "MODULE", "HardwareDecoder",
130 "FAULTTYPE", faultType,
131 "MSG", msg);
132 }
133
UpdateOwner(OMX_DIRTYPE port)134 void HCodec::UpdateOwner(OMX_DIRTYPE port)
135 {
136 std::array<int, OWNER_CNT>& arr = record_[port].currOwner_;
137 const vector<BufferInfo>& pool = (port == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
138
139 arr.fill(0);
140 for (const BufferInfo &info : pool) {
141 arr[info.owner]++;
142 }
143 for (uint32_t owner = 0; owner < static_cast<uint32_t>(OWNER_CNT); owner++) {
144 CountTrace(HITRACE_TAG_ZMEDIA, record_[port].ownerTraceTag_[owner], arr[owner]);
145 }
146 }
147
ReduceOwner(OMX_DIRTYPE port,BufferOwner owner)148 void HCodec::ReduceOwner(OMX_DIRTYPE port, BufferOwner owner)
149 {
150 Record& record = record_[port];
151 record.currOwner_[owner]--;
152 CountTrace(HITRACE_TAG_ZMEDIA, record.ownerTraceTag_[owner], record.currOwner_[owner]);
153 }
154
ChangeOwner(BufferInfo & info,BufferOwner newOwner)155 void HCodec::ChangeOwner(BufferInfo& info, BufferOwner newOwner)
156 {
157 auto now = chrono::steady_clock::now();
158 OMX_DIRTYPE port = info.isInput ? OMX_DirInput : OMX_DirOutput;
159 Record& record = record_[port];
160 std::array<int, OWNER_CNT>& currOwner = record.currOwner_;
161 BufferOwner oldOwner = info.owner;
162 if (!record.beginOfInterval_.has_value()) {
163 record.ResetInterval(now);
164 }
165
166 UpdateHoldCnt(now, port, oldOwner);
167 UpdateHoldCnt(now, port, newOwner);
168 UpdateHoldTime(now, info, newOwner);
169
170 // now change owner
171 currOwner[oldOwner]--;
172 currOwner[newOwner]++;
173 info.owner = newOwner;
174 info.lastOwnerChangeTime = now;
175 record.lastOwnerChangeTime_[oldOwner] = now;
176 record.lastOwnerChangeTime_[newOwner] = now;
177 lastOwnerChangeTime_ = now;
178 if (circulateHasStopped_) {
179 HLOGI("circulate resume, %s, %s -> %s, pts=%" PRId64,
180 (info.isInput ? "in" : "out"), ToString(oldOwner), ToString(newOwner), info.omxBuffer->pts);
181 circulateHasStopped_ = false;
182 }
183
184 CountTrace(HITRACE_TAG_ZMEDIA, record.ownerTraceTag_[oldOwner], currOwner[oldOwner]);
185 CountTrace(HITRACE_TAG_ZMEDIA, record.ownerTraceTag_[newOwner], currOwner[newOwner]);
186
187 if (info.isInput && oldOwner == OWNED_BY_US && newOwner == OWNED_BY_OMX) {
188 record.frameCntTotal_++;
189 record.frameCntInterval_++;
190 record.frameMbitsInterval_ += info.omxBuffer->filledLen * BYTE_TO_MBIT;
191 record.lastPts_ = info.omxBuffer->pts;
192 debugMode_ ? UpdateInputRecord(now, info) : PrintStatistic(now, port);
193 }
194 if (!info.isInput && oldOwner == OWNED_BY_US && newOwner == OWNED_BY_USER) {
195 record.frameCntTotal_++;
196 record.frameCntInterval_++;
197 record.frameMbitsInterval_ += info.omxBuffer->filledLen * BYTE_TO_MBIT;
198 record.lastPts_ = info.omxBuffer->pts;
199 debugMode_ ? UpdateOutputRecord(now, info) : PrintStatistic(now, port);
200 }
201 }
202
203 // now, on this port, this owner's hold cnt is gonna change
UpdateHoldCnt(const TimePoint & now,OMX_DIRTYPE port,BufferOwner owner)204 void HCodec::UpdateHoldCnt(const TimePoint& now, OMX_DIRTYPE port, BufferOwner owner)
205 {
206 Record& record = record_[port];
207 if (!record.lastOwnerChangeTime_[owner].has_value()) {
208 return;
209 }
210 auto holdUs = chrono::duration_cast<chrono::microseconds>(
211 now - record.lastOwnerChangeTime_[owner].value()).count();
212 if (holdUs < 0) {
213 HLOGW("steady clock has go backwards, %ld us", holdUs);
214 record.ResetInterval(now);
215 return;
216 }
217 TotalEvent& holdCnt = record.holdCntInterval_[owner];
218 holdCnt.eventCnt += static_cast<uint64_t>(holdUs);
219 holdCnt.eventSum += (static_cast<uint64_t>(holdUs) *
220 static_cast<uint64_t>(record.currOwner_[owner]));
221 }
222
223 // now, this buffer is gonna change to new owner
UpdateHoldTime(const TimePoint & now,const BufferInfo & info,BufferOwner newOwner)224 void HCodec::UpdateHoldTime(const TimePoint& now, const BufferInfo& info, BufferOwner newOwner)
225 {
226 Record& record = record_[info.isInput ? OMX_DirInput : OMX_DirOutput];
227 auto holdUs = chrono::duration_cast<chrono::microseconds>(now - info.lastOwnerChangeTime).count();
228 if (holdUs < 0) {
229 HLOGW("steady clock has go backwards, %ld us", holdUs);
230 record.ResetInterval(now);
231 return;
232 }
233 BufferOwner oldOwner = info.owner;
234 TotalEvent& oldOwnerHoldTime = record.holdTimeInterval_[oldOwner];
235 oldOwnerHoldTime.eventCnt++;
236 oldOwnerHoldTime.eventSum += static_cast<uint64_t>(holdUs);
237 if (debugMode_) {
238 std::array<int, OWNER_CNT> currOwner = record.currOwner_;
239 currOwner[oldOwner]--;
240 currOwner[newOwner]++;
241 HLOGI("%s = %u, after hold %.1f ms, %s -> %s, %d/%d/%d/%d", (info.isInput ? "inBufId" : "outBufId"),
242 info.bufferId, holdUs / US_TO_MS, ToString(oldOwner), ToString(newOwner),
243 currOwner[OWNED_BY_US], currOwner[OWNED_BY_USER], currOwner[OWNED_BY_OMX], currOwner[OWNED_BY_SURFACE]);
244 }
245 }
246
CalculateInterval(const TimePoint & now,OMX_DIRTYPE port,IntervalAverage & ave)247 bool HCodec::CalculateInterval(const TimePoint& now, OMX_DIRTYPE port, IntervalAverage& ave)
248 {
249 Record& record = record_[port];
250 auto fromBeginOfIntervalToNowUs = chrono::duration_cast<chrono::microseconds>(
251 now - record.beginOfInterval_.value()).count();
252 if (fromBeginOfIntervalToNowUs < 0) {
253 HLOGW("steady clock has go backwards, %ld us", fromBeginOfIntervalToNowUs);
254 record.ResetInterval(now);
255 return false;
256 }
257 if (fromBeginOfIntervalToNowUs == 0) {
258 return false;
259 }
260
261 ave.fps = record.frameCntInterval_ * US_TO_S / fromBeginOfIntervalToNowUs;
262 ave.mbps = record.frameMbitsInterval_ * US_TO_S / fromBeginOfIntervalToNowUs;
263 for (uint32_t owner = 0; owner < static_cast<uint32_t>(OWNER_CNT); owner++) {
264 const TotalEvent& holdCnt = record.holdCntInterval_[owner];
265 ave.holdCnt[owner] = (holdCnt.eventCnt == 0) ? 0 :
266 static_cast<double>(holdCnt.eventSum) / holdCnt.eventCnt;
267 const TotalEvent& holdTime = record.holdTimeInterval_[owner];
268 ave.holdMs[owner] = (holdTime.eventCnt == 0) ? -1 :
269 (holdTime.eventSum / US_TO_MS / holdTime.eventCnt);
270 }
271 return true;
272 }
273
PrintStatistic(const TimePoint & now,OMX_DIRTYPE port)274 void HCodec::PrintStatistic(const TimePoint& now, OMX_DIRTYPE port)
275 {
276 Record& record = record_[port];
277 if (record.frameCntInterval_ % PRINT_PER_FRAME != 0) {
278 return;
279 }
280 IntervalAverage ave;
281 bool ret = CalculateInterval(now, port, ave);
282 if (!ret) {
283 return;
284 }
285 const char* inOutStr = (port == OMX_DirInput) ? " in" : "out";
286 HLOGI("%s: fps=%.1f, Mbps=%.1f, cnt=%" PRIu64 ", pts=%" PRId64 ", %.1f/%.1f/%.1f/%.1f, %.0f/%.0f/%.0f/%.0f, "
287 "fence %.3f, discard %.0f%%", inOutStr, ave.fps, ave.mbps, record.frameCntTotal_, record.lastPts_,
288 ave.holdCnt[OWNED_BY_US], ave.holdCnt[OWNED_BY_USER], ave.holdCnt[OWNED_BY_OMX], ave.holdCnt[OWNED_BY_SURFACE],
289 ave.holdMs[OWNED_BY_US], ave.holdMs[OWNED_BY_USER], ave.holdMs[OWNED_BY_OMX], ave.holdMs[OWNED_BY_SURFACE],
290 record.waitFenceCostUsInterval_ / US_TO_MS / PRINT_PER_FRAME,
291 static_cast<double>(record.discardCntInterval_) / PRINT_PER_FRAME * 100); // 100: percent
292 record.ResetInterval(now);
293 }
294
UpdateInputRecord(const TimePoint & now,const BufferInfo & info)295 void HCodec::UpdateInputRecord(const TimePoint& now, const BufferInfo& info)
296 {
297 if (!info.IsValidFrame()) {
298 return;
299 }
300 inTimeMap_[info.omxBuffer->pts] = now;
301 Record& record = record_[info.isInput ? OMX_DirInput : OMX_DirOutput];
302 auto fromBeginOfIntervalToNowUs = chrono::duration_cast<chrono::microseconds>(
303 now - record.beginOfInterval_.value()).count();
304 if (fromBeginOfIntervalToNowUs < 0) {
305 HLOGW("steady clock has go backwards, %ld us", fromBeginOfIntervalToNowUs);
306 record.ResetInterval(now);
307 return;
308 }
309 if (fromBeginOfIntervalToNowUs == 0) {
310 HLOGI("pts = %" PRId64 ", len = %u, flags = 0x%x",
311 info.omxBuffer->pts, info.omxBuffer->filledLen, info.omxBuffer->flag);
312 } else {
313 double inFps = record.frameCntInterval_ * US_TO_S / fromBeginOfIntervalToNowUs;
314 HLOGI("pts = %" PRId64 ", len = %u, flags = 0x%x, in fps %.2f",
315 info.omxBuffer->pts, info.omxBuffer->filledLen, info.omxBuffer->flag, inFps);
316 }
317 }
318
UpdateOutputRecord(const TimePoint & now,const BufferInfo & info)319 void HCodec::UpdateOutputRecord(const TimePoint& now, const BufferInfo& info)
320 {
321 if (!info.IsValidFrame()) {
322 return;
323 }
324 auto it = inTimeMap_.find(info.omxBuffer->pts);
325 if (it == inTimeMap_.end()) {
326 return;
327 }
328 Record& record = record_[info.isInput ? OMX_DirInput : OMX_DirOutput];
329 auto fromInToOut = chrono::duration_cast<chrono::microseconds>(now - it->second).count();
330 inTimeMap_.erase(it);
331 if (fromInToOut < 0) {
332 HLOGW("steady clock has go backwards, %ld us", fromInToOut);
333 record.ResetInterval(now);
334 return;
335 }
336 onePtsInToOutTotalCostUs_ += static_cast<uint64_t>(fromInToOut);
337 double oneFrameCostMs = fromInToOut / US_TO_MS;
338 double averageCostMs = onePtsInToOutTotalCostUs_ / US_TO_MS / record.frameCntInterval_;
339
340 auto fromBeginOfIntervalToNowUs = chrono::duration_cast<chrono::microseconds>(
341 now - record.beginOfInterval_.value()).count();
342 if (fromBeginOfIntervalToNowUs < 0) {
343 HLOGW("steady clock has go backwards, %ld us", fromBeginOfIntervalToNowUs);
344 record.ResetInterval(now);
345 return;
346 }
347 if (fromBeginOfIntervalToNowUs == 0) {
348 HLOGI("pts = %" PRId64 ", len = %u, flags = 0x%x, "
349 "cost %.2f ms (%.2f ms)",
350 info.omxBuffer->pts, info.omxBuffer->filledLen, info.omxBuffer->flag,
351 oneFrameCostMs, averageCostMs);
352 } else {
353 double outFps = record.frameCntInterval_ * US_TO_S / fromBeginOfIntervalToNowUs;
354 HLOGI("pts = %" PRId64 ", len = %u, flags = 0x%x, "
355 "cost %.2f ms (%.2f ms), out fps %.2f",
356 info.omxBuffer->pts, info.omxBuffer->filledLen, info.omxBuffer->flag,
357 oneFrameCostMs, averageCostMs, outFps);
358 }
359 }
360
IsValidFrame() const361 bool HCodec::BufferInfo::IsValidFrame() const
362 {
363 if (omxBuffer->flag & OMX_BUFFERFLAG_EOS) {
364 return false;
365 }
366 if (omxBuffer->flag & OMX_BUFFERFLAG_CODECCONFIG) {
367 return false;
368 }
369 if (omxBuffer->filledLen == 0) {
370 return false;
371 }
372 return true;
373 }
374
375 #ifdef BUILD_ENG_VERSION
Dump(const string & prefix,uint64_t cnt,DumpMode dumpMode,bool isEncoder) const376 void HCodec::BufferInfo::Dump(const string& prefix, uint64_t cnt, DumpMode dumpMode, bool isEncoder) const
377 {
378 if (isInput) {
379 if (((dumpMode & DUMP_ENCODER_INPUT) && isEncoder) ||
380 ((dumpMode & DUMP_DECODER_INPUT) && !isEncoder)) {
381 Dump(prefix + "_Input", cnt);
382 }
383 } else {
384 if (((dumpMode & DUMP_ENCODER_OUTPUT) && isEncoder) ||
385 ((dumpMode & DUMP_DECODER_OUTPUT) && !isEncoder)) {
386 Dump(prefix + "_Output", cnt);
387 }
388 }
389 }
390
Dump(const string & prefix,uint64_t cnt) const391 void HCodec::BufferInfo::Dump(const string& prefix, uint64_t cnt) const
392 {
393 if (surfaceBuffer) {
394 DumpSurfaceBuffer(prefix, cnt);
395 } else {
396 DumpLinearBuffer(prefix);
397 }
398 }
399
DumpSurfaceBuffer(const std::string & prefix,uint64_t cnt) const400 void HCodec::BufferInfo::DumpSurfaceBuffer(const std::string& prefix, uint64_t cnt) const
401 {
402 if (omxBuffer->filledLen == 0) {
403 return;
404 }
405 const char* va = reinterpret_cast<const char*>(surfaceBuffer->GetVirAddr());
406 IF_TRUE_RETURN_VOID_WITH_MSG(va == nullptr, "null va");
407 int w = surfaceBuffer->GetWidth();
408 int h = surfaceBuffer->GetHeight();
409 int byteStride = surfaceBuffer->GetStride();
410 IF_TRUE_RETURN_VOID_WITH_MSG(byteStride == 0, "stride 0");
411 int alignedH = h;
412 uint32_t totalSize = surfaceBuffer->GetSize();
413 uint32_t seq = surfaceBuffer->GetSeqNum();
414 GraphicPixelFormat graphicFmt = static_cast<GraphicPixelFormat>(surfaceBuffer->GetFormat());
415 std::optional<PixelFmt> fmt = TypeConverter::GraphicFmtToFmt(graphicFmt);
416 IF_TRUE_RETURN_VOID_WITH_MSG(!fmt.has_value(), "unknown fmt %d", graphicFmt);
417
418 string suffix;
419 bool dumpAsVideo = true;
420 DecideDumpInfo(alignedH, totalSize, suffix, dumpAsVideo);
421
422 char name[128];
423 int ret = 0;
424 if (dumpAsVideo) {
425 ret = sprintf_s(name, sizeof(name), "%s/%s_%dx%d(%dx%d)_fmt%s.%s",
426 DUMP_PATH, prefix.c_str(), w, h, byteStride, alignedH,
427 fmt->strFmt.c_str(), suffix.c_str());
428 } else {
429 ret = sprintf_s(name, sizeof(name), "%s/%s_%" PRIu64 "_%dx%d(%d)_fmt%s_pts%" PRId64 "_seq%u.%s",
430 DUMP_PATH, prefix.c_str(), cnt, w, h, byteStride,
431 fmt->strFmt.c_str(), omxBuffer->pts, seq, suffix.c_str());
432 }
433 if (ret > 0) {
434 ofstream ofs(name, ios::binary | ios::app);
435 if (ofs.is_open()) {
436 ofs.write(va, totalSize);
437 } else {
438 LOGW("cannot open %s", name);
439 }
440 }
441 // if we unmap here, flush cache will fail
442 }
443
DecideDumpInfo(int & alignedH,uint32_t & totalSize,string & suffix,bool & dumpAsVideo) const444 void HCodec::BufferInfo::DecideDumpInfo(int& alignedH, uint32_t& totalSize, string& suffix, bool& dumpAsVideo) const
445 {
446 int h = surfaceBuffer->GetHeight();
447 int byteStride = surfaceBuffer->GetStride();
448 GraphicPixelFormat fmt = static_cast<GraphicPixelFormat>(surfaceBuffer->GetFormat());
449 switch (fmt) {
450 case GRAPHIC_PIXEL_FMT_YCBCR_420_P:
451 case GRAPHIC_PIXEL_FMT_YCRCB_420_SP:
452 case GRAPHIC_PIXEL_FMT_YCBCR_420_SP:
453 case GRAPHIC_PIXEL_FMT_YCBCR_P010:
454 case GRAPHIC_PIXEL_FMT_YCRCB_P010: {
455 OH_NativeBuffer_Planes *planes = nullptr;
456 GSError err = surfaceBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
457 if (err != GSERROR_OK || planes == nullptr) { // compressed
458 suffix = "bin";
459 dumpAsVideo = false;
460 return;
461 }
462 alignedH = static_cast<int32_t>(static_cast<int64_t>(planes->planes[1].offset) / byteStride);
463 totalSize = GetYuv420Size(byteStride, alignedH);
464 suffix = "yuv";
465 break;
466 }
467 case GRAPHIC_PIXEL_FMT_RGBA_1010102:
468 case GRAPHIC_PIXEL_FMT_RGBA_8888: {
469 totalSize = static_cast<uint32_t>(byteStride * h);
470 suffix = "rgba";
471 break;
472 }
473 default: {
474 suffix = "bin";
475 dumpAsVideo = false;
476 break;
477 }
478 }
479 }
480
DumpLinearBuffer(const string & prefix) const481 void HCodec::BufferInfo::DumpLinearBuffer(const string& prefix) const
482 {
483 if (omxBuffer->filledLen == 0) {
484 return;
485 }
486 if (avBuffer == nullptr || avBuffer->memory_ == nullptr) {
487 LOGW("invalid avbuffer");
488 return;
489 }
490 const char* va = reinterpret_cast<const char*>(avBuffer->memory_->GetAddr());
491 if (va == nullptr) {
492 LOGW("null va");
493 return;
494 }
495
496 char name[128];
497 int ret = sprintf_s(name, sizeof(name), "%s/%s.bin", DUMP_PATH, prefix.c_str());
498 if (ret <= 0) {
499 LOGW("sprintf_s failed");
500 return;
501 }
502 ofstream ofs(name, ios::binary | ios::app);
503 if (ofs.is_open()) {
504 ofs.write(va, omxBuffer->filledLen);
505 } else {
506 LOGW("cannot open %s", name);
507 }
508 }
509 #endif // BUILD_ENG_VERSION
510 }