diff --git a/Assets/Libs/Hypernex.CCK/Hypernex.CCK.Unity.dll b/Assets/Libs/Hypernex.CCK/Hypernex.CCK.Unity.dll index 5330923e..c3c965eb 100644 Binary files a/Assets/Libs/Hypernex.CCK/Hypernex.CCK.Unity.dll and b/Assets/Libs/Hypernex.CCK/Hypernex.CCK.Unity.dll differ diff --git a/Assets/Libs/YoutubeDLSharp/YoutubeDLSharp.dll b/Assets/Libs/YoutubeDLSharp/YoutubeDLSharp.dll index 814fc639..0b2ba726 100644 Binary files a/Assets/Libs/YoutubeDLSharp/YoutubeDLSharp.dll and b/Assets/Libs/YoutubeDLSharp/YoutubeDLSharp.dll differ diff --git a/Assets/Scripts/Game/Video/FFVideoPlayer.cs b/Assets/Scripts/Game/Video/FFVideoPlayer.cs new file mode 100644 index 00000000..e72cfc81 --- /dev/null +++ b/Assets/Scripts/Game/Video/FFVideoPlayer.cs @@ -0,0 +1,130 @@ +using System; +using FFmpeg.Unity; +using Hypernex.CCK.Unity; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace Hypernex.Game.Video +{ + public class FFVideoPlayer : IVideoPlayer + { + private VideoPlayerDescriptor desc; + private FFPlayUnity videoPlayer; + private FFTexturePlayer texture; + private FFAudioPlayer audio; + private BufferAudioSource buffer; + private AudioSource audioSource; + private Material material; + + public FFVideoPlayer(VideoPlayerDescriptor descriptor) + { + GameObject attachedObject = descriptor.gameObject; + desc = descriptor; + videoPlayer = attachedObject.GetComponent(); + if (videoPlayer == null) + { + videoPlayer = attachedObject.AddComponent(); + videoPlayer.videoOffset = -0.5d; + texture = attachedObject.AddComponent(); + audio = attachedObject.AddComponent(); + audio.bufferSize = 2f; + videoPlayer.texturePlayer = texture; + videoPlayer.audioPlayer = audio; + } + audioSource = descriptor.AudioOutput; + if (audioSource == null) audioSource = attachedObject.GetComponent(); + if (audioSource == null) audioSource = attachedObject.AddComponent(); + buffer = audioSource.GetComponent(); + if (buffer == null) buffer = audioSource.gameObject.AddComponent(); + buffer.audioPlayer = videoPlayer.audioPlayer; + buffer.audioSource = audioSource; + videoPlayer.texturePlayer.OnDisplay += OnDisplay; + descriptor.AudioOutput = audioSource; + audioSource.outputAudioMixerGroup = Init.Instance.WorldGroup; + audioSource.spatialize = true; + descriptor.CurrentVideoPlayer = this; + } + + private void OnDisplay(Texture2D tex) + { + foreach (Renderer renderer in desc.VideoOutputs) + { + if (renderer.material == null) + { + renderer.material = new Material(Shader.Find("Universal Render Pipeline/Lit")); + desc.ShaderEmissionProperty = "_EmissionMap"; + } + renderer.material.mainTexture = tex; + renderer.material.mainTextureScale = new Vector2(1f, -1f); + if (desc.IsEmissive) + { + renderer.material.SetTexture(desc.ShaderEmissionProperty, tex); + renderer.material.SetTextureScale(desc.ShaderEmissionProperty, new Vector2(1f, -1f)); + } + } + } + + public static bool CanBeUsed() => true; + + public static bool CanBeUsed(Uri source) + { + // if (source.Scheme != "file") return false; + // TODO: Check to see if file is in compatible format + return true; + } + + public bool IsPlaying => videoPlayer.IsPlaying; + public bool Muted + { + get => audioSource.mute; + set => audioSource.mute = value; + } + + public bool Looping { get; set; } = false; + + public float Pitch + { + get => audioSource.pitch; + set => audioSource.pitch = value; + } + + public float Volume + { + get => audioSource.volume; + set => audioSource.volume = value; + } + + public double Position + { + get => videoPlayer.PlaybackTime; + set => videoPlayer.Seek(value); + } + + public double Length => videoPlayer.GetLength(); + + private string url; + public string Source + { + get => url; + set + { + if (url != value) + { + url = value; + videoPlayer.Play(url); + } + } + } + + public void Play() => videoPlayer.Resume(); + public void Pause() => videoPlayer.Pause(); + public void Stop() => videoPlayer.Pause(); + + public string GetFileHeader() => String.Empty; + + public void Dispose() + { + Object.Destroy(material); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Game/Video/FFVideoPlayer.cs.meta b/Assets/Scripts/Game/Video/FFVideoPlayer.cs.meta new file mode 100644 index 00000000..62aae4ee --- /dev/null +++ b/Assets/Scripts/Game/Video/FFVideoPlayer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 05dd27ee639e21dcfacea6ba824fbf7f \ No newline at end of file diff --git a/Assets/Scripts/Game/Video/UnityVideoPlayer.cs b/Assets/Scripts/Game/Video/UnityVideoPlayer.cs index 2bfd4fff..7d3a775c 100644 --- a/Assets/Scripts/Game/Video/UnityVideoPlayer.cs +++ b/Assets/Scripts/Game/Video/UnityVideoPlayer.cs @@ -100,6 +100,7 @@ public string Source public void Play() => videoPlayer.Play(); public void Pause() => videoPlayer.Pause(); public void Stop() => videoPlayer.Stop(); + public string GetFileHeader() => "file:///"; public void Dispose() { diff --git a/Assets/Scripts/Game/Video/VLCVideoPlayer.cs b/Assets/Scripts/Game/Video/VLCVideoPlayer.cs index 8ab37b05..3cdc654e 100644 --- a/Assets/Scripts/Game/Video/VLCVideoPlayer.cs +++ b/Assets/Scripts/Game/Video/VLCVideoPlayer.cs @@ -172,6 +172,8 @@ public async void Stop() DestroyRenderTexture(); } + public string GetFileHeader() => "file:///"; + public bool IsStream { get; private set; } public VideoOrientation? GetVideoOrientation() diff --git a/Assets/Scripts/Game/Video/VideoPlayerManager.cs b/Assets/Scripts/Game/Video/VideoPlayerManager.cs index b6a4ad79..6c7dc2f8 100644 --- a/Assets/Scripts/Game/Video/VideoPlayerManager.cs +++ b/Assets/Scripts/Game/Video/VideoPlayerManager.cs @@ -29,6 +29,7 @@ static VideoPlayerManager() #if VLC Register(VLCVideoPlayer.CanBeUsed, VLCVideoPlayer.CanBeUsed); #endif + Register(FFVideoPlayer.CanBeUsed, FFVideoPlayer.CanBeUsed); } public static void Register(Func canBeUsed, Func fileCanBePlayed) where T : IVideoPlayer diff --git a/Assets/Scripts/Sandboxing/SandboxedTypes/Components/Video.cs b/Assets/Scripts/Sandboxing/SandboxedTypes/Components/Video.cs index e7bb0af4..eb96c947 100644 --- a/Assets/Scripts/Sandboxing/SandboxedTypes/Components/Video.cs +++ b/Assets/Scripts/Sandboxing/SandboxedTypes/Components/Video.cs @@ -129,12 +129,12 @@ public void LoadFromStream(Streaming.StreamDownload streamDownload) { if (!File.Exists(streamDownload.pathToFile)) return; - string filePath = "file:///" + streamDownload.pathToFile; IVideoPlayer videoPlayer = videoPlayerDescriptor.Replace( - VideoPlayerManager.GetVideoPlayerType(new Uri(filePath)) ?? + VideoPlayerManager.GetVideoPlayerType(new Uri(streamDownload.pathToFile)) ?? VideoPlayerManager.DefaultVideoPlayerType); if (videoPlayer == null) return; + string filePath = videoPlayer.GetFileHeader() + streamDownload.pathToFile; videoPlayer.Source = filePath; } } diff --git a/Packages/manifest.json b/Packages/manifest.json index 6a29c1cc..f9bced22 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -19,6 +19,7 @@ "com.unity.xr.interaction.toolkit": "2.5.4", "com.unity.xr.management": "4.4.0", "com.unity.xr.openxr": "1.11.0", + "net.virtualwebsite.ffmpegunity": "https://github.com/VirtualBrightPlayz/FFmpeg.Unity.git?path=/Packages/FFmpeg.Unity#dynload", "com.unity.modules.accessibility": "1.0.0", "com.unity.modules.ai": "1.0.0", "com.unity.modules.androidjni": "1.0.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index a2d0a87a..4b3b3267 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -356,6 +356,13 @@ }, "url": "https://packages.unity.com" }, + "net.virtualwebsite.ffmpegunity": { + "version": "https://github.com/VirtualBrightPlayz/FFmpeg.Unity.git?path=/Packages/FFmpeg.Unity#dynload", + "depth": 0, + "source": "git", + "dependencies": {}, + "hash": "5a87f04a9c812610e03dbf3770eb337201105c5d" + }, "com.unity.modules.accessibility": { "version": "1.0.0", "depth": 0,