]> git.sesse.net Git - nageru/blob - futatabi/frame_on_disk.h
Set CEF autoplay policy to be more lenient.
[nageru] / futatabi / frame_on_disk.h
1 #ifndef _FRAME_ON_DISK_H
2 #define _FRAME_ON_DISK_H 1
3
4 #include "defs.h"
5
6 #include <algorithm>
7 #include <mutex>
8 #include <stdint.h>
9 #include <string>
10 #include <vector>
11
12 extern std::mutex frame_mu;
13 struct FrameOnDisk {
14         int64_t pts = -1;  // -1 means empty.
15         off_t offset;
16         unsigned filename_idx;
17         uint32_t size;  // Not using size_t saves a few bytes; we can have so many frames. TODO: Not anymore due to audio_size.
18         uint32_t audio_size;
19         // Unfortunately, 32 bits wasted in padding here.
20 };
21 extern std::vector<FrameOnDisk> frames[MAX_STREAMS];  // Under frame_mu.
22 extern std::vector<std::string> frame_filenames;  // Under frame_mu.
23
24 static bool inline operator==(const FrameOnDisk &a, const FrameOnDisk &b)
25 {
26         return a.pts == b.pts &&
27                 a.offset == b.offset &&
28                 a.filename_idx == b.filename_idx &&
29                 a.size == b.size &&
30                 a.audio_size == b.audio_size;
31 }
32
33 // A helper class to read frames from disk. It caches the file descriptor
34 // so that the kernel has a better chance of doing readahead when it sees
35 // the sequential reads. (For this reason, each display has a private
36 // FrameReader. Thus, we can easily keep multiple open file descriptors around
37 // for a single .frames file.)
38 //
39 // Thread-compatible, but not thread-safe.
40 class FrameReader {
41 public:
42         FrameReader();
43         ~FrameReader();
44
45         struct Frame {
46                 std::string video;
47                 std::string audio;
48         };
49         Frame read_frame(FrameOnDisk frame, bool read_video, bool read_audio);
50
51 private:
52         int fd = -1;
53         int last_filename_idx = -1;
54 };
55
56 // Utility functions for dealing with binary search.
57 inline std::vector<FrameOnDisk>::iterator
58 find_last_frame_before(std::vector<FrameOnDisk> &frames, int64_t pts_origin)
59 {
60         return std::lower_bound(frames.begin(), frames.end(), pts_origin,
61                                 [](const FrameOnDisk &frame, int64_t pts) { return frame.pts < pts; });
62 }
63
64 inline std::vector<FrameOnDisk>::const_iterator
65 find_last_frame_before(const std::vector<FrameOnDisk> &frames, int64_t pts_origin)
66 {
67         return std::lower_bound(frames.begin(), frames.end(), pts_origin,
68                                 [](const FrameOnDisk &frame, int64_t pts) { return frame.pts < pts; });
69 }
70
71 inline std::vector<FrameOnDisk>::iterator
72 find_first_frame_at_or_after(std::vector<FrameOnDisk> &frames, int64_t pts_origin)
73 {
74         return std::upper_bound(frames.begin(), frames.end(), pts_origin - 1,
75                                 [](int64_t pts, const FrameOnDisk &frame) { return pts < frame.pts; });
76 }
77
78 inline std::vector<FrameOnDisk>::const_iterator
79 find_first_frame_at_or_after(const std::vector<FrameOnDisk> &frames, int64_t pts_origin)
80 {
81         return std::upper_bound(frames.begin(), frames.end(), pts_origin - 1,
82                                 [](int64_t pts, const FrameOnDisk &frame) { return pts < frame.pts; });
83 }
84
85 #endif  // !defined(_FRAME_ON_DISK_H)