欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

obs 属性窗口 及 属性获得

程序员文章站 2022-07-08 22:27:00
...

 

以摄像头属性窗口为例进行介绍:

obs 属性窗口 及 属性获得

几个常用的宏

属性名字

#define VIDEO_DEVICE_ID   "video_device_id"  //设备ID

#define RESOLUTION        "resolution"              //分辨率

 

#define VIDEO_DEVICE_ID   "video_device_id"
#define RES_TYPE          "res_type"
#define RESOLUTION        "resolution"
#define FRAME_INTERVAL    "frame_interval"
#define VIDEO_FORMAT      "video_format"
#define LAST_VIDEO_DEV_ID "last_video_device_id"
#define LAST_RESOLUTION   "last_resolution"
#define BUFFERING_VAL     "buffering"
#define FLIP_IMAGE        "flip_vertically"
#define AUDIO_OUTPUT_MODE "audio_output_mode"
#define USE_CUSTOM_AUDIO  "use_custom_audio_device"
#define AUDIO_DEVICE_ID   "audio_device_id"
#define COLOR_SPACE       "color_space"
#define COLOR_RANGE       "color_range"
#define DEACTIVATE_WNS    "deactivate_when_not_showing"

 

属性描述

#define TEXT_RESOLUTION     obs_module_text("Resolution")  //分辨率

 

#define TEXT_INPUT_NAME     obs_module_text("VideoCaptureDevice")
#define TEXT_DEVICE         obs_module_text("Device")
#define TEXT_CONFIG_VIDEO   obs_module_text("ConfigureVideo")
#define TEXT_CONFIG_XBAR    obs_module_text("ConfigureCrossbar")
#define TEXT_RES_FPS_TYPE   obs_module_text("ResFPSType")
#define TEXT_CUSTOM_RES     obs_module_text("ResFPSType.Custom")
#define TEXT_PREFERRED_RES  obs_module_text("ResFPSType.DevPreferred")
#define TEXT_FPS_MATCHING   obs_module_text("FPS.Matching")
#define TEXT_FPS_HIGHEST    obs_module_text("FPS.Highest")
#define TEXT_RESOLUTION     obs_module_text("Resolution")  //分辨率
#define TEXT_VIDEO_FORMAT   obs_module_text("VideoFormat")
#define TEXT_FORMAT_UNKNOWN obs_module_text("VideoFormat.Unknown")
#define TEXT_BUFFERING      obs_module_text("Buffering")
#define TEXT_BUFFERING_AUTO obs_module_text("Buffering.AutoDetect")
#define TEXT_BUFFERING_ON   obs_module_text("Buffering.Enable")
#define TEXT_BUFFERING_OFF  obs_module_text("Buffering.Disable")
#define TEXT_FLIP_IMAGE     obs_module_text("FlipVertically")
#define TEXT_AUDIO_MODE     obs_module_text("AudioOutputMode")
#define TEXT_MODE_CAPTURE   obs_module_text("AudioOutputMode.Capture")
#define TEXT_MODE_DSOUND    obs_module_text("AudioOutputMode.DirectSound")
#define TEXT_MODE_WAVEOUT   obs_module_text("AudioOutputMode.WaveOut")
#define TEXT_CUSTOM_AUDIO   obs_module_text("UseCustomAudioDevice")
#define TEXT_AUDIO_DEVICE   obs_module_text("AudioDevice")
#define TEXT_ACTIVATE       obs_module_text("Activate")
#define TEXT_DEACTIVATE     obs_module_text("Deactivate")
#define TEXT_COLOR_SPACE    obs_module_text("ColorSpace")
#define TEXT_COLOR_DEFAULT  obs_module_text("ColorSpace.Default")
#define TEXT_COLOR_RANGE    obs_module_text("ColorRange")
#define TEXT_RANGE_PARTIAL  obs_module_text("ColorRange.Partial")
#define TEXT_RANGE_FULL     obs_module_text("ColorRange.Full")
#define TEXT_DWNS           obs_module_text("DeactivateWhenNotShowing")

 

1 属性窗口 通过CreatePropertiesWindow 创建,

 

