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 REPLAY_TOOL_CLIENT
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 
58     uint32_t versionId = RSFILE_VERSION_LATEST;
59     Utils::FileWrite(&versionId, sizeof(versionId), 1, file_);
60 
61     headerOff_ = 0; // TEMP VALUE
62     Utils::FileWrite(&headerOff_, sizeof(headerOff_), 1, file_);
63 
64     writeDataOff_ = RSFileLayer::MARKUP_SIZE;
65 
66     wasChanged_ = true;
67 }
68 
Open(const std::string & fname)69 bool RSFile::Open(const std::string& fname)
70 {
71     if (file_ != nullptr) {
72         Close();
73     }
74 
75 #ifdef REPLAY_TOOL_CLIENT
76     file_ = Utils::FileOpen(fname, "rb");
77 #else
78     file_ = Utils::FileOpen(fname, "rbe");
79 #endif
80     if (file_ == nullptr) {
81         return false;
82     }
83 
84     uint32_t headerId;
85     Utils::FileRead(&headerId, sizeof(headerId), 1, file_);
86     if (headerId == 'ROHR') {
87         Utils::FileRead(&versionId_, sizeof(versionId_), 1, file_);
88     } else if (headerId == 'RPLY') {
89         versionId_ = 0;
90     } else {
91         Utils::FileClose(file_);
92         file_ = nullptr;
93         return false;
94     }
95 
96     Utils::FileRead(&headerOff_, sizeof(headerOff_), 1, file_);
97 
98     Utils::FileSeek(file_, 0, SEEK_END);
99     writeDataOff_ = Utils::FileTell(file_);
100 
101     Utils::FileSeek(file_, headerOff_, SEEK_SET);
102     ReadHeaders();
103 
104     wasChanged_ = false;
105 
106     return true;
107 }
108 
IsOpen() const109 bool RSFile::IsOpen() const
110 {
111     return file_ != nullptr;
112 }
113 
SetWriteTime(double time)114 void RSFile::SetWriteTime(double time)
115 {
116     writeStartTime_ = time;
117 }
118 
GetWriteTime() const119 double RSFile::GetWriteTime() const
120 {
121     return writeStartTime_;
122 }
123 
124 // ***********************************
125 // *** GLOBAL HEADER
126 
AddHeaderPid(pid_t pid)127 void RSFile::AddHeaderPid(pid_t pid)
128 {
129     if (std::find(std::begin(headerPidList_), std::end(headerPidList_), pid) != std::end(headerPidList_)) {
130         return;
131     }
132     headerPidList_.push_back(pid);
133 
134     wasChanged_ = true;
135 }
136 
GetHeaderPids() const137 const std::vector<pid_t>& RSFile::GetHeaderPids() const
138 {
139     return headerPidList_;
140 }
141 
SetPreparedHeader(const std::vector<uint8_t> & headerData)142 void RSFile::SetPreparedHeader(const std::vector<uint8_t>& headerData)
143 {
144     preparedHeader_ = headerData;
145 }
146 
GetPreparedHeader(std::vector<uint8_t> & headerData)147 void RSFile::GetPreparedHeader(std::vector<uint8_t>& headerData)
148 {
149     headerData = preparedHeader_;
150 }
151 
SetPreparedHeaderMode(bool mode)152 void RSFile::SetPreparedHeaderMode(bool mode)
153 {
154     preparedHeaderMode_ = mode;
155 }
156 
WriteHeader()157 void RSFile::WriteHeader()
158 {
159     // WARNING removed redundant mutex
160     if (!file_) {
161         return;
162     }
163 
164     headerOff_ = writeDataOff_;
165     Utils::FileSeek(file_, writeDataOff_, SEEK_SET);
166 
167     if (preparedHeaderMode_) {
168         // WRITE RAW
169         Utils::FileWrite(preparedHeader_.data(), 1, preparedHeader_.size(), file_);
170         preparedHeader_.clear();
171     } else {
172         // WRITE TIME START
173         Utils::FileWrite(&writeStartTime_, 1, sizeof(writeStartTime_), file_);
174 
175         // SAVE PID LIST
176         const uint32_t recordSize = headerPidList_.size();
177         Utils::FileWrite(&recordSize, sizeof(recordSize), 1, file_);
178         Utils::FileWrite(headerPidList_.data(), headerPidList_.size(), sizeof(pid_t), file_);
179 
180         // SAVE FIRST SCREEN
181         uint32_t firstScrSize = headerFirstFrame_.size();
182         Utils::FileWrite(&firstScrSize, sizeof(firstScrSize), 1, file_);
183         Utils::FileWrite(headerFirstFrame_.data(), headerFirstFrame_.size(), 1, file_);
184 
185         // ALL TEXTURES
186         ImageCache::Serialize(file_);
187     }
188 
189     // SAVE LAYERS OFFSETS
190     const uint32_t recordSize = layerData_.size();
191     Utils::FileWrite(&recordSize, sizeof(recordSize), 1, file_);
192     for (auto& i : layerData_) {
193         Utils::FileWrite(&i.layerHeader, sizeof(i.layerHeader), 1, file_);
194     }
195 
196     constexpr int preambleSize = 8;
197     Utils::FileSeek(file_, preambleSize, SEEK_SET);
198     Utils::FileWrite(&headerOff_, sizeof(headerOff_), 1, file_);
199 }
200 
ReadHeader()201 void RSFile::ReadHeader()
202 {
203     if (!file_) {
204         return;
205     }
206 
207     Utils::FileSeek(file_, headerOff_, SEEK_SET);
208 
209     // READ what was write start time
210     Utils::FileRead(&writeStartTime_, 1, sizeof(writeStartTime_), file_);
211 
212     // READ PID LIST
213     uint32_t recordSize;
214     Utils::FileRead(&recordSize, sizeof(recordSize), 1, file_);
215     headerPidList_.resize(recordSize);
216     Utils::FileRead(headerPidList_.data(), headerPidList_.size(), sizeof(pid_t), file_);
217 
218     // READ FIRST SCREEN
219     uint32_t firstScrSize;
220     Utils::FileRead(&firstScrSize, sizeof(firstScrSize), 1, file_);
221     headerFirstFrame_.resize(firstScrSize);
222     Utils::FileRead(headerFirstFrame_.data(), headerFirstFrame_.size(), 1, file_);
223 
224     // ALL TEXTURES
225     ImageCache::Deserialize(file_);
226 
227     if (preparedHeaderMode_) {
228         const size_t subHeaderEndOff = Utils::FileTell(file_);
229         Utils::FileSeek(file_, headerOff_, SEEK_SET);
230         const size_t subHeaderLen = subHeaderEndOff - headerOff_;
231         preparedHeader_.resize(subHeaderLen);
232         Utils::FileRead(preparedHeader_.data(), subHeaderLen, 1, file_);
233     }
234 
235     // READ LAYERS OFFSETS
236     Utils::FileRead(&recordSize, sizeof(recordSize), 1, file_);
237     layerData_.resize(recordSize);
238     for (auto& i : layerData_) {
239         Utils::FileRead(&i.layerHeader, sizeof(i.layerHeader), 1, file_);
240         i.readindexRsData = 0;
241     }
242 }
243 
244 // ***********************************
245 // *** LAYER HEADER
246 
AddLayer()247 uint32_t RSFile::AddLayer()
248 {
249     const uint32_t newId = layerData_.size();
250     const RSFileLayer data;
251     layerData_.push_back(data);
252 
253     wasChanged_ = true;
254 
255     return newId;
256 }
257 
LayerAddHeaderProperty(uint32_t layer,const std::string & name,const std::string & value)258 void RSFile::LayerAddHeaderProperty(uint32_t layer, const std::string& name, const std::string& value)
259 {
260     if (!HasLayer(layer)) {
261         return;
262     }
263 
264     RSFileLayer& layerData = layerData_[layer];
265     layerData.property.SetProperty(name, value);
266 
267     wasChanged_ = true;
268 }
269 
LayerWriteHeader(uint32_t layer)270 void RSFile::LayerWriteHeader(uint32_t layer)
271 {
272     const std::lock_guard<std::mutex> lgMutex(writeMutex_);
273 
274     if (!file_ || !HasLayer(layer)) {
275         return;
276     }
277 
278     RSFileLayer& layerData = layerData_[layer];
279 
280     const uint32_t layerHeaderOff = writeDataOff_; // position of layer table
281     Utils::FileSeek(file_, writeDataOff_, SEEK_SET);
282 
283     std::vector<char> propertyData;
284     layerData.property.Serialize(propertyData);
285 
286     // SAVE LAYER PROPERTY
287     uint32_t recordSize = propertyData.size();
288     Utils::FileWrite(&recordSize, sizeof(recordSize), 1, file_);
289     Utils::FileWrite(propertyData.data(), propertyData.size(), 1, file_);
290 
291     LayerWriteHeaderOfTrack(layerData.rsData);
292     LayerWriteHeaderOfTrack(layerData.oglData);
293     LayerWriteHeaderOfTrack(layerData.rsMetrics);
294     LayerWriteHeaderOfTrack(layerData.renderMetrics);
295     LayerWriteHeaderOfTrack(layerData.oglMetrics);
296     LayerWriteHeaderOfTrack(layerData.gfxMetrics);
297     layerData.layerHeader = { layerHeaderOff, Utils::FileTell(file_) - layerHeaderOff }; // position of layer table
298 
299     writeDataOff_ = Utils::FileTell(file_);
300 }
301 
LayerReadHeader(uint32_t layer)302 void RSFile::LayerReadHeader(uint32_t layer)
303 {
304     if (!file_ || !HasLayer(layer)) {
305         return;
306     }
307 
308     RSFileLayer& layerData = layerData_[layer];
309 
310     Utils::FileSeek(file_, layerData.layerHeader.first, SEEK_SET);
311 
312     // READ LAYER PROPERTY
313     uint32_t recordSize = 0u;
314     Utils::FileRead(&recordSize, sizeof(recordSize), 1, file_);
315     std::vector<char> propertyData;
316     propertyData.resize(recordSize);
317     Utils::FileRead(propertyData.data(), recordSize, 1, file_);
318 
319     layerData.property.Deserialize(propertyData);
320     LayerReadHeaderOfTrack(layerData.rsData);
321     LayerReadHeaderOfTrack(layerData.oglData);
322     LayerReadHeaderOfTrack(layerData.rsMetrics);
323     if (versionId_ >= RSFILE_VERSION_RENDER_METRICS_ADDED) {
324         LayerReadHeaderOfTrack(layerData.renderMetrics);
325     }
326     LayerReadHeaderOfTrack(layerData.oglMetrics);
327     LayerReadHeaderOfTrack(layerData.gfxMetrics);
328 }
329 
GetVersion()330 uint32_t RSFile::GetVersion()
331 {
332     return versionId_;
333 }
334 
335 // ***********************************
336 // *** LAYER DATA - WRITE
337 
338 // XXX: static std::map<uint64_t, std::pair<std::shared_ptr<void>, int>> ImageMap;
339 
WriteRSData(double time,const void * data,size_t size)340 void RSFile::WriteRSData(double time, const void* data, size_t size)
341 {
342     WriteTrackData(&RSFileLayer::rsData, 0, time, data, size);
343 }
344 
WriteOGLData(uint32_t layer,double time,const void * data,size_t size)345 void RSFile::WriteOGLData(uint32_t layer, double time, const void* data, size_t size)
346 {
347     WriteTrackData(&RSFileLayer::oglData, layer, time, data, size);
348 }
349 
WriteRSMetrics(uint32_t layer,double time,const void * data,size_t size)350 void RSFile::WriteRSMetrics(uint32_t layer, double time, const void* data, size_t size)
351 {
352     WriteTrackData(&RSFileLayer::rsMetrics, layer, time, data, size);
353 }
354 
WriteRenderMetrics(uint32_t layer,double time,const void * data,size_t size)355 void RSFile::WriteRenderMetrics(uint32_t layer, double time, const void* data, size_t size)
356 {
357     WriteTrackData(&RSFileLayer::renderMetrics, layer, time, data, size);
358 }
359 
WriteOGLMetrics(uint32_t layer,double time,uint32_t,const void * data,size_t size)360 void RSFile::WriteOGLMetrics(uint32_t layer, double time, uint32_t /*frame*/, const void* data, size_t size)
361 {
362     WriteTrackData(&RSFileLayer::oglMetrics, layer, time, data, size);
363 }
364 
WriteGFXMetrics(uint32_t layer,double time,uint32_t,const void * data,size_t size)365 void RSFile::WriteGFXMetrics(uint32_t layer, double time, uint32_t /*frame*/, const void* data, size_t size)
366 {
367     WriteTrackData(&RSFileLayer::gfxMetrics, layer, time, data, size);
368 }
369 
370 // ***********************************
371 // *** LAYER DATA - READ
372 
ReadRSDataRestart()373 void RSFile::ReadRSDataRestart()
374 {
375     ReadTrackDataRestart(&RSFileLayer::readindexRsData, 0);
376 }
377 
ReadOGLDataRestart(uint32_t layer)378 void RSFile::ReadOGLDataRestart(uint32_t layer)
379 {
380     ReadTrackDataRestart(&RSFileLayer::readindexOglData, layer);
381 }
382 
ReadRSMetricsRestart(uint32_t layer)383 void RSFile::ReadRSMetricsRestart(uint32_t layer)
384 {
385     ReadTrackDataRestart(&RSFileLayer::readindexRsMetrics, layer);
386 }
387 
ReadRenderMetricsRestart(uint32_t layer)388 void RSFile::ReadRenderMetricsRestart(uint32_t layer)
389 {
390     ReadTrackDataRestart(&RSFileLayer::readindexRenderMetrics, layer);
391 }
392 
ReadOGLMetricsRestart(uint32_t layer)393 void RSFile::ReadOGLMetricsRestart(uint32_t layer)
394 {
395     ReadTrackDataRestart(&RSFileLayer::readindexOglMetrics, layer);
396 }
397 
ReadGFXMetricsRestart(uint32_t layer)398 void RSFile::ReadGFXMetricsRestart(uint32_t layer)
399 {
400     ReadTrackDataRestart(&RSFileLayer::readindexGfxMetrics, layer);
401 }
402 
RSDataEOF() const403 bool RSFile::RSDataEOF() const
404 {
405     return TrackEOF({ &RSFileLayer::readindexRsData, &RSFileLayer::rsData }, 0);
406 }
407 
OGLDataEOF(uint32_t layer) const408 bool RSFile::OGLDataEOF(uint32_t layer) const
409 {
410     return TrackEOF({ &RSFileLayer::readindexOglData, &RSFileLayer::oglData }, layer);
411 }
412 
RSMetricsEOF(uint32_t layer) const413 bool RSFile::RSMetricsEOF(uint32_t layer) const
414 {
415     return TrackEOF({ &RSFileLayer::readindexRsMetrics, &RSFileLayer::rsMetrics }, layer);
416 }
417 
RenderMetricsEOF(uint32_t layer) const418 bool RSFile::RenderMetricsEOF(uint32_t layer) const
419 {
420     return TrackEOF({ &RSFileLayer::readindexRenderMetrics, &RSFileLayer::renderMetrics }, layer);
421 }
422 
OGLMetricsEOF(uint32_t layer) const423 bool RSFile::OGLMetricsEOF(uint32_t layer) const
424 {
425     return TrackEOF({ &RSFileLayer::readindexOglMetrics, &RSFileLayer::oglMetrics }, layer);
426 }
427 
GFXMetricsEOF(uint32_t layer) const428 bool RSFile::GFXMetricsEOF(uint32_t layer) const
429 {
430     return TrackEOF({ &RSFileLayer::readindexGfxMetrics, &RSFileLayer::gfxMetrics }, layer);
431 }
432 
ReadRSData(double untilTime,std::vector<uint8_t> & data,double & readTime)433 bool RSFile::ReadRSData(double untilTime, std::vector<uint8_t>& data, double& readTime)
434 {
435     if (!file_ || layerData_.empty()) {
436         return false;
437     }
438 
439     RSFileLayer& layerData = layerData_[0];
440 
441     if (layerData.readindexRsData >= layerData.rsData.size()) {
442         return false;
443     }
444 
445     Utils::FileSeek(file_, layerData.rsData[layerData.readindexRsData].first, SEEK_SET);
446 
447     Utils::FileRead(&readTime, sizeof(readTime), 1, file_);
448     constexpr double epsilon = 1e-9;
449     if (readTime >= untilTime + epsilon) {
450         return false;
451     }
452 
453     const uint32_t dataLen = layerData.rsData[layerData.readindexRsData].second - sizeof(readTime);
454     data.resize(dataLen);
455     Utils::FileRead(data.data(), dataLen, 1, file_);
456 
457     layerData.readindexRsData++;
458     return true;
459 }
460 
ReadOGLData(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)461 bool RSFile::ReadOGLData(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
462 {
463     return ReadTrackData({ &RSFileLayer::readindexOglData, &RSFileLayer::oglData }, untilTime, layer, data, readTime);
464 }
465 
ReadRSMetrics(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)466 bool RSFile::ReadRSMetrics(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
467 {
468     return ReadTrackData(
469         { &RSFileLayer::readindexRsMetrics, &RSFileLayer::rsMetrics }, untilTime, layer, data, readTime);
470 }
471 
ReadRenderMetrics(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)472 bool RSFile::ReadRenderMetrics(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
473 {
474     return ReadTrackData(
475         { &RSFileLayer::readindexRenderMetrics, &RSFileLayer::renderMetrics }, untilTime, layer, data, readTime);
476 }
477 
ReadOGLMetrics(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)478 bool RSFile::ReadOGLMetrics(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
479 {
480     return ReadTrackData(
481         { &RSFileLayer::readindexOglMetrics, &RSFileLayer::oglMetrics }, untilTime, layer, data, readTime);
482 }
483 
ReadGFXMetrics(double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)484 bool RSFile::ReadGFXMetrics(double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
485 {
486     return ReadTrackData(
487         { &RSFileLayer::readindexGfxMetrics, &RSFileLayer::gfxMetrics }, untilTime, layer, data, readTime);
488 }
489 
GetDataCopy(std::vector<uint8_t> & data)490 bool RSFile::GetDataCopy(std::vector<uint8_t>& data)
491 {
492     WriteHeaders(); // Make sure the header is written
493 
494     size_t fileSize = Utils::FileSize(file_);
495     if (fileSize == 0) {
496         return false;
497     }
498 
499     // File size threshold is set to ensure that the file is valid
500     const size_t maxFileSize = 300000000;
501     if (fileSize > maxFileSize) {
502         return false;
503     }
504 
505     data.clear();
506     data.resize(fileSize);
507 
508     const int64_t position = static_cast<int64_t>(Utils::FileTell(file_));
509     Utils::FileSeek(file_, 0, SEEK_SET);
510     Utils::FileRead(file_, data.data(), fileSize);
511     Utils::FileSeek(file_, position, SEEK_SET); // set ptr back
512 
513     return true;
514 }
515 
HasLayer(uint32_t layer) const516 bool RSFile::HasLayer(uint32_t layer) const
517 {
518     // if this condition is true, then layerData_ is surely not empty
519     return layer < layerData_.size();
520 }
521 
522 // ***********************************
523 // *** READ/SAVE HEADERS
524 
WriteHeaders()525 void RSFile::WriteHeaders()
526 {
527     if (!(file_ && wasChanged_)) {
528         return;
529     }
530     for (size_t i = 0; i < layerData_.size(); i++) {
531         LayerWriteHeader(i);
532     }
533     WriteHeader();
534 }
535 
ReadHeaders()536 void RSFile::ReadHeaders()
537 {
538     ReadHeader();
539     for (size_t i = 0; i < layerData_.size(); i++) {
540         LayerReadHeader(i);
541     }
542 }
543 
Close()544 void RSFile::Close()
545 {
546     if (!file_) {
547         return;
548     }
549 
550     WriteHeaders();
551 
552     const std::lock_guard<std::mutex> lgMutex(writeMutex_);
553 
554     Utils::FileClose(file_);
555     file_ = nullptr;
556 
557     headerOff_ = 0;
558     headerPidList_.clear();
559     layerData_.clear();
560 
561     writeDataOff_ = 0;
562     wasChanged_ = false;
563 }
564 
WriteTrackData(LayerTrackMarkupPtr trackMarkup,uint32_t layer,double time,const void * data,size_t size)565 void RSFile::WriteTrackData(LayerTrackMarkupPtr trackMarkup, uint32_t layer, double time, const void* data, size_t size)
566 {
567     const std::lock_guard<std::mutex> lgMutex(writeMutex_);
568 
569     if (!file_ || layerData_.empty()) {
570         return;
571     }
572 
573     RSFileLayer& layerData = layerData_[layer];
574     (layerData.*trackMarkup).emplace_back(writeDataOff_, size + sizeof(time));
575 
576     Utils::FileSeek(file_, writeDataOff_, SEEK_SET);
577     Utils::FileWrite(&time, sizeof(time), 1, file_);
578     Utils::FileWrite(data, size, 1, file_);
579     writeDataOff_ = Utils::FileTell(file_);
580 }
581 
ReadTrackData(LayerTrackPtr track,double untilTime,uint32_t layer,std::vector<uint8_t> & data,double & readTime)582 bool RSFile::ReadTrackData(
583     LayerTrackPtr track, double untilTime, uint32_t layer, std::vector<uint8_t>& data, double& readTime)
584 {
585     if (!file_ || !HasLayer(layer)) {
586         return false;
587     }
588 
589     RSFileLayer& layerData = layerData_[layer];
590     auto& trackIndex = layerData.*track.index;
591     auto& trackData = layerData.*track.markup;
592 
593     if (trackIndex >= trackData.size()) {
594         return false;
595     }
596 
597     Utils::FileSeek(file_, trackData[trackIndex].first, SEEK_SET);
598     Utils::FileRead(&readTime, sizeof(readTime), 1, file_);
599     if (readTime > untilTime) {
600         return false;
601     }
602 
603     const uint32_t dataLen = trackData[trackIndex].second - RSFileLayer::MARKUP_SIZE;
604     data.resize(dataLen);
605     Utils::FileRead(data.data(), dataLen, 1, file_);
606 
607     trackIndex++;
608     return true;
609 }
610 
ReadTrackDataRestart(LayerTrackIndexPtr trackIndex,uint32_t layer)611 void RSFile::ReadTrackDataRestart(LayerTrackIndexPtr trackIndex, uint32_t layer)
612 {
613     if (layerData_.empty()) {
614         return;
615     }
616 
617     RSFileLayer& layerData = layerData_[layer];
618     layerData.*trackIndex = 0;
619 }
620 
TrackEOF(LayerTrackPtr track,uint32_t layer) const621 bool RSFile::TrackEOF(LayerTrackPtr track, uint32_t layer) const
622 {
623     if (!file_ || !HasLayer(layer)) {
624         return true;
625     }
626 
627     const RSFileLayer& layerData = layerData_[layer];
628     return layerData.*track.index >= (layerData.*track.markup).size();
629 }
630 
GetHeaderFirstFrame() const631 const std::string& RSFile::GetHeaderFirstFrame() const
632 {
633     return headerFirstFrame_;
634 }
635 
AddHeaderFirstFrame(const std::string & dataFirstFrame)636 void RSFile::AddHeaderFirstFrame(const std::string& dataFirstFrame)
637 {
638     headerFirstFrame_ = dataFirstFrame;
639     wasChanged_ = true;
640 }
641 
642 } // namespace OHOS::Rosen