int BrowserManager::Impl::CreateBrowser( const BrowserSettings &browserSettings, const std::shared_ptr<BrowserListener> &browserListener) { int browserIdentifier = 0; os_event_t *createdEvent; os_event_init(&createdEvent, OS_EVENT_TYPE_AUTO); CefPostTask(TID_UI, BrowserTask::newTask( [&] { CefRefPtr<BrowserRenderHandler> renderHandler( new BrowserRenderHandler(browserSettings.width, browserSettings.height, browserListener)); CefRefPtr<BrowserLoadHandler> loadHandler( new BrowserLoadHandler(browserSettings.css)); CefRefPtr<BrowserClient> browserClient( new BrowserClient(renderHandler,loadHandler)); CefWindowInfo windowInfo; windowInfo.transparent_painting_enabled = true; windowInfo.width = browserSettings.width; windowInfo.height = browserSettings.height; windowInfo.windowless_rendering_enabled = true; CefBrowserSettings cefBrowserSettings; cefBrowserSettings.windowless_frame_rate = browserSettings.fps; CefRefPtr<CefBrowser> browser = CefBrowserHost::CreateBrowserSync(windowInfo, browserClient, browserSettings.url, cefBrowserSettings, nullptr); if (browser != nullptr) { browserIdentifier = browser->GetIdentifier(); browserMap[browserIdentifier] = browser; } os_event_signal(createdEvent); })); os_event_wait(createdEvent); os_event_destroy(createdEvent); return browserIdentifier; }
int video_output_open(video_t *video, struct video_output_info *info) { struct video_output *out; if (!valid_video_params(info)) return VIDEO_OUTPUT_INVALIDPARAM; out = bzalloc(sizeof(struct video_output)); memcpy(&out->info, info, sizeof(struct video_output_info)); out->frame_time = (uint64_t)(1000000000.0 * (double)info->fps_den / (double)info->fps_num); out->initialized = false; if (pthread_mutex_init(&out->data_mutex, NULL) != 0) goto fail; if (pthread_mutex_init(&out->input_mutex, NULL) != 0) goto fail; if (os_event_init(&out->stop_event, OS_EVENT_TYPE_MANUAL) != 0) goto fail; if (os_event_init(&out->update_event, OS_EVENT_TYPE_AUTO) != 0) goto fail; if (pthread_create(&out->thread, NULL, video_thread, out) != 0) goto fail; out->initialized = true; *video = out; return VIDEO_OUTPUT_SUCCESS; fail: video_output_close(out); return VIDEO_OUTPUT_FAIL; }
static void *rtmp_stream_create(obs_data_t *settings, obs_output_t *output) { struct rtmp_stream *stream = bzalloc(sizeof(struct rtmp_stream)); stream->output = output; pthread_mutex_init_value(&stream->packets_mutex); RTMP_Init(&stream->rtmp); RTMP_LogSetCallback(log_rtmp); RTMP_LogSetLevel(RTMP_LOGWARNING); if (pthread_mutex_init(&stream->packets_mutex, NULL) != 0) goto fail; if (os_event_init(&stream->stop_event, OS_EVENT_TYPE_MANUAL) != 0) goto fail; if (pthread_mutex_init(&stream->write_buf_mutex, NULL) != 0) { warn("Failed to initialize write buffer mutex"); goto fail; } if (os_event_init(&stream->buffer_space_available_event, OS_EVENT_TYPE_AUTO) != 0) { warn("Failed to initialize write buffer event"); goto fail; } if (os_event_init(&stream->buffer_has_data_event, OS_EVENT_TYPE_AUTO) != 0) { warn("Failed to initialize data buffer event"); goto fail; } if (os_event_init(&stream->socket_available_event, OS_EVENT_TYPE_AUTO) != 0) { warn("Failed to initialize socket buffer event"); goto fail; } if (os_event_init(&stream->send_thread_signaled_exit, OS_EVENT_TYPE_MANUAL) != 0) { warn("Failed to initialize socket exit event"); goto fail; } UNUSED_PARAMETER(settings); return stream; fail: rtmp_stream_destroy(stream); return NULL; }
/* * Create the plugin object */ static void *pulse_create(obs_data_t settings, obs_source_t source) { UNUSED_PARAMETER(settings); struct pulse_data *data = bmalloc(sizeof(struct pulse_data)); memset(data, 0, sizeof(struct pulse_data)); data->source = source; data->speakers = SPEAKERS_STEREO; blog(LOG_DEBUG, "pulse-input: obs wants '%s'", obs_data_getstring(settings, "device_id")); /* TODO: use obs-studio icon */ data->props = pa_proplist_new(); pa_proplist_sets(data->props, PA_PROP_APPLICATION_NAME, "OBS Studio"); pa_proplist_sets(data->props, PA_PROP_APPLICATION_ICON_NAME, "application-exit"); pa_proplist_sets(data->props, PA_PROP_MEDIA_ROLE, "production"); if (os_event_init(&data->event, OS_EVENT_TYPE_MANUAL) != 0) goto fail; if (pthread_create(&data->thread, NULL, pulse_thread, data) != 0) goto fail; return data; fail: pulse_destroy(data); return NULL; }
obs_output_t *obs_output_create(const char *id, const char *name, obs_data_t *settings, obs_data_t *hotkey_data) { const struct obs_output_info *info = find_output(id); struct obs_output *output; int ret; output = bzalloc(sizeof(struct obs_output)); pthread_mutex_init_value(&output->interleaved_mutex); pthread_mutex_init_value(&output->delay_mutex); if (pthread_mutex_init(&output->interleaved_mutex, NULL) != 0) goto fail; if (pthread_mutex_init(&output->delay_mutex, NULL) != 0) goto fail; if (!init_output_handlers(output, name, settings, hotkey_data)) goto fail; if (!info) { blog(LOG_ERROR, "Output ID '%s' not found", id); output->info.id = bstrdup(id); output->owns_info_id = true; } else { output->info = *info; } output->video = obs_get_video(); output->audio = obs_get_audio(); if (output->info.get_defaults) output->info.get_defaults(output->context.settings); ret = os_event_init(&output->reconnect_stop_event, OS_EVENT_TYPE_MANUAL); if (ret < 0) goto fail; if (info) output->context.data = info->create(output->context.settings, output); if (!output->context.data) blog(LOG_ERROR, "Failed to create output '%s'!", name); output->reconnect_retry_sec = 2; output->reconnect_retry_max = 20; output->valid = true; output->control = bzalloc(sizeof(obs_weak_output_t)); output->control->output = output; obs_context_data_insert(&output->context, &obs->data.outputs_mutex, &obs->data.first_output); blog(LOG_INFO, "output '%s' (%s) created", name, id); return output; fail: obs_output_destroy(output); return NULL; }
obs_output_t obs_output_create(const char *id, const char *name, obs_data_t settings) { const struct obs_output_info *info = find_output(id); struct obs_output *output; int ret; if (!info) { blog(LOG_ERROR, "Output '%s' not found", id); return NULL; } output = bzalloc(sizeof(struct obs_output)); pthread_mutex_init_value(&output->interleaved_mutex); if (pthread_mutex_init(&output->interleaved_mutex, NULL) != 0) goto fail; if (!init_output_handlers(output, name, settings)) goto fail; output->info = *info; output->video = obs_video(); output->audio = obs_audio(); if (output->info.defaults) output->info.defaults(output->context.settings); ret = os_event_init(&output->reconnect_stop_event, OS_EVENT_TYPE_MANUAL); if (ret < 0) goto fail; output->context.data = info->create(output->context.settings, output); if (!output->context.data) goto fail; output->reconnect_retry_sec = 2; output->reconnect_retry_max = 20; output->valid = true; obs_context_data_insert(&output->context, &obs->data.outputs_mutex, &obs->data.first_output); return output; fail: obs_output_destroy(output); return NULL; }
void BrowserManager::Impl::DestroyBrowser(int browserIdentifier) { if (browserMap.count(browserIdentifier) > 0) { CefRefPtr<CefBrowser> browser = browserMap[browserIdentifier]; os_event_t *closeEvent; os_event_init(&closeEvent, OS_EVENT_TYPE_AUTO); CefPostTask(TID_UI, BrowserTask::newTask([&, browser] { browser->GetHost()->CloseBrowser(true); os_event_signal(closeEvent); })); os_event_wait(closeEvent); os_event_destroy(closeEvent); browserMap.erase(browserIdentifier); } }
static void *sinewave_create(obs_data_t settings, obs_source_t source) { struct sinewave_data *swd = bzalloc(sizeof(struct sinewave_data)); swd->source = source; if (os_event_init(&swd->event, OS_EVENT_TYPE_MANUAL) != 0) goto fail; if (pthread_create(&swd->thread, NULL, sinewave_thread, swd) != 0) goto fail; swd->initialized_thread = true; UNUSED_PARAMETER(settings); return swd; fail: sinewave_destroy(swd); return NULL; }
void BrowserManager::Impl::Shutdown() { os_event_t *shutdown_event; os_event_init(&shutdown_event, OS_EVENT_TYPE_AUTO); // post the task CefPostTask(TID_UI, BrowserTask::newTask([] { CefQuitMessageLoop(); })); // this event will then get processed and shut down the dispatcher loop PushEvent([this, shutdown_event] { threadAlive = false; os_event_signal(shutdown_event); }); os_event_wait(shutdown_event); os_event_destroy(shutdown_event); return; }
int audio_output_open(audio_t *audio, struct audio_output_info *info) { struct audio_output *out; pthread_mutexattr_t attr; bool planar = is_audio_planar(info->format); if (!valid_audio_params(info)) return AUDIO_OUTPUT_INVALIDPARAM; out = bzalloc(sizeof(struct audio_output)); if (!out) goto fail; memcpy(&out->info, info, sizeof(struct audio_output_info)); pthread_mutex_init_value(&out->line_mutex); out->channels = get_audio_channels(info->speakers); out->planes = planar ? out->channels : 1; out->block_size = (planar ? 1 : out->channels) * get_audio_bytes_per_channel(info->format); if (pthread_mutexattr_init(&attr) != 0) goto fail; if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) goto fail; if (pthread_mutex_init(&out->line_mutex, &attr) != 0) goto fail; if (pthread_mutex_init(&out->input_mutex, NULL) != 0) goto fail; if (os_event_init(&out->stop_event, OS_EVENT_TYPE_MANUAL) != 0) goto fail; if (pthread_create(&out->thread, NULL, audio_thread, out) != 0) goto fail; out->initialized = true; *audio = out; return AUDIO_OUTPUT_SUCCESS; fail: audio_output_close(out); return AUDIO_OUTPUT_FAIL; }
static void *rtmp_stream_create(obs_data_t *settings, obs_output_t *output) { struct rtmp_stream *stream = bzalloc(sizeof(struct rtmp_stream)); stream->output = output; pthread_mutex_init_value(&stream->packets_mutex); RTMP_Init(&stream->rtmp); RTMP_LogSetCallback(log_rtmp); RTMP_LogSetLevel(RTMP_LOGWARNING); if (pthread_mutex_init(&stream->packets_mutex, NULL) != 0) goto fail; if (os_event_init(&stream->stop_event, OS_EVENT_TYPE_MANUAL) != 0) goto fail; UNUSED_PARAMETER(settings); return stream; fail: rtmp_stream_destroy(stream); return NULL; }
void BrowserManager::Impl::ExecuteOnBrowser(int browserIdentifier, std::function<void(CefRefPtr<CefBrowser>)> f, bool async) { if (browserMap.count(browserIdentifier) > 0) { CefRefPtr<CefBrowser> browser = browserMap[browserIdentifier]; if (async) { CefPostTask(TID_UI, BrowserTask::newTask([&] { f(browser); })); } else { os_event_t *finishedEvent; os_event_init(&finishedEvent, OS_EVENT_TYPE_AUTO); CefPostTask(TID_UI, BrowserTask::newTask([&] { f(browser); os_event_signal(finishedEvent); })); os_event_wait(finishedEvent); os_event_destroy(finishedEvent); } } }
/** * Initialize the v4l2 device * * This function: * - tries to open the device * - sets pixelformat and requested resolution * - sets the requested framerate * - maps the buffers * - starts the capture thread */ static void v4l2_init(struct v4l2_data *data) { uint32_t input_caps; int fps_num, fps_denom; blog(LOG_INFO, "Start capture from %s", data->device_id); data->dev = v4l2_open(data->device_id, O_RDWR | O_NONBLOCK); if (data->dev == -1) { blog(LOG_ERROR, "Unable to open device"); goto fail; } /* set input */ if (v4l2_set_input(data->dev, &data->input) < 0) { blog(LOG_ERROR, "Unable to set input %d", data->input); goto fail; } blog(LOG_INFO, "Input: %d", data->input); if (v4l2_get_input_caps(data->dev, -1, &input_caps) < 0) { blog(LOG_ERROR, "Unable to get input capabilities"); goto fail; } /* set video standard if supported */ if (input_caps & V4L2_IN_CAP_STD) { if (v4l2_set_standard(data->dev, &data->standard) < 0) { blog(LOG_ERROR, "Unable to set video standard"); goto fail; } data->resolution = -1; data->framerate = -1; } /* set dv timing if supported */ if (input_caps & V4L2_IN_CAP_DV_TIMINGS) { if (v4l2_set_dv_timing(data->dev, &data->dv_timing) < 0) { blog(LOG_ERROR, "Unable to set dv timing"); goto fail; } data->resolution = -1; data->framerate = -1; } /* set pixel format and resolution */ if (v4l2_set_format(data->dev, &data->resolution, &data->pixfmt, &data->linesize) < 0) { blog(LOG_ERROR, "Unable to set format"); goto fail; } if (v4l2_to_obs_video_format(data->pixfmt) == VIDEO_FORMAT_NONE) { blog(LOG_ERROR, "Selected video format not supported"); goto fail; } v4l2_unpack_tuple(&data->width, &data->height, data->resolution); blog(LOG_INFO, "Resolution: %dx%d", data->width, data->height); blog(LOG_INFO, "Pixelformat: %s", V4L2_FOURCC_STR(data->pixfmt)); blog(LOG_INFO, "Linesize: %d Bytes", data->linesize); /* set framerate */ if (v4l2_set_framerate(data->dev, &data->framerate) < 0) { blog(LOG_ERROR, "Unable to set framerate"); goto fail; } v4l2_unpack_tuple(&fps_num, &fps_denom, data->framerate); blog(LOG_INFO, "Framerate: %.2f fps", (float) fps_denom / fps_num); /* map buffers */ if (v4l2_create_mmap(data->dev, &data->buffers) < 0) { blog(LOG_ERROR, "Failed to map buffers"); goto fail; } /* start the capture thread */ if (os_event_init(&data->event, OS_EVENT_TYPE_MANUAL) != 0) goto fail; if (pthread_create(&data->thread, NULL, v4l2_thread, data) != 0) goto fail; return; fail: blog(LOG_ERROR, "Initialization failed"); v4l2_terminate(data); }
BrowserManager::Impl::~Impl() { os_event_init(&dispatchEvent, OS_EVENT_TYPE_AUTO); pthread_mutex_init(&dispatchLock, nullptr); }