static bool VideoFormatChanged(obs_properties_t props, obs_property_t p, obs_data_t settings) { PropertiesData *data = (PropertiesData*)obs_properties_get_param(props); const char *id = obs_data_get_string(settings, VIDEO_DEVICE_ID); VideoDevice device; VideoFormat curFormat = (VideoFormat)obs_data_get_int(settings, VIDEO_FORMAT); if (!data->GetDevice(device, id)) return UpdateVideoFormats(curFormat, p); int cx, cy; if (!DetermineResolution(cx, cy, settings, device)) { UpdateVideoFormats(device, VideoFormat::Any, cx, cy, 0, props); UpdateFPS(device, VideoFormat::Any, 0, 0, 0, props); return true; } long long interval = obs_data_get_int(settings, FRAME_INTERVAL); UpdateVideoFormats(device, curFormat, cx, cy, interval, props); UpdateFPS(device, curFormat, interval, cx, cy, props); return true; }
static bool DeviceSelectionChanged(obs_properties_t props, obs_property_t p, obs_data_t settings) { PropertiesData *data = (PropertiesData*)obs_properties_get_param(props); VideoDevice device; string id = obs_data_get_string(settings, VIDEO_DEVICE_ID); string old_id = obs_data_get_string(settings, LAST_VIDEO_DEV_ID); bool device_list_updated = UpdateDeviceList(p, id); if (!data->GetDevice(device, id.c_str())) return !device_list_updated; vector<Resolution> resolutions; for (const VideoInfo &cap : device.caps) AddCap(resolutions, cap); p = obs_properties_get(props, RESOLUTION); obs_property_list_clear(p); for (size_t idx = resolutions.size(); idx > 0; idx--) { const Resolution &res = resolutions[idx-1]; string strRes; strRes += to_string(res.cx); strRes += "x"; strRes += to_string(res.cy); obs_property_list_add_string(p, strRes.c_str(), strRes.c_str()); } /* only refresh properties if device legitimately changed */ if (!id.size() || !old_id.size() || id != old_id) { p = obs_properties_get(props, RES_TYPE); ResTypeChanged(props, p, settings); obs_data_set_string(settings, LAST_VIDEO_DEV_ID, id.c_str()); } return true; }
static bool DeviceResolutionChanged(obs_properties_t props, obs_property_t p, obs_data_t settings) { UNUSED_PARAMETER(p); PropertiesData *data = (PropertiesData*)obs_properties_get_param(props); const char *id; VideoDevice device; id = obs_data_get_string(settings, VIDEO_DEVICE_ID); string res = obs_data_get_string(settings, RESOLUTION); string last_res = obs_data_get_string(settings, LAST_RESOLUTION); if (!data->GetDevice(device, id)) return false; if (TryResolution(device, res)) return SetResolution(props, settings, res); if (TryResolution(device, last_res)) return SetResolution(props, settings, last_res, true); return false; }
bool DShowInput::UpdateVideoConfig(obs_data_t settings) { string video_device_id = obs_data_get_string(settings, VIDEO_DEVICE_ID); DeviceId id; if (!DecodeDeviceId(id, video_device_id.c_str())) return false; PropertiesData data; Device::EnumVideoDevices(data.devices); VideoDevice dev; if (!data.GetDevice(dev, video_device_id.c_str())) return false; int resType = (int)obs_data_get_int(settings, RES_TYPE); int cx = 0, cy = 0; long long interval = 0; VideoFormat format = VideoFormat::Any; if (resType == ResType_Custom) { bool has_autosel_val; string resolution = obs_data_get_string(settings, RESOLUTION); if (!ResolutionValid(resolution, cx, cy)) return false; has_autosel_val = obs_data_has_autoselect_value(settings, FRAME_INTERVAL); interval = has_autosel_val ? obs_data_get_autoselect_int(settings, FRAME_INTERVAL) : obs_data_get_int(settings, FRAME_INTERVAL); if (interval == FPS_MATCHING) interval = GetOBSFPS(); format = (VideoFormat)obs_data_get_int(settings, VIDEO_FORMAT); long long best_interval = numeric_limits<long long>::max(); bool video_format_match = false; if (!CapsMatch(dev, ResolutionMatcher(cx, cy), VideoFormatMatcher(format, video_format_match), ClosestFrameRateSelector(interval, best_interval), FrameRateMatcher(interval)) && !video_format_match) return false; interval = best_interval; blog(LOG_INFO, "%s: Using interval %lld", obs_source_get_name(source), interval); } videoConfig.name = id.name.c_str(); videoConfig.path = id.path.c_str(); videoConfig.useDefaultConfig = resType == ResType_Preferred; videoConfig.cx = cx; videoConfig.cy = cy; videoConfig.frameInterval = interval; videoConfig.internalFormat = format; deviceHasAudio = dev.audioAttached; videoConfig.callback = std::bind(&DShowInput::OnVideoData, this, placeholders::_1, placeholders::_2, placeholders::_3, placeholders::_4, placeholders::_5); if (videoConfig.internalFormat != VideoFormat::MJPEG) videoConfig.format = videoConfig.internalFormat; if (!device.SetVideoConfig(&videoConfig)) return false; if (videoConfig.internalFormat == VideoFormat::MJPEG) { videoConfig.format = VideoFormat::XRGB; if (!device.SetVideoConfig(&videoConfig)) return false; } return true; }
static bool DeviceIntervalChanged(obs_properties_t props, obs_property_t p, obs_data_t settings) { long long val = obs_data_get_int(settings, FRAME_INTERVAL); PropertiesData *data = (PropertiesData*)obs_properties_get_param(props); const char *id = obs_data_get_string(settings, VIDEO_DEVICE_ID); VideoDevice device; if (!data->GetDevice(device, id)) return UpdateFPS(val, p); int cx = 0, cy = 0; if (!DetermineResolution(cx, cy, settings, device)) { UpdateVideoFormats(device, VideoFormat::Any, 0, 0, 0, props); UpdateFPS(device, VideoFormat::Any, 0, 0, 0, props); return true; } int resType = (int)obs_data_get_int(settings, RES_TYPE); if (resType != ResType_Custom) return true; if (val == FPS_MATCHING) val = GetOBSFPS(); VideoFormat format = (VideoFormat)obs_data_get_int(settings, VIDEO_FORMAT); bool video_format_matches = false; long long best_interval = numeric_limits<long long>::max(); bool frameRateSupported = CapsMatch(device, ResolutionMatcher(cx, cy), VideoFormatMatcher(format, video_format_matches), ClosestFrameRateSelector(val, best_interval), FrameRateMatcher(val)); if (video_format_matches && !frameRateSupported && best_interval != val) { long long listed_val = 0; for (const FPSFormat &format : validFPSFormats) { long long diff = llabs(format.interval - best_interval); if (diff < DEVICE_INTERVAL_DIFF_LIMIT) { listed_val = format.interval; break; } } if (listed_val != val) obs_data_set_autoselect_int(settings, FRAME_INTERVAL, listed_val); } else { obs_data_unset_autoselect_value(settings, FRAME_INTERVAL); } UpdateVideoFormats(device, format, cx, cy, val, props); UpdateFPS(device, format, val, cx, cy, props); UNUSED_PARAMETER(p); return true; }
bool DShowInput::UpdateVideoConfig(obs_data_t *settings) { string video_device_id = obs_data_get_string(settings, VIDEO_DEVICE_ID); flip = obs_data_get_bool(settings, FLIP_IMAGE); DeviceId id; if (!DecodeDeviceId(id, video_device_id.c_str())) return false; PropertiesData data; Device::EnumVideoDevices(data.devices); VideoDevice dev; if (!data.GetDevice(dev, video_device_id.c_str())) return false; int resType = (int)obs_data_get_int(settings, RES_TYPE); int cx = 0, cy = 0; long long interval = 0; VideoFormat format = VideoFormat::Any; if (resType == ResType_Custom) { bool has_autosel_val; string resolution = obs_data_get_string(settings, RESOLUTION); if (!ResolutionValid(resolution, cx, cy)) return false; has_autosel_val = obs_data_has_autoselect_value(settings, FRAME_INTERVAL); interval = has_autosel_val ? obs_data_get_autoselect_int(settings, FRAME_INTERVAL) : obs_data_get_int(settings, FRAME_INTERVAL); if (interval == FPS_MATCHING) interval = GetOBSFPS(); format = (VideoFormat)obs_data_get_int(settings, VIDEO_FORMAT); long long best_interval = numeric_limits<long long>::max(); bool video_format_match = false; if (!CapsMatch(dev, ResolutionMatcher(cx, cy), VideoFormatMatcher(format, video_format_match), ClosestFrameRateSelector(interval, best_interval), FrameRateMatcher(interval)) && !video_format_match) return false; interval = best_interval; } videoConfig.name = id.name.c_str(); videoConfig.path = id.path.c_str(); videoConfig.useDefaultConfig = resType == ResType_Preferred; videoConfig.cx = cx; videoConfig.cy = cy; videoConfig.frameInterval = interval; videoConfig.internalFormat = format; deviceHasAudio = dev.audioAttached; videoConfig.callback = std::bind(&DShowInput::OnVideoData, this, placeholders::_1, placeholders::_2, placeholders::_3, placeholders::_4, placeholders::_5); if (videoConfig.internalFormat != VideoFormat::MJPEG) videoConfig.format = videoConfig.internalFormat; if (!device.SetVideoConfig(&videoConfig)) return false; if (videoConfig.internalFormat == VideoFormat::MJPEG) { videoConfig.format = VideoFormat::XRGB; if (!device.SetVideoConfig(&videoConfig)) return false; } DStr formatName = GetVideoFormatName(videoConfig.internalFormat); double fps = 0.0; if (videoConfig.frameInterval) fps = 10000000.0 / double(videoConfig.frameInterval); BPtr<char> name_utf8; BPtr<char> path_utf8; os_wcs_to_utf8_ptr(videoConfig.name.c_str(), videoConfig.name.size(), &name_utf8); os_wcs_to_utf8_ptr(videoConfig.path.c_str(), videoConfig.path.size(), &path_utf8); blog(LOG_INFO, "---------------------------------"); blog(LOG_INFO, "[DShow Device: '%s'] settings updated: \n" "\tvideo device: %s\n" "\tvideo path: %s\n" "\tresolution: %dx%d\n" "\tfps: %0.2f (interval: %lld)\n" "\tformat: %s", obs_source_get_name(source), (const char*)name_utf8, (const char*)path_utf8, videoConfig.cx, videoConfig.cy, fps, videoConfig.frameInterval, formatName->array); SetupBuffering(settings); return true; }
void DShowInput::Update(obs_data_t settings) { string video_device_id = obs_data_getstring(settings, VIDEO_DEVICE_ID); if (!comInitialized) { CoInitialize(nullptr); comInitialized = true; } if (!device.ResetGraph()) return; DeviceId id; if (!DecodeDeviceId(id, video_device_id.c_str())) return; PropertiesData data; Device::EnumVideoDevices(data.devices); VideoDevice dev; if (!data.GetDevice(dev, video_device_id.c_str())) return; int resType = (int)obs_data_getint(settings, RES_TYPE); int cx = 0, cy = 0; long long interval = 0; VideoFormat format = VideoFormat::Any; if (resType == ResType_Custom) { string resolution = obs_data_getstring(settings, RESOLUTION); if (!ResolutionValid(resolution, cx, cy)) return; interval = obs_data_has_autoselect(settings, FRAME_INTERVAL) ? obs_data_get_autoselect_int(settings, FRAME_INTERVAL) : obs_data_getint(settings, FRAME_INTERVAL); if (interval == FPS_MATCHING) interval = GetOBSFPS(); format = (VideoFormat)obs_data_getint(settings, VIDEO_FORMAT); long long best_interval = numeric_limits<long long>::max(); bool video_format_match = false; if (!CapsMatch(dev, ResolutionMatcher(cx, cy), VideoFormatMatcher(format, video_format_match), ClosestFrameRateSelector(interval, best_interval), FrameRateMatcher(interval)) && !video_format_match) return; interval = best_interval; blog(LOG_INFO, "%s: Using interval %lld", obs_source_getname(source), interval); } videoConfig.name = id.name.c_str(); videoConfig.path = id.path.c_str(); videoConfig.callback = CaptureProc(DShowInput::OnVideoData); videoConfig.param = this; videoConfig.useDefaultConfig = resType == ResType_Preferred; videoConfig.cx = cx; videoConfig.cy = cy; videoConfig.frameInterval = interval; videoConfig.internalFormat = format; if (videoConfig.internalFormat != VideoFormat::MJPEG) videoConfig.format = videoConfig.internalFormat; device.SetVideoConfig(&videoConfig); if (videoConfig.internalFormat == VideoFormat::MJPEG) { videoConfig.format = VideoFormat::XRGB; device.SetVideoConfig(&videoConfig); } if (!device.ConnectFilters()) return; if (device.Start() != Result::Success) return; frame.width = videoConfig.cx; frame.height = videoConfig.cy; frame.format = ConvertVideoFormat(videoConfig.format); frame.full_range = false; frame.flip = (videoConfig.format == VideoFormat::XRGB || videoConfig.format == VideoFormat::ARGB); if (!video_format_get_parameters(VIDEO_CS_601, VIDEO_RANGE_PARTIAL, frame.color_matrix, frame.color_range_min, frame.color_range_max)) { blog(LOG_ERROR, "Failed to get video format parameters for " \ "video format %u", VIDEO_CS_601); } }