From debef007b62bc5e8696e02f96111bd2a10072562 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 7 Oct 2020 15:29:39 +0300 Subject: rename omap wb utils to omap-wb --- utils/CMakeLists.txt | 8 +- utils/meson.build | 4 +- utils/omap-wbcap.cpp | 411 +++++++++++++++++++++++++++++++++++++++++++++++++++ utils/omap-wbm2m.cpp | 200 +++++++++++++++++++++++++ utils/wbcap.cpp | 411 --------------------------------------------------- utils/wbm2m.cpp | 200 ------------------------- 6 files changed, 617 insertions(+), 617 deletions(-) create mode 100644 utils/omap-wbcap.cpp create mode 100644 utils/omap-wbm2m.cpp delete mode 100644 utils/wbcap.cpp delete mode 100644 utils/wbm2m.cpp diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 25216f2..d28527a 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -27,11 +27,11 @@ if(LIBEVDEV_FOUND) target_link_libraries(kmstouch kms++ kms++util ${LIBDRM_LIBRARIES} ${LIBEVDEV_LIBRARIES}) endif() -add_executable (wbcap wbcap.cpp) -target_link_libraries(wbcap kms++ kms++util ${LIBDRM_LIBRARIES}) +add_executable (omap-wbcap omap-wbcap.cpp) +target_link_libraries(omap-wbcap kms++ kms++util ${LIBDRM_LIBRARIES}) -add_executable (wbm2m wbm2m.cpp) -target_link_libraries(wbm2m kms++ kms++util ${LIBDRM_LIBRARIES}) +add_executable (omap-wbm2m omap-wbm2m.cpp) +target_link_libraries(omap-wbm2m kms++ kms++util ${LIBDRM_LIBRARIES}) install(TARGETS kmstest kmsprint fbtest DESTINATION bin) diff --git a/utils/meson.build b/utils/meson.build index 10f49f2..b1e7918 100644 --- a/utils/meson.build +++ b/utils/meson.build @@ -13,5 +13,5 @@ if libevdev_dep.found() executable('kmstouch', 'kmstouch.cpp', dependencies : [ common_deps, libevdev_dep ], install : false) endif -executable('wbcap', 'wbcap.cpp', dependencies : [ common_deps ], install : false) -executable('wbm2m', 'wbm2m.cpp', dependencies : [ common_deps ], install : false) +executable('omap-wbcap', 'omap-wbcap.cpp', dependencies : [ common_deps ], install : false) +executable('omap-wbm2m', 'omap-wbm2m.cpp', dependencies : [ common_deps ], install : false) diff --git a/utils/omap-wbcap.cpp b/utils/omap-wbcap.cpp new file mode 100644 index 0000000..8033869 --- /dev/null +++ b/utils/omap-wbcap.cpp @@ -0,0 +1,411 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#define CAMERA_BUF_QUEUE_SIZE 5 + +using namespace std; +using namespace kms; + +static vector s_fbs; +static vector s_free_fbs; +static vector s_wb_fbs; +static vector s_ready_fbs; + +class WBStreamer +{ +public: + WBStreamer(VideoStreamer* streamer, Crtc* crtc, PixelFormat pixfmt) + : m_capdev(*streamer) + { + Videomode m = crtc->mode(); + + m_capdev.set_port(crtc->idx()); + m_capdev.set_format(pixfmt, m.hdisplay, m.vdisplay / (m.interlace() ? 2 : 1)); + m_capdev.set_queue_size(s_fbs.size()); + + for (auto fb : s_free_fbs) { + m_capdev.queue(fb); + s_wb_fbs.push_back(fb); + } + + s_free_fbs.clear(); + } + + ~WBStreamer() + { + } + + WBStreamer(const WBStreamer& other) = delete; + WBStreamer& operator=(const WBStreamer& other) = delete; + + int fd() const { return m_capdev.fd(); } + + void start_streaming() + { + m_capdev.stream_on(); + } + + void stop_streaming() + { + m_capdev.stream_off(); + } + + DumbFramebuffer* Dequeue() + { + auto fb = m_capdev.dequeue(); + + auto iter = find(s_wb_fbs.begin(), s_wb_fbs.end(), fb); + s_wb_fbs.erase(iter); + + s_ready_fbs.insert(s_ready_fbs.begin(), fb); + + return fb; + } + + void Queue() + { + if (s_free_fbs.size() == 0) + return; + + auto fb = s_free_fbs.back(); + s_free_fbs.pop_back(); + + m_capdev.queue(fb); + + s_wb_fbs.insert(s_wb_fbs.begin(), fb); + } + +private: + VideoStreamer& m_capdev; +}; + +class WBFlipState : private PageFlipHandlerBase +{ +public: + WBFlipState(Card& card, Crtc* crtc, Plane* plane) + : m_card(card), m_crtc(crtc), m_plane(plane) + { + auto fb = s_ready_fbs.back(); + s_ready_fbs.pop_back(); + + AtomicReq req(m_card); + + req.add(m_plane, "CRTC_ID", m_crtc->id()); + req.add(m_plane, "FB_ID", fb->id()); + + req.add(m_plane, "CRTC_X", 0); + req.add(m_plane, "CRTC_Y", 0); + req.add(m_plane, "CRTC_W", min((uint32_t)m_crtc->mode().hdisplay, fb->width())); + req.add(m_plane, "CRTC_H", min((uint32_t)m_crtc->mode().vdisplay, fb->height())); + + req.add(m_plane, "SRC_X", 0); + req.add(m_plane, "SRC_Y", 0); + req.add(m_plane, "SRC_W", fb->width() << 16); + req.add(m_plane, "SRC_H", fb->height() << 16); + + int r = req.commit_sync(); + FAIL_IF(r, "initial plane setup failed"); + + m_current_fb = fb; + } + + void queue_next() + { + if (m_queued_fb) + return; + + if (s_ready_fbs.size() == 0) + return; + + auto fb = s_ready_fbs.back(); + s_ready_fbs.pop_back(); + + AtomicReq req(m_card); + req.add(m_plane, "FB_ID", fb->id()); + + int r = req.commit(this); + if (r) + EXIT("Flip commit failed: %d\n", r); + + m_queued_fb = fb; + } + +private: + void handle_page_flip(uint32_t frame, double time) + { + if (m_queued_fb) { + if (m_current_fb) + s_free_fbs.insert(s_free_fbs.begin(), m_current_fb); + + m_current_fb = m_queued_fb; + m_queued_fb = nullptr; + } + + queue_next(); + } + + Card& m_card; + Crtc* m_crtc; + Plane* m_plane; + + DumbFramebuffer* m_current_fb = nullptr; + DumbFramebuffer* m_queued_fb = nullptr; +}; + +class BarFlipState : private PageFlipHandlerBase +{ +public: + BarFlipState(Card& card, Crtc* crtc, Plane* plane, uint32_t width, uint32_t height) + : m_card(card), m_crtc(crtc), m_plane(plane) + { + for (unsigned i = 0; i < s_num_buffers; ++i) + m_fbs[i] = new DumbFramebuffer(card, width, height, PixelFormat::XRGB8888); + } + + ~BarFlipState() + { + for (unsigned i = 0; i < s_num_buffers; ++i) + delete m_fbs[i]; + } + + void start_flipping() + { + m_frame_num = 0; + queue_next(); + } + +private: + void handle_page_flip(uint32_t frame, double time) + { + m_frame_num++; + queue_next(); + } + + static unsigned get_bar_pos(DumbFramebuffer* fb, unsigned frame_num) + { + return (frame_num * bar_speed) % (fb->width() - bar_width + 1); + } + + void draw_bar(DumbFramebuffer* fb, unsigned frame_num) + { + int old_xpos = frame_num < s_num_buffers ? -1 : get_bar_pos(fb, frame_num - s_num_buffers); + int new_xpos = get_bar_pos(fb, frame_num); + + draw_color_bar(*fb, old_xpos, new_xpos, bar_width); + draw_text(*fb, fb->width() / 2, 0, to_string(frame_num), RGB(255, 255, 255)); + } + + void queue_next() + { + AtomicReq req(m_card); + + unsigned cur = m_frame_num % s_num_buffers; + + auto fb = m_fbs[cur]; + + draw_bar(fb, m_frame_num); + + req.add(m_plane, { + { "CRTC_ID", m_crtc->id() }, + { "FB_ID", fb->id() }, + + { "CRTC_X", 0 }, + { "CRTC_Y", 0 }, + { "CRTC_W", min((uint32_t)m_crtc->mode().hdisplay, fb->width()) }, + { "CRTC_H", min((uint32_t)m_crtc->mode().vdisplay, fb->height()) }, + + { "SRC_X", 0 }, + { "SRC_Y", 0 }, + { "SRC_W", fb->width() << 16 }, + { "SRC_H", fb->height() << 16 }, + }); + + int r = req.commit(this); + if (r) + EXIT("Flip commit failed: %d\n", r); + } + + static const unsigned s_num_buffers = 3; + + DumbFramebuffer* m_fbs[s_num_buffers]; + + Card& m_card; + Crtc* m_crtc; + Plane* m_plane; + + unsigned m_frame_num; + + static const unsigned bar_width = 20; + static const unsigned bar_speed = 8; +}; + +static const char* usage_str = + "Usage: wbcap [OPTIONS]\n\n" + "Options:\n" + " -s, --src=CONN Source connector\n" + " -d, --dst=CONN Destination connector\n" + " -m, --smode=MODE Source connector videomode\n" + " -M, --dmode=MODE Destination connector videomode\n" + " -f, --format=4CC Format\n" + " -w, --write Write captured frames to wbcap.raw file\n" + " -h, --help Print this help\n"; + +int main(int argc, char** argv) +{ + string src_conn_name; + string src_mode_name; + string dst_conn_name; + string dst_mode_name; + PixelFormat pixfmt = PixelFormat::XRGB8888; + bool write_file = false; + + OptionSet optionset = { + Option("s|src=", [&](string s) { + src_conn_name = s; + }), + Option("m|smode=", [&](string s) { + src_mode_name = s; + }), + Option("d|dst=", [&](string s) { + dst_conn_name = s; + }), + Option("M|dmode=", [&](string s) { + dst_mode_name = s; + }), + Option("f|format=", [&](string s) { + pixfmt = FourCCToPixelFormat(s); + }), + Option("w|write", [&]() { + write_file = true; + }), + Option("h|help", [&]() { + puts(usage_str); + exit(-1); + }), + }; + + optionset.parse(argc, argv); + + if (optionset.params().size() > 0) { + puts(usage_str); + exit(-1); + } + + if (src_conn_name.empty()) + EXIT("No source connector defined"); + + if (dst_conn_name.empty()) + EXIT("No destination connector defined"); + + VideoDevice vid("/dev/video11"); + + Card card; + ResourceManager resman(card); + + card.disable_all(); + + auto src_conn = resman.reserve_connector(src_conn_name); + auto src_crtc = resman.reserve_crtc(src_conn); + auto src_plane = resman.reserve_generic_plane(src_crtc, pixfmt); + FAIL_IF(!src_plane, "Plane not found"); + Videomode src_mode = src_mode_name.empty() ? src_conn->get_default_mode() : src_conn->get_mode(src_mode_name); + src_crtc->set_mode(src_conn, src_mode); + + auto dst_conn = resman.reserve_connector(dst_conn_name); + auto dst_crtc = resman.reserve_crtc(dst_conn); + auto dst_plane = resman.reserve_overlay_plane(dst_crtc, pixfmt); + FAIL_IF(!dst_plane, "Plane not found"); + Videomode dst_mode = dst_mode_name.empty() ? dst_conn->get_default_mode() : dst_conn->get_mode(dst_mode_name); + dst_crtc->set_mode(dst_conn, dst_mode); + + uint32_t src_width = src_mode.hdisplay; + uint32_t src_height = src_mode.vdisplay; + + uint32_t dst_width = src_mode.hdisplay; + uint32_t dst_height = src_mode.vdisplay; + if (src_mode.interlace()) + dst_height /= 2; + + printf("src %s, crtc %s\n", src_conn->fullname().c_str(), src_mode.to_string_short().c_str()); + + printf("dst %s, crtc %s\n", dst_conn->fullname().c_str(), dst_mode.to_string_short().c_str()); + + printf("src_fb %ux%u, dst_fb %ux%u\n", src_width, src_height, dst_width, dst_height); + + for (int i = 0; i < CAMERA_BUF_QUEUE_SIZE; ++i) { + auto fb = new DumbFramebuffer(card, dst_width, dst_height, pixfmt); + s_fbs.push_back(fb); + s_free_fbs.push_back(fb); + } + + // get one fb for initial setup + s_ready_fbs.push_back(s_free_fbs.back()); + s_free_fbs.pop_back(); + + // This draws a moving bar to SRC display + BarFlipState barflipper(card, src_crtc, src_plane, src_width, src_height); + barflipper.start_flipping(); + + // This shows the captured SRC frames on DST display + WBFlipState wbflipper(card, dst_crtc, dst_plane); + + WBStreamer wb(vid.get_capture_streamer(), src_crtc, pixfmt); + wb.start_streaming(); + + vector fds(3); + + fds[0].fd = 0; + fds[0].events = POLLIN; + fds[1].fd = wb.fd(); + fds[1].events = POLLIN; + fds[2].fd = card.fd(); + fds[2].events = POLLIN; + + uint32_t dst_frame_num = 0; + + const string filename = "wbcap.raw"; + unique_ptr os; + if (write_file) + os = unique_ptr(new ofstream(filename, ofstream::binary)); + + while (true) { + int r = poll(fds.data(), fds.size(), -1); + ASSERT(r > 0); + + if (fds[0].revents != 0) + break; + + if (fds[1].revents) { + fds[1].revents = 0; + + DumbFramebuffer* fb = wb.Dequeue(); + + if (write_file) { + printf("Writing frame %u to %s\n", dst_frame_num, filename.c_str()); + + for (unsigned i = 0; i < fb->num_planes(); ++i) + os->write((char*)fb->map(i), fb->size(i)); + + dst_frame_num++; + } + + wbflipper.queue_next(); + } + + if (fds[2].revents) { + fds[2].revents = 0; + + card.call_page_flip_handlers(); + wb.Queue(); + } + } + + printf("exiting...\n"); +} diff --git a/utils/omap-wbm2m.cpp b/utils/omap-wbm2m.cpp new file mode 100644 index 0000000..a00fab2 --- /dev/null +++ b/utils/omap-wbm2m.cpp @@ -0,0 +1,200 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +const uint32_t NUM_SRC_BUFS = 2; +const uint32_t NUM_DST_BUFS = 2; + +using namespace std; +using namespace kms; + +static const char* usage_str = + "Usage: wbm2m [OPTIONS]\n\n" + "Options:\n" + " -f, --format=4CC Output format\n" + " -c, --crop=CROP CROP is ,-x\n" + " -h, --help Print this help\n"; + +const int bar_speed = 4; +const int bar_width = 10; + +static unsigned get_bar_pos(DumbFramebuffer* fb, unsigned frame_num) +{ + return (frame_num * bar_speed) % (fb->width() - bar_width + 1); +} + +static void read_frame(DumbFramebuffer* fb, unsigned frame_num) +{ + static map s_bar_pos_map; + + int old_pos = -1; + if (s_bar_pos_map.find(fb) != s_bar_pos_map.end()) + old_pos = s_bar_pos_map[fb]; + + int pos = get_bar_pos(fb, frame_num); + draw_color_bar(*fb, old_pos, pos, bar_width); + draw_text(*fb, fb->width() / 2, 0, to_string(frame_num), RGB(255, 255, 255)); + s_bar_pos_map[fb] = pos; +} + +static void parse_crop(const string& crop_str, uint32_t& c_left, uint32_t& c_top, + uint32_t& c_width, uint32_t& c_height) +{ + const regex crop_re("(\\d+),(\\d+)-(\\d+)x(\\d+)"); // 400,400-400x400 + + smatch sm; + if (!regex_match(crop_str, sm, crop_re)) + EXIT("Failed to parse crop option '%s'", crop_str.c_str()); + + c_left = stoul(sm[1]); + c_top = stoul(sm[2]); + c_width = stoul(sm[3]); + c_height = stoul(sm[4]); +} + +int main(int argc, char** argv) +{ + // XXX get from args + const uint32_t src_width = 800; + const uint32_t src_height = 480; + const auto src_fmt = PixelFormat::XRGB8888; + const uint32_t num_src_frames = 10; + + const uint32_t dst_width = 800; + const uint32_t dst_height = 480; + uint32_t c_top, c_left, c_width, c_height; + + auto dst_fmt = PixelFormat::XRGB8888; + bool use_selection = false; + + OptionSet optionset = { + Option("f|format=", [&](string s) { + dst_fmt = FourCCToPixelFormat(s); + }), + Option("c|crop=", [&](string s) { + parse_crop(s, c_left, c_top, c_width, c_height); + use_selection = true; + }), + Option("h|help", [&]() { + puts(usage_str); + exit(-1); + }), + }; + + optionset.parse(argc, argv); + + if (optionset.params().size() > 0) { + puts(usage_str); + exit(-1); + } + + printf("%ux%u-%s -> %ux%u-%s\n", src_width, src_height, PixelFormatToFourCC(src_fmt).c_str(), + dst_width, dst_height, PixelFormatToFourCC(dst_fmt).c_str()); + + const string filename = fmt::format("wb-out-{}x{}-{}.raw", dst_width, dst_height, + PixelFormatToFourCC(dst_fmt)); + + printf("writing to %s\n", filename.c_str()); + + VideoDevice vid("/dev/video10"); + + Card card; + + uint32_t src_frame_num = 0; + uint32_t dst_frame_num = 0; + + VideoStreamer* out = vid.get_output_streamer(); + VideoStreamer* in = vid.get_capture_streamer(); + + out->set_format(src_fmt, src_width, src_height); + in->set_format(dst_fmt, dst_width, dst_height); + + if (use_selection) { + out->set_selection(c_left, c_top, c_width, c_height); + printf("crop -> %u,%u-%ux%u\n", c_left, c_top, c_width, c_height); + } + + out->set_queue_size(NUM_SRC_BUFS); + in->set_queue_size(NUM_DST_BUFS); + + for (unsigned i = 0; i < min(NUM_SRC_BUFS, num_src_frames); ++i) { + auto fb = new DumbFramebuffer(card, src_width, src_height, src_fmt); + + read_frame(fb, src_frame_num++); + + out->queue(fb); + } + + for (unsigned i = 0; i < min(NUM_DST_BUFS, num_src_frames); ++i) { + auto fb = new DumbFramebuffer(card, dst_width, dst_height, dst_fmt); + in->queue(fb); + } + + vector fds(3); + + fds[0].fd = 0; + fds[0].events = POLLIN; + fds[1].fd = vid.fd(); + fds[1].events = POLLIN; + fds[2].fd = card.fd(); + fds[2].events = POLLIN; + + ofstream os(filename, ofstream::binary); + + out->stream_on(); + in->stream_on(); + + while (true) { + int r = poll(fds.data(), fds.size(), -1); + ASSERT(r > 0); + + if (fds[0].revents != 0) + break; + + if (fds[1].revents) { + fds[1].revents = 0; + + try { + DumbFramebuffer* dst_fb = in->dequeue(); + printf("Writing frame %u\n", dst_frame_num); + for (unsigned i = 0; i < dst_fb->num_planes(); ++i) + os.write((char*)dst_fb->map(i), dst_fb->size(i)); + in->queue(dst_fb); + + dst_frame_num++; + + if (dst_frame_num >= num_src_frames) + break; + + } catch (system_error& se) { + if (se.code() != errc::resource_unavailable_try_again) + FAIL("dequeue failed: %s", se.what()); + + break; + } + + DumbFramebuffer* src_fb = out->dequeue(); + + if (src_frame_num < num_src_frames) { + read_frame(src_fb, src_frame_num++); + out->queue(src_fb); + } + } + + if (fds[2].revents) { + fds[2].revents = 0; + } + } + + printf("exiting...\n"); +} diff --git a/utils/wbcap.cpp b/utils/wbcap.cpp deleted file mode 100644 index 8033869..0000000 --- a/utils/wbcap.cpp +++ /dev/null @@ -1,411 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include - -#define CAMERA_BUF_QUEUE_SIZE 5 - -using namespace std; -using namespace kms; - -static vector s_fbs; -static vector s_free_fbs; -static vector s_wb_fbs; -static vector s_ready_fbs; - -class WBStreamer -{ -public: - WBStreamer(VideoStreamer* streamer, Crtc* crtc, PixelFormat pixfmt) - : m_capdev(*streamer) - { - Videomode m = crtc->mode(); - - m_capdev.set_port(crtc->idx()); - m_capdev.set_format(pixfmt, m.hdisplay, m.vdisplay / (m.interlace() ? 2 : 1)); - m_capdev.set_queue_size(s_fbs.size()); - - for (auto fb : s_free_fbs) { - m_capdev.queue(fb); - s_wb_fbs.push_back(fb); - } - - s_free_fbs.clear(); - } - - ~WBStreamer() - { - } - - WBStreamer(const WBStreamer& other) = delete; - WBStreamer& operator=(const WBStreamer& other) = delete; - - int fd() const { return m_capdev.fd(); } - - void start_streaming() - { - m_capdev.stream_on(); - } - - void stop_streaming() - { - m_capdev.stream_off(); - } - - DumbFramebuffer* Dequeue() - { - auto fb = m_capdev.dequeue(); - - auto iter = find(s_wb_fbs.begin(), s_wb_fbs.end(), fb); - s_wb_fbs.erase(iter); - - s_ready_fbs.insert(s_ready_fbs.begin(), fb); - - return fb; - } - - void Queue() - { - if (s_free_fbs.size() == 0) - return; - - auto fb = s_free_fbs.back(); - s_free_fbs.pop_back(); - - m_capdev.queue(fb); - - s_wb_fbs.insert(s_wb_fbs.begin(), fb); - } - -private: - VideoStreamer& m_capdev; -}; - -class WBFlipState : private PageFlipHandlerBase -{ -public: - WBFlipState(Card& card, Crtc* crtc, Plane* plane) - : m_card(card), m_crtc(crtc), m_plane(plane) - { - auto fb = s_ready_fbs.back(); - s_ready_fbs.pop_back(); - - AtomicReq req(m_card); - - req.add(m_plane, "CRTC_ID", m_crtc->id()); - req.add(m_plane, "FB_ID", fb->id()); - - req.add(m_plane, "CRTC_X", 0); - req.add(m_plane, "CRTC_Y", 0); - req.add(m_plane, "CRTC_W", min((uint32_t)m_crtc->mode().hdisplay, fb->width())); - req.add(m_plane, "CRTC_H", min((uint32_t)m_crtc->mode().vdisplay, fb->height())); - - req.add(m_plane, "SRC_X", 0); - req.add(m_plane, "SRC_Y", 0); - req.add(m_plane, "SRC_W", fb->width() << 16); - req.add(m_plane, "SRC_H", fb->height() << 16); - - int r = req.commit_sync(); - FAIL_IF(r, "initial plane setup failed"); - - m_current_fb = fb; - } - - void queue_next() - { - if (m_queued_fb) - return; - - if (s_ready_fbs.size() == 0) - return; - - auto fb = s_ready_fbs.back(); - s_ready_fbs.pop_back(); - - AtomicReq req(m_card); - req.add(m_plane, "FB_ID", fb->id()); - - int r = req.commit(this); - if (r) - EXIT("Flip commit failed: %d\n", r); - - m_queued_fb = fb; - } - -private: - void handle_page_flip(uint32_t frame, double time) - { - if (m_queued_fb) { - if (m_current_fb) - s_free_fbs.insert(s_free_fbs.begin(), m_current_fb); - - m_current_fb = m_queued_fb; - m_queued_fb = nullptr; - } - - queue_next(); - } - - Card& m_card; - Crtc* m_crtc; - Plane* m_plane; - - DumbFramebuffer* m_current_fb = nullptr; - DumbFramebuffer* m_queued_fb = nullptr; -}; - -class BarFlipState : private PageFlipHandlerBase -{ -public: - BarFlipState(Card& card, Crtc* crtc, Plane* plane, uint32_t width, uint32_t height) - : m_card(card), m_crtc(crtc), m_plane(plane) - { - for (unsigned i = 0; i < s_num_buffers; ++i) - m_fbs[i] = new DumbFramebuffer(card, width, height, PixelFormat::XRGB8888); - } - - ~BarFlipState() - { - for (unsigned i = 0; i < s_num_buffers; ++i) - delete m_fbs[i]; - } - - void start_flipping() - { - m_frame_num = 0; - queue_next(); - } - -private: - void handle_page_flip(uint32_t frame, double time) - { - m_frame_num++; - queue_next(); - } - - static unsigned get_bar_pos(DumbFramebuffer* fb, unsigned frame_num) - { - return (frame_num * bar_speed) % (fb->width() - bar_width + 1); - } - - void draw_bar(DumbFramebuffer* fb, unsigned frame_num) - { - int old_xpos = frame_num < s_num_buffers ? -1 : get_bar_pos(fb, frame_num - s_num_buffers); - int new_xpos = get_bar_pos(fb, frame_num); - - draw_color_bar(*fb, old_xpos, new_xpos, bar_width); - draw_text(*fb, fb->width() / 2, 0, to_string(frame_num), RGB(255, 255, 255)); - } - - void queue_next() - { - AtomicReq req(m_card); - - unsigned cur = m_frame_num % s_num_buffers; - - auto fb = m_fbs[cur]; - - draw_bar(fb, m_frame_num); - - req.add(m_plane, { - { "CRTC_ID", m_crtc->id() }, - { "FB_ID", fb->id() }, - - { "CRTC_X", 0 }, - { "CRTC_Y", 0 }, - { "CRTC_W", min((uint32_t)m_crtc->mode().hdisplay, fb->width()) }, - { "CRTC_H", min((uint32_t)m_crtc->mode().vdisplay, fb->height()) }, - - { "SRC_X", 0 }, - { "SRC_Y", 0 }, - { "SRC_W", fb->width() << 16 }, - { "SRC_H", fb->height() << 16 }, - }); - - int r = req.commit(this); - if (r) - EXIT("Flip commit failed: %d\n", r); - } - - static const unsigned s_num_buffers = 3; - - DumbFramebuffer* m_fbs[s_num_buffers]; - - Card& m_card; - Crtc* m_crtc; - Plane* m_plane; - - unsigned m_frame_num; - - static const unsigned bar_width = 20; - static const unsigned bar_speed = 8; -}; - -static const char* usage_str = - "Usage: wbcap [OPTIONS]\n\n" - "Options:\n" - " -s, --src=CONN Source connector\n" - " -d, --dst=CONN Destination connector\n" - " -m, --smode=MODE Source connector videomode\n" - " -M, --dmode=MODE Destination connector videomode\n" - " -f, --format=4CC Format\n" - " -w, --write Write captured frames to wbcap.raw file\n" - " -h, --help Print this help\n"; - -int main(int argc, char** argv) -{ - string src_conn_name; - string src_mode_name; - string dst_conn_name; - string dst_mode_name; - PixelFormat pixfmt = PixelFormat::XRGB8888; - bool write_file = false; - - OptionSet optionset = { - Option("s|src=", [&](string s) { - src_conn_name = s; - }), - Option("m|smode=", [&](string s) { - src_mode_name = s; - }), - Option("d|dst=", [&](string s) { - dst_conn_name = s; - }), - Option("M|dmode=", [&](string s) { - dst_mode_name = s; - }), - Option("f|format=", [&](string s) { - pixfmt = FourCCToPixelFormat(s); - }), - Option("w|write", [&]() { - write_file = true; - }), - Option("h|help", [&]() { - puts(usage_str); - exit(-1); - }), - }; - - optionset.parse(argc, argv); - - if (optionset.params().size() > 0) { - puts(usage_str); - exit(-1); - } - - if (src_conn_name.empty()) - EXIT("No source connector defined"); - - if (dst_conn_name.empty()) - EXIT("No destination connector defined"); - - VideoDevice vid("/dev/video11"); - - Card card; - ResourceManager resman(card); - - card.disable_all(); - - auto src_conn = resman.reserve_connector(src_conn_name); - auto src_crtc = resman.reserve_crtc(src_conn); - auto src_plane = resman.reserve_generic_plane(src_crtc, pixfmt); - FAIL_IF(!src_plane, "Plane not found"); - Videomode src_mode = src_mode_name.empty() ? src_conn->get_default_mode() : src_conn->get_mode(src_mode_name); - src_crtc->set_mode(src_conn, src_mode); - - auto dst_conn = resman.reserve_connector(dst_conn_name); - auto dst_crtc = resman.reserve_crtc(dst_conn); - auto dst_plane = resman.reserve_overlay_plane(dst_crtc, pixfmt); - FAIL_IF(!dst_plane, "Plane not found"); - Videomode dst_mode = dst_mode_name.empty() ? dst_conn->get_default_mode() : dst_conn->get_mode(dst_mode_name); - dst_crtc->set_mode(dst_conn, dst_mode); - - uint32_t src_width = src_mode.hdisplay; - uint32_t src_height = src_mode.vdisplay; - - uint32_t dst_width = src_mode.hdisplay; - uint32_t dst_height = src_mode.vdisplay; - if (src_mode.interlace()) - dst_height /= 2; - - printf("src %s, crtc %s\n", src_conn->fullname().c_str(), src_mode.to_string_short().c_str()); - - printf("dst %s, crtc %s\n", dst_conn->fullname().c_str(), dst_mode.to_string_short().c_str()); - - printf("src_fb %ux%u, dst_fb %ux%u\n", src_width, src_height, dst_width, dst_height); - - for (int i = 0; i < CAMERA_BUF_QUEUE_SIZE; ++i) { - auto fb = new DumbFramebuffer(card, dst_width, dst_height, pixfmt); - s_fbs.push_back(fb); - s_free_fbs.push_back(fb); - } - - // get one fb for initial setup - s_ready_fbs.push_back(s_free_fbs.back()); - s_free_fbs.pop_back(); - - // This draws a moving bar to SRC display - BarFlipState barflipper(card, src_crtc, src_plane, src_width, src_height); - barflipper.start_flipping(); - - // This shows the captured SRC frames on DST display - WBFlipState wbflipper(card, dst_crtc, dst_plane); - - WBStreamer wb(vid.get_capture_streamer(), src_crtc, pixfmt); - wb.start_streaming(); - - vector fds(3); - - fds[0].fd = 0; - fds[0].events = POLLIN; - fds[1].fd = wb.fd(); - fds[1].events = POLLIN; - fds[2].fd = card.fd(); - fds[2].events = POLLIN; - - uint32_t dst_frame_num = 0; - - const string filename = "wbcap.raw"; - unique_ptr os; - if (write_file) - os = unique_ptr(new ofstream(filename, ofstream::binary)); - - while (true) { - int r = poll(fds.data(), fds.size(), -1); - ASSERT(r > 0); - - if (fds[0].revents != 0) - break; - - if (fds[1].revents) { - fds[1].revents = 0; - - DumbFramebuffer* fb = wb.Dequeue(); - - if (write_file) { - printf("Writing frame %u to %s\n", dst_frame_num, filename.c_str()); - - for (unsigned i = 0; i < fb->num_planes(); ++i) - os->write((char*)fb->map(i), fb->size(i)); - - dst_frame_num++; - } - - wbflipper.queue_next(); - } - - if (fds[2].revents) { - fds[2].revents = 0; - - card.call_page_flip_handlers(); - wb.Queue(); - } - } - - printf("exiting...\n"); -} diff --git a/utils/wbm2m.cpp b/utils/wbm2m.cpp deleted file mode 100644 index a00fab2..0000000 --- a/utils/wbm2m.cpp +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -const uint32_t NUM_SRC_BUFS = 2; -const uint32_t NUM_DST_BUFS = 2; - -using namespace std; -using namespace kms; - -static const char* usage_str = - "Usage: wbm2m [OPTIONS]\n\n" - "Options:\n" - " -f, --format=4CC Output format\n" - " -c, --crop=CROP CROP is ,-x\n" - " -h, --help Print this help\n"; - -const int bar_speed = 4; -const int bar_width = 10; - -static unsigned get_bar_pos(DumbFramebuffer* fb, unsigned frame_num) -{ - return (frame_num * bar_speed) % (fb->width() - bar_width + 1); -} - -static void read_frame(DumbFramebuffer* fb, unsigned frame_num) -{ - static map s_bar_pos_map; - - int old_pos = -1; - if (s_bar_pos_map.find(fb) != s_bar_pos_map.end()) - old_pos = s_bar_pos_map[fb]; - - int pos = get_bar_pos(fb, frame_num); - draw_color_bar(*fb, old_pos, pos, bar_width); - draw_text(*fb, fb->width() / 2, 0, to_string(frame_num), RGB(255, 255, 255)); - s_bar_pos_map[fb] = pos; -} - -static void parse_crop(const string& crop_str, uint32_t& c_left, uint32_t& c_top, - uint32_t& c_width, uint32_t& c_height) -{ - const regex crop_re("(\\d+),(\\d+)-(\\d+)x(\\d+)"); // 400,400-400x400 - - smatch sm; - if (!regex_match(crop_str, sm, crop_re)) - EXIT("Failed to parse crop option '%s'", crop_str.c_str()); - - c_left = stoul(sm[1]); - c_top = stoul(sm[2]); - c_width = stoul(sm[3]); - c_height = stoul(sm[4]); -} - -int main(int argc, char** argv) -{ - // XXX get from args - const uint32_t src_width = 800; - const uint32_t src_height = 480; - const auto src_fmt = PixelFormat::XRGB8888; - const uint32_t num_src_frames = 10; - - const uint32_t dst_width = 800; - const uint32_t dst_height = 480; - uint32_t c_top, c_left, c_width, c_height; - - auto dst_fmt = PixelFormat::XRGB8888; - bool use_selection = false; - - OptionSet optionset = { - Option("f|format=", [&](string s) { - dst_fmt = FourCCToPixelFormat(s); - }), - Option("c|crop=", [&](string s) { - parse_crop(s, c_left, c_top, c_width, c_height); - use_selection = true; - }), - Option("h|help", [&]() { - puts(usage_str); - exit(-1); - }), - }; - - optionset.parse(argc, argv); - - if (optionset.params().size() > 0) { - puts(usage_str); - exit(-1); - } - - printf("%ux%u-%s -> %ux%u-%s\n", src_width, src_height, PixelFormatToFourCC(src_fmt).c_str(), - dst_width, dst_height, PixelFormatToFourCC(dst_fmt).c_str()); - - const string filename = fmt::format("wb-out-{}x{}-{}.raw", dst_width, dst_height, - PixelFormatToFourCC(dst_fmt)); - - printf("writing to %s\n", filename.c_str()); - - VideoDevice vid("/dev/video10"); - - Card card; - - uint32_t src_frame_num = 0; - uint32_t dst_frame_num = 0; - - VideoStreamer* out = vid.get_output_streamer(); - VideoStreamer* in = vid.get_capture_streamer(); - - out->set_format(src_fmt, src_width, src_height); - in->set_format(dst_fmt, dst_width, dst_height); - - if (use_selection) { - out->set_selection(c_left, c_top, c_width, c_height); - printf("crop -> %u,%u-%ux%u\n", c_left, c_top, c_width, c_height); - } - - out->set_queue_size(NUM_SRC_BUFS); - in->set_queue_size(NUM_DST_BUFS); - - for (unsigned i = 0; i < min(NUM_SRC_BUFS, num_src_frames); ++i) { - auto fb = new DumbFramebuffer(card, src_width, src_height, src_fmt); - - read_frame(fb, src_frame_num++); - - out->queue(fb); - } - - for (unsigned i = 0; i < min(NUM_DST_BUFS, num_src_frames); ++i) { - auto fb = new DumbFramebuffer(card, dst_width, dst_height, dst_fmt); - in->queue(fb); - } - - vector fds(3); - - fds[0].fd = 0; - fds[0].events = POLLIN; - fds[1].fd = vid.fd(); - fds[1].events = POLLIN; - fds[2].fd = card.fd(); - fds[2].events = POLLIN; - - ofstream os(filename, ofstream::binary); - - out->stream_on(); - in->stream_on(); - - while (true) { - int r = poll(fds.data(), fds.size(), -1); - ASSERT(r > 0); - - if (fds[0].revents != 0) - break; - - if (fds[1].revents) { - fds[1].revents = 0; - - try { - DumbFramebuffer* dst_fb = in->dequeue(); - printf("Writing frame %u\n", dst_frame_num); - for (unsigned i = 0; i < dst_fb->num_planes(); ++i) - os.write((char*)dst_fb->map(i), dst_fb->size(i)); - in->queue(dst_fb); - - dst_frame_num++; - - if (dst_frame_num >= num_src_frames) - break; - - } catch (system_error& se) { - if (se.code() != errc::resource_unavailable_try_again) - FAIL("dequeue failed: %s", se.what()); - - break; - } - - DumbFramebuffer* src_fb = out->dequeue(); - - if (src_frame_num < num_src_frames) { - read_frame(src_fb, src_frame_num++); - out->queue(src_fb); - } - } - - if (fds[2].revents) { - fds[2].revents = 0; - } - } - - printf("exiting...\n"); -} -- cgit v1.2.3