void OBSBasic::CreatePropertiesWindow(obs_source_t *source, bool bShow)
{
	if (properties)
		properties->close();

	properties = new OBSBasicProperties(this, source);
	if (bShow)
		properties->Init();
	properties->setAttribute(Qt::WA_DeleteOnClose, true);
}

 

属性VIEW 

 

	view = new OBSPropertiesView(settings, source,
			(PropertiesReloadCallback)obs_source_properties,
			(PropertiesUpdateCallback)obs_source_update);
	view->setMinimumHeight(150);


 

obs_properties_t *obs_source_properties(const obs_source_t *source)
{
	if (!data_valid(source, "obs_source_properties"))
		return NULL;

	if (source->info.get_properties) {
		obs_properties_t *props;
		props = source->info.get_properties(source->context.data);
		obs_properties_apply_settings(props, source->context.settings);
		return props;
	}

	return NULL;
}

我们来看看win-dshow接口

void RegisterDShowSource()
{
	SetLogCallback(DShowModuleLogCallback, nullptr);

	obs_source_info info = {};
	info.id              = "dshow_input";
	info.type            = OBS_SOURCE_TYPE_INPUT;
	info.output_flags    = OBS_SOURCE_VIDEO |
	                       OBS_SOURCE_AUDIO |
	                       OBS_SOURCE_ASYNC |
	                       OBS_SOURCE_DO_NOT_DUPLICATE;
	info.show            = ShowDShowInput;
	info.hide            = HideDShowInput;
	info.get_name        = GetDShowInputName;
	info.create          = CreateDShowInput;
	info.destroy         = DestroyDShowInput;
	info.update          = UpdateDShowInput;
	info.get_defaults    = GetDShowDefaults;
	info.get_properties  = GetDShowProperties;
	obs_register_source(&info);
}

 

win-dshow属性设置

