コード例 #1
0
        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);
        }
コード例 #2
0
 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"));
     }
 }
コード例 #3
0
        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);
            }
        }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
        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"));
            }
        }
コード例 #6
0
 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))));
 }
コード例 #7
0
        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"));
            }
        }
コード例 #8
0
        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"));
            }
        }
コード例 #9
0
 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)));
 }
コード例 #10
0
 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"));
     }
 }
コード例 #11
0
        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));
        }