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的各项属性,就可以改变视频呈现的基本特效.