static obs_properties_t *GetDShowProperties(void *obj)
{
	DShowInput *input = reinterpret_cast<DShowInput*>(obj);
	obs_properties_t *ppts = obs_properties_create();
	PropertiesData *data = new PropertiesData;

	data->input = input;

	obs_properties_set_param(ppts, data, PropertiesDataDestroy);

	//#define VIDEO_DEVICE_ID     "video_device_id"
    //#define TEXT_DEVICE         obs_module_text("Device")
	obs_property_t *p = obs_properties_add_list(ppts,        //设备列表
			VIDEO_DEVICE_ID, TEXT_DEVICE,
			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);   

	obs_property_set_modified_callback(p, DeviceSelectionChanged);

	Device::EnumVideoDevices(data->devices);
	for (const VideoDevice &device : data->devices)
		AddDevice(p, device);

	const char *activateText = TEXT_ACTIVATE;
	if (input) {
		if (input->active)
			activateText = TEXT_DEACTIVATE;
	}

	obs_properties_add_button(ppts, "activate", activateText,              
			ActivateClicked);
	obs_properties_add_button(ppts, "video_config", TEXT_CONFIG_VIDEO, //ConfigureVideo
			VideoConfigClicked);
	obs_properties_add_button(ppts, "xbar_config", TEXT_CONFIG_XBAR,   //ConfigureCrossbar
			CrossbarConfigClicked);

	obs_properties_add_bool(ppts, DEACTIVATE_WNS, TEXT_DWNS);          //deactivate_when_not_showing

	/* ------------------------------------- */
	/* video settings */

	//name   res_type
	//des:   ResFPSType="分辨率/帧率 类型"                           //默认 设备默认
	p = obs_properties_add_list(ppts, RES_TYPE, TEXT_RES_FPS_TYPE,
			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);

	obs_property_set_modified_callback(p, ResTypeChanged);

	//ResFPSType.DevPreferred="设备默认"
	obs_property_list_add_int(p, TEXT_PREFERRED_RES, ResType_Preferred);
	//ResFPSType.Custom="自定义"
	obs_property_list_add_int(p, TEXT_CUSTOM_RES, ResType_Custom);
	//Resolution = "分辨率"
	p = obs_properties_add_list(ppts, RESOLUTION, TEXT_RESOLUTION,
			OBS_COMBO_TYPE_EDITABLE, OBS_COMBO_FORMAT_STRING);

	obs_property_set_modified_callback(p, DeviceResolutionChanged);

	p = obs_properties_add_list(ppts, FRAME_INTERVAL, "FPS",
			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);

	obs_property_set_modified_callback(p, DeviceIntervalChanged);
	//VideoFormat="视频格式"
	p = obs_properties_add_list(ppts, VIDEO_FORMAT, TEXT_VIDEO_FORMAT,
			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);

	obs_property_set_modified_callback(p, VideoFormatChanged);
	//ColorSpace="YUV 颜色空间"
	p = obs_properties_add_list(ppts, COLOR_SPACE, TEXT_COLOR_SPACE,
			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
	obs_property_list_add_string(p, TEXT_COLOR_DEFAULT, "default");
	obs_property_list_add_string(p, "709", "709");
	obs_property_list_add_string(p, "601", "601");

	p = obs_properties_add_list(ppts, COLOR_RANGE, TEXT_COLOR_RANGE,
			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
	obs_property_list_add_string(p, TEXT_RANGE_PARTIAL, "partial");
	obs_property_list_add_string(p, TEXT_RANGE_FULL, "full");

	p = obs_properties_add_list(ppts, BUFFERING_VAL, TEXT_BUFFERING,
			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
	obs_property_list_add_int(p, TEXT_BUFFERING_AUTO,
			(int64_t)BufferingType::Auto);
	obs_property_list_add_int(p, TEXT_BUFFERING_ON,
			(int64_t)BufferingType::On);
	obs_property_list_add_int(p, TEXT_BUFFERING_OFF,
			(int64_t)BufferingType::Off);

	obs_property_set_long_description(p,
			obs_module_text("Buffering.ToolTip"));

	obs_properties_add_bool(ppts, FLIP_IMAGE, TEXT_FLIP_IMAGE);

	/* ------------------------------------- */
	/* audio settings */

	Device::EnumAudioDevices(data->audioDevices);

	p = obs_properties_add_list(ppts, AUDIO_OUTPUT_MODE, TEXT_AUDIO_MODE,
			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
	obs_property_list_add_int(p, TEXT_MODE_CAPTURE,
			(int64_t)AudioMode::Capture);
	obs_property_list_add_int(p, TEXT_MODE_DSOUND,
			(int64_t)AudioMode::DirectSound);
	obs_property_list_add_int(p, TEXT_MODE_WAVEOUT,
			(int64_t)AudioMode::WaveOut);

	if (!data->audioDevices.size())
		return ppts;

	p = obs_properties_add_bool(ppts, USE_CUSTOM_AUDIO, TEXT_CUSTOM_AUDIO);

	obs_property_set_modified_callback(p, CustomAudioClicked);

	p = obs_properties_add_list(ppts, AUDIO_DEVICE_ID, TEXT_AUDIO_DEVICE,
			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);

	for (const AudioDevice &device : data->audioDevices)
		AddAudioDevice(p, device);

	return ppts;
}

 

2 属性分析

 

#define VIDEO_DEVICE_ID   "video_device_id"

#define TEXT_DEVICE         obs_module_text("Device")

obs 属性窗口 及 属性获得

 

对应着 

obs 属性窗口 及 属性获得

不过,只是添加了这个列表项,但列表中还没有添加子项

 

 

obs 属性窗口 及 属性获得

 

static bool AddDevice(obs_property_t *device_list, const VideoDevice &device)
{
	DStr name, path, device_id;

	dstr_from_wcs(name, device.name.c_str());
	dstr_from_wcs(path, device.path.c_str());

	encode_dstr(path);

	dstr_copy_dstr(device_id, name);
	encode_dstr(device_id);
	dstr_cat(device_id, ":");
	dstr_cat_dstr(device_id, path);

	obs_property_list_add_string(device_list, name, device_id);

	return true;
}

 

EXPORT size_t obs_property_list_add_string(obs_property_t *p,
		const char *name, const char *val);

  往这个列表项中,添加元素,其中元素的名字为name, 值为val

size_t obs_property_list_add_string(obs_property_t *p,
		const char *name, const char *val)
{
	struct list_data *data = get_list_data(p);
	if (data && data->format == OBS_COMBO_FORMAT_STRING)
		return add_item(data, name, val);
	return 0;
}

 

static size_t add_item(struct list_data *data, const char *name,
		const void *val)
{
	struct list_item item = { NULL };
	item.name  = bstrdup(name);

	if (data->format == OBS_COMBO_FORMAT_INT)
		item.ll  = *(const long long*)val;
	else if (data->format == OBS_COMBO_FORMAT_FLOAT)
		item.d   = *(const double*)val;
	else
		item.str = bstrdup(val);

	return da_push_back(data->items, &item);
}

 

比如 

obs 属性窗口 及 属性获得

 

obs 属性窗口 及 属性获得

 

再看添加几个按钮属性

obs 属性窗口 及 属性获得

 

对应的是 

obs 属性窗口 及 属性获得

 

再看以下几个属性列表

 

obs 属性窗口 及 属性获得

 

obs 属性窗口 及 属性获得

 

其它类似 ,不再介绍

3 获得相关属性

如果我们能获得到 属性值,就可以获得设备的很多信息

比如,获得显示器数量,摄像头数量等

 

int  OBSBasic::GetCameraNum(){
	obs_properties_t *props = obs_get_source_properties("dshow_input");

	size_t count = 0;
	if (!props)
		return count;


	obs_property_t *cams = obs_properties_get(props, "video_device_id");
	if (cams)
		count = obs_property_list_item_count(cams);

	//QString  name = obs_property_list_item_name(cams, 0);
	//QString  devicePath = obs_property_list_item_string(cams, 0);
	return count;
}

 


int  OBSBasic::GetMonitorNum(){

	obs_properties_t *props = obs_get_source_properties("monitor_capture");

	size_t count = 0;
	if (!props)
		return count;


	obs_property_t *monitors = obs_properties_get(props, "monitor");
	if (monitors)
		count = obs_property_list_item_count(monitors);

	/*QString  name = obs_property_list_item_name(cams, 0);*/

	return count;
}

 

获得源或id属性的方法

/** Returns the property list, if any.  Free with obs_properties_destroy */
EXPORT obs_properties_t *obs_get_source_properties(const char *id);


/**
 * Returns the properties list for a specific existing source.  Free with
 * obs_properties_destroy
 */
EXPORT obs_properties_t
 *obs_source_properties(const obs_source_t *source);



//.....................................................................................

/** Returns the property list, if any.  Free with obs_properties_destroy */
EXPORT obs_properties_t *obs_get_output_properties(const char *id);

/**
 * Returns the property list of an existing output, if any.  Free with
 * obs_properties_destroy
 */
EXPORT obs_properties_t *obs_output_properties(const obs_output_t *output);

 

  比如说:

  获得显示器分辨率

				//获得属性
				obs_property_t *monitors = obs_properties_get(props, "monitor");
				if (monitors)
					count = obs_property_list_item_count(monitors);

				assert(nMonitor < count);
				
				//获得显示器 分辨率
				QString  name = obs_property_list_item_name(monitors, nMonitor); //显示器 1: 1920x1080 @ 1366,9
				QRegExp rx("(\\d{2,})");  // 匹配数字 至少两个数字
				int pos = 0;						
				int nIndex = 0;
				while ((pos = rx.indexIn(name, pos)) != -1) {

					if (nIndex == 0)
						monitorW = rx.cap(0).toInt();
					if (nIndex == 1)
						monitorH = rx.cap(0).toInt();
					pos += rx.matchedLength();
					nIndex++;
				}

 

比如说 获得摄像头name path

			obs_properties_t *props = obs_get_source_properties(id);

			size_t count = 0;
			if (!props)
				return;


				obs_property_t *cams = obs_properties_get(props, "video_device_id");
				if (cams)
					count = obs_property_list_item_count(cams);

				std::string  name = obs_property_list_item_name(cams, 0);

				////获得属性
				int nDeviceCount = 0;
				std::string video_device_id = obs_property_list_item_string(cams, 0);

 

比如,添加新视频源的时候,可以直接从属性中获得设备ID,然后传入到这个视频源的setting中, 从而直接为该视频源选择了某个摄像头设备

 

				obs_property_t *cams = obs_properties_get(props, "video_device_id");
				if (cams)
					nDeviceCount = obs_property_list_item_count(cams);

				if (nCam >= nDeviceCount)
					return;

				std::string  video_device_name = obs_property_list_item_name(cams, nCam);			
				std::string video_device_id = obs_property_list_item_string(cams, nCam);


				//更新setting  选择显示器,传递参数
				obs_data_t * settings;
				settings = obs_source_get_settings(sourceSelect.newSource); //获得settings

				obs_data_set_string(settings, "video_device_id", video_device_id.c_str());
				obs_data_set_bool(settings, "active", true);

				obs_source_update(sourceSelect.newSource, settings);      //更新settings

 

4 添加新源时,选择设备,更新设置,调整位置

 

1) 添加新源时,希望新源为自己指定的某个摄像头  指定的某个显示器

       如果是摄像头,此时需要获得摄像头的device_id,

       比如,获得设备列表中第1个摄像头的device_id

 

                obs_properties_t *props = obs_get_source_properties(id);

                int nDeviceCount = 0;
                if (!props)
                       return;

 

 

                obs_property_t *cams = obs_properties_get(props, "video_device_id");
                if (cams)
                    nDeviceCount = obs_property_list_item_count(cams);         //  获得设备数量

                if (nCam >= nDeviceCount)
                    return;

                std::string  video_device_name = obs_property_list_item_name(cams, nCam);       //设备名称      
                std::string  video_device_id = obs_property_list_item_string(cams, nCam);              //设备ID

 

2) 将设备信息传入setting ,更新新源的setting

 

比如摄像头源的 获取更新setting方式

                 //更新setting  选择显示器,传递参数
                obs_data_t * settings;
                settings = obs_source_get_settings(sourceSelect.newSource); //获得settings

               //设置setting

                obs_data_set_string(settings, "video_device_id", video_device_id.c_str());
                obs_data_set_bool(settings, "active", true);

                //更新setting               

                obs_source_update(sourceSelect.newSource, settings);      //更新settings

          

 

比如显示器源的 设置更新setting方式

				//更新setting  选择显示器,传递参数
				obs_data_t * settings;
				settings = obs_source_get_settings(sourceSelect.newSource); //获得settings

				obs_data_set_int(settings, "monitor", nMonitor);
				obs_data_set_int(settings, "nCursor", 111);				
				obs_data_set_bool(settings, "capture_cursor", false);
				obs_source_update(sourceSelect.newSource, settings);      //更新settings

3)更新项目位置

 

新添加的源,为场景的当前项,要更新项目位置,首先要获得此项

 

 

            OBSSceneItem item = GetCurrentSceneItem();
            if (!item)
                return;

           更换位置,使用变换方法

           

				obs_sceneitem_defer_update_begin(item);
				obs_transform_info info;

				if (bMainScreen)
					vec2_set(&info.pos, 30.0f, 30.0f);
				else{
					vec2_set(&info.pos, 930.0f, 30.0f);
				}
				vec2_set(&info.scale, 1.0f, 1.0f);
				info.rot = 0.0f;
				info.alignment = OBS_ALIGN_TOP | OBS_ALIGN_LEFT;
				info.bounds_type = OBS_BOUNDS_SCALE_INNER;
				info.bounds_alignment = OBS_ALIGN_CENTER;

				if (bMainScreen)
					vec2_set(&info.bounds, mainbound_w, mainbound_h);
				else
					vec2_set(&info.bounds, secbound_w, secbound_h);
				obs_sceneitem_set_info(item, &info);

				if (bFullCut)
				{
					obs_sceneitem_crop crop = { cropLeft, cropTop, cropRight, cropBottom };
					obs_sceneitem_set_crop(item, &crop);
				}

				obs_sceneitem_defer_update_end(item);

 

 

 

 

 

 

 

 

 

相关标签: obs