Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGLでのビデオ再生をJavaScriptに委譲できるようにする #9

Merged
merged 12 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ crashlytics-build.properties
# npm
WebScripts~/dist*
WebScripts~/node_modules*
Samples~/MVS/WebGLScripts~/node_modules*
Samples~/*/WebGLScripts~/node_modules*
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
yarn dev
```

- Import the sample MVS from Package Manager.
- Enter the following command in the `MVS/WebScripts` directory.
- Import the sample MVS or MVS2 from Package Manager.
- Enter the following command in the `WebScripts~` directory under the imported directory.

```bash
yarn
Expand All @@ -23,3 +23,23 @@
- Add all scenes in MVS to `Scenes In Build`.
- Play
- See [README](https://github.com/extreal-dev/Extreal.Dev/blob/main/WebGLBuild/README.md) to run WebGL application in local environment.

## Test cases for manual testing

### MVS (main feature of this library)

Listed above the scene played.

### MVS2 (video feature)

- Title screen
- Ability to specify url (used when set url to VideoPlayer)
- Ability to go to video screen (initialize, set url, prepare)
- Video screen
- Display the length of the video (video preparation is completed, get video length)
- Ability to play video (play)
- Ability to pause video (pause)
- Ability to stop video (stop)
- Ability to adjust volume (set volume)
- Error notification if specified url is invalid (error is received)
- Ability to return title screen (dispose VideoPlayer)
8 changes: 7 additions & 1 deletion Runtime/Extreal.Integration.Web.Common.asmdef
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
{
"name": "Extreal.Integration.Web.Common",
"rootNamespace": "Extreal.Integration.Web.Common",
"references": [],
"references": [
"Extreal.Framework.Analyzer",
"Extreal.Core.Logging",
"Extreal.Core.Common",
"UniTask",
"UniRx"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
Expand Down
4 changes: 2 additions & 2 deletions Runtime/Plugins/helper.jslib
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const plugin = {};

const helperNames = ["lengthBytesUTF8", "stringToUTF8", "UTF8ToString", "Module"];
const helperNames = ["lengthBytesUTF8", "stringToUTF8", "UTF8ToString", "Module", "GL"];
const helper = "{" + helperNames.map(func => `${func}:${func}`).join(",") + "}";
plugin["Nop"] = function () {};
plugin["Nop__postset"] = `_Nop = __getNop(${helper})`;
plugin["Nop__postset"] = `_Nop = __getNop(${helper}, () => GLctx)`;

const methods = ["CallAction", "CallFunction", "AddCallback"];
for (let i = 0; i < methods.length; i++) {
Expand Down
33 changes: 31 additions & 2 deletions Runtime/Plugins/helper.jslib.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Runtime/Video.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

130 changes: 130 additions & 0 deletions Runtime/Video/EVideoPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using UnityEngine;
using UnityEngine.Video;
using System;
using Extreal.Core.Logging;
using UniRx;
using System.Diagnostics.CodeAnalysis;

namespace Extreal.Integration.Web.Common.Video
{
/// <summary>
/// Class that handles VideoPlayer depending on the platform.
/// </summary>
public class EVideoPlayer : MonoBehaviour
{
[Header("Use on platforms other than WebGL")]
[SerializeField] private VideoPlayer videoPlayer;

[Header("Use only on WebGL platform")]
[SerializeField] private RenderTexture targetRenderTexture;

/// <summary>
/// Invokes immediately after the preparation is completed.
/// </summary>
public IObservable<Unit> OnPrepareCompleted => onPrepareCompleted.TakeUntilDestroy(this);
[SuppressMessage("Usage", "CC0033")]
private readonly Subject<Unit> onPrepareCompleted = new Subject<Unit>();

/// <summary>
/// <para>Invokes immediately after an error has occurred.</para>
/// Arg: Error message
/// </summary>
public IObservable<string> OnErrorReceived => onErrorReceived.TakeUntilDestroy(this);
[SuppressMessage("Usage", "CC0033")]
private readonly Subject<string> onErrorReceived = new Subject<string>();

/// <summary>
/// Video length.
/// </summary>
public double Length
=> eVideoPlayer.Length;

private string url;
private IVideoPlayer eVideoPlayer;

private static readonly ELogger Logger = LoggingManager.GetLogger(nameof(EVideoPlayer));

/// <summary>
/// Initializes the VideoPlayer.
/// </summary>
public void Initialize()
{
onErrorReceived.AddTo(this);
onPrepareCompleted.AddTo(this);

eVideoPlayer
#if UNITY_WEBGL && !UNITY_EDITOR
= new WebGLVideoPlayer(targetRenderTexture)
#else
= new NativeVideoPlayer(videoPlayer)
#endif
.AddTo(this);

eVideoPlayer.OnPrepareCompleted
.Subscribe(onPrepareCompleted.OnNext)
.AddTo(this);

eVideoPlayer.OnErrorReceived
.Subscribe(onErrorReceived.OnNext)
.AddTo(this);
}

/// <summary>
/// Sets the video url.
/// </summary>
/// <param name="url">Video url.</param>
public void SetUrl(string url)
{
this.url = url;
eVideoPlayer.SetUrl(this.url);
}

/// <summary>
/// Sets the playback position.
/// </summary>
/// <param name="time">Playback position.</param>
public void SetTime(double time)
=> eVideoPlayer.SetTime(time);

/// <summary>
/// Prepares the VideoPlayer.
/// </summary>
public void Prepare()
{
if (Logger.IsDebug())
{
Logger.LogDebug("Prepare: " + url);
}
eVideoPlayer.Prepare();
}

/// <summary>
/// Plays the video.
/// </summary>
public void Play()
=> eVideoPlayer.Play();

/// <summary>
/// Pauses the video.
/// </summary>
public void Pause()
=> eVideoPlayer.Pause();

/// <summary>
/// Stops the video.
/// </summary>
public void Stop()
=> eVideoPlayer.Stop();

/// <summary>
/// Sets the audio volume.
/// </summary>
/// <param name="volume">Audio volume (0.0 - 1.0).</param>
/// <param name="trackIndex">Track index.</param>
public void SetAudioVolume(float volume, ushort trackIndex = default)
{
var clampedVolume = Mathf.Clamp(volume, 0f, 1f);
eVideoPlayer.SetAudioVolume(trackIndex, clampedVolume);
}
}
}
11 changes: 11 additions & 0 deletions Runtime/Video/EVideoPlayer.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions Runtime/Video/IVideoPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using UniRx;

namespace Extreal.Integration.Web.Common.Video
{
public interface IVideoPlayer : IDisposable
kiyohome marked this conversation as resolved.
Show resolved Hide resolved
kiyohome marked this conversation as resolved.
Show resolved Hide resolved
{
IObservable<Unit> OnPrepareCompleted { get; }
IObservable<string> OnErrorReceived { get; }
double Length { get; }
void SetUrl(string url);
void SetTime(double time);
void Prepare();
void Play();
void Pause();
void Stop();
void SetAudioVolume(ushort trackIndex, float volume);
}
}
11 changes: 11 additions & 0 deletions Runtime/Video/IVideoPlayer.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 76 additions & 0 deletions Runtime/Video/NativeVideoPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Extreal.Core.Common.System;
using UniRx;
using UnityEngine.Video;

namespace Extreal.Integration.Web.Common.Video
{
public class NativeVideoPlayer : DisposableBase, IVideoPlayer
{

public IObservable<Unit> OnPrepareCompleted => onPrepareCompleted;
[SuppressMessage("Usage", "CC0033")]
private readonly Subject<Unit> onPrepareCompleted;
private void PrepareCompletedEventHandler(VideoPlayer videoPlayer)
=> onPrepareCompleted.OnNext(Unit.Default);

public IObservable<string> OnErrorReceived => onErrorReceived;
[SuppressMessage("Usage", "CC0033")]
private readonly Subject<string> onErrorReceived;
private void ErrorReceivedEventHandler(VideoPlayer source, string message)
=> onErrorReceived.OnNext(message);

public double Length
=> videoPlayer.length;

private readonly VideoPlayer videoPlayer;
private string url;

private readonly CompositeDisposable disposables = new CompositeDisposable();

public NativeVideoPlayer(VideoPlayer videoPlayer)
{
this.videoPlayer = videoPlayer;
onPrepareCompleted = new Subject<Unit>().AddTo(disposables);
onErrorReceived = new Subject<string>().AddTo(disposables);
this.videoPlayer.prepareCompleted += PrepareCompletedEventHandler;
this.videoPlayer.errorReceived += ErrorReceivedEventHandler;
}

protected override void ReleaseManagedResources()
{
videoPlayer.prepareCompleted -= PrepareCompletedEventHandler;
videoPlayer.errorReceived -= ErrorReceivedEventHandler;
if (videoPlayer.renderMode == VideoRenderMode.RenderTexture)
{
videoPlayer.targetTexture.Release();
}
disposables.Dispose();
}

public void SetUrl(string url)
=> this.url = url;

public void SetTime(double time)
=> videoPlayer.time = time;

public void Prepare()
{
videoPlayer.url = url;
videoPlayer.Prepare();
}

public void Play()
=> videoPlayer.Play();

public void Pause()
=> videoPlayer.Pause();

public void Stop()
=> videoPlayer.Stop();

public void SetAudioVolume(ushort trackIndex, float volume)
=> videoPlayer.SetDirectAudioVolume(trackIndex, volume);
}
}
11 changes: 11 additions & 0 deletions Runtime/Video/NativeVideoPlayer.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.