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