UWP 给MediaPlayer控件内播放的视频添加基本特效,比如对比度,饱和度,锐利度,色温等.
----------------------------
先看参考[重要]:
英文版
https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/custom-video-effects
中文版
https://docs.microsoft.com/zh-cn/windows/uwp/audio-video-camera/custom-video-effects
-----------------------------
正文
---
根据前面的参考,添加WinRT组件项目,并使用win2d插件的方式添加特效
WinRT组件代码如下:
using Windows.Media.Effects; using Windows.Media.MediaProperties; using Windows.Foundation.Collections; using Windows.Graphics.DirectX.Direct3D11; using Windows.Graphics.Imaging; using System.Collections.Generic; using System.Runtime.InteropServices; using Microsoft.Graphics.Canvas; using Microsoft.Graphics.Canvas.Effects; namespace ClockLightPlayerRuntime { public sealed class MyVideoEffect : IBasicVideoEffect { private CanvasDevice canvasDevice; public void SetEncodingProperties(VideoEncodingProperties encodingProperties, IDirect3DDevice device) { canvasDevice = CanvasDevice.CreateFromDirect3D11Device(device); } public void ProcessFrame(ProcessVideoFrameContext context) { using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromDirect3D11Surface(canvasDevice, context.InputFrame.Direct3DSurface)) using (CanvasRenderTarget renderTarget = CanvasRenderTarget.CreateFromDirect3D11Surface(canvasDevice, context.OutputFrame.Direct3DSurface)) using (CanvasDrawingSession ds = renderTarget.CreateDrawingSession()) { bool hasColor = (Contrast != 0.0f || Brightness != 0.0f || Saturation != 0.0f); hasColor = true; if (hasColor) { var effect = getColorEffect(inputBitmap, Contrast+1, Brightness, Saturation+1); ds.DrawImage(effect); } // 色温 if (Temperature != 0 | Tint != 0) { ds.DrawImage( new TemperatureAndTintEffect { Source = inputBitmap, Temperature = Temperature, Tint = Tint, }); } // 锐利度 if (Sharpness != 0 | SharpnessThreshold != 0) { var SharpEffect = new SharpenEffect { Source = inputBitmap, Amount = Sharpness, Threshold = SharpnessThreshold }; ds.DrawImage(SharpEffect); } } } public ColorMatrixEffect getColorEffect(CanvasBitmap source, float c, float b, float s) { const float lumR = 0.2125f; const float lumG = 0.7154f; const float lumB = 0.0721f; float t = (1.0f - c) / 2.0f; float sr = (1.0f - s) * lumR; float sg = (1.0f - s) * lumG; float sb = (1.0f - s) * lumB; Matrix5x4 matrix = new Matrix5x4 { M11 = c * (sr + s), M12 = c * (sr), M13 = c * (sr), M14 = 0, M21 = c * (sg), M22 = c * (sg + s), M23 = c * (sg), M24 = 0, M31 = c * (sb), M32 = c * (sb), M33 = c * (sb + s), M34 = 0, M41 = 0, M42 = 0, M43 = 0, M44 = 1, M51 = t + b, M52 = t + b, M53 = t + b, M54 = 0, }; var colorMatrixEffect = new ColorMatrixEffect { ColorMatrix = matrix, Source = source }; return colorMatrixEffect; } public void Close(MediaEffectClosedReason reason) { //throw new System.NotImplementedException(); } private int frameCount; public void DiscardQueuedFrames() { frameCount = 0; } public bool IsReadOnly { get { return false; } } public IReadOnlyList<VideoEncodingProperties> SupportedEncodingProperties { get { var encodingProperties = new VideoEncodingProperties(); encodingProperties.Subtype = "ARGB32"; return new List<VideoEncodingProperties>() { encodingProperties }; } } public MediaMemoryTypes SupportedMemoryTypes { get { return MediaMemoryTypes.Gpu; } } public bool TimeIndependent { get { return true; } } private IPropertySet configuration; public void SetProperties(IPropertySet configuration) { this.configuration = configuration; } public float Brightness { get { object val; if (configuration != null && configuration.TryGetValue("Brightness", out val)) { return (float)val; } return 0; } set { ChangeProperty("Brightness", value); } } public void ChangeProperty(string PropertyName, object Value) { if (configuration.TryGetValue(PropertyName, out object val)) { configuration[PropertyName] = Value; } else { configuration.Add(PropertyName, Value); } } public float Contrast { get { object val; if (configuration != null && configuration.TryGetValue("Contrast", out val)) { return (float)val; } return 0; } set { ChangeProperty("Contrast", value); } } public float Saturation { get { object val; if (configuration != null && configuration.TryGetValue("Saturation", out val)) { return (float)val; } return 0; } set { ChangeProperty("Saturation", value); } } public float Temperature { get { object val; if (configuration != null && configuration.TryGetValue("Temperature", out val)) { return (float)val; } return 0; } set { ChangeProperty("Temperature", value); } } public float Tint { get { object val; if (configuration != null && configuration.TryGetValue("Tint", out val)) { return (float)val; } return 0; } set { ChangeProperty("Tint", value); } } public float Sharpness { get { object val; if (configuration != null && configuration.TryGetValue("Sharpness", out val)) { return (float)val; } return 0; } set { ChangeProperty("Sharpness", value); } } public float SharpnessThreshold { get { object val; if (configuration != null && configuration.TryGetValue("SharpnessThreshold", out val)) { return (float)val; } return 0; } set { ChangeProperty("SharpnessThreshold", value); } } } }
然后,引用此组件.添加辅助类
using System; using System.Threading; using System.Threading.Tasks; using Windows.Foundation.Collections; using Windows.Media.Core; using Windows.Media.Playback; using Windows.Storage.Streams; namespace WindowsMediaPlayer.Helpers { public class VideoEffectConfiguration { public PropertySet configuration { get; set; } public void AddVideoEffect(MediaPlayer player) { configuration = new PropertySet { {"Brightness" ,0f}, {"Contrast" ,0f}, {"Saturation" ,0f}, {"Temperature" ,0f}, {"Tint" ,0f}, {"Sharpness" ,0f}, {"SharpnessThreshold" ,0f}, }; player.AddVideoEffect("ClockLightPlayerRuntime.MyVideoEffect", true, configuration); } public float Brightness { get { object val; if (configuration != null && configuration.TryGetValue("Brightness", out val)) { return (float)val; } return 0; } set { ChangeProperty("Brightness", value); } } public void ChangeProperty<T>(string PropertyName,T Value) { if (configuration.TryGetValue(PropertyName, out object val)) { configuration[PropertyName] = Value; } else { configuration.Add(PropertyName, Value); } } public float Contrast { get { object val; if (configuration != null && configuration.TryGetValue("Contrast", out val)) { return (float)val; } return 0; } set { ChangeProperty("Contrast", value); } } public float Saturation { get { object val; if (configuration != null && configuration.TryGetValue("Saturation", out val)) { return (float)val; } return 0; } set { ChangeProperty("Saturation", value); } } public float Temperature { get { object val; if (configuration != null && configuration.TryGetValue("Temperature", out val)) { return (float)val; } return 0.01f; } set { if (value==0) { value = 0.01f; } ChangeProperty("Temperature", value); } } public float Tint { get { object val; if (configuration != null && configuration.TryGetValue("Tint", out val)) { return (float)val; } return 0; } set { ChangeProperty("Tint", value); } } public float Sharpness { get { object val; if (configuration != null && configuration.TryGetValue("Sharpness", out val)) { return (float)val; } return 0; } set { ChangeProperty("Sharpness", value); } } public float SharpnessThreshold { get { object val; if (configuration != null && configuration.TryGetValue("SharpnessThreshold", out val)) { return (float)val; } return 0; } set { ChangeProperty("SharpnessThreshold", value); } } } }
使用起来很简单,在给MeidaPlayer/MediaElement设置source之前
VideoEffectConfiguration.AddVideoEffect(mediaElement.MediaPlayer); //mediaElement.MediaPlayer.Source = playbackItem;调整VideoEffectConfiguration的各项属性,就可以改变视频呈现的基本特效.