forked from hzeller/rpi-rgb-led-matrix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent-streamer.h
133 lines (106 loc) · 3.46 KB
/
content-streamer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
//
// Abstractions to read and write FrameCanvas objects to streams. This allows
// you to create canned streams of content with minimal overhead at runtime
// to play with extreme pixel-throughput which also minimizes overheads in
// the Pi to avoid stuttering or brightness glitches.
//
// The disadvantage is, that this represents the full expanded internal
// representation of a frame, so is very large memory wise.
//
// These abstractions are used in util/led-image-viewer.cc to read and
// write such animations to disk. It is also used in util/video-viewer.cc
// to write a version to disk that then can be played with the led-image-viewer.
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string>
namespace rgb_matrix {
class FrameCanvas;
// An abstraction of a data stream. Two implementations exist for files and
// an in-memory representation, but this allows your own implementation, e.g.
// reading from a socket.
class StreamIO {
public:
virtual ~StreamIO() {}
// Rewind stream.
virtual void Rewind() = 0;
// Read bytes into buffer at current position of stream.
// Similar to Posix behavior that allows short reads.
virtual ssize_t Read(void *buf, size_t count) = 0;
// Write bytes from buffer. Similar to Posix behavior that allows short
// writes.
virtual ssize_t Append(const void *buf, size_t count) = 0;
};
class FileStreamIO : public StreamIO {
public:
explicit FileStreamIO(int fd);
~FileStreamIO();
void Rewind() final;
ssize_t Read(void *buf, size_t count) final;
ssize_t Append(const void *buf, size_t count) final;
private:
const int fd_;
};
// Storing a stream in memory. Owns the memory.
class MemStreamIO : public StreamIO {
public:
void Rewind() final;
ssize_t Read(void *buf, size_t count) final;
ssize_t Append(const void *buf, size_t count) final;
private:
std::string buffer_; // super simplistic.
size_t pos_;
};
// Just a view around the memory, possibly a memory mapped file.
class MemMapViewInput : public StreamIO {
public:
MemMapViewInput(int fd);
~MemMapViewInput();
// Since mmmap() might fail, this tells us if it was successful.
bool IsInitialized() const { return buffer_ != nullptr; }
void Rewind() final;
ssize_t Read(void *buf, size_t count) final;
// No append, this is purely read-only.
ssize_t Append(const void *buf, size_t count) final { return -1; }
private:
char *buffer_;
char *end_;
char *pos_;
};
class StreamWriter {
public:
// Does not take ownership of StreamIO
StreamWriter(StreamIO *io);
// Stream out given canvas at the given time. "hold_time_us" indicates
// for how long this frame is to be shown in microseconds.
bool Stream(const FrameCanvas &frame, uint32_t hold_time_us);
private:
void WriteFileHeader(const FrameCanvas &frame, size_t len);
StreamIO *const io_;
bool header_written_;
};
class StreamReader {
public:
// Does not take ownership of StreamIO
StreamReader(StreamIO *io);
~StreamReader();
// Go back to the beginning.
void Rewind();
// Get next frame and its timestamp. Returns 'false' if there is an error
// or end of stream reached..
bool GetNext(FrameCanvas *frame, uint32_t* hold_time_us);
private:
enum State {
STREAM_AT_BEGIN,
STREAM_READING,
STREAM_ERROR,
};
bool ReadFileHeader(const FrameCanvas &frame);
StreamIO *io_;
size_t frame_buf_size_;
State state_;
char *header_frame_buffer_;
};
}