MediaPlayerEditor_Windows.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. using UnityEngine;
  2. using UnityEditor;
  3. //-----------------------------------------------------------------------------
  4. // Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
  5. //-----------------------------------------------------------------------------
  6. namespace RenderHeads.Media.AVProVideo.Editor
  7. {
  8. /// <summary>
  9. /// Editor for the MediaPlayer component
  10. /// </summary>
  11. public partial class MediaPlayerEditor : UnityEditor.Editor
  12. {
  13. private SerializedProperty _propSourceAudioSampleRate;
  14. private SerializedProperty _propSourceAudioChannels;
  15. private SerializedProperty _propManualSetAudioProps;
  16. private readonly static GUIContent[] _audioModesWindows =
  17. {
  18. new GUIContent("System Direct"),
  19. new GUIContent("Unity", "Allows the AudioOutput component to grab audio from the video and play it through Unity to the AudioListener"),
  20. new GUIContent("Facebook Audio 360", "Initialises player with Facebook Audio 360 support"),
  21. new GUIContent("None", "No audio"),
  22. };
  23. private readonly static GUIContent[] _audioModesUWP =
  24. {
  25. new GUIContent("System Direct"),
  26. new GUIContent("Unity", "Allows the AudioOutput component to grab audio from the video and play it through Unity to the AudioListener"),
  27. new GUIContent("Facebook Audio 360", "Initialises player with Facebook Audio 360 support"),
  28. new GUIContent("None", "No audio"),
  29. };
  30. private readonly static FieldDescription _optionLowLatency = new FieldDescription(".useLowLatency", new GUIContent("Use Low Latency", "Provides a hint to the decoder to use less buffering - may degrade performance and quality"));
  31. private readonly static FieldDescription _optionVideoAPI = new FieldDescription(".videoApi", new GUIContent("Video API", "The preferred video API to use"));
  32. private readonly static FieldDescription _optionTextureMips = new FieldDescription(".useTextureMips", new GUIContent("Generate Mipmaps", "Automatically create mip-maps for the texture to reducing aliasing when texture is scaled down"));
  33. private readonly static FieldDescription _option10BitTextures = new FieldDescription(".use10BitTextures", new GUIContent("Use 10-Bit Textures", "Provides a hint to the decoder to use 10-bit textures - allowing more quality for videos encoded with a 10-bit profile"));
  34. private readonly static FieldDescription _optionUseHardwareDecoding = new FieldDescription(".useHardwareDecoding", new GUIContent("Hardware Decoding"));
  35. private readonly static FieldDescription _optionUseStereoDetection = new FieldDescription(".useStereoDetection", new GUIContent("Use Stereo Detection", "Disable if no stereo detection is required"));
  36. private readonly static FieldDescription _optionUseTextTrackSupport = new FieldDescription(".useTextTrackSupport", new GUIContent("Use Text Tracks", "Disable if no text tracks are required"));
  37. private readonly static FieldDescription _optionUseAudioDelay = new FieldDescription(".useAudioDelay", new GUIContent("Use Audio Delay", "Allows audio to be offset"));
  38. private readonly static FieldDescription _optionUseFacebookAudio360Support = new FieldDescription(".useFacebookAudio360Support", new GUIContent("Use Facebook Audio 360", "Disable if no Facebook Audio 360 support is required for"));
  39. #if AVPROVIDEO_SUPPORT_BUFFERED_DISPLAY
  40. private readonly static FieldDescription _optionPauseOnPrerollComplete = new FieldDescription(".pauseOnPrerollComplete", new GUIContent("Pause On Preroll Complete", "Internally pause once preroll is completed. This is useful for syncing video playback to make sure all players are prerolled"));
  41. private readonly static FieldDescription _optionBufferedFrameSelection = new FieldDescription(".bufferedFrameSelection", new GUIContent("Frame Selection", "Mode for selecting the next frame to display from the buffer fo frames"));
  42. #endif
  43. private readonly static FieldDescription _optionUseHapNotchLC = new FieldDescription(".useHapNotchLC", new GUIContent("Use Hap/NotchLC", "Disable if no Hap/NotchLC playback is required"));
  44. private readonly static FieldDescription _optionCustomMovParser = new FieldDescription(".useCustomMovParser", new GUIContent("Use Custom MOV Parser", "For playback of Hap and NotchLC media to handle high bit-rates"));
  45. private readonly static FieldDescription _optionParallelFrameCount = new FieldDescription(".parallelFrameCount", new GUIContent("Parallel Frame Count", "Number of frames to decode in parallel via multi-threading. Higher values increase latency but can improve performance for demanding videos."));
  46. private readonly static FieldDescription _optionPrerollFrameCount = new FieldDescription(".prerollFrameCount", new GUIContent("Preroll Frame Count", "Number of frames to pre-decode before playback starts. Higher values increase latency but can improve performance for demanding videos."));
  47. private readonly static FieldDescription _optionAudioOutput = new FieldDescription(".audioOutput", new GUIContent("Audio Output"));
  48. private readonly static FieldDescription _optionAudio360ChannelMode = new FieldDescription(".audio360ChannelMode", new GUIContent("Channel Mode", "Specifies what channel mode Facebook Audio 360 needs to be initialised with"));
  49. private readonly static FieldDescription _optionStartMaxBitrate = new FieldDescription(".startWithHighestBitrate", new GUIContent("Start Max Bitrate"));
  50. private readonly static FieldDescription _optionUseLowLiveLatency = new FieldDescription(".useLowLiveLatency", new GUIContent("Low Live Latency"));
  51. private readonly static FieldDescription _optionHintAlphaChannel = new FieldDescription(".hintAlphaChannel", new GUIContent("Alpha Channel Hint", "If a video is detected as 32-bit, use or ignore the alpha channel"));
  52. private readonly static FieldDescription _optionForceAudioOutputDeviceName = new FieldDescription(".forceAudioOutputDeviceName", new GUIContent("Force Audio Output Device Name", "Useful for VR when you need to output to the VR audio device"));
  53. private readonly static FieldDescription _optionPreferredFilters = new FieldDescription(".preferredFilters", new GUIContent("Preferred Filters", "Priority list for preferred filters to be used instead of default"));
  54. private void OnInspectorGUI_Override_Windows()
  55. {
  56. //MediaPlayer media = (this.target) as MediaPlayer;
  57. //MediaPlayer.OptionsWindows options = media._optionsWindows;
  58. GUILayout.Space(8f);
  59. EditorGUILayout.BeginVertical(GUI.skin.box);
  60. string optionsVarName = MediaPlayer.GetPlatformOptionsVariable(Platform.Windows);
  61. {
  62. SerializedProperty propVideoApi = DisplayPlatformOption(optionsVarName, _optionVideoAPI);
  63. {
  64. SerializedProperty propUseTextureMips = DisplayPlatformOption(optionsVarName, _optionTextureMips);
  65. if (propUseTextureMips.boolValue && ((FilterMode)_propFilter.enumValueIndex) != FilterMode.Trilinear)
  66. {
  67. EditorHelper.IMGUI.NoticeBox(MessageType.Info, "Recommend changing the texture filtering mode to Trilinear when using mip-maps.");
  68. }
  69. }
  70. {
  71. SerializedProperty propUseHardwareDecoding = serializedObject.FindProperty(optionsVarName + _optionUseHardwareDecoding.fieldName);
  72. EditorGUI.BeginDisabledGroup(!propUseHardwareDecoding.boolValue && propVideoApi.enumValueIndex == (int)Windows.VideoApi.MediaFoundation);
  73. {
  74. DisplayPlatformOption(optionsVarName, _option10BitTextures);
  75. }
  76. EditorGUI.EndDisabledGroup();
  77. }
  78. }
  79. EditorGUILayout.EndVertical();
  80. // Media Foundation Options
  81. {
  82. EditorGUILayout.BeginVertical(GUI.skin.box);
  83. GUILayout.Label("Media Foundation API Options", EditorStyles.boldLabel);
  84. {
  85. DisplayPlatformOption(optionsVarName, _optionUseHardwareDecoding);
  86. }
  87. {
  88. DisplayPlatformOption(optionsVarName, _optionLowLatency);
  89. DisplayPlatformOption(optionsVarName, _optionUseStereoDetection);
  90. DisplayPlatformOption(optionsVarName, _optionUseTextTrackSupport);
  91. #if AVPROVIDEO_SUPPORT_BUFFERED_DISPLAY
  92. if (_showUltraOptions)
  93. {
  94. SerializedProperty propBufferedFrameSelection = DisplayPlatformOption(optionsVarName, _optionBufferedFrameSelection);
  95. if (propBufferedFrameSelection.enumValueIndex != (int)BufferedFrameSelectionMode.None)
  96. {
  97. EditorGUI.indentLevel++;
  98. DisplayPlatformOption(optionsVarName, _optionPauseOnPrerollComplete);
  99. EditorGUI.indentLevel--;
  100. }
  101. }
  102. #endif
  103. if (_showUltraOptions)
  104. {
  105. SerializedProperty useHapNotchLC = DisplayPlatformOption(optionsVarName, _optionUseHapNotchLC);
  106. if (useHapNotchLC.boolValue)
  107. {
  108. EditorGUI.indentLevel++;
  109. DisplayPlatformOption(optionsVarName, _optionCustomMovParser);
  110. DisplayPlatformOption(optionsVarName, _optionParallelFrameCount);
  111. DisplayPlatformOption(optionsVarName, _optionPrerollFrameCount);
  112. EditorGUI.indentLevel--;
  113. }
  114. }
  115. }
  116. // Audio Output
  117. {
  118. SerializedProperty propAudioDelay = DisplayPlatformOption(optionsVarName, _optionUseAudioDelay);
  119. if (propAudioDelay.boolValue)
  120. {
  121. //EditorGUI.indentLevel++;
  122. //EditorGUI.indentLevel--;
  123. }
  124. DisplayPlatformOption(optionsVarName, _optionUseFacebookAudio360Support);
  125. SerializedProperty propAudioOutput = DisplayPlatformOptionEnum(optionsVarName, _optionAudioOutput, _audioModesWindows);
  126. if (_showUltraOptions && (Windows.AudioOutput)propAudioOutput.enumValueIndex == Windows.AudioOutput.FacebookAudio360)
  127. {
  128. EditorGUILayout.Space();
  129. EditorGUILayout.LabelField("Facebook Audio 360", EditorStyles.boldLabel);
  130. DisplayPlatformOptionEnum(optionsVarName, _optionAudio360ChannelMode, _audio360ChannelMapGuiNames);
  131. {
  132. SerializedProperty propForceAudioOutputDeviceName = serializedObject.FindProperty(optionsVarName + ".forceAudioOutputDeviceName");
  133. if (propForceAudioOutputDeviceName != null)
  134. {
  135. string[] deviceNames = { "Default", Windows.AudioDeviceOutputName_Rift, Windows.AudioDeviceOutputName_Vive, "Custom" };
  136. int index = 0;
  137. if (!string.IsNullOrEmpty(propForceAudioOutputDeviceName.stringValue))
  138. {
  139. switch (propForceAudioOutputDeviceName.stringValue)
  140. {
  141. case Windows.AudioDeviceOutputName_Rift:
  142. index = 1;
  143. break;
  144. case Windows.AudioDeviceOutputName_Vive:
  145. index = 2;
  146. break;
  147. default:
  148. index = 3;
  149. break;
  150. }
  151. }
  152. int newIndex = EditorGUILayout.Popup("Audio Device Name", index, deviceNames);
  153. if (newIndex == 0)
  154. {
  155. propForceAudioOutputDeviceName.stringValue = string.Empty;
  156. }
  157. else if (newIndex == 3)
  158. {
  159. if (index != newIndex)
  160. {
  161. if (string.IsNullOrEmpty(propForceAudioOutputDeviceName.stringValue) ||
  162. propForceAudioOutputDeviceName.stringValue == Windows.AudioDeviceOutputName_Rift ||
  163. propForceAudioOutputDeviceName.stringValue == Windows.AudioDeviceOutputName_Vive)
  164. {
  165. propForceAudioOutputDeviceName.stringValue = "?";
  166. }
  167. }
  168. EditorGUILayout.PropertyField(propForceAudioOutputDeviceName, new GUIContent("Audio Device Name", "Useful for VR when you need to output to the VR audio device"));
  169. }
  170. else
  171. {
  172. propForceAudioOutputDeviceName.stringValue = deviceNames[newIndex];
  173. }
  174. }
  175. }
  176. }
  177. }
  178. EditorGUILayout.EndVertical();
  179. }
  180. // WinRT Options
  181. {
  182. EditorGUILayout.BeginVertical(GUI.skin.box);
  183. GUILayout.Label("WinRT API Options", EditorStyles.boldLabel);
  184. DisplayPlatformOption(optionsVarName, _optionStartMaxBitrate);
  185. DisplayPlatformOption(optionsVarName, _optionUseLowLiveLatency);
  186. if (_showUltraOptions)
  187. {
  188. SerializedProperty httpHeadersProp = serializedObject.FindProperty(optionsVarName + ".httpHeaders.httpHeaders");
  189. if (httpHeadersProp != null)
  190. {
  191. OnInspectorGUI_HttpHeaders(httpHeadersProp);
  192. }
  193. GUILayout.Space(8f);
  194. SerializedProperty keyAuthProp = serializedObject.FindProperty(optionsVarName + ".keyAuth");
  195. if (keyAuthProp != null)
  196. {
  197. OnInspectorGUI_HlsDecryption(keyAuthProp);
  198. }
  199. }
  200. EditorGUILayout.EndVertical();
  201. }
  202. // DirectShow Options
  203. {
  204. EditorGUILayout.BeginVertical(GUI.skin.box);
  205. GUILayout.Label("DirectShow API Options", EditorStyles.boldLabel);
  206. DisplayPlatformOption(optionsVarName, _optionHintAlphaChannel);
  207. DisplayPlatformOption(optionsVarName, _optionForceAudioOutputDeviceName);
  208. {
  209. int prevIndentLevel = EditorGUI.indentLevel;
  210. EditorGUI.indentLevel = 1;
  211. SerializedProperty propPreferredFilter = DisplayPlatformOption(optionsVarName, _optionPreferredFilters);
  212. if (propPreferredFilter.arraySize > 0)
  213. {
  214. EditorHelper.IMGUI.NoticeBox(MessageType.Info, "Command filter names are:\n1) \"Microsoft DTV-DVD Video Decoder\" (best for compatibility when playing H.264 videos)\n2) \"LAV Video Decoder\"\n3) \"LAV Audio Decoder\"");
  215. }
  216. EditorGUI.indentLevel = prevIndentLevel;
  217. }
  218. EditorGUILayout.EndVertical();
  219. }
  220. }
  221. private void OnInspectorGUI_Override_WindowsUWP()
  222. {
  223. //MediaPlayer media = (this.target) as MediaPlayer;
  224. //MediaPlayer.OptionsWindowsUWP options = media._optionsWindowsUWP;
  225. GUILayout.Space(8f);
  226. string optionsVarName = MediaPlayer.GetPlatformOptionsVariable(Platform.WindowsUWP);
  227. EditorGUILayout.BeginVertical(GUI.skin.box);
  228. if (_showUltraOptions)
  229. {
  230. SerializedProperty propVideoApi = DisplayPlatformOption(optionsVarName, _optionVideoAPI);
  231. {
  232. SerializedProperty propUseHardwareDecoding = serializedObject.FindProperty(optionsVarName + _optionUseHardwareDecoding.fieldName);
  233. EditorGUI.BeginDisabledGroup(!propUseHardwareDecoding.boolValue && propVideoApi.enumValueIndex == (int)Windows.VideoApi.MediaFoundation);
  234. {
  235. DisplayPlatformOption(optionsVarName, _option10BitTextures);
  236. }
  237. EditorGUI.EndDisabledGroup();
  238. }
  239. }
  240. EditorGUILayout.EndVertical();
  241. // Media Foundation Options
  242. {
  243. EditorGUILayout.BeginVertical(GUI.skin.box);
  244. GUILayout.Label("Media Foundation API Options", EditorStyles.boldLabel);
  245. DisplayPlatformOption(optionsVarName, _optionUseHardwareDecoding);
  246. {
  247. SerializedProperty propUseTextureMips = DisplayPlatformOption(optionsVarName, _optionTextureMips);
  248. if (propUseTextureMips.boolValue && ((FilterMode)_propFilter.enumValueIndex) != FilterMode.Trilinear)
  249. {
  250. EditorHelper.IMGUI.NoticeBox(MessageType.Info, "Recommend changing the texture filtering mode to Trilinear when using mip-maps.");
  251. }
  252. }
  253. DisplayPlatformOption(optionsVarName, _optionLowLatency);
  254. DisplayPlatformOptionEnum(optionsVarName, _optionAudioOutput, _audioModesUWP);
  255. EditorGUILayout.EndVertical();
  256. }
  257. // WinRT Options
  258. {
  259. EditorGUILayout.BeginVertical(GUI.skin.box);
  260. GUILayout.Label("WinRT API Options", EditorStyles.boldLabel);
  261. DisplayPlatformOption(optionsVarName, _optionStartMaxBitrate);
  262. DisplayPlatformOption(optionsVarName, _optionUseLowLiveLatency);
  263. if (_showUltraOptions)
  264. {
  265. {
  266. SerializedProperty httpHeadersProp = serializedObject.FindProperty(optionsVarName + ".httpHeaders.httpHeaders");
  267. if (httpHeadersProp != null)
  268. {
  269. OnInspectorGUI_HttpHeaders(httpHeadersProp);
  270. }
  271. }
  272. {
  273. SerializedProperty keyAuthProp = serializedObject.FindProperty(optionsVarName + ".keyAuth");
  274. if (keyAuthProp != null)
  275. {
  276. OnInspectorGUI_HlsDecryption(keyAuthProp);
  277. }
  278. }
  279. }
  280. EditorGUILayout.EndVertical();
  281. }
  282. GUI.enabled = true;
  283. }
  284. }
  285. }