WindowsRtMediaPlayer.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. // NOTE: We only allow this script to compile in editor so we can easily check for compilation issues
  2. #if (UNITY_EDITOR || (UNITY_STANDALONE_WIN || UNITY_WSA_10_0))
  3. #if UNITY_WSA_10 || ENABLE_IL2CPP
  4. #define AVPROVIDEO_MARSHAL_RETURN_BOOL
  5. #endif
  6. using UnityEngine;
  7. using System.Runtime.InteropServices;
  8. using System.Collections.Generic;
  9. using System;
  10. using System.Text;
  11. //-----------------------------------------------------------------------------
  12. // Copyright 2018-2021 RenderHeads Ltd. All rights reserved.
  13. //-----------------------------------------------------------------------------
  14. namespace RenderHeads.Media.AVProVideo
  15. {
  16. public enum PlaybackState
  17. {
  18. None = 0,
  19. Opening = 1,
  20. Buffering = 2, // Replace with Stalled and add Buffering as State 64??
  21. Playing = 3,
  22. Paused = 4,
  23. StateMask = 7,
  24. Seeking = 32,
  25. }
  26. public class AuthData
  27. {
  28. public string URL { get; set; }
  29. public string Token { get; set; }
  30. public byte[] KeyBytes { get; set; }
  31. public AuthData()
  32. {
  33. Clear();
  34. }
  35. public void Clear()
  36. {
  37. URL = string.Empty;
  38. Token = string.Empty;
  39. KeyBytes = null;
  40. }
  41. public string KeyBase64
  42. {
  43. get
  44. {
  45. if (KeyBytes != null)
  46. {
  47. return System.Convert.ToBase64String(KeyBytes);
  48. }
  49. else
  50. {
  51. return string.Empty;
  52. }
  53. }
  54. set
  55. {
  56. if (value != null)
  57. {
  58. KeyBytes = System.Convert.FromBase64String(value);
  59. }
  60. else
  61. {
  62. KeyBytes = null;
  63. }
  64. }
  65. }
  66. };
  67. public partial class WindowsRtMediaPlayer : BaseMediaPlayer
  68. {
  69. private bool _isMediaLoaded = false;
  70. private bool _isLooping = false;
  71. private float _volume = 1.0f;
  72. private bool _use10BitTextures = false;
  73. private bool _useLowLiveLatency = false;
  74. public WindowsRtMediaPlayer(MediaPlayer.OptionsWindows options) : base()
  75. {
  76. _playerDescription = "WinRT";
  77. _use10BitTextures = options.use10BitTextures;
  78. _useLowLiveLatency = options.useLowLiveLatency;
  79. for (int i = 0; i < _eyeTextures.Length; i++)
  80. {
  81. _eyeTextures[i] = new EyeTexture();
  82. }
  83. }
  84. public WindowsRtMediaPlayer(MediaPlayer.OptionsWindowsUWP options) : base()
  85. {
  86. _playerDescription = "WinRT";
  87. _use10BitTextures = options.use10BitTextures;
  88. _useLowLiveLatency = options.useLowLiveLatency;
  89. for (int i = 0; i < _eyeTextures.Length; i++)
  90. {
  91. _eyeTextures[i] = new EyeTexture();
  92. }
  93. }
  94. public override bool CanPlay()
  95. {
  96. return HasMetaData();
  97. }
  98. public override void Dispose()
  99. {
  100. CloseMedia();
  101. if (_playerInstance != System.IntPtr.Zero)
  102. {
  103. Native.DestroyPlayer(_playerInstance); _playerInstance = System.IntPtr.Zero;
  104. Native.IssueRenderThreadEvent_FreeAllTextures();
  105. }
  106. for (int i = 0; i < _eyeTextures.Length; i++)
  107. {
  108. _eyeTextures[i].Dispose();
  109. }
  110. }
  111. public override bool PlayerSupportsLinearColorSpace()
  112. {
  113. // The current player doesn't support rendering to SRGB textures
  114. return false;
  115. }
  116. public override double GetCurrentTime()
  117. {
  118. return Native.GetCurrentPosition(_playerInstance);
  119. }
  120. public override double GetDuration()
  121. {
  122. return Native.GetDuration(_playerInstance);
  123. }
  124. public override float GetPlaybackRate()
  125. {
  126. return Native.GetPlaybackRate(_playerInstance);
  127. }
  128. public override Texture GetTexture(int index = 0)
  129. {
  130. Texture result = null;
  131. if (_frameTimeStamp > 0 && index < _eyeTextures.Length)
  132. {
  133. result = _eyeTextures[index].texture;
  134. }
  135. return result;
  136. }
  137. public override int GetTextureCount()
  138. {
  139. if (_eyeTextures[1].texture != null)
  140. {
  141. return 2;
  142. }
  143. return 1;
  144. }
  145. public override int GetTextureFrameCount()
  146. {
  147. return (int)_frameTimeStamp;
  148. }
  149. internal override StereoPacking InternalGetTextureStereoPacking()
  150. {
  151. return Native.GetStereoPacking(_playerInstance);
  152. }
  153. public override string GetVersion()
  154. {
  155. return _version;
  156. }
  157. public override string GetExpectedVersion()
  158. {
  159. return Helper.ExpectedPluginVersion.WinRT;
  160. }
  161. public override float GetVideoFrameRate()
  162. {
  163. float result = 0f;
  164. Native.VideoTrack videoTrack;
  165. if (Native.GetActiveVideoTrackInfo(_playerInstance, out videoTrack))
  166. {
  167. result = videoTrack.frameRate;
  168. }
  169. return result;
  170. }
  171. public override int GetVideoWidth()
  172. {
  173. int result = 0;
  174. if (_eyeTextures[0].texture)
  175. {
  176. result = _eyeTextures[0].texture.width;
  177. }
  178. return result;
  179. }
  180. public override int GetVideoHeight()
  181. {
  182. int result = 0;
  183. if (_eyeTextures[0].texture)
  184. {
  185. result = _eyeTextures[0].texture.height;
  186. }
  187. return result;
  188. }
  189. public override float GetVolume()
  190. {
  191. return _volume;//Native.GetAudioVolume(_playerInstance);
  192. }
  193. public override void SetBalance(float balance)
  194. {
  195. Native.SetAudioBalance(_playerInstance, balance);
  196. }
  197. public override float GetBalance()
  198. {
  199. return Native.GetAudioBalance(_playerInstance);
  200. }
  201. public override bool HasAudio()
  202. {
  203. return _audioTracks.Count > 0;
  204. }
  205. public override bool HasMetaData()
  206. {
  207. return Native.GetDuration(_playerInstance) > 0f;
  208. }
  209. public override bool HasVideo()
  210. {
  211. return _videoTracks.Count > 0;
  212. }
  213. public override bool IsBuffering()
  214. {
  215. return ((Native.GetPlaybackState(_playerInstance) & PlaybackState.StateMask) == PlaybackState.Buffering);
  216. }
  217. public override bool IsFinished()
  218. {
  219. bool result = false;
  220. if (IsPaused() && !IsSeeking() && GetCurrentTime() >= GetDuration())
  221. {
  222. result = true;
  223. }
  224. return result;
  225. }
  226. public override bool IsLooping()
  227. {
  228. return _isLooping;//Native.IsLooping(_playerInstance);
  229. }
  230. public override bool IsMuted()
  231. {
  232. return Native.IsAudioMuted(_playerInstance);
  233. }
  234. public override bool IsPaused()
  235. {
  236. return ((Native.GetPlaybackState(_playerInstance) & PlaybackState.StateMask) == PlaybackState.Paused);
  237. }
  238. public override bool IsPlaying()
  239. {
  240. return ((Native.GetPlaybackState(_playerInstance) & PlaybackState.StateMask) == PlaybackState.Playing);
  241. }
  242. public override bool IsSeeking()
  243. {
  244. return ((Native.GetPlaybackState(_playerInstance) & PlaybackState.Seeking) != 0);
  245. }
  246. public override void MuteAudio(bool bMuted)
  247. {
  248. Native.SetAudioMuted(_playerInstance, bMuted);
  249. }
  250. // TODO: replace all these options with a structure
  251. public override bool OpenMedia(string path, long offset, string httpHeader, MediaHints mediaHints, int forceFileFormat = 0, bool startWithHighestBitrate = false)
  252. {
  253. bool result = false;
  254. // RJT NOTE: Commented out as already called by 'InternalOpenMedia()' which calls this function
  255. // CloseMedia();
  256. if (_playerInstance == System.IntPtr.Zero)
  257. {
  258. _playerInstance = Native.CreatePlayer();
  259. // Force setting any auth data as it wouldn't have been set without a _playerInstance
  260. AuthenticationData = _nextAuthData;
  261. }
  262. if (_playerInstance != System.IntPtr.Zero)
  263. {
  264. result = Native.OpenMedia(_playerInstance, path, httpHeader, (FileFormat)forceFileFormat, startWithHighestBitrate, _use10BitTextures);
  265. if (result)
  266. {
  267. if (_useLowLiveLatency)
  268. {
  269. Native.SetLiveOffset(_playerInstance, 0.0);
  270. }
  271. // RJT NOTE: Other platforms create their native instances earlier than 'OpenMedia()' and set looping at that
  272. // point which Windows misses, so make sure once we have an instance we pass the looping flag down retrospectively
  273. // - https://github.com/RenderHeads/UnityPlugin-AVProVideo/issues/1913
  274. // - Same now with volume: https://github.com/RenderHeads/UnityPlugin-AVProVideo/issues/1916
  275. Native.SetLooping(_playerInstance, _isLooping);
  276. Native.SetAudioVolume(_playerInstance, _volume);
  277. }
  278. _mediaHints = mediaHints;
  279. }
  280. return result;
  281. }
  282. public override void CloseMedia()
  283. {
  284. // NOTE: This unloads the current video, but the texture should remain
  285. _isMediaLoaded = false;
  286. _isLooping = false;
  287. _volume = 1.0f;
  288. Native.CloseMedia(_playerInstance);
  289. base.CloseMedia();
  290. }
  291. public override void Pause()
  292. {
  293. Native.Pause(_playerInstance);
  294. }
  295. public override void Play()
  296. {
  297. Native.Play(_playerInstance);
  298. }
  299. public override void Render()
  300. {
  301. Native.IssueRenderThreadEvent_UpdateAllTextures();
  302. }
  303. private void Update_Textures()
  304. {
  305. // See if there is a new frame ready
  306. {
  307. System.IntPtr texturePointerLeft = System.IntPtr.Zero;
  308. System.IntPtr texturePointerRight = System.IntPtr.Zero;
  309. ulong frameTimeStamp = 0;
  310. int width, height;
  311. if (Native.GetLatestFrame(_playerInstance, out texturePointerLeft, out texturePointerRight, out frameTimeStamp, out width, out height))
  312. {
  313. bool isFrameUpdated = false;
  314. bool isNewFrameTime = (frameTimeStamp > _frameTimeStamp) || (_frameTimeStamp == 0 && frameTimeStamp == 0);
  315. for (int i = 0; i < _eyeTextures.Length; i++)
  316. {
  317. EyeTexture eyeTexture = _eyeTextures[i];
  318. System.IntPtr texturePointer = texturePointerLeft;
  319. if (i == 1)
  320. {
  321. texturePointer = texturePointerRight;
  322. }
  323. bool isNewFrameSpecs = (eyeTexture.texture != null && (texturePointer == IntPtr.Zero || eyeTexture.texture.width != width || eyeTexture.texture.height != height));
  324. //Debug.Log("tex? " + i + " " + width + " " + height + " " + (eyeTexture.texture != null) + " " + texturePointer.ToString() + " " + frameTimeStamp);
  325. // Check whether the latest frame is newer than the one we got last time
  326. if (isNewFrameTime || isNewFrameSpecs)
  327. {
  328. if (isNewFrameSpecs)
  329. {
  330. eyeTexture.Dispose();
  331. // TODO: blit from the old texture to the new texture before destroying?
  332. }
  333. /// Switch to the latest texture pointer
  334. if (eyeTexture.texture != null)
  335. {
  336. // TODO: check whether UpdateExternalTexture resets the sampling filter to POINT - it seems to in Unity 5.6.6
  337. if (eyeTexture.nativePointer != texturePointer)
  338. {
  339. eyeTexture.texture.UpdateExternalTexture(texturePointer);
  340. eyeTexture.nativePointer = texturePointer;
  341. }
  342. }
  343. else
  344. {
  345. if (texturePointer != IntPtr.Zero)
  346. {
  347. eyeTexture.texture = Texture2D.CreateExternalTexture(width, height, TextureFormat.BGRA32, false, false, texturePointer);
  348. if (eyeTexture.texture != null)
  349. {
  350. eyeTexture.texture.name = "AVProVideo";
  351. eyeTexture.nativePointer = texturePointer;
  352. ApplyTextureProperties(eyeTexture.texture);
  353. }
  354. else
  355. {
  356. Debug.LogError("[AVProVideo] Failed to create texture");
  357. }
  358. }
  359. }
  360. isFrameUpdated = true;
  361. }
  362. }
  363. if (isFrameUpdated)
  364. {
  365. _frameTimeStamp = frameTimeStamp;
  366. }
  367. }
  368. }
  369. }
  370. private AuthData _nextAuthData = new AuthData();
  371. public AuthData AuthenticationData
  372. {
  373. get
  374. {
  375. return _nextAuthData;
  376. }
  377. set
  378. {
  379. _nextAuthData = value;
  380. Native.SetNextAuthData(_playerInstance, _nextAuthData);
  381. }
  382. }
  383. public override bool RequiresVerticalFlip()
  384. {
  385. return true;
  386. }
  387. public override void Seek(double time)
  388. {
  389. Native.SeekParams seekParams = new Native.SeekParams();
  390. seekParams.timeSeconds = time;
  391. seekParams.mode = Native.SeekMode.Accurate;
  392. Native.Seek(_playerInstance, ref seekParams);
  393. }
  394. public override void SeekFast(double time)
  395. {
  396. // Keyframe seeking is not supported on this platform
  397. Seek(time);
  398. }
  399. public override void SetLooping(bool bLooping)
  400. {
  401. _isLooping = bLooping;
  402. Native.SetLooping(_playerInstance, _isLooping);
  403. }
  404. public override void SetPlaybackRate(float rate)
  405. {
  406. // Clamp rate as WinRT doesn't seem to be able to handle negative rate
  407. rate = Mathf.Max(0f, rate);
  408. Native.SetPlaybackRate(_playerInstance, rate);
  409. }
  410. public override void SetVolume(float volume)
  411. {
  412. _volume = volume;
  413. Native.SetAudioVolume(_playerInstance, _volume);
  414. }
  415. public override void Stop()
  416. {
  417. Pause();
  418. }
  419. private void UpdateTimeRanges()
  420. {
  421. UpdateTimeRange(ref _seekableTimes._ranges, Native.TimeRangeTypes.Seekable);
  422. UpdateTimeRange(ref _bufferedTimes._ranges, Native.TimeRangeTypes.Buffered);
  423. _seekableTimes.CalculateRange();
  424. _bufferedTimes.CalculateRange();
  425. }
  426. private void UpdateTimeRange(ref TimeRange[] range, Native.TimeRangeTypes timeRangeType)
  427. {
  428. int newCount = Native.GetTimeRanges(_playerInstance, range, range.Length, timeRangeType);
  429. if (newCount != range.Length)
  430. {
  431. range = new TimeRange[newCount];
  432. Native.GetTimeRanges(_playerInstance, range, range.Length, timeRangeType);
  433. }
  434. }
  435. public override System.DateTime GetProgramDateTime()
  436. {
  437. double seconds = Native.GetCurrentDateTimeSecondsSince1970(_playerInstance);
  438. return Helper.ConvertSecondsSince1970ToDateTime(seconds);
  439. }
  440. public override void Update()
  441. {
  442. Native.Update(_playerInstance);
  443. UpdateTracks();
  444. UpdateTextCue();
  445. _lastError = (ErrorCode)Native.GetLastErrorCode(_playerInstance);
  446. UpdateTimeRanges();
  447. UpdateSubtitles();
  448. Update_Textures();
  449. UpdateDisplayFrameRate();
  450. if (!_isMediaLoaded)
  451. {
  452. if (HasVideo() && _eyeTextures[0].texture != null)
  453. {
  454. Native.VideoTrack videoTrack;
  455. if (Native.GetActiveVideoTrackInfo(_playerInstance, out videoTrack))
  456. {
  457. Helper.LogInfo("Using playback path: " + _playerDescription + " (" + videoTrack.frameWidth + "x" + videoTrack.frameHeight + "@" + videoTrack.frameRate.ToString("F2") + ")");
  458. _isMediaLoaded = true;
  459. }
  460. }
  461. else if (HasAudio() && !HasVideo())
  462. {
  463. Helper.LogInfo("Using playback path: " + _playerDescription);
  464. _isMediaLoaded = true;
  465. }
  466. }
  467. }
  468. /*public override void SetKeyServerURL(string url)
  469. {
  470. _nextAuthData.URL = url;
  471. AuthenticationData = _nextAuthData;
  472. }*/
  473. public override void SetKeyServerAuthToken(string token)
  474. {
  475. _nextAuthData.Token = token;
  476. AuthenticationData = _nextAuthData;
  477. }
  478. public override void SetOverrideDecryptionKey(byte[] key)
  479. {
  480. _nextAuthData.KeyBytes = key;
  481. AuthenticationData = _nextAuthData;
  482. }
  483. }
  484. // Tracks
  485. public sealed partial class WindowsRtMediaPlayer
  486. {
  487. internal override bool InternalSetActiveTrack(TrackType trackType, int trackUid)
  488. {
  489. return Native.SetActiveTrack(_playerInstance, trackType, trackUid);
  490. }
  491. // Has it changed since the last frame 'tick'
  492. internal override bool InternalIsChangedTracks(TrackType trackType)
  493. {
  494. return Native.IsChangedTracks(_playerInstance, trackType);
  495. }
  496. internal override int InternalGetTrackCount(TrackType trackType)
  497. {
  498. return Native.GetTrackCount(_playerInstance, trackType);
  499. }
  500. internal override TrackBase InternalGetTrackInfo(TrackType trackType, int trackIndex, ref bool isActiveTrack)
  501. {
  502. TrackBase result = null;
  503. StringBuilder name = new StringBuilder(128);
  504. StringBuilder language = new StringBuilder(16);
  505. int uid = -1;
  506. if (Native.GetTrackInfo(_playerInstance, trackType, trackIndex, ref uid, ref isActiveTrack, name, name.Capacity, language, language.Capacity))
  507. {
  508. if (trackType == TrackType.Video)
  509. {
  510. result = new VideoTrack(uid, name.ToString(), language.ToString(), false);
  511. }
  512. else if (trackType == TrackType.Audio)
  513. {
  514. result = new AudioTrack(uid, name.ToString(), language.ToString(), false);
  515. }
  516. else if (trackType == TrackType.Text)
  517. {
  518. result = new TextTrack(uid, name.ToString(), language.ToString(), false);
  519. }
  520. }
  521. return result;
  522. }
  523. private partial struct Native
  524. {
  525. [DllImport("AVProVideoWinRT")]
  526. [return: MarshalAs(UnmanagedType.I1)]
  527. public static extern bool IsChangedTracks(System.IntPtr instance, TrackType trackType);
  528. [DllImport("AVProVideoWinRT")]
  529. public static extern int GetTrackCount(System.IntPtr instance, TrackType trackType);
  530. [DllImport("AVProVideoWinRT")]
  531. [return: MarshalAs(UnmanagedType.I1)]
  532. public static extern bool GetTrackInfo(System.IntPtr instance, TrackType trackType, int index, ref int uid,
  533. ref bool isActive,
  534. [MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int maxNameLength,
  535. [MarshalAs(UnmanagedType.LPWStr)] StringBuilder language, int maxLanguageLength);
  536. [DllImport("AVProVideoWinRT")]
  537. [return: MarshalAs(UnmanagedType.I1)]
  538. public static extern bool SetActiveTrack(System.IntPtr instance, TrackType trackType, int trackUid);
  539. }
  540. }
  541. // Text Cue
  542. public sealed partial class WindowsRtMediaPlayer
  543. {
  544. // Has it changed since the last frame 'tick'
  545. internal override bool InternalIsChangedTextCue()
  546. {
  547. return Native.IsChangedTextCue(_playerInstance);
  548. }
  549. internal override string InternalGetCurrentTextCue()
  550. {
  551. string result = null;
  552. System.IntPtr ptr = Native.GetCurrentTextCue(_playerInstance);
  553. if (ptr != System.IntPtr.Zero)
  554. {
  555. result = System.Runtime.InteropServices.Marshal.PtrToStringUni(ptr);
  556. }
  557. return result;
  558. }
  559. private partial struct Native
  560. {
  561. [DllImport("AVProVideoWinRT")]
  562. [return: MarshalAs(UnmanagedType.I1)]
  563. public static extern bool IsChangedTextCue(System.IntPtr instance);
  564. [DllImport("AVProVideoWinRT")]
  565. public static extern System.IntPtr GetCurrentTextCue(System.IntPtr instance);
  566. }
  567. }
  568. public sealed partial class WindowsRtMediaPlayer
  569. {
  570. private partial struct Native
  571. {
  572. [DllImport("AVProVideoWinRT", EntryPoint = "GetPluginVersion")]
  573. private static extern System.IntPtr GetPluginVersionStringPointer();
  574. public static string GetPluginVersion()
  575. {
  576. return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(GetPluginVersionStringPointer());
  577. }
  578. [DllImport("AVProVideoWinRT")]
  579. public static extern System.IntPtr CreatePlayer();
  580. [DllImport("AVProVideoWinRT")]
  581. public static extern void DestroyPlayer(System.IntPtr playerInstance);
  582. [DllImport("AVProVideoWinRT")]
  583. #if AVPROVIDEO_MARSHAL_RETURN_BOOL
  584. [return: MarshalAs(UnmanagedType.I1)]
  585. #endif
  586. public static extern bool OpenMedia(System.IntPtr playerInstance, [MarshalAs(UnmanagedType.LPWStr)] string filePath,
  587. [MarshalAs(UnmanagedType.LPWStr)] string httpHeader, FileFormat overrideFileFormat,
  588. bool startWithHighestBitrate, bool use10BitTextures);
  589. [DllImport("AVProVideoWinRT")]
  590. public static extern void CloseMedia(System.IntPtr playerInstance);
  591. [DllImport("AVProVideoWinRT")]
  592. public static extern void Pause(System.IntPtr playerInstance);
  593. [DllImport("AVProVideoWinRT")]
  594. public static extern void Play(System.IntPtr playerInstance);
  595. [DllImport("AVProVideoWinRT")]
  596. public static extern void SetAudioVolume(System.IntPtr playerInstance, float volume);
  597. [DllImport("AVProVideoWinRT")]
  598. public static extern void SetAudioBalance(System.IntPtr playerInstance, float balance);
  599. [DllImport("AVProVideoWinRT")]
  600. public static extern void SetPlaybackRate(System.IntPtr playerInstance, float rate);
  601. [DllImport("AVProVideoWinRT")]
  602. public static extern void SetAudioMuted(System.IntPtr playerInstance, bool muted);
  603. [DllImport("AVProVideoWinRT")]
  604. public static extern float GetAudioVolume(System.IntPtr playerInstance);
  605. [DllImport("AVProVideoWinRT")]
  606. #if AVPROVIDEO_MARSHAL_RETURN_BOOL
  607. [return: MarshalAs(UnmanagedType.I1)]
  608. #endif
  609. public static extern bool IsAudioMuted(System.IntPtr playerInstance);
  610. [DllImport("AVProVideoWinRT")]
  611. public static extern float GetAudioBalance(System.IntPtr playerInstance);
  612. [DllImport("AVProVideoWinRT")]
  613. public static extern float GetPlaybackRate(System.IntPtr playerInstance);
  614. [DllImport("AVProVideoWinRT")]
  615. public static extern void SetLooping(System.IntPtr playerInstance, bool looping);
  616. [DllImport("AVProVideoWinRT")]
  617. #if AVPROVIDEO_MARSHAL_RETURN_BOOL
  618. [return: MarshalAs(UnmanagedType.I1)]
  619. #endif
  620. public static extern bool IsLooping(System.IntPtr playerInstance);
  621. [DllImport("AVProVideoWinRT")]
  622. public static extern int GetLastErrorCode(System.IntPtr playerInstance);
  623. [DllImport("AVProVideoWinRT")]
  624. public static extern void Update(System.IntPtr playerInstance);
  625. [DllImport("AVProVideoWinRT")]
  626. public static extern double GetDuration(System.IntPtr playerInstance);
  627. [DllImport("AVProVideoWinRT")]
  628. public static extern StereoPacking GetStereoPacking(System.IntPtr playerInstance);
  629. [DllImport("AVProVideoWinRT")]
  630. public static extern double GetCurrentPosition(System.IntPtr playerInstance);
  631. [DllImport("AVProVideoWinRT")]
  632. #if AVPROVIDEO_MARSHAL_RETURN_BOOL
  633. [return: MarshalAs(UnmanagedType.I1)]
  634. #endif
  635. public static extern bool GetLatestFrame(System.IntPtr playerInstance, out System.IntPtr leftEyeTexturePointer, out System.IntPtr rightEyeTexturePointer, out ulong frameTimeStamp, out int width, out int height);
  636. [DllImport("AVProVideoWinRT")]
  637. public static extern PlaybackState GetPlaybackState(System.IntPtr playerInstance);
  638. [DllImport("AVProVideoWinRT")]
  639. #if AVPROVIDEO_MARSHAL_RETURN_BOOL
  640. [return: MarshalAs(UnmanagedType.I1)]
  641. #endif
  642. public static extern bool GetActiveVideoTrackInfo(System.IntPtr playerInstance, out VideoTrack videoTrack);
  643. [DllImport("AVProVideoWinRT")]
  644. #if AVPROVIDEO_MARSHAL_RETURN_BOOL
  645. [return: MarshalAs(UnmanagedType.I1)]
  646. #endif
  647. public static extern bool GetActiveAudioTrackInfo(System.IntPtr playerInstance, out AudioTrack audioTrack);
  648. [DllImport("AVProVideoWinRT")]
  649. public static extern double GetCurrentDateTimeSecondsSince1970(System.IntPtr playerInstance);
  650. [DllImport("AVProVideoWinRT")]
  651. public static extern void SetLiveOffset(System.IntPtr playerInstance, double seconds);
  652. [DllImport("AVProVideoWinRT")]
  653. public static extern void DebugValues(System.IntPtr playerInstance, out int isD3D, out int isUnityD3D, out int isTexture, out int isSharedTexture, out int isSurface);
  654. public enum SeekMode
  655. {
  656. Fast = 0,
  657. Accurate = 1,
  658. // TODO: Add Fast_Before and Fast_After
  659. }
  660. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  661. public struct VideoTrack
  662. {
  663. public int trackIndex;
  664. public int frameWidth;
  665. public int frameHeight;
  666. public float frameRate;
  667. public uint averageBitRate;
  668. //public string trackName;
  669. // TODO: add index, language, name, bitrate, codec etc
  670. }
  671. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  672. public struct AudioTrack
  673. {
  674. public int trackIndex;
  675. public uint channelCount;
  676. public uint sampleRate;
  677. public uint bitsPerSample;
  678. public uint averageBitRate;
  679. //public string trackName;
  680. // TODO: add index, language, name, bitrate, codec etc
  681. }
  682. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  683. public struct SeekParams
  684. {
  685. public double timeSeconds;
  686. public SeekMode mode;
  687. // TODO: add min-max thresholds
  688. }
  689. [DllImport("AVProVideoWinRT")]
  690. public static extern void Seek(System.IntPtr playerInstance, ref SeekParams seekParams);
  691. public static void SetNextAuthData(System.IntPtr playerInstance, RenderHeads.Media.AVProVideo.AuthData srcAuthData)
  692. {
  693. Native.AuthData ad = new Native.AuthData();
  694. ad.url = string.IsNullOrEmpty(srcAuthData.URL) ? null : srcAuthData.URL;
  695. ad.token = string.IsNullOrEmpty(srcAuthData.Token) ? null : srcAuthData.Token;
  696. if (srcAuthData.KeyBytes != null && srcAuthData.KeyBytes.Length > 0)
  697. {
  698. ad.keyBytes = Marshal.AllocHGlobal(srcAuthData.KeyBytes.Length);
  699. Marshal.Copy(srcAuthData.KeyBytes, 0, ad.keyBytes, srcAuthData.KeyBytes.Length);
  700. ad.keyBytesLength = srcAuthData.KeyBytes.Length;
  701. }
  702. else
  703. {
  704. ad.keyBytes = System.IntPtr.Zero;
  705. ad.keyBytesLength = 0;
  706. }
  707. SetNextAuthData(playerInstance, ref ad);
  708. if (ad.keyBytes != System.IntPtr.Zero)
  709. {
  710. Marshal.FreeHGlobal(ad.keyBytes);
  711. }
  712. }
  713. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  714. public struct AuthData
  715. {
  716. [MarshalAs(UnmanagedType.LPWStr)]
  717. public string url;
  718. [MarshalAs(UnmanagedType.LPWStr)]
  719. public string token;
  720. public System.IntPtr keyBytes;
  721. public int keyBytesLength;
  722. };
  723. [DllImport("AVProVideoWinRT")]
  724. private static extern void SetNextAuthData(System.IntPtr playerInstance, ref AuthData authData);
  725. internal enum TimeRangeTypes
  726. {
  727. Seekable = 0,
  728. Buffered = 1,
  729. }
  730. [DllImport("AVProVideoWinRT")]
  731. public static extern int GetTimeRanges(System.IntPtr playerInstance, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] TimeRange[] ranges, int rangeCount, TimeRangeTypes timeRangeType);
  732. // RJT TODO: Clean this up to better match non-WinRT
  733. [DllImport("AVProVideoWinRT")]
  734. public static extern System.IntPtr GetRenderEventFunc();
  735. private static System.IntPtr _nativeFunction_UnityRenderEvent;
  736. public static void IssueRenderThreadEvent_UpdateAllTextures()
  737. {
  738. if (_nativeFunction_UnityRenderEvent == System.IntPtr.Zero)
  739. {
  740. _nativeFunction_UnityRenderEvent = Native.GetRenderEventFunc();
  741. }
  742. if (_nativeFunction_UnityRenderEvent != System.IntPtr.Zero)
  743. {
  744. GL.IssuePluginEvent(_nativeFunction_UnityRenderEvent, /*(int)Native.RenderThreadEvent.UpdateAllTextures*/1);
  745. }
  746. }
  747. public static void IssueRenderThreadEvent_FreeAllTextures()
  748. {
  749. if (_nativeFunction_UnityRenderEvent == System.IntPtr.Zero)
  750. {
  751. _nativeFunction_UnityRenderEvent = Native.GetRenderEventFunc();
  752. }
  753. if (_nativeFunction_UnityRenderEvent != System.IntPtr.Zero)
  754. {
  755. GL.IssuePluginEvent(_nativeFunction_UnityRenderEvent, /*(int)Native.RenderThreadEvent.FreeTextures*/2);
  756. }
  757. }
  758. }
  759. }
  760. public sealed partial class WindowsRtMediaPlayer
  761. {
  762. private static bool _isInitialised = false;
  763. private static string _version = "Plug-in not yet initialised";
  764. private ulong _frameTimeStamp;
  765. private System.IntPtr _playerInstance;
  766. class EyeTexture
  767. {
  768. public Texture2D texture = null;
  769. public System.IntPtr nativePointer = System.IntPtr.Zero;
  770. public void Dispose()
  771. {
  772. if (texture)
  773. {
  774. if (Application.isPlaying) { Texture2D.Destroy(texture); }
  775. else { Texture2D.DestroyImmediate(texture); }
  776. texture = null;
  777. }
  778. nativePointer = System.IntPtr.Zero;
  779. }
  780. }
  781. private EyeTexture[] _eyeTextures = new EyeTexture[2];
  782. public static bool InitialisePlatform()
  783. {
  784. if (!_isInitialised)
  785. {
  786. try
  787. {
  788. #if !UNITY_2019_3_OR_NEWER
  789. if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D12)
  790. {
  791. Debug.LogError("[AVProVideo] Direct3D 12 is not supported until Unity 2019.3");
  792. return false;
  793. }
  794. #endif
  795. if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Null ||
  796. SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D11 ||
  797. SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D12)
  798. {
  799. /*if (!Native.Init(QualitySettings.activeColorSpace == ColorSpace.Linear))
  800. {
  801. Debug.LogError("[AVProVideo] Failing to initialise platform");
  802. }
  803. else*/
  804. {
  805. _isInitialised = true;
  806. _version = Native.GetPluginVersion();
  807. }
  808. }
  809. else
  810. {
  811. Debug.LogError("[AVProVideo] Only Direct3D 11 and 12 are supported, graphicsDeviceType not supported: " + SystemInfo.graphicsDeviceType);
  812. }
  813. }
  814. catch (System.DllNotFoundException e)
  815. {
  816. Debug.LogError("[AVProVideo] Failed to load DLL. " + e.Message);
  817. }
  818. }
  819. return _isInitialised;
  820. }
  821. public static void DeinitPlatform()
  822. {
  823. //Native.Deinit();
  824. _isInitialised = false;
  825. }
  826. }
  827. }
  828. #endif