Newer
Older
Qwilight / Qwilight / System / MediaInputSystem.cs
@Taehui Taehui on 14 Nov 5 KB 2023-11-15 오전 12:09
using Microsoft.Graphics.Canvas;
using Qwilight.UIComponent;
using Qwilight.Utilities;
using System.Collections.ObjectModel;
using Windows.Graphics.Imaging;
using Windows.Media.Capture;
using Windows.Media.Capture.Frames;
using Windows.Media.MediaProperties;

namespace Qwilight
{
    public sealed class MediaInputSystem : Model
    {
        public static readonly MediaInputSystem Instance = QwilightComponent.GetBuiltInData<MediaInputSystem>(nameof(MediaInputSystem));

        readonly CanvasDevice _mediaFrameSystem = new CanvasDevice();
        MediaCapture _mediaInputSystem;
        CanvasBitmap _mediaFrame;
        MediaFrameReader _mediaInputComputer;
        MediaInputItem? _mediaInputItem;
        MediaInputQuality? _mediaInputQuality;

        public MediaInputItem? MediaInputItemValue
        {
            get => _mediaInputItem;

            set
            {
                if (SetProperty(ref _mediaInputItem, value, nameof(MediaInputItemValue)) && value.HasValue)
                {
                    InitMediaInput();

                    async void InitMediaInput()
                    {
                        _mediaInputComputer = await _mediaInputSystem.CreateFrameReaderAsync(_mediaInputSystem.FrameSources[value.Value.ID], MediaEncodingSubtypes.Bgra8);
                        _mediaInputComputer.FrameArrived += OnMediaFrameAvailable;
                        await _mediaInputComputer.StartAsync();
                    }
                }
            }
        }

        public MediaInputQuality? MediaInputQualityValue
        {
            get => _mediaInputQuality;

            set
            {
                if (SetProperty(ref _mediaInputQuality, value, nameof(MediaInputQualityValue)) && value.HasValue)
                {
                    SetMediaInputQuality();

                    async void SetMediaInputQuality()
                    {
                        await _mediaInputSystem.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, value.Value.Data);
                    }
                }
            }
        }

        public ObservableCollection<MediaInputQuality> MediaInputQualityCollection { get; } = new();

        public ObservableCollection<MediaInputItem> MediaInputItemCollection { get; } = new();

        public CanvasBitmap MediaFrame { get; set; }

        public MediaInputSystem() => GetMediaInputItems();

        public void PaintMediaInput(CanvasDrawingSession targetSession, ref Bound r, float mediaInputFaint)
        {
            if (MediaFrame != null)
            {
                var mediaFrameBound = MediaFrame.Bounds;
                Utility.SetFilledMediaDrawing(ref r, Configure.Instance.IsMediaFill, mediaFrameBound.Width, mediaFrameBound.Height, r.Position0, r.Position1, r.Length, r.Height);
                targetSession.PaintDrawing(ref r, MediaFrame, mediaInputFaint);
            }
        }

        public async void GetMediaInputItems()
        {
            if (Configure.Instance.MediaInput)
            {
                try
                {
                    _mediaInputSystem?.Dispose();
                    _mediaInputSystem = new MediaCapture();
                    await _mediaInputSystem.InitializeAsync(new MediaCaptureInitializationSettings
                    {
                        MemoryPreference = MediaCaptureMemoryPreference.Cpu,
                        StreamingCaptureMode = StreamingCaptureMode.Video
                    });
                    Utility.SetUICollection(MediaInputItemCollection, _mediaInputSystem.FrameSources.Select(pair => new MediaInputItem
                    {
                        ID = pair.Key,
                        Name = pair.Value.Info.DeviceInformation.Name
                    }).ToArray());
                    Utility.SetUICollection(MediaInputQualityCollection, _mediaInputSystem.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoRecord).Cast<VideoEncodingProperties>().Select(vep => new MediaInputQuality
                    {
                        Data = vep
                    }).Order().ToArray());
                }
                catch
                {
                    MediaInputItemCollection.Clear();
                    MediaInputQualityCollection.Clear();
                }
                MediaInputItemValue = MediaInputItemCollection.Count > 0 ? MediaInputItemCollection.First() : null;
                MediaInputQualityValue = MediaInputQualityCollection.Count > 0 ? MediaInputQualityCollection.First() : null;
            }
        }

        public void CloseMediaInput()
        {
            _mediaInputComputer?.Dispose();
            _mediaInputSystem?.Dispose();
        }

        void OnMediaFrameAvailable(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
        {
            try
            {
                using (var mediaFrame = sender.TryAcquireLatestFrame().VideoMediaFrame.SoftwareBitmap)
                using (var mediaFrameModified = mediaFrame.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || mediaFrame.BitmapAlphaMode != BitmapAlphaMode.Ignore ? SoftwareBitmap.Convert(mediaFrame, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore) : mediaFrame)
                {
                    _mediaFrame?.Dispose();
                    _mediaFrame = CanvasBitmap.CreateFromSoftwareBitmap(_mediaFrameSystem, mediaFrameModified);
                    if (MediaFrame == null || MediaFrame.Bounds.Width != _mediaFrame.Bounds.Width || MediaFrame.Bounds.Height != _mediaFrame.Bounds.Height)
                    {
                        MediaFrame?.Dispose();
                        MediaFrame = CanvasBitmap.CreateFromSoftwareBitmap(CanvasDevice.GetSharedDevice(), mediaFrameModified);
                    }
                }
                MediaFrame.CopyPixelsFromBitmap(_mediaFrame);
            }
            catch
            {
            }
        }
    }
}