• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "rs_profiler_file.h"
17 
18 #include <algorithm>
19 #include <chrono>
20 #include <iostream>
21 #include <memory>
22 #include <string>
23 #include <thread>
24 #include <utility>
25 #include <vector>
26 
27 #include "rs_profiler_cache.h"
28 
29 namespace OHOS::Rosen {
30 
31 RSFile::RSFile() = default;
32 
GetDefaultPath()33 const std::string& RSFile::GetDefaultPath()
34 {
35     static const std::string PATH("RECORD_IN_MEMORY");
36     return PATH;
37 }
38 
Create(const std::string & fname)39 void RSFile::Create(const std::string& fname)
40 {
41     if (file_ != nullptr) {
42         Close();
43     }
44     const std::lock_guard<std::mutex> lgMutex(writeMutex_);
45 
46 #ifdef RENDER_PROFILER_APPLICATION
47     file_ = Utils::FileOpen(fname, "wb");
48 #else
49     file_ = Utils::FileOpen(fname, "wbe");
50 #endif
51     if (file_ == nullptr) {
52         return;
53     }
54 
55     uint32_t headerId = 'ROHR';
56     Utils::FileWrite(&headerId, sizeof(headerId), 1, file_);
57     Utils::FileWrite(&versionId_, sizeof(versionId_), 1, file_);
58 
59     headerOff_ = 0; // TEMP VALUE
60     Utils::FileWrite(&headerOff_, sizeof(headerOff_), 1, file_);
61 
62     writeDataOff_ = Utils::FileTell(file_);
63 
64     wasChanged_ = true;
65 }
66 
Open(const std::string & fname)67 bool RSFile::Open(const std::string& fname)
68 {
69     if (file_ != nullptr) {
70         Close();
71     }
72 
73 #ifdef RENDER_PROFILER_APPLICATION
74     file_ = Utils::FileOpen(fname, "rb");
75 #else
76     file_ = Utils::FileOpen(fname, "rbe");
77 #endif
78     if (file_ == nullptr) {
79         return false;
80     }
81 
82     uint32_t headerId;
83     Utils::FileRead(&headerId, sizeof(headerId), 1, file_);
84     if (headerId != 'ROHR') { // Prohibit too old file versions
85         Utils::FileClose(file_);
86         file_ = nullptr;
87         return false;
88     }
89 
90     Utils::FileRead(&versionId_, sizeof(versionId_), 1, file_);
91     Utils::FileRead(&headerOff_, sizeof(headerOff_), 1, file_);
92     Utils::FileSeek(file_, 0, SEEK_END);
93     writeDataOff_ = Utils::FileTell(file_);
94     Utils::FileSeek(file_, headerOff_, SEEK_SET);
95     std::string errReason = ReadHeaders();
96     if (errReason.size()) {
97         Utils::FileClose(file_);
98         file_ = nullptr;
99         return false;
100     }
101     wasChanged_ = false;
102 
103     return true;
104 }
105 
IsOpen() const106 bool RSFile::IsOpen() const
107 {
108     return file_ != nullptr;
109 }
110 
SetWriteTime(double time)111 void RSFile::SetWriteTime(double time)
112 {
113     writeStartTime_ = time;
114 }
115 
GetWriteTime() const116 double RSFile::GetWriteTime() const
117 {
118     return writeStartTime_;
119 }
120 
121 // ***********************************
122 // *** GLOBAL HEADER
123 
AddHeaderPid(pid_t pid)124 void RSFile::AddHeaderPid(pid_t pid)
125 {
126     if (std::find(std::begin(headerPidList_), std::end(headerPidList_), pid) != std::end(headerPidList_)) {
127         return;
128     }
129     headerPidList_.push_back(pid);
130 
131     wasChanged_ = true;
132 }
133 
GetHeaderPids() const134 const std::vector<pid_t>& RSFile::GetHeaderPids() const
135 {
136     return headerPidList_;
137 }
138 
SetPreparedHeader(const std::vector<uint8_t> & headerData)139 void RSFile::SetPreparedHeader(const std::vector<uint8_t>& headerData)
140 {
141     preparedHeader_ = headerData;
142 }
143 
GetPreparedHeader(std::vector<uint8_t> & headerData)144 void RSFile::GetPreparedHeader(std::vector<uint8_t>& headerData)
145 {
146     headerData = preparedHeader_;
147 }
148 
SetPreparedHeaderMode(bool mode)149 void RSFile::SetPreparedHeaderMode(bool mode)
150 {
151     preparedHeaderMode_ = mode;
152 }
153 
WriteHeader()154 void RSFile::WriteHeader()
155 {
156     // WARNING removed redundant mutex
157     if (!file_) {
158         return;
159     }
160 
161     headerOff_ = writeDataOff_;
162     Utils::FileSeek(file_, writeDataOff_, SEEK_SET);
163 
164     if (preparedHeaderMode_) {
165         // WRITE RAW
166         Utils::FileWrite(preparedHeader_.data(), 1, preparedHeader_.size(), file_);
167         preparedHeader_.clear();
168     } else {
169         // WRITE TIME START
170         Utils::FileWrite(&writeStartTime_, 1, sizeof(writeStartTime_), file_);
171 
172         // SAVE PID LIST
173         const uint32_t recordSize = headerPidList_.size();
174         Utils::FileWrite(&recordSize, sizeof(recordSize), 1, file_);
175         Utils::FileWrite(headerPidList_.data(), headerPidList_.size(), sizeof(pid_t), file_);
176 
177         // SAVE FIRST SCREEN
178         uint32_t firstScrSize = headerFirstFrame_.size();
179         Utils::FileWrite(&firstScrSize, sizeof(firstScrSize), 1, file_);
180         Utils::FileWrite(headerFirstFrame_.data(), headerFirstFrame_.size(), 1, file_);
181 
182         if (versionId_ >= RSFILE_VERSION_RENDER_ANIMESTARTTIMES_ADDED) {
183             // ANIME START TIMES
184             uint32_t startTimesSize = headerAnimeStartTimes_.size();
185             Utils::FileWrite(&startTimesSize, sizeof(startTimesSize), 1, file_);
186             Utils::FileWrite(headerAnimeStartTimes_.data(),
187                 headerAnimeStartTimes_.size() * sizeof(std::pair<uint64_t, int64_t>), 1, file_);
188         }
189 
190         // ALL TEXTURES
191         ImageCache::Serialize(file_);
192     }
193 
194     // SAVE LAYERS OFFSETS
195     const uint32_t recordSize = layerData_.size();
196     Utils::FileWrite(&recordSize, sizeof(recordSize), 1, file_);
197     for (auto& i : layerData_) {
198         Utils::FileWrite(&i.layerHeader, sizeof(i.layerHeader), 1, file_);
199     }
200 
201     constexpr int preambleSize = 8;
202     Utils::FileSeek(file_, preambleSize, SEEK_SET);
203     Utils::FileWrite(&headerOff_, sizeof(headerOff_), 1, file_);
204 }
205 
ReadHeaderPidList()206 bool RSFile::ReadHeaderPidList()
207 {
208     uint32_t recordSize;
209     Utils::FileRead(&recordSize, sizeof(recordSize), 1, file_);
210     if (recordSize > chunkSizeMax) {
211         return false;
212     }
213     headerPidList_.resize(recordSize);
214     Utils::FileRead(headerPidList_.data(), headerPidList_.size(), sizeof(pid_t), file_);
215     return true;
216 }
217 
ReadHeaderFirstScreen()218 bool RSFile::ReadHeaderFirstScreen()
219 {
220     // READ FIRST SCREEN
221     uint32_t firstScrSize;
222     Utils::FileRead(&firstScrSize, sizeof(firstScrSize), 1, file_);
223     if (firstScrSize > chunkSizeMax) {
224         return false;
225     }
226     headerFirstFrame_.resize(firstScrSize);
227     Utils::FileRead(headerFirstFrame_.data(), headerFirstFrame_.size(), 1, file_);
228     return true;
229 }
230 
ReadHeader()231 std::string RSFile::ReadHeader()
232 {
233     const std::string errCode = "can't read header";
234     if (!file_) {
235         return errCode;
236     }
237 
238     Utils::FileSeek(file_, headerOff_, SEEK_SET);
239     const size_t subHeaderStartOff = Utils::FileTell(file_);
240 
241     // READ what was write start time
242     Utils::FileRead(&writeStartTime_, 1, sizeof(writeStartTime_), file_);
243 
244     if (!ReadHeaderPidList()) {
245         return errCode;
246     }
247 
248     if (!ReadHeaderFirstScreen()) {
249         return errCode;
250     }
251 
252      // READ ANIME START TIMES
253     if (versionId_ >= RSFILE_VERSION_RENDER_ANIMESTARTTIMES_ADDED) {
254         uint32_t startTimesSize;
255         Utils::FileRead(&startTimesSize, sizeof(startTimesSize), 1, file_);
256         if (startTimesSize > chunkSizeMax) {
257             return errCode;
258         }
259         headerAnimeStartTimes_.resize(startTimesSize);
260         Utils::FileRead(headerAnimeStartTimes_.data(),
261             headerAnimeStartTimes_.size() * sizeof(std::pair<uint64_t, int64_t>), 1, file_);
262     }
263 
264     // ALL TEXTURES
265     ImageCache::Deserialize(file_);
266 
267     if (preparedHeaderMode_) {
268         const size_t subHeaderEndOff = Utils::FileTell(file_);
269         Utils::FileSeek(file_, subHeaderStartOff, SEEK_SET);
270         const size_t subHeaderLen = subHeaderEndOff - subHeaderStartOff;
271         if (subHeaderLen > headerSizeMax) {
272             return errCode;
273         }
274         preparedHeader_.resize(subHeaderLen);
275         Utils::FileRead(preparedHeader_.data(), subHeaderLen, 1, file_);
276     }
277 
278     // READ LAYERS OFFSETS
279     uint32_t recordSize;
280     Utils::FileRead(&recordSize, sizeof(recordSize), 1, file_);
281     if (recordSize > chunkSizeMax) {
282         return errCode;
283     }
284     layerData_.resize(recordSize);
285     for (auto& i : layerData_) {
286         Utils::FileRead(&i.layerHeader, sizeof(i.layerHeader), 1, file_);
287         i.readindexRsData = 0;
288     }
289     return "";
290 }
291 
292 // ***********************************
293 // *** LAYER HEADER
294 
AddLayer()295 uint32_t RSFile::AddLayer()
296 {
297     const uint32_t newId = layerData_.size();
298     const RSFileLayer data;
299     layerData_.push_back(data);
300 
301     wasChanged_ = true;
302 
303     return newId;
304 }
305 
LayerAddHeaderProperty(uint32_t layer,const std::string & name,const std::string & value)306 void RSFile::LayerAddHeaderProperty(uint32_t layer, const std::string& name, const std::string& value)
307 {
308     if (!HasLayer(layer)) {
309         return;
310     }
311 
312     RSFileLayer& layerData = layerData_[layer];
313     layerData.property.SetProperty(name, value);
314 
315     wasChanged_ = true;
316 }
317 
LayerWriteHeader(uint32_t layer)318 void RSFile::LayerWriteHeader(uint32_t layer)
319 {
320     if (!file_ || !HasLayer(layer)) {
321         return;
322     }
323 
324     RSFileLayer& layerData = layerData_[layer];
325 
326     const uint32_t layerHeaderOff = writeDataOff_; // position of layer table
327     Utils::FileSeek(file_, writeDataOff_, SEEK_SET);
328 
329     std::vector<char> propertyData;
330     layerData.property.Serialize(propertyData);
331 
332     // SAVE LAYER PROPERTY
333     uint32_t recordSize = propertyData.size();
334     Utils::FileWrite(&recordSize, sizeof(recordSize), 1, file_);
335     Utils::FileWrite(propertyData.data(), propertyData.size(), 1, file_);
336 
337     LayerWriteHeaderOfTrack(layerData.rsData);
338     LayerWriteHeaderOfTrack(layerData.oglData);
339     LayerWriteHeaderOfTrack(layerData.rsMetrics);
340     if (versionId_ >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
341         LayerWriteHeaderOfTrack(layerData.renderMetrics);
342     }
343     LayerWriteHeaderOfTrack(layerData.oglMetrics);
344     LayerWriteHeaderOfTrack(layerData.gfxMetrics);
345     layerData.layerHeader = { layerHeaderOff, Utils::FileTell(file_) - layerHeaderOff }; // position of layer table
346 
347     writeDataOff_ = Utils::FileTell(file_);
348 }
349 
LayerReadHeader(uint32_t layer)350 std::string RSFile::LayerReadHeader(uint32_t layer)
351 {
352     const std::string errCode = "can't read layer header";
353     if (!file_ || !HasLayer(layer)) {
354         return errCode;
355     }
356 
357     RSFileLayer& layerData = layerData_[layer];
358 
359     Utils::FileSeek(file_, layerData.layerHeader.first, SEEK_SET);
360 
361     // READ LAYER PROPERTY
362     uint32_t recordSize = 0u;
363     Utils::FileRead(&recordSize, sizeof(recordSize), 1, file_);
364     if (recordSize > chunkSizeMax) {
365         return errCode;
366     }
367     std::vector<char> propertyData;
368     propertyData.resize(recordSize);
369     Utils::FileRead(propertyData.data(), recordSize, 1, file_);
370 
371     layerData.property.Deserialize(propertyData);
372     LayerReadHeaderOfTrack(layerData.rsData);
373     LayerReadHeaderOfTrack(layerData.oglData);
374     LayerReadHeaderOfTrack(layerData.rsMetrics);
375     if (versionId_ >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
376         LayerReadHeaderOfTrack(layerData.renderMetrics);
377     }
378     LayerReadHeaderOfTrack(layerData.oglMetrics);
379     LayerReadHeaderOfTrack(layerData.gfxMetrics);
380 
381     return "";
382 }
383 
GetVersion() const384 uint32_t RSFile::GetVersion() const
385 {
386     return versionId_;
387 }
388 
SetVersion(uint32_t version)389 void RSFile::SetVersion(uint32_t version)
390 {
391     versionId_ = version;
392 }
393 
394 // ***********************************
395 // *** LAYER DATA - WRITE
396 
WriteRSData(double time,const void * data,size_t size)397 void RSFile::WriteRSData(double time, const void* data, size_t size)
398 {
399     WriteTrackData(&RSFileLayer::rsData, 0, time, data, size);
400 }
401 
WriteOGLData(uint32_t layer,double time,const void * data,size_t size)402 void RSFile::WriteOGLData(uint32_t layer, double time, const void* data, size_t size)
403 {
404     WriteTrackData(&RSFileLayer::oglData, layer, time, data, size);
405 }
406 
WriteRSMetrics(uint32_t layer,double time,const void * data,size_t size)407 void RSFile::WriteRSMetrics(uint32_t layer, double time, const void* data, size_t size)
408 {
409     WriteTrackData(&RSFileLayer::rsMetrics, layer, time, data, size);
410 }
411 
WriteRenderMetrics(uint32_t layer,double time,const void * data,size_t size)412 void RSFile::WriteRenderMetrics(uint32_t layer, double time, const void* data, size_t size)
413 {
414     WriteTrackData(&RSFileLayer::renderMetrics, layer, time, data, size);
415 }
416 
WriteOGLMetrics(uint32_t layer,double time,uint32_t,const void * data,size_t size)417 void RSFile::WriteOGLMetrics(uint32_t layer, double time, uint32_t /*frame*/, const void* data, size_t size)
418 {
419     WriteTrackData(&RSFileLayer::oglMetrics, layer, time, data, size);
420 }
421 
WriteGFXMetrics(uint32_t layer,double time,uint32_t,const void * data,size_t size)422 void RSFile::WriteGFXMetrics(uint32_t layer, double time, uint32_t /*frame*/, const void* data, size_t size)
423 {
424     WriteTrackData(&RSFileLayer::gfxMetrics, layer, time, data, size);
425 }
426 
427 // ***********************************
428 // *** LAYER DATA - READ
429 
ReadRSDataRestart()430 void RSFile::ReadRSDataRestart()
431 {
432     ReadTrackDataRestart(&RSFileLayer::readindexRsData, 0);
433 }
434 
ReadOGLDataRestart(uint32_t layer)435 void RSFile::ReadOGLDataRestart(uint32_t layer)
436 {
437     ReadTrackDataRestart(&RSFileLayer::readindexOglData, layer);
438 }
439 
ReadRSMetricsRestart(uint32_t layer)440 void RSFile::ReadRSMetricsRestart(uint32_t layer)
441 {
442     ReadTrackDataRestart(&RSFileLayer::readindexRsMetrics, layer);
443 }
444 
ReadRenderMetricsRestart(uint32_t layer)445 void RSFile::ReadRenderMetricsRestart(uint32_t layer)
446 {
447     ReadTrackDataRestart(&RSFileLayer::readindexRenderMetrics, layer);
448 }
449 
ReadOGLMetricsRestart(uint32_t layer)450 void RSFile::ReadOGLMetricsRestart(uint32_t layer)
451 {
452     ReadTrackDataRestart(&RSFileLayer::readindexOglMetrics, layer);
453 }
454 
ReadGFXMetricsRestart(uint32_t layer)455 void RSFile::ReadGFXMetricsRestart(uint32_t layer)
456 {
457     ReadTrackDataRestart(&RSFileLayer::readindexGfxMetrics, layer);
458 }
459 
RSDataEOF() const460 bool RSFile::RSDataEOF() const
461 {
462     return TrackEOF({ &RSFileLayer::readindexRsData, &RSFileLayer::rsData }, 0);
463 }
464 
OGLDataEOF(uint32_t layer) const465 bool RSFile::OGLDataEOF(uint32_t layer) const
466 {
467     return TrackEOF({ &RSFileLayer::readindexOglData, &RSFileLayer::oglData }, layer);
468 }
469 
RSMetricsEOF(uint32_t layer) const470 bool RSFile::RSMetricsEOF(uint32_t layer) const
471 {
472     return TrackEOF({ &RSFileLayer::readindexRsMetrics, &RSFileLayer::rsMetrics }, layer);
473 }
474 
RenderMetricsEOF(uint32_t layer) const475 bool RSFile::RenderMetricsEOF(uint32_t layer) const
476 {
477     return TrackEOF({ &RSFileLayer::readindexRenderMetrics, &RSFileLayer::renderMetrics }, layer);
478 }
479 
OGLMetricsEOF(uint32_t layer) const480 bool RSFile::OGLMetricsEOF(uint32_t layer) const
481 {
482     return TrackEOF({ &RSFileLayer::readindexOglMetrics, &RSFileLayer::oglMetrics }, layer);
483 }
484 
GFXMetricsEOF(uint32_t layer) const485 bool RSFile::GFXMetricsEOF(uint32_t layer) const
486 {
487     return TrackEOF({ &RSFileLayer::readindexGfxMetrics, &RSFileLayer::gfxMetrics }, layer);
488 }
489 
ReadRSData(double untilTime,std::vector<uint8_t> & data,double & readTime)490 bool RSFile::ReadRSData(double untilTime, std::vector<uint8_t>& data, double& readTime)
491 {
492     readTime = 0.0;
493     if (!file_ || layerData_.empty()) {
494         return false;
495     }
496 
497     RSFileLayer& layerData = layerData_[0];
498 
499     if (layerData.readindexRsData >= layerData.rsData.size()) {
500         return false;
501     }
502 
503     Utils::FileSeek(file_, layerData.rsData[layerData.readindexRsData].first, SEEK_SET);
504 
505     Utils::FileRead(&readTime, sizeof(readTime), 1, file_);
506     constexpr double epsilon = 1e-9;
507     if (readTime >= untilTime + epsilon) {
508         return false;
509     }
510 
511     const uint32_t dataLen = layerData.rsData[layerData.readindexRsData].second - sizeof(readTime);
512     if (dataLen > chunkSizeMax) {
513         return false;
514     }
515     data.resize(dataLen);
516     Utils::FileRead(data.data(), dataLen, 1, file_);
517 
518     layerData.readindexRsData++;
519     return true;
520 }
521 
ReadOGLData(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)522 bool RSFile::ReadOGLData(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
523 {
524     return ReadTrackData({ &RSFileLayer::readindexOglData, &RSFileLayer::oglData }, untilTime, layer, data, readTime);
525 }
526 
ReadRSMetrics(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)527 bool RSFile::ReadRSMetrics(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
528 {
529     return ReadTrackData(
530         { &RSFileLayer::readindexRsMetrics, &RSFileLayer::rsMetrics }, untilTime, layer, data, readTime);
531 }
532 
ReadRenderMetrics(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)533 bool RSFile::ReadRenderMetrics(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
534 {
535     return ReadTrackData(
536         { &RSFileLayer::readindexRenderMetrics, &RSFileLayer::renderMetrics }, untilTime, layer, data, readTime);
537 }
538 
ReadOGLMetrics(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)539 bool RSFile::ReadOGLMetrics(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
540 {
541     return ReadTrackData(
542         { &RSFileLayer::readindexOglMetrics, &RSFileLayer::oglMetrics }, untilTime, layer, data, readTime);
543 }
544 
ReadGFXMetrics(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)545 bool RSFile::ReadGFXMetrics(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
546 {
547     return ReadTrackData(
548         { &RSFileLayer::readindexGfxMetrics, &RSFileLayer::gfxMetrics }, untilTime, layer, data, readTime);
549 }
550 
GetDataCopy(std::vector<uint8_t> & data)551 bool RSFile::GetDataCopy(std::vector<uint8_t>& data)
552 {
553     const std::lock_guard<std::mutex> lgMutex(writeMutex_);
554 
555     WriteHeaders(); // Make sure the header is written
556 
557     size_t fileSize = Utils::FileSize(file_);
558     if (fileSize == 0) {
559         return false;
560     }
561 
562     // File size threshold is set to ensure that the file is valid
563     const size_t maxFileSize = 300000000;
564     if (fileSize > maxFileSize) {
565         return false;
566     }
567 
568     data.clear();
569     data.resize(fileSize);
570 
571     const int64_t position = static_cast<int64_t>(Utils::FileTell(file_));
572     Utils::FileSeek(file_, 0, SEEK_SET);
573     Utils::FileRead(file_, data.data(), fileSize);
574     Utils::FileSeek(file_, position, SEEK_SET); // set ptr back
575 
576     return true;
577 }
578 
HasLayer(uint32_t layer) const579 bool RSFile::HasLayer(uint32_t layer) const
580 {
581     // if this condition is true, then layerData_ is surely not empty
582     return layer < layerData_.size();
583 }
584 
585 // ***********************************
586 // *** READ/SAVE HEADERS
587 
WriteHeaders()588 void RSFile::WriteHeaders()
589 {
590     if (!(file_ && wasChanged_)) {
591         return;
592     }
593     for (size_t i = 0; i < layerData_.size(); i++) {
594         LayerWriteHeader(i);
595     }
596     WriteHeader();
597 }
598 
ReadHeaders()599 std::string RSFile::ReadHeaders()
600 {
601     std::string errReason = ReadHeader();
602     if (errReason.size()) {
603         return errReason;
604     }
605     for (size_t i = 0; i < layerData_.size(); i++) {
606         errReason = LayerReadHeader(i);
607         if (errReason.size()) {
608             return errReason;
609         }
610     }
611     return "";
612 }
613 
Close()614 void RSFile::Close()
615 {
616     if (!file_) {
617         return;
618     }
619 
620     const std::lock_guard<std::mutex> lgMutex(writeMutex_);
621 
622     WriteHeaders();
623 
624     Utils::FileClose(file_);
625     file_ = nullptr;
626 
627     headerOff_ = 0;
628     headerPidList_.clear();
629     layerData_.clear();
630 
631     writeDataOff_ = 0;
632     wasChanged_ = false;
633 }
634 
WriteTrackData(LayerTrackMarkupPtr trackMarkup,uint32_t layer,double time,const void * data,size_t size)635 void RSFile::WriteTrackData(LayerTrackMarkupPtr trackMarkup, uint32_t layer, double time, const void* data, size_t size)
636 {
637     const std::lock_guard<std::mutex> lgMutex(writeMutex_);
638 
639     if (!file_ || !HasLayer(layer)) {
640         return;
641     }
642 
643     RSFileLayer& layerData = layerData_[layer];
644     (layerData.*trackMarkup).emplace_back(writeDataOff_, size + sizeof(time));
645 
646     Utils::FileSeek(file_, writeDataOff_, SEEK_SET);
647     Utils::FileWrite(&time, sizeof(time), 1, file_);
648     Utils::FileWrite(data, size, 1, file_);
649     writeDataOff_ = Utils::FileTell(file_);
650 }
651 
ReadTrackData(LayerTrackPtr track,double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)652 bool RSFile::ReadTrackData(
653     LayerTrackPtr track, double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
654 {
655     if (!file_ || !HasLayer(layer)) {
656         return false;
657     }
658 
659     RSFileLayer& layerData = layerData_[layer];
660     auto& trackIndex = layerData.*track.index;
661     auto& trackData = layerData.*track.markup;
662 
663     if (trackIndex >= trackData.size()) {
664         return false;
665     }
666 
667     Utils::FileSeek(file_, trackData[trackIndex].first, SEEK_SET);
668     Utils::FileRead(&readTime, sizeof(readTime), 1, file_);
669     if (readTime > untilTime) {
670         return false;
671     }
672 
673     const uint32_t dataLen = trackData[trackIndex].second - RSFileLayer::MARKUP_SIZE;
674     if (dataLen > chunkSizeMax) {
675         return false;
676     }
677     data.resize(dataLen);
678     Utils::FileRead(data.data(), dataLen, 1, file_);
679 
680     trackIndex++;
681     return true;
682 }
683 
ReadTrackDataRestart(LayerTrackIndexPtr trackIndex,uint32_t layer)684 void RSFile::ReadTrackDataRestart(LayerTrackIndexPtr trackIndex, uint32_t layer)
685 {
686     if (!HasLayer(layer)) {
687         return;
688     }
689 
690     RSFileLayer& layerData = layerData_[layer];
691     layerData.*trackIndex = 0;
692 }
693 
TrackEOF(LayerTrackPtr track,uint32_t layer) const694 bool RSFile::TrackEOF(LayerTrackPtr track, uint32_t layer) const
695 {
696     if (!file_ || !HasLayer(layer)) {
697         return true;
698     }
699 
700     const RSFileLayer& layerData = layerData_[layer];
701     return layerData.*track.index >= (layerData.*track.markup).size();
702 }
703 
GetHeaderFirstFrame() const704 const std::string& RSFile::GetHeaderFirstFrame() const
705 {
706     return headerFirstFrame_;
707 }
708 
AddHeaderFirstFrame(const std::string & dataFirstFrame)709 void RSFile::AddHeaderFirstFrame(const std::string& dataFirstFrame)
710 {
711     headerFirstFrame_ = dataFirstFrame;
712     wasChanged_ = true;
713 }
714 
GetAnimeStartTimes() const715 const std::vector<std::pair<uint64_t, int64_t>>& RSFile::GetAnimeStartTimes() const
716 {
717     return headerAnimeStartTimes_;
718 }
719 
AddAnimeStartTimes(const std::vector<std::pair<uint64_t,int64_t>> & startTimes)720 void RSFile::AddAnimeStartTimes(const std::vector<std::pair<uint64_t, int64_t>>& startTimes)
721 {
722     headerAnimeStartTimes_ = startTimes;
723     wasChanged_ = true;
724 }
725 
ConvertVsyncId2Time(int64_t vsyncId)726 double RSFile::ConvertVsyncId2Time(int64_t vsyncId)
727 {
728     if (mapVsyncId2Time_.count(vsyncId)) {
729         return mapVsyncId2Time_[vsyncId];
730     }
731     constexpr int64_t maxInt64t = std::numeric_limits<int64_t>::max();
732     int64_t minVSync = std::numeric_limits<int64_t>::max();
733     int64_t maxVSync = -1;
734     for (const auto& item : mapVsyncId2Time_) {
735         if (minVSync > item.first) {
736             minVSync = item.first;
737         }
738         if (maxVSync < item.first) {
739             maxVSync = item.first;
740         }
741     }
742     if (vsyncId < minVSync) {
743         if (mapVsyncId2Time_.count(minVSync)) {
744             return mapVsyncId2Time_[minVSync];
745         }
746     }
747     if (vsyncId > maxVSync) {
748         if (mapVsyncId2Time_.count(maxVSync)) {
749             return mapVsyncId2Time_[maxVSync];
750         }
751     }
752     return 0.0;
753 }
754 
ConvertTime2VsyncId(double time) const755 int64_t RSFile::ConvertTime2VsyncId(double time) const
756 {
757     constexpr double numericError = 1e-5;
758     for (const auto& item : mapVsyncId2Time_) {
759         if (time <= item.second + numericError) {
760             return item.first;
761         }
762     }
763     return 0;
764 }
765 
CacheVsyncId2Time(uint32_t layer)766 void RSFile::CacheVsyncId2Time(uint32_t layer)
767 {
768     mapVsyncId2Time_.clear();
769 
770     if (!file_ || !HasLayer(layer)) {
771         return;
772     }
773 
774     LayerTrackPtr track = { &RSFileLayer::readindexRsMetrics, &RSFileLayer::rsMetrics };
775 
776     RSFileLayer& layerData = layerData_[layer];
777     const auto& trackData = layerData.*track.markup;
778 
779     double readTime;
780     std::vector<char> data;
781 
782     for (const auto& trackItem : trackData) {
783         Utils::FileSeek(file_, trackItem.first, SEEK_SET);
784         Utils::FileRead(&readTime, sizeof(readTime), 1, file_);
785 
786         constexpr char packetTypeRsMetrics = 2;
787         char packetType;
788 
789         Utils::FileRead(&packetType, sizeof(packetType), 1, file_);
790         if (packetType != packetTypeRsMetrics) {
791             continue;
792         }
793 
794         const int32_t dataLen = trackItem.second - RSFileLayer::MARKUP_SIZE - 1;
795         constexpr int32_t dataLenMax = 100'000;
796         if (dataLen < 0 || dataLen > dataLenMax) {
797             continue;
798         }
799         data.resize(dataLen);
800         Utils::FileRead(data.data(), dataLen, 1, file_);
801 
802         RSCaptureData captureData;
803         captureData.Deserialize(data);
804         int64_t readVsyncId = captureData.GetPropertyInt64(RSCaptureData::KEY_RS_VSYNC_ID);
805         if (readVsyncId > 0 && !mapVsyncId2Time_.count(readVsyncId)) {
806             mapVsyncId2Time_.insert({readVsyncId, readTime});
807         }
808     }
809 }
810 
811 } // namespace OHOS::Rosen