UP-Viagg-io/Viagg-io/Assets/Packages/AVProVideo/Runtime/Scripts/Components/ResolveToRenderTexture.cs

235 lines
6.9 KiB
C#
Executable File

using UnityEngine;
//-----------------------------------------------------------------------------
// Copyright 2019-2023 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo
{
/// Renders the video texture to a RenderTexture - either one provided by the user (external) or to an internal one.
/// The video frames can optionally be "resolved" to unpack packed alpha, display a single stereo eye, generate mip maps, and apply colorspace conversions
[AddComponentMenu("AVPro Video/Resolve To RenderTexture", 330)]
[HelpURL("https://www.renderheads.com/products/avpro-video/")]
public class ResolveToRenderTexture : MonoBehaviour
{
[SerializeField] MediaPlayer _mediaPlayer = null;
[SerializeField] VideoResolveOptions _options = VideoResolveOptions.Create();
[SerializeField] VideoRender.ResolveFlags _resolveFlags = (VideoRender.ResolveFlags.ColorspaceSRGB | VideoRender.ResolveFlags.Mipmaps | VideoRender.ResolveFlags.PackedAlpha | VideoRender.ResolveFlags.StereoLeft);
[SerializeField] RenderTexture _externalTexture = null;
private Material _materialResolve;
private bool _isMaterialSetup;
private bool _isMaterialDirty;
private bool _isMaterialOES;
private RenderTexture _internalTexture;
private int _textureFrameCount = -1;
// Material used for blitting the texture as we need a shader to provide clamp to border colour style texture sampling
private Material _materialBlit;
private int _srcTexId;
public MediaPlayer MediaPlayer
{
get
{
return _mediaPlayer;
}
set
{
ChangeMediaPlayer(value);
}
}
public VideoResolveOptions VideoResolveOptions
{
get
{
return _options;
}
set
{
_options = value;
_isMaterialDirty = true;
}
}
public RenderTexture ExternalTexture
{
get
{
return _externalTexture;
}
set
{
_externalTexture = value;
}
}
public RenderTexture TargetTexture
{
get
{
if (_externalTexture == null)
return _internalTexture;
return _externalTexture;
}
}
public void SetMaterialDirty()
{
_isMaterialDirty = true;
}
private void ChangeMediaPlayer(MediaPlayer mediaPlayer)
{
if (_mediaPlayer != mediaPlayer)
{
_mediaPlayer = mediaPlayer;
_textureFrameCount = -1;
_isMaterialSetup = false;
_isMaterialDirty = true;
Resolve();
}
}
void Start()
{
_isMaterialOES = _mediaPlayer != null ? _mediaPlayer.IsUsingAndroidOESPath() : false;
_materialResolve = VideoRender.CreateResolveMaterial(_isMaterialOES);
VideoRender.SetupMaterialForMedia(_materialResolve, _mediaPlayer, -1);
_materialBlit = new Material(Shader.Find("AVProVideo/Internal/Blit"));
_srcTexId = Shader.PropertyToID("_SrcTex");
}
void LateUpdate()
{
Debug.Assert(_mediaPlayer != null);
Resolve();
}
public void Resolve()
{
ITextureProducer textureProducer = _mediaPlayer != null ? _mediaPlayer.TextureProducer : null;
if (textureProducer == null)
return;
if (textureProducer.GetTexture())
{
// Check for a swap between OES and none-OES
bool playerIsOES = _mediaPlayer.IsUsingAndroidOESPath();
if (_isMaterialOES != playerIsOES)
{
_isMaterialOES = playerIsOES;
_materialResolve = VideoRender.CreateResolveMaterial(playerIsOES);
}
if (!_isMaterialSetup)
{
VideoRender.SetupMaterialForMedia(_materialResolve, _mediaPlayer, -1);
_isMaterialSetup = true;
_isMaterialDirty = true;
}
if (_isMaterialDirty)
{
VideoRender.SetupResolveMaterial(_materialResolve, _options);
_isMaterialDirty = false;
}
int textureFrameCount = textureProducer.GetTextureFrameCount();
if (textureFrameCount != _textureFrameCount)
{
_internalTexture = VideoRender.ResolveVideoToRenderTexture(_materialResolve, _internalTexture, textureProducer, _resolveFlags);
_textureFrameCount = textureFrameCount;
if (_internalTexture && _externalTexture)
{
float srcAspectRatio = (float)_internalTexture.width / (float)_internalTexture.height;
float dstAspectRatio = (float)_externalTexture.width / (float)_externalTexture.height;
Vector2 offset = Vector2.zero;
Vector2 scale = new Vector2(1.0f, 1.0f);
// No point in handling the aspect ratio if the textures dimension's are the same
if (srcAspectRatio != dstAspectRatio)
{
switch (_options.aspectRatio)
{
case VideoResolveOptions.AspectRatio.NoScaling:
scale.x = (float)_externalTexture.width / (float)_internalTexture.width;
scale.y = (float)_externalTexture.height / (float)_internalTexture.height;
offset.x = (1.0f - scale.x) * 0.5f;
offset.y = (1.0f - scale.y) * 0.5f;
break;
case VideoResolveOptions.AspectRatio.FitVertically:
scale.x = (float)_internalTexture.height / (float)_internalTexture.width * dstAspectRatio;
offset.x = (1.0f - scale.x) * 0.5f;
break;
case VideoResolveOptions.AspectRatio.FitHorizontally:
scale.y = (float)_externalTexture.height / (float)_externalTexture.width * srcAspectRatio;
offset.y = (1.0f - scale.y) * 0.5f;
break;
case VideoResolveOptions.AspectRatio.FitInside:
{
if (srcAspectRatio > dstAspectRatio)
goto case VideoResolveOptions.AspectRatio.FitHorizontally;
else if (srcAspectRatio < dstAspectRatio)
goto case VideoResolveOptions.AspectRatio.FitVertically;
} break;
case VideoResolveOptions.AspectRatio.FitOutside:
{
if (srcAspectRatio > dstAspectRatio)
goto case VideoResolveOptions.AspectRatio.FitVertically;
else if (srcAspectRatio < dstAspectRatio)
goto case VideoResolveOptions.AspectRatio.FitHorizontally;
} break;
case VideoResolveOptions.AspectRatio.Stretch:
break;
}
}
// NOTE: This blit can be removed once we can ResolveVideoToRenderTexture is made not to recreate textures
// NOTE: This blit probably doesn't do correct linear/srgb conversion if the colorspace settings differ, may have to use GL.sRGBWrite
// NOTE: Cannot use _MainTex as Graphics.Blit replaces the texture offset and scale when using a material
_materialBlit.SetTexture(_srcTexId, _internalTexture);
_materialBlit.SetTextureOffset(_srcTexId, offset);
_materialBlit.SetTextureScale(_srcTexId, scale);
Graphics.Blit(null, _externalTexture, _materialBlit, 0);
}
}
}
}
void OnDisable()
{
if (_internalTexture)
{
RenderTexture.ReleaseTemporary(_internalTexture); _internalTexture = null;
}
}
void OnDestroy()
{
if (_materialResolve)
{
Destroy(_materialResolve); _materialResolve = null;
}
}
#if false
void OnGUI()
{
if (TargetTexture)
{
GUI.DrawTexture(new Rect(0f, 0f, Screen.width * 0.8f, Screen.height * 0.8f), TargetTexture, ScaleMode.ScaleToFit, true);
}
}
#endif
}
}