ApplyToMaterial.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. #if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN
  2. #define UNITY_PLATFORM_SUPPORTS_LINEAR
  3. #elif UNITY_IOS || UNITY_ANDROID
  4. #if UNITY_5_5_OR_NEWER || (UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 && !UNITY_5_3 && !UNITY_5_4)
  5. #define UNITY_PLATFORM_SUPPORTS_LINEAR
  6. #endif
  7. #endif
  8. #if UNITY_5_4_OR_NEWER || (UNITY_5 && !UNITY_5_0)
  9. #define UNITY_HELPATTRIB
  10. #endif
  11. using UnityEngine;
  12. //-----------------------------------------------------------------------------
  13. // Copyright 2015-2020 RenderHeads Ltd. All rights reserved.
  14. //-----------------------------------------------------------------------------
  15. namespace RenderHeads.Media.AVProVideo
  16. {
  17. /// <summary>
  18. /// Sets up a material to display the video from a MediaPlayer
  19. /// </summary>
  20. [AddComponentMenu("AVPro Video/Apply To Material", 300)]
  21. #if UNITY_HELPATTRIB
  22. [HelpURL("http://renderheads.com/products/avpro-video/")]
  23. #endif
  24. public class ApplyToMaterial : MonoBehaviour
  25. {
  26. [Header("Media Source")]
  27. [Space(8f)]
  28. [SerializeField] MediaPlayer _media = null;
  29. public MediaPlayer Player
  30. {
  31. get { return _media; }
  32. set { ChangeMediaPlayer(value); }
  33. }
  34. [Tooltip("Default texture to display when the video texture is preparing")]
  35. [SerializeField] Texture2D _defaultTexture = null;
  36. public Texture2D DefaultTexture
  37. {
  38. get { return _defaultTexture; }
  39. set { if (_defaultTexture != value) { _defaultTexture = value; _isDirty = true; } }
  40. }
  41. [Space(8f)]
  42. [Header("Material Target")]
  43. [SerializeField] Material _material = null;
  44. public Material Material
  45. {
  46. get { return _material; }
  47. set { if (_material != value) { _material = value; _isDirty = true; } }
  48. }
  49. [SerializeField] string _texturePropertyName = "_MainTex";
  50. public string TexturePropertyName
  51. {
  52. get { return _texturePropertyName; }
  53. set
  54. {
  55. if (_texturePropertyName != value)
  56. {
  57. _texturePropertyName = value;
  58. #if UNITY_5_6_OR_NEWER
  59. _propTexture = Shader.PropertyToID(_texturePropertyName);
  60. #endif
  61. _isDirty = true;
  62. }
  63. }
  64. }
  65. [SerializeField] Vector2 _offset = Vector2.zero;
  66. public Vector2 Offset
  67. {
  68. get { return _offset; }
  69. set { if (_offset != value) { _offset = value; _isDirty = true; } }
  70. }
  71. [SerializeField] Vector2 _scale = Vector2.one;
  72. public Vector2 Scale
  73. {
  74. get { return _scale; }
  75. set { if (_scale != value) { _scale = value; _isDirty = true; } }
  76. }
  77. private bool _isDirty = false;
  78. private Texture _lastTextureApplied;
  79. #if UNITY_5_6_OR_NEWER
  80. private int _propTexture;
  81. #endif
  82. private Texture _originalTexture;
  83. private Vector2 _originalScale = Vector2.one;
  84. private Vector2 _originalOffset = Vector2.zero;
  85. private static int _propStereo;
  86. private static int _propAlphaPack;
  87. private static int _propApplyGamma;
  88. private static int _propLayout;
  89. private static int _propCroppingScalars;
  90. private const string PropChromaTexName = "_ChromaTex";
  91. private static int _propChromaTex;
  92. private const string PropYpCbCrTransformName = "_YpCbCrTransform";
  93. private static int _propYpCbCrTransform;
  94. private const string PropUseYpCbCrName = "_UseYpCbCr";
  95. private static int _propUseYpCbCr;
  96. private void Awake()
  97. {
  98. if (_propStereo == 0)
  99. {
  100. _propStereo = Shader.PropertyToID("Stereo");
  101. }
  102. if (_propAlphaPack == 0)
  103. {
  104. _propAlphaPack = Shader.PropertyToID("AlphaPack");
  105. }
  106. if (_propApplyGamma == 0)
  107. {
  108. _propApplyGamma = Shader.PropertyToID("_ApplyGamma");
  109. }
  110. if (_propLayout == 0)
  111. {
  112. _propLayout = Shader.PropertyToID("Layout");
  113. }
  114. if (_propChromaTex == 0)
  115. {
  116. _propChromaTex = Shader.PropertyToID(PropChromaTexName);
  117. }
  118. if (_propYpCbCrTransform == 0)
  119. {
  120. _propYpCbCrTransform = Shader.PropertyToID(PropYpCbCrTransformName);
  121. }
  122. if (_propUseYpCbCr == 0)
  123. {
  124. _propUseYpCbCr = Shader.PropertyToID(PropUseYpCbCrName);
  125. }
  126. if (_propCroppingScalars == 0)
  127. {
  128. _propCroppingScalars = Shader.PropertyToID("_CroppingScalars");
  129. }
  130. if (_media != null)
  131. {
  132. _media.Events.AddListener(OnMediaPlayerEvent);
  133. }
  134. }
  135. private void ChangeMediaPlayer(MediaPlayer player)
  136. {
  137. if (_media != player)
  138. {
  139. if (_media != null)
  140. {
  141. _media.Events.RemoveListener(OnMediaPlayerEvent);
  142. }
  143. _media = player;
  144. if (_media != null)
  145. {
  146. _media.Events.AddListener(OnMediaPlayerEvent);
  147. }
  148. _isDirty = true;
  149. }
  150. }
  151. public void ForceUpdate()
  152. {
  153. _isDirty = true;
  154. LateUpdate();
  155. }
  156. // Callback function to handle events
  157. private void OnMediaPlayerEvent(MediaPlayer mp, MediaPlayerEvent.EventType et, ErrorCode errorCode)
  158. {
  159. switch (et)
  160. {
  161. case MediaPlayerEvent.EventType.FirstFrameReady:
  162. case MediaPlayerEvent.EventType.PropertiesChanged:
  163. ForceUpdate();
  164. break;
  165. }
  166. }
  167. // We do a LateUpdate() to allow for any changes in the texture that may have happened in Update()
  168. private void LateUpdate()
  169. {
  170. bool applied = false;
  171. if (_media != null && _media.TextureProducer != null)
  172. {
  173. Texture resamplerTex = _media.FrameResampler == null || _media.FrameResampler.OutputTexture == null ? null : _media.FrameResampler.OutputTexture[0];
  174. Texture texture = _media.m_Resample ? resamplerTex : _media.TextureProducer.GetTexture(0);
  175. if (texture != null)
  176. {
  177. // Check for changing texture
  178. if (texture != _lastTextureApplied)
  179. {
  180. _isDirty = true;
  181. }
  182. if (_isDirty)
  183. {
  184. int planeCount = _media.m_Resample ? 1 : _media.TextureProducer.GetTextureCount();
  185. for (int plane = 0; plane < planeCount; ++plane)
  186. {
  187. Texture resamplerTexPlane = _media.FrameResampler == null || _media.FrameResampler.OutputTexture == null ? null : _media.FrameResampler.OutputTexture[plane];
  188. texture = _media.m_Resample ? resamplerTexPlane : _media.TextureProducer.GetTexture(plane);
  189. if (texture != null)
  190. {
  191. ApplyMapping(texture, _media.TextureProducer.RequiresVerticalFlip(), plane);
  192. }
  193. }
  194. }
  195. applied = true;
  196. }
  197. }
  198. // If the media didn't apply a texture, then try to apply the default texture
  199. if (!applied)
  200. {
  201. if (_defaultTexture != _lastTextureApplied)
  202. {
  203. _isDirty = true;
  204. Debug.Log("different");
  205. }
  206. if (_isDirty)
  207. {
  208. if (_material != null && _material.HasProperty(_propUseYpCbCr))
  209. {
  210. _material.DisableKeyword("USE_YPCBCR");
  211. }
  212. Debug.Log("apply default");
  213. ApplyMapping(_defaultTexture, false);
  214. }
  215. }
  216. }
  217. private void ApplyMapping(Texture texture, bool requiresYFlip, int plane = 0)
  218. {
  219. if (_material != null)
  220. {
  221. _isDirty = false;
  222. if (plane == 0)
  223. {
  224. if (string.IsNullOrEmpty(_texturePropertyName))
  225. {
  226. _material.mainTexture = texture;
  227. _lastTextureApplied = texture;
  228. if (texture != null)
  229. {
  230. if (requiresYFlip)
  231. {
  232. _material.mainTextureScale = new Vector2(_scale.x, -_scale.y);
  233. _material.mainTextureOffset = Vector2.up + _offset;
  234. }
  235. else
  236. {
  237. _material.mainTextureScale = _scale;
  238. _material.mainTextureOffset = _offset;
  239. }
  240. }
  241. }
  242. else
  243. {
  244. #if UNITY_5_6_OR_NEWER
  245. _material.SetTexture(_propTexture, texture);
  246. #else
  247. _material.SetTexture(_texturePropertyName, texture);
  248. #endif
  249. _lastTextureApplied = texture;
  250. if (texture != null)
  251. {
  252. if (requiresYFlip)
  253. {
  254. _material.SetTextureScale(_texturePropertyName, new Vector2(_scale.x, -_scale.y));
  255. _material.SetTextureOffset(_texturePropertyName, Vector2.up + _offset);
  256. }
  257. else
  258. {
  259. _material.SetTextureScale(_texturePropertyName, _scale);
  260. _material.SetTextureOffset(_texturePropertyName, _offset);
  261. }
  262. }
  263. }
  264. }
  265. else if (plane == 1)
  266. {
  267. if (_material.HasProperty(_propUseYpCbCr))
  268. {
  269. _material.EnableKeyword("USE_YPCBCR");
  270. }
  271. if (_material.HasProperty(_propChromaTex))
  272. {
  273. _material.SetTexture(_propChromaTex, texture);
  274. _material.SetMatrix(_propYpCbCrTransform, _media.TextureProducer.GetYpCbCrTransform());
  275. if (texture != null)
  276. {
  277. #if UNITY_5_6_OR_NEWER
  278. if (requiresYFlip)
  279. {
  280. _material.SetTextureScale(_propChromaTex, new Vector2(_scale.x, -_scale.y));
  281. _material.SetTextureOffset(_propChromaTex, Vector2.up + _offset);
  282. }
  283. else
  284. {
  285. _material.SetTextureScale(_propChromaTex, _scale);
  286. _material.SetTextureOffset(_propChromaTex, _offset);
  287. }
  288. #else
  289. if (requiresYFlip)
  290. {
  291. _material.SetTextureScale(PropChromaTexName, new Vector2(_scale.x, -_scale.y));
  292. _material.SetTextureOffset(PropChromaTexName, Vector2.up + _offset);
  293. }
  294. else
  295. {
  296. _material.SetTextureScale(PropChromaTexName, _scale);
  297. _material.SetTextureOffset(PropChromaTexName, _offset);
  298. }
  299. #endif
  300. }
  301. }
  302. }
  303. if (_media != null)
  304. {
  305. // Apply changes for layout
  306. if (_material.HasProperty(_propLayout))
  307. {
  308. Helper.SetupLayoutMaterial(_material, _media.VideoLayoutMapping);
  309. }
  310. // Apply changes for stereo videos
  311. if (_material.HasProperty(_propStereo))
  312. {
  313. Helper.SetupStereoMaterial(_material, _media.m_StereoPacking, _media.m_DisplayDebugStereoColorTint);
  314. }
  315. // Apply changes for alpha videos
  316. if (_material.HasProperty(_propAlphaPack))
  317. {
  318. Helper.SetupAlphaPackedMaterial(_material, _media.m_AlphaPacking);
  319. }
  320. #if UNITY_PLATFORM_SUPPORTS_LINEAR
  321. // Apply gamma
  322. if (_material.HasProperty(_propApplyGamma) && _media.Info != null)
  323. {
  324. Helper.SetupGammaMaterial(_material, _media.Info.PlayerSupportsLinearColorSpace());
  325. }
  326. #else
  327. _propApplyGamma |= 0; // Prevent compiler warning about unused variable
  328. #endif
  329. #if (!UNITY_EDITOR && UNITY_ANDROID)
  330. // Adjust for cropping (when the decoder decodes in blocks that overrun the video frame size, it pads), OES only as we apply this lower down for none-OES
  331. if (_media.PlatformOptionsAndroid.useFastOesPath &&
  332. _media.Info != null &&
  333. _material.HasProperty(_propCroppingScalars) )
  334. {
  335. float[] transform = _media.Info.GetTextureTransform();
  336. if (transform != null)
  337. {
  338. _material.SetVector(_propCroppingScalars, new Vector4(transform[0], transform[3], 1.0f, 1.0f));
  339. }
  340. }
  341. #else
  342. _propCroppingScalars |= 0; // Prevent compiler warning about unused variable
  343. #endif
  344. }
  345. }
  346. }
  347. private void Start()
  348. {
  349. SaveProperties();
  350. LateUpdate();
  351. }
  352. private void OnEnable()
  353. {
  354. SaveProperties();
  355. #if UNITY_5_6_OR_NEWER
  356. _propTexture = Shader.PropertyToID(_texturePropertyName);
  357. #endif
  358. _isDirty = true;
  359. LateUpdate();
  360. }
  361. private void OnDisable()
  362. {
  363. RestoreProperties();
  364. }
  365. private void SaveProperties()
  366. {
  367. if (_material != null)
  368. {
  369. if (string.IsNullOrEmpty(_texturePropertyName))
  370. {
  371. _originalTexture = _material.mainTexture;
  372. _originalScale = _material.mainTextureScale;
  373. _originalOffset = _material.mainTextureOffset;
  374. }
  375. else
  376. {
  377. _originalTexture = _material.GetTexture(_texturePropertyName);
  378. _originalScale = _material.GetTextureScale(_texturePropertyName);
  379. _originalOffset = _material.GetTextureOffset(_texturePropertyName);
  380. }
  381. }
  382. }
  383. private void RestoreProperties()
  384. {
  385. if (_material != null)
  386. {
  387. if (string.IsNullOrEmpty(_texturePropertyName))
  388. {
  389. _material.mainTexture = _originalTexture;
  390. _material.mainTextureScale = _originalScale;
  391. _material.mainTextureOffset = _originalOffset;
  392. }
  393. else
  394. {
  395. _material.SetTexture(_texturePropertyName, _originalTexture);
  396. _material.SetTextureScale(_texturePropertyName, _originalScale);
  397. _material.SetTextureOffset(_texturePropertyName, _originalOffset);
  398. }
  399. }
  400. }
  401. }
  402. }