static bool update_remote_files(void *param, obs_data_t *remote_file) { struct update_info *info = param; struct file_update_data data = { .name = obs_data_get_string(remote_file, "name"), .version = (int)obs_data_get_int(remote_file, "version") }; enum_files(info->cache_package, newer_than_cache, &data); if (!data.newer && data.found) return true; if (!do_relative_http_request(info, info->remote_url, data.name)) return true; if (info->callback) { struct file_download_data download_data; bool confirm; download_data.name = data.name; download_data.version = data.version; download_data.buffer.da = info->file_data.da; confirm = info->callback(info->param, &download_data); info->file_data.da = download_data.buffer.da; if (!confirm) { info("Update file '%s' (version %d) rejected", data.name, data.version); return true; } } write_file_data(info, info->temp, data.name); replace_file(info->temp, info->cache, data.name); info("Successfully updated file '%s' (version %d)", data.name, data.version); return true; } static void update_save_metadata(struct update_info *info) { struct dstr path = { 0 }; if (!info->etag_remote) return; dstr_copy(&path, info->cache); dstr_cat(&path, "meta.json"); obs_data_t *data; data = obs_data_create(); obs_data_set_string(data, "etag", info->etag_remote); obs_data_save_json(data, path.array); obs_data_release(data); } static void update_remote_version(struct update_info *info, int cur_version) { int remote_version; long response_code; if (!do_http_request(info, info->url, &response_code)) return; if (response_code == 304) return; if (!info->file_data.array || info->file_data.array[0] != '{') { warn("Remote package does not exist or is not valid json"); return; } update_save_metadata(info); info->remote_package = obs_data_create_from_json( (char*)info->file_data.array); if (!info->remote_package) { warn("Failed to initialize remote package json"); return; } remote_version = (int)obs_data_get_int(info->remote_package, "version"); if (remote_version <= cur_version) return; write_file_data(info, info->temp, "package.json"); info->remote_url = obs_data_get_string(info->remote_package, "url"); if (!info->remote_url) { warn("No remote url in package file"); return; } /* download new files */ enum_files(info->remote_package, update_remote_files, info); replace_file(info->temp, info->cache, "package.json"); info("Successfully updated package (version %d)", remote_version); return; }
static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) { video_t *video = obs_encoder_video(obsqsv->encoder); const struct video_output_info *voi = video_output_get_info(video); const char *target_usage = obs_data_get_string(settings, "target_usage"); const char *profile = obs_data_get_string(settings, "profile"); const char *rate_control = obs_data_get_string(settings, "rate_control"); int async_depth = (int)obs_data_get_int(settings, "async_depth"); int target_bitrate = (int)obs_data_get_int(settings, "bitrate"); int max_bitrate = (int)obs_data_get_int(settings, "max_bitrate"); int accuracy = (int)obs_data_get_int(settings, "accuracy"); int convergence = (int)obs_data_get_int(settings, "convergence"); int qpi = (int)obs_data_get_int(settings, "qpi"); int qpp = (int)obs_data_get_int(settings, "qpp"); int qpb = (int)obs_data_get_int(settings, "qpb"); int icq_quality = (int)obs_data_get_int(settings, "icq_quality"); int la_depth = (int)obs_data_get_int(settings, "la_depth"); int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec"); bool cbr_override = obs_data_get_bool(settings, "cbr"); int bFrames = 7; if (obs_data_has_user_value(settings, "bf")) bFrames = (int)obs_data_get_int(settings, "bf"); int width = (int)obs_encoder_get_width(obsqsv->encoder); int height = (int)obs_encoder_get_height(obsqsv->encoder); if (astrcmpi(target_usage, "quality") == 0) obsqsv->params.nTargetUsage = MFX_TARGETUSAGE_BEST_QUALITY; else if (astrcmpi(target_usage, "balanced") == 0) obsqsv->params.nTargetUsage = MFX_TARGETUSAGE_BALANCED; else if (astrcmpi(target_usage, "speed") == 0) obsqsv->params.nTargetUsage = MFX_TARGETUSAGE_BEST_SPEED; if (astrcmpi(profile, "baseline") == 0) obsqsv->params.nCodecProfile = MFX_PROFILE_AVC_BASELINE; else if (astrcmpi(profile, "main") == 0) obsqsv->params.nCodecProfile = MFX_PROFILE_AVC_MAIN; else if (astrcmpi(profile, "high") == 0) obsqsv->params.nCodecProfile = MFX_PROFILE_AVC_HIGH; /* internal convenience parameter, overrides rate control param * XXX: Deprecated */ if (cbr_override) { warn("\"cbr\" setting has been deprecated for all encoders! " "Please set \"rate_control\" to \"CBR\" instead. " "Forcing CBR mode. " "(Note to all: this is why you shouldn't use strings for " "common settings)"); rate_control = "CBR"; } if (astrcmpi(rate_control, "CBR") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_CBR; else if (astrcmpi(rate_control, "VBR") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_VBR; else if (astrcmpi(rate_control, "VCM") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_VCM; else if (astrcmpi(rate_control, "CQP") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_CQP; else if (astrcmpi(rate_control, "AVBR") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_AVBR; else if (astrcmpi(rate_control, "ICQ") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_ICQ; else if (astrcmpi(rate_control, "LA_ICQ") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_LA_ICQ; else if (astrcmpi(rate_control, "LA") == 0) obsqsv->params.nRateControl = MFX_RATECONTROL_LA; obsqsv->params.nAsyncDepth = (mfxU16)async_depth; obsqsv->params.nAccuracy = (mfxU16)accuracy; obsqsv->params.nConvergence = (mfxU16)convergence; obsqsv->params.nQPI = (mfxU16)qpi; obsqsv->params.nQPP = (mfxU16)qpp; obsqsv->params.nQPB = (mfxU16)qpb; obsqsv->params.nLADEPTH = (mfxU16)la_depth; obsqsv->params.nTargetBitRate = (mfxU16)target_bitrate; obsqsv->params.nMaxBitRate = (mfxU16)max_bitrate; obsqsv->params.nWidth = (mfxU16)width; obsqsv->params.nHeight = (mfxU16)height; obsqsv->params.nFpsNum = (mfxU16)voi->fps_num; obsqsv->params.nFpsDen = (mfxU16)voi->fps_den; obsqsv->params.nbFrames = (mfxU16)bFrames; obsqsv->params.nKeyIntSec = (mfxU16)keyint_sec; obsqsv->params.nICQQuality = (mfxU16)icq_quality; info("settings:\n\trate_control: %s", rate_control); if (obsqsv->params.nRateControl != MFX_RATECONTROL_LA_ICQ && obsqsv->params.nRateControl != MFX_RATECONTROL_ICQ && obsqsv->params.nRateControl != MFX_RATECONTROL_CQP) blog(LOG_INFO, "\ttarget_bitrate: %d", (int)obsqsv->params.nTargetBitRate); if (obsqsv->params.nRateControl == MFX_RATECONTROL_VBR || obsqsv->params.nRateControl == MFX_RATECONTROL_VCM) blog(LOG_INFO, "\tmax_bitrate: %d", (int)obsqsv->params.nMaxBitRate); if (obsqsv->params.nRateControl == MFX_RATECONTROL_LA_ICQ || obsqsv->params.nRateControl == MFX_RATECONTROL_ICQ) blog(LOG_INFO, "\tICQ Quality: %d", (int)obsqsv->params.nICQQuality); if (obsqsv->params.nRateControl == MFX_RATECONTROL_LA_ICQ || obsqsv->params.nRateControl == MFX_RATECONTROL_LA) blog(LOG_INFO, "\tLookahead Depth:%d", (int)obsqsv->params.nLADEPTH); if (obsqsv->params.nRateControl == MFX_RATECONTROL_CQP) blog(LOG_INFO, "\tqpi: %d\n" "\tqpb: %d\n" "\tqpp: %d", qpi, qpb, qpp); blog(LOG_INFO, "\tfps_num: %d\n" "\tfps_den: %d\n" "\twidth: %d\n" "\theight: %d", voi->fps_num, voi->fps_den, width, height); info("debug info:"); }
static bool audio_monitor_init(struct audio_monitor *monitor, obs_source_t *source) { IMMDeviceEnumerator *immde = NULL; WAVEFORMATEX *wfex = NULL; bool success = false; UINT32 frames; HRESULT hr; pthread_mutex_init_value(&monitor->playback_mutex); monitor->source = source; const char *id = obs->audio.monitoring_device_id; if (!id) { return false; } if (source->info.output_flags & OBS_SOURCE_DO_NOT_SELF_MONITOR) { obs_data_t *s = obs_source_get_settings(source); const char *s_dev_id = obs_data_get_string(s, "device_id"); bool match = devices_match(s_dev_id, id); obs_data_release(s); if (match) { monitor->ignore = true; return true; } } /* ------------------------------------------ * * Init device */ hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void**)&immde); if (FAILED(hr)) { return false; } if (strcmp(id, "default") == 0) { hr = immde->lpVtbl->GetDefaultAudioEndpoint(immde, eRender, eConsole, &monitor->device); } else { wchar_t w_id[512]; os_utf8_to_wcs(id, 0, w_id, 512); hr = immde->lpVtbl->GetDevice(immde, w_id, &monitor->device); } if (FAILED(hr)) { goto fail; } /* ------------------------------------------ * * Init client */ hr = monitor->device->lpVtbl->Activate(monitor->device, &IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&monitor->client); if (FAILED(hr)) { goto fail; } hr = monitor->client->lpVtbl->GetMixFormat(monitor->client, &wfex); if (FAILED(hr)) { goto fail; } hr = monitor->client->lpVtbl->Initialize(monitor->client, AUDCLNT_SHAREMODE_SHARED, 0, 10000000, 0, wfex, NULL); if (FAILED(hr)) { goto fail; } /* ------------------------------------------ * * Init resampler */ const struct audio_output_info *info = audio_output_get_info( obs->audio.audio); WAVEFORMATEXTENSIBLE *ext = (WAVEFORMATEXTENSIBLE*)wfex; struct resample_info from; struct resample_info to; from.samples_per_sec = info->samples_per_sec; from.speakers = info->speakers; from.format = AUDIO_FORMAT_FLOAT_PLANAR; to.samples_per_sec = (uint32_t)wfex->nSamplesPerSec; to.speakers = convert_speaker_layout(ext->dwChannelMask, wfex->nChannels); to.format = AUDIO_FORMAT_FLOAT; monitor->sample_rate = (uint32_t)wfex->nSamplesPerSec; monitor->channels = wfex->nChannels; monitor->resampler = audio_resampler_create(&to, &from); if (!monitor->resampler) { goto fail; } /* ------------------------------------------ * * Init client */ hr = monitor->client->lpVtbl->GetBufferSize(monitor->client, &frames); if (FAILED(hr)) { goto fail; } hr = monitor->client->lpVtbl->GetService(monitor->client, &IID_IAudioRenderClient, (void**)&monitor->render); if (FAILED(hr)) { goto fail; } if (pthread_mutex_init(&monitor->playback_mutex, NULL) != 0) { goto fail; } hr = monitor->client->lpVtbl->Start(monitor->client); if (FAILED(hr)) { goto fail; } success = true; fail: safe_release(immde); if (wfex) CoTaskMemFree(wfex); return success; }
static void scene_load_item(struct obs_scene *scene, obs_data_t *item_data) { const char *name = obs_data_get_string(item_data, "name"); obs_source_t *source = obs_get_source_by_name(name); struct obs_scene_item *item; bool visible; if (!source) { blog(LOG_WARNING, "[scene_load_item] Source %s not found!", name); return; } item = obs_scene_add(scene, source); if (!item) { blog(LOG_WARNING, "[scene_load_item] Could not add source '%s' " "to scene '%s'!", name, obs_source_get_name(scene->source)); obs_source_release(source); return; } obs_data_set_default_int(item_data, "align", OBS_ALIGN_TOP | OBS_ALIGN_LEFT); item->rot = (float)obs_data_get_double(item_data, "rot"); item->align = (uint32_t)obs_data_get_int(item_data, "align"); visible = obs_data_get_bool(item_data, "visible"); obs_data_get_vec2(item_data, "pos", &item->pos); obs_data_get_vec2(item_data, "scale", &item->scale); set_visibility(item, visible); item->bounds_type = (enum obs_bounds_type)obs_data_get_int(item_data, "bounds_type"); item->bounds_align = (uint32_t)obs_data_get_int(item_data, "bounds_align"); obs_data_get_vec2(item_data, "bounds", &item->bounds); item->crop.left = (uint32_t)obs_data_get_int(item_data, "crop_left"); item->crop.top = (uint32_t)obs_data_get_int(item_data, "crop_top"); item->crop.right = (uint32_t)obs_data_get_int(item_data, "crop_right"); item->crop.bottom = (uint32_t)obs_data_get_int(item_data, "crop_bottom"); if (item->crop_render && !crop_enabled(&item->crop)) { obs_enter_graphics(); gs_texrender_destroy(item->crop_render); item->crop_render = NULL; obs_leave_graphics(); } else if (!item->crop_render && crop_enabled(&item->crop)) { obs_enter_graphics(); item->crop_render = gs_texrender_create(GS_RGBA, GS_ZS_NONE); obs_leave_graphics(); } obs_source_release(source); update_item_transform(item); }
/** * The x server was changed */ static bool xshm_server_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { UNUSED_PARAMETER(p); bool advanced = obs_data_get_bool(settings, "advanced"); int_fast32_t old_screen = obs_data_get_int(settings, "screen"); const char *server = obs_data_get_string(settings, "server"); obs_property_t *screens = obs_properties_get(props, "screen"); /* we want a real NULL here in case there is no string here */ server = (advanced && *server) ? server : NULL; obs_property_list_clear(screens); xcb_connection_t *xcb = xcb_connect(server, NULL); if (!xcb || xcb_connection_has_error(xcb)) { obs_property_set_enabled(screens, false); return true; } struct dstr screen_info; dstr_init(&screen_info); bool xinerama = xinerama_is_active(xcb); int_fast32_t count = (xinerama) ? xinerama_screen_count(xcb) : xcb_setup_roots_length(xcb_get_setup(xcb)); for (int_fast32_t i = 0; i < count; ++i) { int_fast32_t x, y, w, h; x = y = w = h = 0; if (xinerama) xinerama_screen_geo(xcb, i, &x, &y, &w, &h); else x11_screen_geo(xcb, i, &w, &h); dstr_printf(&screen_info, "Screen %"PRIuFAST32" (%"PRIuFAST32 "x%"PRIuFAST32" @ %"PRIuFAST32 ",%"PRIuFAST32")", i, w, h, x, y); obs_property_list_add_int(screens, screen_info.array, i); } /* handle missing screen */ if (old_screen + 1 > count) { dstr_printf(&screen_info, "Screen %"PRIuFAST32" (not found)", old_screen); size_t index = obs_property_list_add_int(screens, screen_info.array, old_screen); obs_property_list_item_disable(screens, index, true); } dstr_free(&screen_info); xcb_disconnect(xcb); obs_property_set_enabled(screens, true); return true; }
static void ffmpeg_source_update(void *data, obs_data_t *settings) { struct ffmpeg_source *s = data; bool is_local_file = obs_data_get_bool(settings, "is_local_file"); bool is_advanced = obs_data_get_bool(settings, "advanced"); bool is_looping; char *input; char *input_format; if (is_local_file) { input = (char *)obs_data_get_string(settings, "local_file"); input_format = NULL; is_looping = obs_data_get_bool(settings, "looping"); } else { input = (char *)obs_data_get_string(settings, "input"); input_format = (char *)obs_data_get_string(settings, "input_format"); is_looping = false; } s->is_forcing_scale = obs_data_get_bool(settings, "force_scale"); s->is_hw_decoding = obs_data_get_bool(settings, "hw_decode"); s->is_clear_on_media_end = obs_data_get_bool(settings, "clear_on_media_end"); if (s->demuxer != NULL) ff_demuxer_free(s->demuxer); s->demuxer = ff_demuxer_init(); s->demuxer->options.is_hw_decoding = s->is_hw_decoding; s->demuxer->options.is_looping = is_looping; if (is_advanced) { int audio_buffer_size = (int)obs_data_get_int(settings, "audio_buffer_size"); int video_buffer_size = (int)obs_data_get_int(settings, "video_buffer_size"); enum AVDiscard frame_drop = (enum AVDiscard)obs_data_get_int(settings, "frame_drop"); if (audio_buffer_size < 1) { audio_buffer_size = 1; FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d", audio_buffer_size); } if (video_buffer_size < 1) { video_buffer_size = 1; FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d", audio_buffer_size); } s->demuxer->options.audio_frame_queue_size = audio_buffer_size; s->demuxer->options.video_frame_queue_size = video_buffer_size; if (frame_drop < AVDISCARD_NONE || frame_drop > AVDISCARD_ALL) { frame_drop = AVDISCARD_NONE; FF_BLOG(LOG_WARNING, "invalid frame_drop %d", frame_drop); } s->demuxer->options.frame_drop = frame_drop; } ff_demuxer_set_callbacks(&s->demuxer->video_callbacks, video_frame, NULL, NULL, NULL, NULL, s); ff_demuxer_set_callbacks(&s->demuxer->audio_callbacks, audio_frame, NULL, NULL, NULL, NULL, s); dump_source_info(s, input, input_format, is_advanced); ff_demuxer_open(s->demuxer, input, input_format); }
void XCompcapMain::updateSettings(obs_data_t *settings) { PLock lock(&p->lock); XErrorLock xlock; ObsGsContextHolder obsctx; blog(LOG_DEBUG, "Settings updating"); Window prevWin = p->win; xcc_cleanup(p); if (settings) { const char *windowName = obs_data_get_string(settings, "capture_window"); p->win = getWindowFromString(windowName); p->cut_top = obs_data_get_int(settings, "cut_top"); p->cut_left = obs_data_get_int(settings, "cut_left"); p->cut_right = obs_data_get_int(settings, "cut_right"); p->cut_bot = obs_data_get_int(settings, "cut_bot"); p->lockX = obs_data_get_bool(settings, "lock_x"); p->swapRedBlue = obs_data_get_bool(settings, "swap_redblue"); p->show_cursor = obs_data_get_bool(settings, "show_cursor"); } else { p->win = prevWin; } xlock.resetError(); XCompositeRedirectWindow(xdisp, p->win, CompositeRedirectAutomatic); if (xlock.gotError()) { blog(LOG_ERROR, "XCompositeRedirectWindow failed: %s", xlock.getErrorText().c_str()); return; } XSelectInput(xdisp, p->win, StructureNotifyMask); XSync(xdisp, 0); XWindowAttributes attr; if (!XGetWindowAttributes(xdisp, p->win, &attr)) { p->win = 0; p->width = 0; p->height = 0; return; } if (p->cursor && p->show_cursor) { Window child; int x, y; XTranslateCoordinates(xdisp, p->win, attr.root, 0, 0, &x, &y, &child); xcursor_offset(p->cursor, x, y); } gs_color_format cf = GS_RGBA; p->width = attr.width; p->height = attr.height; if (p->cut_top + p->cut_bot < (int)p->height) { p->cur_cut_top = p->cut_top; p->cur_cut_bot = p->cut_bot; } else { p->cur_cut_top = 0; p->cur_cut_bot = 0; } if (p->cut_left + p->cut_right < (int)p->width) { p->cur_cut_left = p->cut_left; p->cur_cut_right = p->cut_right; } else { p->cur_cut_left = 0; p->cur_cut_right = 0; } if (p->tex) gs_texture_destroy(p->tex); uint8_t *texData = new uint8_t[width() * height() * 4]; for (unsigned int i = 0; i < width() * height() * 4; i += 4) { texData[i + 0] = p->swapRedBlue ? 0 : 0xFF; texData[i + 1] = 0; texData[i + 2] = p->swapRedBlue ? 0xFF : 0; texData[i + 3] = 0xFF; } const uint8_t* texDataArr[] = { texData, 0 }; p->tex = gs_texture_create(width(), height(), cf, 1, texDataArr, 0); delete[] texData; if (p->swapRedBlue) { GLuint tex = *(GLuint*)gs_texture_get_obj(p->tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glBindTexture(GL_TEXTURE_2D, 0); } const int attrs[] = { GLX_BIND_TO_TEXTURE_RGBA_EXT, GL_TRUE, GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, GLX_DOUBLEBUFFER, GL_FALSE, None }; int nelem = 0; GLXFBConfig* configs = glXChooseFBConfig(xdisp, XCompcap::getRootWindowScreen(attr.root), attrs, &nelem); if (nelem <= 0) { blog(LOG_ERROR, "no matching fb config found"); p->win = 0; p->height = 0; p->width = 0; return; } glXGetFBConfigAttrib(xdisp, configs[0], GLX_Y_INVERTED_EXT, &nelem); p->inverted = nelem != 0; xlock.resetError(); p->pixmap = XCompositeNameWindowPixmap(xdisp, p->win); if (xlock.gotError()) { blog(LOG_ERROR, "XCompositeNameWindowPixmap failed: %s", xlock.getErrorText().c_str()); p->pixmap = 0; XFree(configs); return; } const int attribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, None }; p->glxpixmap = glXCreatePixmap(xdisp, configs[0], p->pixmap, attribs); if (xlock.gotError()) { blog(LOG_ERROR, "glXCreatePixmap failed: %s", xlock.getErrorText().c_str()); XFreePixmap(xdisp, p->pixmap); XFree(configs); p->pixmap = 0; p->glxpixmap = 0; return; } XFree(configs); p->gltex = gs_texture_create(p->width, p->height, cf, 1, 0, GS_GL_DUMMYTEX); GLuint gltex = *(GLuint*)gs_texture_get_obj(p->gltex); glBindTexture(GL_TEXTURE_2D, gltex); glXBindTexImageEXT(xdisp, p->glxpixmap, GLX_FRONT_LEFT_EXT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); }
static void ffmpeg_source_update(void *data, obs_data_t *settings) { struct ffmpeg_source *s = data; bool is_local_file = obs_data_get_bool(settings, "is_local_file"); bool is_advanced = obs_data_get_bool(settings, "advanced"); char *input; char *input_format; bfree(s->input); bfree(s->input_format); if (is_local_file) { input = (char *)obs_data_get_string(settings, "local_file"); input_format = NULL; s->is_looping = obs_data_get_bool(settings, "looping"); } else { input = (char *)obs_data_get_string(settings, "input"); input_format = (char *)obs_data_get_string(settings, "input_format"); s->is_looping = false; } s->input = input ? bstrdup(input) : NULL; s->input_format = input_format ? bstrdup(input_format) : NULL; s->is_advanced = is_advanced; s->is_hw_decoding = obs_data_get_bool(settings, "hw_decode"); s->is_clear_on_media_end = obs_data_get_bool(settings, "clear_on_media_end"); s->restart_on_activate = obs_data_get_bool(settings, "restart_on_activate"); s->is_forcing_scale = true; s->range = VIDEO_RANGE_DEFAULT; if (is_advanced) { s->audio_buffer_size = (int)obs_data_get_int(settings, "audio_buffer_size"); s->video_buffer_size = (int)obs_data_get_int(settings, "video_buffer_size"); s->frame_drop = (enum AVDiscard)obs_data_get_int(settings, "frame_drop"); s->is_forcing_scale = obs_data_get_bool(settings, "force_scale"); s->range = (enum video_range_type)obs_data_get_int(settings, "color_range"); if (s->audio_buffer_size < 1) { s->audio_buffer_size = 1; FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d", s->audio_buffer_size); } if (s->video_buffer_size < 1) { s->video_buffer_size = 1; FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d", s->audio_buffer_size); } if (s->frame_drop < AVDISCARD_NONE || s->frame_drop > AVDISCARD_ALL) { s->frame_drop = AVDISCARD_DEFAULT; FF_BLOG(LOG_WARNING, "invalid frame_drop %d", s->frame_drop); } } dump_source_info(s, input, input_format, is_advanced); if (!s->restart_on_activate || obs_source_active(s->source)) ffmpeg_source_start(s); }
static bool vaapi_update(void *data, obs_data_t *settings) { struct vaapi_encoder *enc = data; const char *device = obs_data_get_string(settings, "vaapi_device"); int profile = (int)obs_data_get_int(settings, "profile"); int bf = (int)obs_data_get_int(settings, "bf"); int level = (int)obs_data_get_int(settings, "level"); int bitrate = (int)obs_data_get_int(settings, "bitrate"); int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec"); int qp = (int)obs_data_get_int(settings, "qp"); int quality = (int)obs_data_get_int(settings, "quality"); av_opt_set_int(enc->context->priv_data, "qp", qp, 0); av_opt_set_int(enc->context->priv_data, "quality", quality, 0); video_t * video = obs_encoder_video(enc->encoder); const struct video_output_info *voi = video_output_get_info(video); struct video_scale_info info; info.format = voi->format; info.colorspace = voi->colorspace; info.range = voi->range; vaapi_video_info(enc, &info); enc->context->profile = profile; enc->context->max_b_frames = bf; enc->context->level = level; enc->context->bit_rate = bitrate * 1000; enc->context->width = obs_encoder_get_width(enc->encoder); enc->context->height = obs_encoder_get_height(enc->encoder); enc->context->time_base = (AVRational){voi->fps_den, voi->fps_num}; enc->context->pix_fmt = obs_to_ffmpeg_video_format(info.format); enc->context->colorspace = info.colorspace == VIDEO_CS_709 ? AVCOL_SPC_BT709 : AVCOL_SPC_BT470BG; enc->context->color_range = info.range == VIDEO_RANGE_FULL ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; if (keyint_sec > 0) { enc->context->gop_size = keyint_sec * voi->fps_num / voi->fps_den; } else { enc->context->gop_size = 120; } enc->height = enc->context->height; info("settings:\n" "\tdevice: %s\n" "\tqp: %d\n" "\tquality: %d\n" "\tprofile: %d\n" "\tlevel: %d\n" "\tbitrate: %d\n" "\tkeyint: %d\n" "\twidth: %d\n" "\theight: %d\n" "\tb-frames: %d\n", device, qp, quality, profile, level, bitrate, enc->context->gop_size, enc->context->width, enc->context->height, enc->context->max_b_frames); return vaapi_init_codec(enc, device); }
static bool decklink_device_changed(obs_properties_t *props, obs_property_t *list, obs_data_t *settings) { const char *name = obs_data_get_string(settings, DEVICE_NAME); const char *hash = obs_data_get_string(settings, DEVICE_HASH); const char *mode = obs_data_get_string(settings, MODE_NAME); long long modeId = obs_data_get_int(settings, MODE_ID); size_t itemCount = obs_property_list_item_count(list); bool itemFound = false; for (size_t i = 0; i < itemCount; i++) { const char *curHash = obs_property_list_item_string(list, i); if (strcmp(hash, curHash) == 0) { itemFound = true; break; } } if (!itemFound) { obs_property_list_insert_string(list, 0, name, hash); obs_property_list_item_disable(list, 0, true); } obs_property_t *modeList = obs_properties_get(props, MODE_ID); obs_property_t *channelList = obs_properties_get(props, CHANNEL_FORMAT); obs_property_list_clear(modeList); obs_property_list_clear(channelList); obs_property_list_add_int(channelList, TEXT_CHANNEL_FORMAT_NONE, SPEAKERS_UNKNOWN); obs_property_list_add_int(channelList, TEXT_CHANNEL_FORMAT_2_0CH, SPEAKERS_STEREO); ComPtr<DeckLinkDevice> device; device.Set(deviceEnum->FindByHash(hash)); if (!device) { obs_property_list_add_int(modeList, mode, modeId); obs_property_list_item_disable(modeList, 0, true); } else { const std::vector<DeckLinkDeviceMode*> &modes = device->GetModes(); for (DeckLinkDeviceMode *mode : modes) { obs_property_list_add_int(modeList, mode->GetName().c_str(), mode->GetId()); } if (device->GetMaxChannel() >= 8) { obs_property_list_add_int(channelList, TEXT_CHANNEL_FORMAT_5_1CH, SPEAKERS_5POINT1); obs_property_list_add_int(channelList, TEXT_CHANNEL_FORMAT_5_1CH_BACK, SPEAKERS_5POINT1_SURROUND); obs_property_list_add_int(channelList, TEXT_CHANNEL_FORMAT_7_1CH, SPEAKERS_7POINT1); } } return true; }
static void ft2_source_update(void *data, obs_data_t *settings) { struct ft2_source *srcdata = data; obs_data_t *font_obj = obs_data_get_obj(settings, "font"); bool vbuf_needs_update = false; bool word_wrap = false; uint32_t color[2]; uint32_t custom_width = 0; const char *font_name = obs_data_get_string(font_obj, "face"); const char *font_style = obs_data_get_string(font_obj, "style"); uint16_t font_size = (uint16_t)obs_data_get_int(font_obj, "size"); uint32_t font_flags = (uint32_t)obs_data_get_int(font_obj, "flags"); if (!font_obj) return; srcdata->drop_shadow = obs_data_get_bool(settings, "drop_shadow"); srcdata->outline_text = obs_data_get_bool(settings, "outline"); word_wrap = obs_data_get_bool(settings, "word_wrap"); color[0] = (uint32_t)obs_data_get_int(settings, "color1"); color[1] = (uint32_t)obs_data_get_int(settings, "color2"); custom_width = (uint32_t)obs_data_get_int(settings, "custom_width"); if (custom_width >= 100) { if (custom_width != srcdata->custom_width) { srcdata->custom_width = custom_width; vbuf_needs_update = true; } } else { if (srcdata->custom_width >= 100) vbuf_needs_update = true; srcdata->custom_width = 0; } if (word_wrap != srcdata->word_wrap) { srcdata->word_wrap = word_wrap; vbuf_needs_update = true; } if (color[0] != srcdata->color[0] || color[1] != srcdata->color[1]) { srcdata->color[0] = color[0]; srcdata->color[1] = color[1]; vbuf_needs_update = true; } bool from_file = obs_data_get_bool(settings, "from_file"); bool chat_log_mode = obs_data_get_bool(settings, "log_mode"); srcdata->log_mode = chat_log_mode; if (ft2_lib == NULL) goto error; if (srcdata->draw_effect == NULL) { char *effect_file = NULL; char *error_string = NULL; effect_file = obs_module_file("text_default.effect"); if (effect_file) { obs_enter_graphics(); srcdata->draw_effect = gs_effect_create_from_file( effect_file, &error_string); obs_leave_graphics(); bfree(effect_file); if (error_string != NULL) bfree(error_string); } } if (srcdata->font_size != font_size || srcdata->from_file != from_file) vbuf_needs_update = true; srcdata->file_load_failed = false; srcdata->from_file = from_file; if (srcdata->font_name != NULL) { if (strcmp(font_name, srcdata->font_name) == 0 && strcmp(font_style, srcdata->font_style) == 0 && font_flags == srcdata->font_flags && font_size == srcdata->font_size) goto skip_font_load; bfree(srcdata->font_name); bfree(srcdata->font_style); srcdata->font_name = NULL; srcdata->font_style = NULL; srcdata->max_h = 0; vbuf_needs_update = true; } srcdata->font_name = bstrdup(font_name); srcdata->font_style = bstrdup(font_style); srcdata->font_size = font_size; srcdata->font_flags = font_flags; if (!init_font(srcdata) || srcdata->font_face == NULL) { blog(LOG_WARNING, "FT2-text: Failed to load font %s", srcdata->font_name); goto error; } else { FT_Set_Pixel_Sizes(srcdata->font_face, 0, srcdata->font_size); FT_Select_Charmap(srcdata->font_face, FT_ENCODING_UNICODE); } if (srcdata->texbuf != NULL) { bfree(srcdata->texbuf); srcdata->texbuf = NULL; } srcdata->texbuf = bzalloc(texbuf_w * texbuf_h * 4); if (srcdata->font_face) cache_standard_glyphs(srcdata); skip_font_load: if (from_file) { const char *tmp = obs_data_get_string(settings, "text_file"); if (!tmp || !*tmp || !os_file_exists(tmp)) { const char *emptystr = " "; bfree(srcdata->text); srcdata->text = NULL; os_utf8_to_wcs_ptr(emptystr, strlen(emptystr), &srcdata->text); blog(LOG_WARNING, "FT2-text: Failed to open %s for " "reading", tmp); } else { if (srcdata->text_file != NULL && strcmp(srcdata->text_file, tmp) == 0 && !vbuf_needs_update) goto error; bfree(srcdata->text_file); srcdata->text_file = bstrdup(tmp); if (chat_log_mode) read_from_end(srcdata, tmp); else load_text_from_file(srcdata, tmp); srcdata->last_checked = os_gettime_ns(); } } else { const char *tmp = obs_data_get_string(settings, "text"); if (!tmp || !*tmp) goto error; if (srcdata->text != NULL) { bfree(srcdata->text); srcdata->text = NULL; } os_utf8_to_wcs_ptr(tmp, strlen(tmp), &srcdata->text); } if (srcdata->font_face) { cache_glyphs(srcdata, srcdata->text); set_up_vertex_buffer(srcdata); } error: obs_data_release(font_obj); }
/* * Format selected callback */ static bool format_selected(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { UNUSED_PARAMETER(p); int dev = v4l2_open(obs_data_get_string(settings, "device_id"), O_RDWR | O_NONBLOCK); if (dev == -1) return false; int input = (int) obs_data_get_int(settings, "input"); uint32_t caps = 0; if (v4l2_get_input_caps(dev, input, &caps) < 0) return false; #ifdef __FreeBSD__ caps &= V4L2_IN_CAP_STD | V4L2_IN_CAP_CUSTOM_TIMINGS; #else caps &= V4L2_IN_CAP_STD | V4L2_IN_CAP_DV_TIMINGS; #endif obs_property_t *resolution = obs_properties_get(props, "resolution"); obs_property_t *framerate = obs_properties_get(props, "framerate"); obs_property_t *standard = obs_properties_get(props, "standard"); obs_property_t *dv_timing = obs_properties_get(props, "dv_timing"); obs_property_set_visible(resolution, (!caps) ? true : false); obs_property_set_visible(framerate, (!caps) ? true : false); obs_property_set_visible(standard, (caps & V4L2_IN_CAP_STD) ? true : false); #ifdef __FreeBSD__ obs_property_set_visible(dv_timing, (caps & V4L2_IN_CAP_CUSTOM_TIMINGS) ? true : false); #else obs_property_set_visible(dv_timing, (caps & V4L2_IN_CAP_DV_TIMINGS) ? true : false); #endif if (!caps) { v4l2_resolution_list(dev, obs_data_get_int( settings, "pixelformat"), resolution); } if (caps & V4L2_IN_CAP_STD) v4l2_standard_list(dev, standard); #ifdef __FreeBSD__ if (caps & V4L2_IN_CAP_CUSTOM_TIMINGS) v4l2_dv_timing_list(dev, dv_timing); #else if (caps & V4L2_IN_CAP_DV_TIMINGS) v4l2_dv_timing_list(dev, dv_timing); #endif v4l2_close(dev); if (!caps) obs_property_modified(resolution, settings); if (caps & V4L2_IN_CAP_STD) obs_property_modified(standard, settings); #ifdef __FreeBSD__ if (caps & V4L2_IN_CAP_CUSTOM_TIMINGS) obs_property_modified(dv_timing, settings); #else if (caps & V4L2_IN_CAP_DV_TIMINGS) obs_property_modified(dv_timing, settings); #endif return true; }
/* * List available devices */ static void v4l2_device_list(obs_property_t *prop, obs_data_t *settings) { DIR *dirp; struct dirent *dp; struct dstr device; bool cur_device_found; size_t cur_device_index; const char *cur_device_name; #ifdef __FreeBSD__ dirp = opendir("/dev"); #else dirp = opendir("/sys/class/video4linux"); #endif if (!dirp) return; cur_device_found = false; cur_device_name = obs_data_get_string(settings, "device_id"); obs_property_list_clear(prop); dstr_init_copy(&device, "/dev/"); while ((dp = readdir(dirp)) != NULL) { int fd; uint32_t caps; struct v4l2_capability video_cap; #ifdef __FreeBSD__ if ( strstr(dp->d_name, "video") == NULL) continue; #endif if (dp->d_type == DT_DIR) continue; dstr_resize(&device, 5); dstr_cat(&device, dp->d_name); if ((fd = v4l2_open(device.array, O_RDWR | O_NONBLOCK)) == -1) { blog(LOG_INFO, "Unable to open %s", device.array); continue; } if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) { blog(LOG_INFO, "Failed to query capabilities for %s", device.array); v4l2_close(fd); continue; } #ifndef V4L2_CAP_DEVICE_CAPS caps = video_cap.capabilities; #else /* ... since Linux 3.3 */ caps = (video_cap.capabilities & V4L2_CAP_DEVICE_CAPS) ? video_cap.device_caps : video_cap.capabilities; #endif if (!(caps & V4L2_CAP_VIDEO_CAPTURE)) { blog(LOG_INFO, "%s seems to not support video capture", device.array); v4l2_close(fd); continue; } obs_property_list_add_string(prop, (char *) video_cap.card, device.array); blog(LOG_INFO, "Found device '%s' at %s", video_cap.card, device.array); /* check if this is the currently used device */ if (cur_device_name && !strcmp(cur_device_name, device.array)) cur_device_found = true; v4l2_close(fd); } /* add currently selected device if not present, but disable it ... */ if (!cur_device_found && cur_device_name && strlen(cur_device_name)) { cur_device_index = obs_property_list_add_string(prop, cur_device_name, cur_device_name); obs_property_list_item_disable(prop, cur_device_index, true); } closedir(dirp); dstr_free(&device); }