コード例 #1
0
        /// <summary>
        ///   Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources
        /// </summary>
        private void Dispose()
        {
            this.clipper?.Dispose();
            this.clipper = null;

            this.toolbar?.Dispose();
            this.toolbar = null;

            this.motionSession?.Dispose();
            this.motionSession = null;

            this.codec?.Dispose();
            this.codec = null;

            this.captureDevice?.Dispose();
            this.captureDevice = null;

            this.stream?.Dispose();
            this.stream = null;

            if (this.handlers != null)
            {
                foreach (Handler handler in this.handlers)
                {
                    handler.Dispose();
                }
            }

            this.handlers = null;
        }
コード例 #2
0
        /// <summary>
        ///   Starts the workflow interactively
        /// </summary>
        internal async Task StartAsync(HudContainerInfo container)
        {
            this.currentContainer = container;

            Log.Info($"starting {Type} workflow on {container.ContainerType} container");
            await AcquireRegionAsync();

            if (Region.Size.Width <= Clipper.MinimumWidth || Region.Size.Height <= Clipper.MinimumHeight)
            {
                Log.Trace("capture dismissed");
                Finish();
                return;
            }

            if (this.captureDevice == null || !Equals(this.captureDevice.Size.ToTuple(), Region.Size.ToTuple()))
            {
                // dispose old video provider if size changed
                this.captureDevice?.Dispose();

                // video provider will capture frames
                Log.Debug("creating capture device");
                this.captureDevice = CaptureDeviceFactory.CreateVideoCaptureDevice(
                    Region.Location.X,
                    Region.Location.Y,
                    Region.Size.Width,
                    Region.Size.Height);

                // TODO: create and bind transforms
            }

            // create destination stream, a MultiStream which will act as some kind of stream multiplexer wrapping multiple
            // "sub-streams" onto one
            // TODO: add IImmediateHandler's to the MultiStream
            this.stream = new MultiStream();

            // create codec instance
            if (Type == WorkflowType.Still)
            {
                this.codec = Application.ExtensionManager.CreateObject <StillImageCodec>(Codec.TypeName,
                                                                                         Region.Size.Width,
                                                                                         Region.Size.Height,
                                                                                         this.stream);
            }
            else if (Type == WorkflowType.Motion)
            {
                this.codec = Application.ExtensionManager.CreateObject <VideoCodec>(Codec.TypeName,
                                                                                    Region.Size.Width,
                                                                                    Region.Size.Height,
                                                                                    this.stream);
            }

            // create handlers
            this.handlers = Handlers.Select(handlerData => {
                Handler handler = Application.ExtensionManager.CreateObject <Handler>(
                    handlerData.TypeName,
                    this,
                    this.codec,
                    this.stream,
                    handlerData.Options);

                if (handler is IStreamWrapper streamWrapperHandler)
                {
                    // add stream wrapper to the multi-stream
                    this.stream.Add(streamWrapperHandler.OutputStream);
                    Log.Trace("added stream wrapper handler: " + handlerData.TypeName);
                }

                return(handler);
            }).ToArray();

            if (Type == WorkflowType.Still)
            {
                // still image -- we do not need our stream to be filesystem-backed, as still images can't really be *that*
                // large... I hope
                this.stream.Add(new MemoryStream());

                Log.Info("capturing screen");
                this.captureDevice.AcquireFrame();
                VideoFrame frame = this.captureDevice.LockFrame();

                Log.Info("encoding capture");
                this.codec.Start();
                this.codec.Feed(frame);
                this.codec.Dispose();

                // unlock and release capture
                this.captureDevice.UnlockFrame(frame);
                this.captureDevice.ReleaseFrame();

                Finish();
            }
            else
            {
                // motion capture -- stand back and don't underestimate my expertise on googling
                // save output to a temporary file
                Log.Info("starting recording session");

                // create toolbar
                this.toolbar = new Toolbar(Application.HudManager.GetContainer());
                this.clipper?.AttachToolbar(this.toolbar);

                /* bind toolbar events */
                // option events
                this.toolbar.OnOptionsRequested += delegate(object sender, ToolbarOptionRequestType optionType) {
                    switch (optionType)
                    {
                    case ToolbarOptionRequestType.Generic:
                        try {
                            new OptionsWindow().Show();
                        } catch {
                            /* already open */
                        }

                        break;

                    default:
                        throw new NotImplementedException();
                    }
                };

                // recording control intents
                this.toolbar.OnRecordingIntentReceived += delegate(object sender, ToolbarRecordingControlIntent controlIntent) {
                    try {
                        Log.Info($"received recording control intent: {controlIntent}");
                        this.toolbar.SetPrimaryButtonState(enabled: false);

                        switch (controlIntent)
                        {
                        case ToolbarRecordingControlIntent.Start:
                            /* start recording */
                            if (!(this.motionSession?.Disposed ?? true))
                            {
                                throw new InvalidOperationException("A previous motion capture session has not been closed");
                            }

                            if (!(this.codec is VideoCodec))
                            {
                                throw new NotSupportedException("The current codec does not allow multiple frames");
                            }

                            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                            if (
                                this.captureDevice is DxgiVideoCaptureDevice
                                dxgiCaptureDevice && // make sure our capture device is DXGI-enabled
                                this.codec is IDxgiEnabledVideoCodec dxgiCodec)
                            {
                                // make sure our codec is DXGI-compatible
                                // make sure we have the same D3D device for all sources
                                Device device = dxgiCaptureDevice.Devices.First();
                                if (dxgiCaptureDevice.Devices.All(d => d == device))
                                {
                                    // set device to be bound to the DXGI device manager
                                    // TODO: optimize DxgiVideoProvider so that it only creates one device for each adapter
                                    // TODO: allow ID3DCodec's to operate on multiple DXGI devices
                                    dxgiCodec.BindDevice(device);
                                    Log.Info("bound DXGI device to codec");
                                }
                            }

                            // create motion capture session and change toolbar button intent
                            this.motionSession = new MotionCaptureSession((VideoCodec)this.codec, this.captureDevice);
                            this.toolbar.SetPrimaryButtonState(ToolbarRecordingControlIntent.Stop);
                            break;

                        case ToolbarRecordingControlIntent.Stop:
                            this.motionSession.Dispose();
                            Finish();
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    } finally {
                        this.toolbar?.SetPrimaryButtonState(enabled: true);
                    }
                };
            }
        }