ShanxiKnowledgeBase/SXElectricalInspection/Assets/AVIDEO/AVideo/AVProVideo/Scripts/Internal/WebGLMediaPlayer.cs

758 lines
19 KiB
C#

#if UNITY_WEBGL
using UnityEngine;
using System.Runtime.InteropServices;
using System;
//-----------------------------------------------------------------------------
// Copyright 2015-2018 RenderHeads Ltd. All rights reserverd.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo
{
/// <summary>
/// WebGL implementation of BaseMediaPlayer
/// </summary>
public sealed class WebGLMediaPlayer : BaseMediaPlayer
{
//private enum AVPPlayerStatus
//{
// Unknown,
// ReadyToPlay,
// Playing,
// Finished,
// Seeking,
// Failed
//}
[DllImport("__Internal")]
private static extern bool AVPPlayerInsertVideoElement(string path, int[] idValues);
[DllImport("__Internal")]
private static extern int AVPPlayerWidth(int player);
[DllImport("__Internal")]
private static extern int AVPPlayerHeight(int player);
[DllImport("__Internal")]
private static extern int AVPPlayerGetLastError(int player);
[DllImport("__Internal")]
private static extern int AVPPlayerAudioTrackCount(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerSetAudioTrack(int player, int index);
[DllImport("__Internal")]
private static extern void AVPPlayerClose(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerReady(int player);
[DllImport("__Internal")]
private static extern void AVPPlayerSetLooping(int player, bool loop);
[DllImport("__Internal")]
private static extern bool AVPPlayerIsLooping(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerIsSeeking(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerIsPlaying(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerIsPaused(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerIsFinished(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerIsBuffering(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerIsPlaybackStalled(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerPlay(int player);
[DllImport("__Internal")]
private static extern void AVPPlayerPause(int player);
[DllImport("__Internal")]
private static extern void AVPPlayerSeekToTime(int player, float timeMS, bool fast);
[DllImport("__Internal")]
private static extern float AVPPlayerGetCurrentTime(int player);
[DllImport("__Internal")]
private static extern float AVPPlayerGetPlaybackRate(int player);
[DllImport("__Internal")]
private static extern void AVPPlayerSetPlaybackRate(int player, float rate);
[DllImport("__Internal")]
private static extern void AVPPlayerSetMuted(int player, bool muted);
[DllImport("__Internal")]
private static extern float AVPPlayerGetDuration(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerIsMuted(int player);
[DllImport("__Internal")]
private static extern float AVPPlayerGetVolume(int player);
[DllImport("__Internal")]
private static extern void AVPPlayerSetVolume(int player, float volume);
[DllImport("__Internal")]
private static extern bool AVPPlayerHasVideo(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerHasAudio(int player);
// Need jslib
[DllImport("__Internal")]
private static extern void AVPPlayerFetchVideoTexture(int player, IntPtr texture, bool init);
[DllImport("__Internal")]
private static extern int AVPPlayerGetDecodedFrameCount(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerSupportedDecodedFrameCount(int player);
[DllImport("__Internal")]
private static extern bool AVPPlayerHasMetadata(int player);
[DllImport("__Internal")]
private static extern int AVPPlayerUpdatePlayerIndex(int id);
[DllImport("__Internal")]
private static extern int AVPPlayerGetNumBufferedTimeRanges(int id);
[DllImport("__Internal")]
private static extern float AVPPlayerGetTimeRangeStart(int id, int timeRangeIndex);
[DllImport("__Internal")]
private static extern float AVPPlayerGetTimeRangeEnd(int id, int timeRangeIndex);
private int _playerIndex = -1;
private int _playerID = -1;
private Texture2D _texture = null;
private int _width = 0;
private int _height = 0;
private int _audioTrackCount = 0;
private int _audioTrackIndex = 0;
private System.IntPtr _cachedTextureNativePtr = System.IntPtr.Zero;
private int _lastFrameCount = 0;
private float _displayRateTimer = 0f;
private float _displayRate = 0f;
public static void InitialisePlatform()
{
}
public override string GetVersion()
{
return "1.8.7";
}
public override bool OpenVideoFromFile(string path, long offset, string httpHeaderJson, uint sourceSamplerate = 0, uint sourceChannels = 0, int forceFileFormat = 0)
{
bool result = false;
if (path.StartsWith("http://") ||
path.StartsWith("https://") ||
path.StartsWith("file://") ||
path.StartsWith("chrome-extension://"))
{
int[] idValues = new int[2];
idValues[0] = -1;
AVPPlayerInsertVideoElement(path, idValues);
{
int playerIndex = idValues[0];
_playerID = idValues[1];
if (playerIndex > -1)
{
_playerIndex = playerIndex;
result = true;
}
}
}
return result;
}
public override void CloseVideo()
{
if (_playerIndex != -1)
{
Pause();
_width = 0;
_height = 0;
_audioTrackCount = 0;
_audioTrackIndex = 0;
AVPPlayerClose(_playerIndex);
if (_texture != null)
{
// Have to update with zero to release Metal textures!
//_texture.UpdateExternalTexture(0);
_cachedTextureNativePtr = System.IntPtr.Zero;
Texture2D.Destroy(_texture);
_texture = null;
}
_playerIndex = -1;
_playerID = -1;
base.CloseVideo();
}
}
public override bool IsLooping()
{
//Debug.Assert(_player != -1, "no player IsLooping");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerIsLooping(_playerIndex);
}
return result;
}
public override void SetLooping(bool looping)
{
Debug.Assert(_playerIndex != -1, "no player SetLooping");
AVPPlayerSetLooping(_playerIndex, looping);
}
public override bool HasAudio()
{
//Debug.Assert(_player != -1, "no player HasAudio");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerHasAudio(_playerIndex);
}
return result;
}
public override bool HasVideo()
{
//Debug.Assert(_player != -1, "no player HasVideo");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerHasVideo(_playerIndex);
}
return result;
}
public override bool HasMetaData()
{
//Debug.Assert(_player != -1, "no player HasMetaData");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerHasMetadata(_playerIndex);
}
return result;
}
public override bool CanPlay()
{
//Debug.Assert(_player != -1, "no player CanPlay");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerReady(_playerIndex);
}
return result;
}
public override void Play()
{
Debug.Assert(_playerIndex != -1, "no player Play");
if (!AVPPlayerPlay(_playerIndex))
{
Debug.LogWarning("[AVProVideo] Browser permission prevented video playback");
}
}
public override void Pause()
{
Debug.Assert(_playerIndex != -1, "no player Pause");
AVPPlayerPause(_playerIndex);
}
public override void Stop()
{
Debug.Assert(_playerIndex != -1, "no player Stop");
AVPPlayerPause(_playerIndex);
}
public override void Rewind()
{
Debug.Assert(_playerIndex != -1, "no player Rewind");
AVPPlayerSeekToTime(_playerIndex, 0.0f, true);
}
public override void Seek(float ms)
{
Debug.Assert(_playerIndex != -1, "no player Seek");
AVPPlayerSeekToTime(_playerIndex, ms * 0.001f, false);
}
public override void SeekFast(float ms)
{
Debug.Assert(_playerIndex != -1, "no player SeekFast");
AVPPlayerSeekToTime(_playerIndex, ms * 0.001f, true);
}
public override float GetCurrentTimeMs()
{
//Debug.Assert(_player != -1, "no player GetCurrentTimeMs");
float result = 0.0f;
if (_playerIndex != -1)
{
result = (AVPPlayerGetCurrentTime(_playerIndex) * 1000.0f);
//Debug.Log("CurrentTime C#: " + result);
}
return result;
}
public override void SetPlaybackRate(float rate)
{
Debug.Assert(_playerIndex != -1, "no player SetPlaybackRate");
// No HTML implementations allow negative rate yet
rate = Mathf.Clamp(rate, 0.25f, 8f);
AVPPlayerSetPlaybackRate(_playerIndex, rate);
}
public override float GetPlaybackRate()
{
//Debug.Assert(_player != -1, "no player GetPlaybackRate");
float result = 0.0f;
if (_playerIndex != -1)
{
result = AVPPlayerGetPlaybackRate(_playerIndex);
}
return result;
}
public override float GetDurationMs()
{
//Debug.Assert(_player != -1, "no player GetDurationMs");
float result = 0.0f;
if (_playerIndex != -1)
{
result = (AVPPlayerGetDuration(_playerIndex) * 1000.0f);
}
return result;
}
public override int GetVideoWidth()
{
if (_width == 0)
{
_width = AVPPlayerWidth(_playerIndex);
}
return _width;
}
public override int GetVideoHeight()
{
if (_height == 0)
{
_height = AVPPlayerHeight(_playerIndex);
}
return _height;
}
public override float GetVideoFrameRate()
{
// There is no way in HTML5 yet to get the frame rate of the video
return 0f;
}
public override float GetVideoDisplayRate()
{
return _displayRate;
}
public override bool IsSeeking()
{
//Debug.Assert(_player != -1, "no player IsSeeking");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerIsSeeking(_playerIndex);
}
return result;
}
public override bool IsPlaying()
{
//Debug.Assert(_player != -1, "no player IsPlaying");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerIsPlaying(_playerIndex);
}
return result;
}
public override bool IsPaused()
{
//Debug.Assert(_player != -1, "no player IsPaused");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerIsPaused(_playerIndex);
}
return result;
}
public override bool IsFinished()
{
//Debug.Assert(_player != -1, "no player IsFinished");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerIsFinished(_playerIndex);
}
return result;
}
public override bool IsBuffering()
{
//Debug.Assert(_player != -1, "no player IsBuffering");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerIsBuffering(_playerIndex);
}
return result;
}
public override Texture GetTexture( int index )
{
return _texture;
}
public override int GetTextureFrameCount()
{
//Debug.Assert(_player != -1, "no player GetTextureFrameCount");
int result = 0;
if (_playerIndex != -1)
{
result = AVPPlayerGetDecodedFrameCount(_playerIndex);
}
return result;
}
public override bool SupportsTextureFrameCount()
{
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerSupportedDecodedFrameCount(_playerIndex);
}
return result;
}
public override bool RequiresVerticalFlip()
{
return true;
}
public override bool IsMuted()
{
//Debug.Assert(_player != -1, "no player IsMuted");
bool result = false;
if (_playerIndex != -1)
{
result = AVPPlayerIsMuted(_playerIndex);
}
return result;
}
public override void MuteAudio(bool bMute)
{
Debug.Assert(_playerIndex != -1, "no player MuteAudio");
AVPPlayerSetMuted(_playerIndex, bMute);
}
public override void SetVolume(float volume)
{
Debug.Assert(_playerIndex != -1, "no player SetVolume");
AVPPlayerSetVolume(_playerIndex, volume);
}
public override float GetVolume()
{
//Debug.Assert(_player != -1, "no player GetVolume");
float result = 0.0f;
if (_playerIndex != -1)
{
result = AVPPlayerGetVolume(_playerIndex);
}
return result;
}
public override void Render()
{
}
private void UpdateLastErrorCode()
{
var code = AVPPlayerGetLastError(_playerIndex);
switch(code){
case 0:
_lastError = ErrorCode.None;
break;
case 1:
_lastError = ErrorCode.LoadFailed;
break;
case 2:
_lastError = ErrorCode.LoadFailed;
break;
case 3:
_lastError = ErrorCode.DecodeFailed;
break;
case 4:
_lastError = ErrorCode.LoadFailed;
break;
default:
break;
}
}
public override void Update()
{
if(_playerID > -1) // CheckPlayer's index and update it
{
_playerIndex = AVPPlayerUpdatePlayerIndex(_playerID);
}
if(_playerIndex > -1)
{
UpdateSubtitles();
UpdateLastErrorCode();
if (AVPPlayerReady(_playerIndex))
{
if (AVPPlayerHasVideo(_playerIndex))
{
_width = AVPPlayerWidth(_playerIndex);
_height = AVPPlayerHeight(_playerIndex);
if (_texture == null)
{
_texture = new Texture2D(_width, _height, TextureFormat.ARGB32, false);
_texture.wrapMode = TextureWrapMode.Clamp;
_texture.Apply(false, false);
_cachedTextureNativePtr = _texture.GetNativeTexturePtr();
ApplyTextureProperties(_texture);
AVPPlayerFetchVideoTexture(_playerIndex, _cachedTextureNativePtr, true);
}
if (_texture.width != _width || _texture.height != _height)
{
_texture.Resize(_width, _height, TextureFormat.ARGB32, false);
_texture.Apply(false, false);
_cachedTextureNativePtr = _texture.GetNativeTexturePtr();
AVPPlayerFetchVideoTexture(_playerIndex, _cachedTextureNativePtr, true);
}
if (_cachedTextureNativePtr != System.IntPtr.Zero)
{
// TODO: only update the texture when the frame count changes
// actually this will break the update for certain browsers such as edge and possibly safari - Sunrise
AVPPlayerFetchVideoTexture(_playerIndex, _cachedTextureNativePtr, false);
}
UpdateDisplayFrameRate();
}
if (AVPPlayerHasAudio(_playerIndex))
{
_audioTrackCount = Mathf.Max(1, AVPPlayerAudioTrackCount(_playerIndex));
}
}
}
}
private void UpdateDisplayFrameRate()
{
_displayRateTimer += Time.deltaTime;
if (_displayRateTimer >= 0.5f)
{
int frameCount = AVPPlayerGetDecodedFrameCount(_playerIndex);
int frames = (frameCount - _lastFrameCount);
if (frames > 0)
{
_displayRate = (float)frames / _displayRateTimer;
}
else
{
_displayRate = 0f;
}
_displayRateTimer = 0f;
_lastFrameCount = frameCount;
}
}
public override void Dispose()
{
CloseVideo();
}
public override int GetAudioTrackCount()
{
return _audioTrackCount;
}
public override int GetCurrentAudioTrack()
{
return _audioTrackIndex;
}
public override void SetAudioTrack(int index)
{
if (_playerIndex > -1)
{
if (index >= 0 && index < _audioTrackCount)
{
if (index != _audioTrackIndex)
{
AVPPlayerSetAudioTrack(_playerIndex, index);
_audioTrackIndex = index;
}
}
}
}
public override bool IsPlaybackStalled()
{
bool result = false;
if (_playerIndex > -1)
{
result = AVPPlayerIsPlaybackStalled(_playerIndex);
}
return result;
}
public override string GetCurrentAudioTrackId()
{
// TODO
return "";
}
public override int GetCurrentAudioTrackBitrate()
{
// TODO
return 0;
}
public override int GetVideoTrackCount()
{
// TODO
return 0;
}
public override int GetCurrentVideoTrack()
{
// TODO
return 0;
}
public override void SetVideoTrack( int index )
{
// TODO
}
public override string GetCurrentVideoTrackId()
{
// TODO
return "";
}
public override int GetCurrentVideoTrackBitrate()
{
// TODO
return 0;
}
public override float GetBufferingProgress()
{
//TODO
return 0f;
}
public override int GetBufferedTimeRangeCount()
{
return AVPPlayerGetNumBufferedTimeRanges(_playerIndex);
}
public override bool GetBufferedTimeRange(int index, ref float startTimeMs, ref float endTimeMs)
{
startTimeMs = AVPPlayerGetTimeRangeStart(_playerIndex, index) * 1000.0f;
endTimeMs = AVPPlayerGetTimeRangeEnd(_playerIndex, index) * 1000.0f;
return true;
}
}
}
#endif