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