123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- 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
- }
- }
|