private ClientStreamerConfig RebuildMainStreamerConfig(IScene scene, int dxFailureCounter) { int bitrate = _coreData.Settings.Bitrate; int audioBitrate = Math.Max(Math.Min(bitrate / 14, 224), 50); // 50..224 int videoBitrate = bitrate - audioBitrate; var rebuildContext = new StreamerRebuildContext(); var result = new ClientStreamerConfig ( scene.Items.Select(s => RebuildSceneVideo(s.Key, s.Value, rebuildContext)).ToArray(), scene.Audios.Select(s => RebuildSceneAudio(s.Key, s.Value, rebuildContext)).Where(s => s != null).ToArray(), RebuildVideoEncoder(videoBitrate, false), RebuildVideoRenderOptions(dxFailureCounter), RebuildAudioEncoder(audioBitrate), new[] { RebuildStreamingOutput(), RebuildRecordingOutput() }.Where(s => s != null).ToArray(), BitrateDrcRatio: 1.0, Disposing: false ); _lastRebuildContext = rebuildContext; return(result); }
private VideoInputConfigBase RebuildInputSource_Lovense(string id, StreamerRebuildContext rebuildContext) { if (PluginContextSetup.IsLoaded()) { return(new VideoInputConfigFull(new InputSetup(Type: PluginContext.PluginName, Input: "", ObjectInput: GetWebBrowserObjectInput(0, 0)))); // h, w set in ClientStreamer } else { return(GetFailedInputSource(id, rebuildContext, InputIssueDesc.PluginIsNotInstalled, $"Lovense plugin is not installed or failed to load")); } }
private AudioInputTrunkConfig RebuildSceneAudio(string id, ISceneAudio s, StreamerRebuildContext rebuildContext) { rebuildContext.SetAudioSource(id, s.Source); var level = s.Muted ? -1000.0 : s.Volume; if (s.Source == null) { rebuildContext.AddAudio(id, InputIssueDesc.NoAudioSelected); Log.Warning($"Audio source is null for '{id}'"); return(null); } else if (s.Source.DesktopAudio) { return(new AudioInputTrunkConfig(id, new InputSetup(DesktopAudioContext.Name, String.Empty), level, f => OnAudioFrame(id, f))); } else if (s.Source.DeviceName != null) { var device = _sources.GetLocalAudioDevice(s.Source.DeviceName); if (device != null) { var opts = DShowOptionsSelector.GetAudioOptions(device); return(new AudioInputTrunkConfig(id, new InputSetup("dshow", $"audio={DShowOptionsSelector.GetDeviceName(device)}", opts), level, f => OnAudioFrame(id, f))); } else { rebuildContext.AddAudio(id, InputIssueDesc.AudioRemoved); Log.Warning($"Audio device not found for '{id}'-{s.Source.DeviceName}"); return(null); } } else { rebuildContext.AddAudio(id, InputIssueDesc.NoAudioSelected); Log.Warning($"Audio source is not specified for '{id}'"); return(null); } }
internal void ProcessMain(ClientStreamer mainStreamer, IDeviceIndicators kpi, StreamerRebuildContext lastRebuildContext) { if (mainStreamer == null) { kpi.CloudOut.State = IndicatorState.Disabled; kpi.Encoder.State = IndicatorState.Disabled; _cloudOutAverage = null; } else { if (_cloudOutAverage == null) { _cloudOutAverage = new AverageIntValue(3, true); } var stat = mainStreamer.ResourceManager.GetStatistics(out var period); var overload = mainStreamer.ResourceManager.GetOverload(); int failedInputs = 0; if (_coreData.Root.Settings.SelectedScene != null && _coreData.Root.Scenes.TryGetValue(_coreData.Root.Settings.SelectedScene, out var scene) && scene.Owner == _coreData.ThisDeviceId) { ProcessInputs(stat, lastRebuildContext.Videos, "V", _prevVideos, scene.VideoIssues, s => scene.VideoIssues = s); ProcessInputs(stat, lastRebuildContext.Audios, "A", _prevAudios, scene.AudioIssues, s => scene.AudioIssues = s); if (scene.VideoIssues != null) { foreach (var vi in scene.VideoIssues) { if (scene.Items.TryGetValue(vi.Id, out var item) && item.Visible) { failedInputs++; } } } if (scene.AudioIssues != null) { foreach (var vi in scene.AudioIssues) { if (scene.Audios.TryGetValue(vi.Id, out var item) && !item.Muted) { failedInputs++; } } } } ProcessMainKpi(stat, kpi, period, overload, failedInputs); } }
private VideoInputConfigBase RebuildInputSource_Capture(string id, SceneItemSourceCapture capture, bool isWindow, StreamerRebuildContext rebuildContext) { var ci = _sources.GetOrCreateCaptureItem(capture.Source, isWindow); if (ci?.Wrapped != null) { var request = new ScreenCaptureRequest { Id = $"{capture.Source.CaptureId}", Cursor = capture.CaptureCursor, InitialSize = ci.Wrapped.Size, Item = ci.Wrapped, DebugName = capture.Source.Name }; return(new VideoInputConfigFull(new InputSetup(Type: ScreenCaptureContext.Name, Input: ci.Prefix + capture.Source.CaptureId, ObjectInput: request))); } else { return(GetFailedInputSource(id, rebuildContext, InputIssueDesc.CaptureNotFound, $"Capture target '{capture.Source.Name}' not found")); } }
private VideoInputConfigBase RebuildInputSource_Web(string id, SceneItemSourceWeb web, StreamerRebuildContext rebuildContext) { return(new VideoInputConfigFull(new InputSetup(Type: WebBrowserContext.Name, Input: web.Url, ObjectInput: GetWebBrowserObjectInput(web.Width, web.Height)))); }
private VideoInputConfigBase RebuildInputSource_Image(string id, SceneItemSourceImage image, StreamerRebuildContext rebuildContext) { if (_coreData.Root.Resources.TryGetValue(image.ResourceId, out var resource)) { var data = _resourceService.GetResource(image.ResourceId); if (data == null || data.Length == 0) { return(GetFailedInputSource(id, rebuildContext, InputIssueDesc.ImageNotFound, $"Resource {image.ResourceId} has no data")); } SingleFrameType type = SingleFrameType.Cube; if (resource.Info.Type == ResourceType.ImageJpeg) { type = SingleFrameType.Jpg; } else if (resource.Info.Type == ResourceType.ImagePng) { type = SingleFrameType.Png; } else { return(GetFailedInputSource(id, rebuildContext, InputIssueDesc.ImageUnknownFormat, $"Resource {image.ResourceId} has Unknown format {resource.Info.Type}")); } return(new VideoInputConfigSingleFrame(new FixedFrameData(resource.Info.DataHash, data, type))); } else { return(GetFailedInputSource(id, rebuildContext, InputIssueDesc.ImageNotFound, $"Resource {image.ResourceId} not found")); } }
private VideoInputConfigBase RebuildInputSource_Device(string id, SceneItemSourceDevice device, ISceneItem item, StreamerRebuildContext rebuildContext) { var localDevice = _sources.GetLocalVideoDevice(device.DeviceName); if (localDevice != null) { var options = DShowOptionsSelector.GetVideoOptions(localDevice, _coreData.Settings.Fps, _coreData.Settings.Resolution, item); return(new VideoInputConfigFull(new InputSetup( Type: "dshow", Input: $"video={DShowOptionsSelector.GetDeviceName(localDevice)}", Options: options))); } else { return(GetFailedInputSource(id, rebuildContext, InputIssueDesc.VideoRemoved, $"Video device '{device?.DeviceName}' not found")); } }
private VideoInputConfigSingleFrame GetFailedInputSource(string id, StreamerRebuildContext rebuildContext, InputIssueDesc reason, string log) { Log.Error($"Bad input source in model: {log}"); rebuildContext.AddVideo(id, reason); return(new VideoInputConfigSingleFrame(new FixedFrameData(nameof(StaticResources.BadSource), StaticResources.BadSource, SingleFrameType.Png))); }
private VideoInputConfigBase RebuildInputSource(string id, SceneItemSource source, ISceneItem item, StreamerRebuildContext rebuildContext) { rebuildContext.SetVideoSource(id, source); if (source.Device != null) { return(RebuildInputSource_Device(id, source.Device, item, rebuildContext)); } else if (source.Image != null) { return(RebuildInputSource_Image(id, source.Image, rebuildContext)); } else if (source.Lovense != null) { return(RebuildInputSource_Lovense(id, rebuildContext)); } else if (source.Web != null) { return(RebuildInputSource_Web(id, source.Web, rebuildContext)); } else if (source.CaptureDisplay != null) { return(RebuildInputSource_Capture(id, source.CaptureDisplay, false, rebuildContext)); } else if (source.CaptureWindow != null) { return(RebuildInputSource_Capture(id, source.CaptureWindow, true, rebuildContext)); } else { return(GetFailedInputSource(id, rebuildContext, InputIssueDesc.UnknownTypOfSource, "Video source is unknown")); } }
private VideoInputTrunkConfig RebuildSceneVideo(string id, ISceneItem s, StreamerRebuildContext rebuildContext) { var input = RebuildInputSource(id, s.Source, s, rebuildContext); return(new VideoInputTrunkConfig(id, input, RebuildFilters(s.Filters), ModelToStreamerTranslator.Translate(s.Rect), AdjustPtzHFlip(ModelToStreamerTranslator.Translate(s.Ptz), s.Filters), s.Visible, s.ZOrder)); }