]> git.sesse.net Git - nageru/blob - futatabi/frame_on_disk.h
Add metrics for reading frames from disk.
[nageru] / futatabi / frame_on_disk.h
1 #ifndef _FRAME_ON_DISK_H
2 #define _FRAME_ON_DISK_H 1
3
4 #include <algorithm>
5 #include <mutex>
6 #include <string>
7 #include <vector>
8
9 #include <stdint.h>
10
11 #include "defs.h"
12
13 extern std::mutex frame_mu;
14 struct FrameOnDisk {
15         int64_t pts = -1;  // -1 means empty.
16         off_t offset;
17         unsigned filename_idx;
18         uint32_t size;  // Not using size_t saves a few bytes; we can have so many frames.
19 };
20 extern std::vector<FrameOnDisk> frames[MAX_STREAMS];  // Under frame_mu.
21 extern std::vector<std::string> frame_filenames;  // Under frame_mu.
22
23 // A helper class to read frames from disk. It caches the file descriptor
24 // so that the kernel has a better chance of doing readahead when it sees
25 // the sequential reads. (For this reason, each display has a private
26 // FrameReader. Thus, we can easily keep multiple open file descriptors around
27 // for a single .frames file.)
28 class FrameReader {
29 public:
30         FrameReader();
31         ~FrameReader();
32         std::string read_frame(FrameOnDisk frame);
33
34 private:
35         int fd = -1;
36         int last_filename_idx = -1;
37 };
38
39 // Utility functions for dealing with binary search.
40 inline std::vector<FrameOnDisk>::iterator
41 find_last_frame_before(std::vector<FrameOnDisk> &frames, int64_t pts_origin)
42 {
43         return std::lower_bound(frames.begin(), frames.end(), pts_origin,
44                 [](const FrameOnDisk &frame, int64_t pts) { return frame.pts < pts; });
45 }
46
47 inline std::vector<FrameOnDisk>::iterator
48 find_first_frame_at_or_after(std::vector<FrameOnDisk> &frames, int64_t pts_origin)
49 {
50         return std::upper_bound(frames.begin(), frames.end(), pts_origin - 1,
51                 [](int64_t pts, const FrameOnDisk &frame) { return pts < frame.pts; });
52 }
53
54 #endif  // !defined(_FRAME_ON_DISK_H)