X-Git-Url: https://git.sesse.net/?p=nageru;a=blobdiff_plain;f=cef_capture.cpp;fp=cef_capture.cpp;h=c05c2953deff7cc3837f1f203917eee8f734b843;hp=0000000000000000000000000000000000000000;hb=b68d8a25951faf5b967b7a35fa0a363b4b68fbc0;hpb=25ea462c2847313afd702cea1db29199b845fbd4 diff --git a/cef_capture.cpp b/cef_capture.cpp new file mode 100644 index 0000000..c05c295 --- /dev/null +++ b/cef_capture.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include + +#include "cef_capture.h" +#include "nageru_cef_app.h" + +#undef CHECK +#include +#include +#include + +#include "bmusb/bmusb.h" + +using namespace std; +using namespace std::chrono; +using namespace bmusb; + +extern CefRefPtr cef_app; + +CEFCapture::CEFCapture(const string &url, unsigned width, unsigned height) + : cef_client(new NageruCEFClient(width, height, this)), + width(width), + height(height), + start_url(url) +{ + char buf[256]; + snprintf(buf, sizeof(buf), "CEF card %d", card_index + 1); + description = buf; +} + +CEFCapture::~CEFCapture() +{ + if (has_dequeue_callbacks) { + dequeue_cleanup_callback(); + } +} + +void CEFCapture::OnPaint(const void *buffer, int width, int height) +{ + steady_clock::time_point timestamp = steady_clock::now(); + + VideoFormat video_format; + video_format.width = width; + video_format.height = height; + video_format.stride = width * 4; + video_format.frame_rate_nom = 60; // FIXME + video_format.frame_rate_den = 1; + video_format.has_signal = true; + video_format.is_connected = true; + + FrameAllocator::Frame video_frame = video_frame_allocator->alloc_frame(); + if (video_frame.data != nullptr) { + assert(video_frame.size >= unsigned(width * height * 4)); + assert(!video_frame.interleaved); + memcpy(video_frame.data, buffer, width * height * 4); + video_frame.len = video_format.stride * height; + video_frame.received_timestamp = timestamp; + } + frame_callback(timecode++, + video_frame, 0, video_format, + FrameAllocator::Frame(), 0, AudioFormat()); +} + +#define FRAME_SIZE (8 << 20) // 8 MB. + +void CEFCapture::configure_card() +{ + if (video_frame_allocator == nullptr) { + owned_video_frame_allocator.reset(new MallocFrameAllocator(FRAME_SIZE, NUM_QUEUED_VIDEO_FRAMES)); + set_video_frame_allocator(owned_video_frame_allocator.get()); + } +} + +void CEFCapture::start_bm_capture() +{ + cef_app->initialize_cef(); + + CefBrowserSettings browser_settings; + browser_settings.web_security = cef_state_t::STATE_DISABLED; + browser_settings.webgl = cef_state_t::STATE_ENABLED; + browser_settings.windowless_frame_rate = 60; + + CefWindowInfo window_info; + window_info.SetAsWindowless(0); + CefBrowserHost::CreateBrowser(window_info, cef_client, start_url, browser_settings, nullptr); +} + +void CEFCapture::stop_dequeue_thread() +{ + lock_guard lock(browser_mutex); + cef_app->close_browser(browser); + browser = nullptr; // Or unref_cef() will be sad. + cef_app->unref_cef(); +} + +std::map CEFCapture::get_available_video_modes() const +{ + VideoMode mode; + + char buf[256]; + snprintf(buf, sizeof(buf), "%ux%u", width, height); + mode.name = buf; + + mode.autodetect = false; + mode.width = width; + mode.height = height; + mode.frame_rate_num = 60; // FIXME + mode.frame_rate_den = 1; + mode.interlaced = false; + + return {{ 0, mode }}; +} + +std::map CEFCapture::get_available_video_inputs() const +{ + return {{ 0, "HTML video input" }}; +} + +std::map CEFCapture::get_available_audio_inputs() const +{ + return {{ 0, "Fake HTML audio input (silence)" }}; +} + +void CEFCapture::set_video_mode(uint32_t video_mode_id) +{ + assert(video_mode_id == 0); +} + +void CEFCapture::set_video_input(uint32_t video_input_id) +{ + assert(video_input_id == 0); +} + +void CEFCapture::set_audio_input(uint32_t audio_input_id) +{ + assert(audio_input_id == 0); +} + +void NageruCEFClient::OnPaint(CefRefPtr browser, PaintElementType type, const RectList &dirtyRects, const void *buffer, int width, int height) +{ + parent->OnPaint(buffer, width, height); +} + +bool NageruCEFClient::GetViewRect(CefRefPtr browser, CefRect &rect) +{ + rect = CefRect(0, 0, width, height); + return true; +}