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 all 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)
7 changes: 6 additions & 1 deletion Runtime/Extreal.Integration.Web.Common.asmdef
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"name": "Extreal.Integration.Web.Common",
"rootNamespace": "Extreal.Integration.Web.Common",
"references": [],
"references": [
"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.

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

namespace Extreal.Integration.Web.Common.Video
{
/// <summary>
/// Class that handles VideoPlayer.
/// </summary>
public abstract class EVideoPlayer : DisposableBase
{
private static readonly ELogger Logger = LoggingManager.GetLogger(nameof(EVideoPlayer));

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

/// <summary>
/// Fires the OnPrepareCompleted.
/// </summary>
protected void FireOnPrepareCompleted()
{
if (Logger.IsDebug())
{
Logger.LogDebug(nameof(FireOnPrepareCompleted));
}
onPrepareCompleted.OnNext(Unit.Default);
}

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

/// <summary>
/// Fires the OnErrorReceived.
/// </summary>
/// <param name="message"></param>
protected void FireOnErrorReceived(string message)
{
if (Logger.IsDebug())
{
Logger.LogDebug($"{nameof(FireOnErrorReceived)}: message={message}");
}
onErrorReceived.OnNext(message);
}

/// <summary>
/// Disposables.
/// </summary>
protected CompositeDisposable Disposables { get; } = new CompositeDisposable();

/// <summary>
/// Video url.
/// </summary>
/// <value>Video url.</value>
protected string Url { get; private set; }

/// <summary>
/// Video length.
/// </summary>
public abstract double Length { get; }

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

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

/// <summary>
/// Prepares the VideoPlayer.
/// </summary>
public abstract void Prepare();

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

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

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

/// <summary>
/// Sets the audio volume.
/// </summary>
/// <param name="volume">Audio volume (0.0 - 1.0).</param>
/// <param name="trackIndex">Track index.</param>
public abstract void SetAudioVolume(float volume, ushort trackIndex = default);

/// <inheritdoc/>
protected sealed override void ReleaseManagedResources()
{
DoReleaseManagedResources();
Disposables.Dispose();
}

/// <summary>
/// Releases managed resources.
/// </summary>
protected abstract void DoReleaseManagedResources();
}
}
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.

31 changes: 31 additions & 0 deletions Runtime/Video/EVideoPlayerProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Diagnostics.CodeAnalysis;
using UnityEngine;
using UnityEngine.Video;

namespace Extreal.Integration.Web.Common.Video
{
/// <summary>
/// Class that provides EVideoPlayer.
/// </summary>
public static class EVideoPlayerProvider
{
/// <summary>
/// Provides the EVideoPlayer.
/// </summary>
/// <remarks>
/// Creates and returns a EVideoPlayer for Native (C#) or WebGL (JavaScript) depending on the platform.
/// </remarks>
/// <param name="videoPlayer">Video player for Native (C#)</param>
/// <param name="targetRenderTexture">Target render texture for WebGL</param>
/// <returns></returns>
[SuppressMessage("Usage", "CC0038"), SuppressMessage("Usage", "IDE0022"), SuppressMessage("Usage", "CC0057")]
public static EVideoPlayer Provide(VideoPlayer videoPlayer, RenderTexture targetRenderTexture)
{
#if !UNITY_WEBGL || UNITY_EDITOR
return new NativeEVideoPlayer(videoPlayer);
#else
return new WebGLEVideoPlayer(targetRenderTexture);
#endif
}
}
}
11 changes: 11 additions & 0 deletions Runtime/Video/EVideoPlayerProvider.cs.meta

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

56 changes: 56 additions & 0 deletions Runtime/Video/NativeEVideoPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using UnityEngine.Video;

namespace Extreal.Integration.Web.Common.Video
{
public class NativeEVideoPlayer : EVideoPlayer
{
private void PrepareCompletedEventHandler(VideoPlayer videoPlayer)
=> FireOnPrepareCompleted();

private void ErrorReceivedEventHandler(VideoPlayer source, string message)
=> FireOnErrorReceived(message);

public override double Length
=> videoPlayer.length;

private readonly VideoPlayer videoPlayer;

public NativeEVideoPlayer(VideoPlayer videoPlayer)
{
this.videoPlayer = videoPlayer;
this.videoPlayer.prepareCompleted += PrepareCompletedEventHandler;
this.videoPlayer.errorReceived += ErrorReceivedEventHandler;
}

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

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

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

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

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

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

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

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