WindowsRtMediaPlayer.cs 26 KB

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