1 #include <cstdio>
2 #include <poll.h>
3 #include <unistd.h>
4 #include <algorithm>
5 #include <fstream>
6 #include <map>
7 #include <system_error>
8
9 #include <kms++/kms++.h>
10 #include <kms++util/kms++util.h>
11 #include <kms++util/videodevice.h>
12
13 const uint32_t NUM_SRC_BUFS=2;
14 const uint32_t NUM_DST_BUFS=2;
15
16 using namespace std;
17 using namespace kms;
18
19 static const char* usage_str =
20 "Usage: wbm2m [OPTIONS]\n\n"
21 "Options:\n"
22 " -f, --format=4CC Output format"
23 " -h, --help Print this help\n"
24 ;
25
26 const int bar_speed = 4;
27 const int bar_width = 10;
28
get_bar_pos(DumbFramebuffer * fb,unsigned frame_num)29 static unsigned get_bar_pos(DumbFramebuffer* fb, unsigned frame_num)
30 {
31 return (frame_num * bar_speed) % (fb->width() - bar_width + 1);
32 }
33
read_frame(DumbFramebuffer * fb,unsigned frame_num)34 static void read_frame(DumbFramebuffer* fb, unsigned frame_num)
35 {
36 static map<DumbFramebuffer*, int> s_bar_pos_map;
37
38 int old_pos = -1;
39 if (s_bar_pos_map.find(fb) != s_bar_pos_map.end())
40 old_pos = s_bar_pos_map[fb];
41
42 int pos = get_bar_pos(fb, frame_num);
43 draw_color_bar(*fb, old_pos, pos, bar_width);
44 draw_text(*fb, fb->width() / 2, 0, to_string(frame_num), RGB(255, 255, 255));
45 s_bar_pos_map[fb] = pos;
46 }
47
main(int argc,char ** argv)48 int main(int argc, char** argv)
49 {
50 // XXX get from args
51 const uint32_t src_width = 800;
52 const uint32_t src_height = 480;
53 const auto src_fmt = PixelFormat::XRGB8888;
54 const uint32_t num_src_frames = 10;
55
56 const uint32_t dst_width = 800;
57 const uint32_t dst_height = 480;
58 auto dst_fmt = PixelFormat::XRGB8888;
59
60 const string filename = "wb-out.raw";
61
62 OptionSet optionset = {
63 Option("f|format=", [&](string s)
64 {
65 dst_fmt = FourCCToPixelFormat(s);
66 }),
67 Option("h|help", [&]()
68 {
69 puts(usage_str);
70 exit(-1);
71 }),
72 };
73
74 optionset.parse(argc, argv);
75
76 if (optionset.params().size() > 0) {
77 puts(usage_str);
78 exit(-1);
79 }
80
81 VideoDevice vid("/dev/video10");
82
83 Card card;
84
85 uint32_t src_frame_num = 0;
86 uint32_t dst_frame_num = 0;
87
88 VideoStreamer* out = vid.get_output_streamer();
89 VideoStreamer* in = vid.get_capture_streamer();
90
91 out->set_format(src_fmt, src_width, src_height);
92 in->set_format(dst_fmt, dst_width, dst_height);
93
94 out->set_queue_size(NUM_SRC_BUFS);
95 in->set_queue_size(NUM_DST_BUFS);
96
97
98 for (unsigned i = 0; i < min(NUM_SRC_BUFS, num_src_frames); ++i) {
99 auto fb = new DumbFramebuffer(card, src_width, src_height, src_fmt);
100
101 read_frame(fb, src_frame_num++);
102
103 out->queue(fb);
104 }
105
106 for (unsigned i = 0; i < min(NUM_DST_BUFS, num_src_frames); ++i) {
107 auto fb = new DumbFramebuffer(card, dst_width, dst_height, dst_fmt);
108 in->queue(fb);
109 }
110
111 vector<pollfd> fds(3);
112
113 fds[0].fd = 0;
114 fds[0].events = POLLIN;
115 fds[1].fd = vid.fd();
116 fds[1].events = POLLIN;
117 fds[2].fd = card.fd();
118 fds[2].events = POLLIN;
119
120 ofstream os(filename, ofstream::binary);
121
122 out->stream_on();
123 in->stream_on();
124
125 while (true) {
126 int r = poll(fds.data(), fds.size(), -1);
127 ASSERT(r > 0);
128
129 if (fds[0].revents != 0)
130 break;
131
132 if (fds[1].revents) {
133 fds[1].revents = 0;
134
135
136 try {
137 DumbFramebuffer *dst_fb = in->dequeue();
138 printf("Writing frame %u\n", dst_frame_num);
139 for (unsigned i = 0; i < dst_fb->num_planes(); ++i)
140 os.write((char*)dst_fb->map(i), dst_fb->size(i));
141 in->queue(dst_fb);
142
143 dst_frame_num++;
144
145 if (dst_frame_num >= num_src_frames)
146 break;
147
148 } catch (system_error& se) {
149 if (se.code() != errc::resource_unavailable_try_again)
150 FAIL("dequeue failed: %s", se.what());
151
152 break;
153 }
154
155 DumbFramebuffer *src_fb = out->dequeue();
156
157 if (src_frame_num < num_src_frames) {
158 read_frame(src_fb, src_frame_num++);
159 out->queue(src_fb);
160 }
161 }
162
163 if (fds[2].revents) {
164 fds[2].revents = 0;
165 }
166 }
167
168 printf("exiting...\n");
169 }
170