Skip to content

Commit

Permalink
WebGLでのビデオ再生をJavaScriptに委譲できるようにする (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
sus-taguchi-t committed Feb 22, 2024
1 parent 84f1b10 commit 215f874
Show file tree
Hide file tree
Showing 80 changed files with 7,003 additions and 12 deletions.
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.

0 comments on commit 215f874

Please sign in to comment.