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;
}
Exemple #2
0
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:");
}
Exemple #3
0
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;
}
Exemple #4
0
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);
}
Exemple #5
0
/**
 * 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);
}
Exemple #10
0
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);
}
Exemple #12
0
/*
 * 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;
}
Exemple #13
0
/*
 * 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);
}