ResolveToRenderTexture.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. using UnityEngine;
  2. //-----------------------------------------------------------------------------
  3. // Copyright 2019-2023 RenderHeads Ltd. All rights reserved.
  4. //-----------------------------------------------------------------------------
  5. namespace RenderHeads.Media.AVProVideo
  6. {
  7. /// Renders the video texture to a RenderTexture - either one provided by the user (external) or to an internal one.
  8. /// The video frames can optionally be "resolved" to unpack packed alpha, display a single stereo eye, generate mip maps, and apply colorspace conversions
  9. [AddComponentMenu("AVPro Video/Resolve To RenderTexture", 330)]
  10. [HelpURL("https://www.renderheads.com/products/avpro-video/")]
  11. public class ResolveToRenderTexture : MonoBehaviour
  12. {
  13. [SerializeField] MediaPlayer _mediaPlayer = null;
  14. [SerializeField] VideoResolveOptions _options = VideoResolveOptions.Create();
  15. [SerializeField] VideoRender.ResolveFlags _resolveFlags = (VideoRender.ResolveFlags.ColorspaceSRGB | VideoRender.ResolveFlags.Mipmaps | VideoRender.ResolveFlags.PackedAlpha | VideoRender.ResolveFlags.StereoLeft);
  16. [SerializeField] RenderTexture _externalTexture = null;
  17. private Material _materialResolve;
  18. private bool _isMaterialSetup;
  19. private bool _isMaterialDirty;
  20. private bool _isMaterialOES;
  21. private RenderTexture _internalTexture;
  22. private int _textureFrameCount = -1;
  23. // Material used for blitting the texture as we need a shader to provide clamp to border colour style texture sampling
  24. private Material _materialBlit;
  25. private int _srcTexId;
  26. public MediaPlayer MediaPlayer
  27. {
  28. get
  29. {
  30. return _mediaPlayer;
  31. }
  32. set
  33. {
  34. ChangeMediaPlayer(value);
  35. }
  36. }
  37. public VideoResolveOptions VideoResolveOptions
  38. {
  39. get
  40. {
  41. return _options;
  42. }
  43. set
  44. {
  45. _options = value;
  46. _isMaterialDirty = true;
  47. }
  48. }
  49. public RenderTexture ExternalTexture
  50. {
  51. get
  52. {
  53. return _externalTexture;
  54. }
  55. set
  56. {
  57. _externalTexture = value;
  58. }
  59. }
  60. public RenderTexture TargetTexture
  61. {
  62. get
  63. {
  64. if (_externalTexture == null)
  65. return _internalTexture;
  66. return _externalTexture;
  67. }
  68. }
  69. public void SetMaterialDirty()
  70. {
  71. _isMaterialDirty = true;
  72. }
  73. private void ChangeMediaPlayer(MediaPlayer mediaPlayer)
  74. {
  75. if (_mediaPlayer != mediaPlayer)
  76. {
  77. _mediaPlayer = mediaPlayer;
  78. _textureFrameCount = -1;
  79. _isMaterialSetup = false;
  80. _isMaterialDirty = true;
  81. Resolve();
  82. }
  83. }
  84. void Start()
  85. {
  86. _isMaterialOES = _mediaPlayer != null ? _mediaPlayer.IsUsingAndroidOESPath() : false;
  87. _materialResolve = VideoRender.CreateResolveMaterial(_isMaterialOES);
  88. VideoRender.SetupMaterialForMedia(_materialResolve, _mediaPlayer, -1);
  89. _materialBlit = new Material(Shader.Find("AVProVideo/Internal/Blit"));
  90. _srcTexId = Shader.PropertyToID("_SrcTex");
  91. }
  92. void LateUpdate()
  93. {
  94. Debug.Assert(_mediaPlayer != null);
  95. Resolve();
  96. }
  97. public void Resolve()
  98. {
  99. ITextureProducer textureProducer = _mediaPlayer != null ? _mediaPlayer.TextureProducer : null;
  100. if (textureProducer == null)
  101. return;
  102. if (textureProducer.GetTexture())
  103. {
  104. // Check for a swap between OES and none-OES
  105. bool playerIsOES = _mediaPlayer.IsUsingAndroidOESPath();
  106. if (_isMaterialOES != playerIsOES)
  107. {
  108. _isMaterialOES = playerIsOES;
  109. _materialResolve = VideoRender.CreateResolveMaterial(playerIsOES);
  110. }
  111. if (!_isMaterialSetup)
  112. {
  113. VideoRender.SetupMaterialForMedia(_materialResolve, _mediaPlayer, -1);
  114. _isMaterialSetup = true;
  115. _isMaterialDirty = true;
  116. }
  117. if (_isMaterialDirty)
  118. {
  119. VideoRender.SetupResolveMaterial(_materialResolve, _options);
  120. _isMaterialDirty = false;
  121. }
  122. int textureFrameCount = textureProducer.GetTextureFrameCount();
  123. if (textureFrameCount != _textureFrameCount)
  124. {
  125. _internalTexture = VideoRender.ResolveVideoToRenderTexture(_materialResolve, _internalTexture, textureProducer, _resolveFlags);
  126. _textureFrameCount = textureFrameCount;
  127. if (_internalTexture && _externalTexture)
  128. {
  129. float srcAspectRatio = (float)_internalTexture.width / (float)_internalTexture.height;
  130. float dstAspectRatio = (float)_externalTexture.width / (float)_externalTexture.height;
  131. Vector2 offset = Vector2.zero;
  132. Vector2 scale = new Vector2(1.0f, 1.0f);
  133. // No point in handling the aspect ratio if the textures dimension's are the same
  134. if (srcAspectRatio != dstAspectRatio)
  135. {
  136. switch (_options.aspectRatio)
  137. {
  138. case VideoResolveOptions.AspectRatio.NoScaling:
  139. scale.x = (float)_externalTexture.width / (float)_internalTexture.width;
  140. scale.y = (float)_externalTexture.height / (float)_internalTexture.height;
  141. offset.x = (1.0f - scale.x) * 0.5f;
  142. offset.y = (1.0f - scale.y) * 0.5f;
  143. break;
  144. case VideoResolveOptions.AspectRatio.FitVertically:
  145. scale.x = (float)_internalTexture.height / (float)_internalTexture.width * dstAspectRatio;
  146. offset.x = (1.0f - scale.x) * 0.5f;
  147. break;
  148. case VideoResolveOptions.AspectRatio.FitHorizontally:
  149. scale.y = (float)_externalTexture.height / (float)_externalTexture.width * srcAspectRatio;
  150. offset.y = (1.0f - scale.y) * 0.5f;
  151. break;
  152. case VideoResolveOptions.AspectRatio.FitInside:
  153. {
  154. if (srcAspectRatio > dstAspectRatio)
  155. goto case VideoResolveOptions.AspectRatio.FitHorizontally;
  156. else if (srcAspectRatio < dstAspectRatio)
  157. goto case VideoResolveOptions.AspectRatio.FitVertically;
  158. } break;
  159. case VideoResolveOptions.AspectRatio.FitOutside:
  160. {
  161. if (srcAspectRatio > dstAspectRatio)
  162. goto case VideoResolveOptions.AspectRatio.FitVertically;
  163. else if (srcAspectRatio < dstAspectRatio)
  164. goto case VideoResolveOptions.AspectRatio.FitHorizontally;
  165. } break;
  166. case VideoResolveOptions.AspectRatio.Stretch:
  167. break;
  168. }
  169. }
  170. // NOTE: This blit can be removed once we can ResolveVideoToRenderTexture is made not to recreate textures
  171. // NOTE: This blit probably doesn't do correct linear/srgb conversion if the colorspace settings differ, may have to use GL.sRGBWrite
  172. // NOTE: Cannot use _MainTex as Graphics.Blit replaces the texture offset and scale when using a material
  173. _materialBlit.SetTexture(_srcTexId, _internalTexture);
  174. _materialBlit.SetTextureOffset(_srcTexId, offset);
  175. _materialBlit.SetTextureScale(_srcTexId, scale);
  176. Graphics.Blit(null, _externalTexture, _materialBlit, 0);
  177. }
  178. }
  179. }
  180. }
  181. void OnDisable()
  182. {
  183. if (_internalTexture)
  184. {
  185. RenderTexture.ReleaseTemporary(_internalTexture); _internalTexture = null;
  186. }
  187. }
  188. void OnDestroy()
  189. {
  190. if (_materialResolve)
  191. {
  192. Destroy(_materialResolve); _materialResolve = null;
  193. }
  194. }
  195. #if false
  196. void OnGUI()
  197. {
  198. if (TargetTexture)
  199. {
  200. GUI.DrawTexture(new Rect(0f, 0f, Screen.width * 0.8f, Screen.height * 0.8f), TargetTexture, ScaleMode.ScaleToFit, true);
  201. }
  202. }
  203. #endif
  204. }
  205. }