first commit
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace RenderHeads.Media.AVProVideo
|
||||
{
|
||||
/// <summary>
|
||||
/// This media player fakes video playback for platforms that aren't supported
|
||||
/// </summary>
|
||||
public sealed partial class NullMediaPlayer : BaseMediaPlayer
|
||||
{
|
||||
private bool _isPlaying = false;
|
||||
private bool _isPaused = false;
|
||||
private double _currentTime = 0.0;
|
||||
// private bool _audioMuted = false;
|
||||
private float _volume = 0.0f;
|
||||
private float _playbackRate = 1.0f;
|
||||
private bool _bLoop;
|
||||
|
||||
private int _Width = 256;
|
||||
private int _height = 256;
|
||||
private Texture2D _texture;
|
||||
private Texture2D _texture_AVPro;
|
||||
private Texture2D _texture_AVPro1;
|
||||
private float _fakeFlipTime;
|
||||
private int _frameCount;
|
||||
|
||||
private const float FrameRate = 10f;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetVersion()
|
||||
{
|
||||
return "0.0.0";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetExpectedVersion()
|
||||
{
|
||||
return GetVersion();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool OpenMedia(string path, long offset, string httpHeader, MediaHints mediaHints, int forceFileFormat = 0, bool startWithHighestBitrate = false)
|
||||
{
|
||||
_texture_AVPro = (Texture2D)Resources.Load("Textures/AVProVideo-NullPlayer-Frame0");
|
||||
_texture_AVPro1 = (Texture2D)Resources.Load("Textures/AVProVideo-NullPlayer-Frame1");
|
||||
|
||||
if( _texture_AVPro )
|
||||
{
|
||||
_Width = _texture_AVPro.width;
|
||||
_height = _texture_AVPro.height;
|
||||
}
|
||||
|
||||
_texture = _texture_AVPro;
|
||||
|
||||
_fakeFlipTime = 0.0f;
|
||||
_frameCount = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void CloseMedia()
|
||||
{
|
||||
_frameCount = 0;
|
||||
Resources.UnloadAsset(_texture_AVPro);
|
||||
Resources.UnloadAsset(_texture_AVPro1);
|
||||
|
||||
base.CloseMedia();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetLooping( bool bLooping )
|
||||
{
|
||||
_bLoop = bLooping;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsLooping()
|
||||
{
|
||||
return _bLoop;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool HasMetaData()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool CanPlay()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool HasAudio()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool HasVideo()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Play()
|
||||
{
|
||||
_isPlaying = true;
|
||||
_isPaused = false;
|
||||
_fakeFlipTime = 0.0f;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Pause()
|
||||
{
|
||||
_isPlaying = false;
|
||||
_isPaused = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Stop()
|
||||
{
|
||||
_isPlaying = false;
|
||||
_isPaused = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsSeeking()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override bool IsPlaying()
|
||||
{
|
||||
return _isPlaying;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override bool IsPaused()
|
||||
{
|
||||
return _isPaused;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override bool IsFinished()
|
||||
{
|
||||
return _isPlaying && (_currentTime >= GetDuration());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsBuffering()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override double GetDuration()
|
||||
{
|
||||
return 10.0;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetVideoWidth()
|
||||
{
|
||||
return _Width;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetVideoHeight()
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override float GetVideoDisplayRate()
|
||||
{
|
||||
return FrameRate;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Texture GetTexture( int index )
|
||||
{
|
||||
// return _texture ? _texture : Texture2D.whiteTexture;
|
||||
return _texture;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetTextureFrameCount()
|
||||
{
|
||||
return _frameCount;
|
||||
}
|
||||
|
||||
internal override StereoPacking InternalGetTextureStereoPacking()
|
||||
{
|
||||
return StereoPacking.Unknown;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool RequiresVerticalFlip()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Seek(double time)
|
||||
{
|
||||
_currentTime = time;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SeekFast(double time)
|
||||
{
|
||||
_currentTime = time;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override double GetCurrentTime()
|
||||
{
|
||||
return _currentTime;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetPlaybackRate(float rate)
|
||||
{
|
||||
_playbackRate = rate;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override float GetPlaybackRate()
|
||||
{
|
||||
return _playbackRate;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void MuteAudio(bool bMuted)
|
||||
{
|
||||
// _audioMuted = bMuted;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsMuted()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SetVolume(float volume)
|
||||
{
|
||||
_volume = volume;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override float GetVolume()
|
||||
{
|
||||
return _volume;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override float GetVideoFrameRate()
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Update()
|
||||
{
|
||||
UpdateSubtitles();
|
||||
|
||||
if (_isPlaying)
|
||||
{
|
||||
_currentTime += Time.deltaTime;
|
||||
if (_currentTime >= GetDuration())
|
||||
{
|
||||
_currentTime = GetDuration();
|
||||
if( _bLoop )
|
||||
{
|
||||
Rewind();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
_fakeFlipTime += Time.deltaTime;
|
||||
if( _fakeFlipTime >= (1.0 / FrameRate))
|
||||
{
|
||||
_fakeFlipTime = 0.0f;
|
||||
_texture = ( _texture == _texture_AVPro ) ? _texture_AVPro1 : _texture_AVPro;
|
||||
_frameCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Render()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class NullMediaPlayer : BaseMediaPlayer
|
||||
{
|
||||
internal override bool InternalSetActiveTrack(TrackType trackType, int trackUid)
|
||||
{
|
||||
// Set the active text track using the unique identifier
|
||||
// Or disable all text tracks if < 0
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override bool InternalIsChangedTracks(TrackType trackType)
|
||||
{
|
||||
// Has the tracks changed since the last frame 'tick'
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override int InternalGetTrackCount(TrackType trackType)
|
||||
{
|
||||
// Return number of text tracks
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override TrackBase InternalGetTrackInfo(TrackType trackType, int index, ref bool isActiveTrack)
|
||||
{
|
||||
// Get information about the specific track at index, range is [0...InternalGetTextTrackCount)
|
||||
return null;
|
||||
}
|
||||
|
||||
internal override bool InternalIsChangedTextCue()
|
||||
{
|
||||
// Has the text cue changed since the last frame 'tick'
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override string InternalGetCurrentTextCue()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 478671181ab1c9b42be924da77d7fcbe
|
||||
timeCreated: 1438703159
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,775 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2015-2025 RenderHeads Ltd. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MACOS
|
||||
#endif
|
||||
|
||||
#if !UNITY_EDITOR && (UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS || UNITY_ANDROID || UNITY_OPENHARMONY)
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MOBILE
|
||||
#endif
|
||||
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MOBILE && UNITY_IOS
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_IOS
|
||||
#endif
|
||||
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MOBILE && UNITY_TVOS
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_TVOS
|
||||
#endif
|
||||
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MOBILE && UNITY_VISIONOS
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_VISIONOS
|
||||
#endif
|
||||
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MOBILE && UNITY_ANDROID
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_ANDROID
|
||||
#endif
|
||||
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MOBILE && UNITY_OPENHARMONY
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_OPENHARMONY
|
||||
#endif
|
||||
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_IOS || AVPRO_VIDEO_PLATFORMMEDIAPLAYER_TVOS || AVPRO_VIDEO_PLATFORMMEDIAPLAYER_VISIONOS
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_IPHONE
|
||||
#endif
|
||||
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MACOS || AVPRO_VIDEO_PLATFORMMEDIAPLAYER_IPHONE
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_APPLE
|
||||
#endif
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER && (AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MACOS || AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MOBILE)
|
||||
#define AVPRO_VIDEO_PLATFORMMEDIAPLAYER_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_SUPPORTED
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RenderHeads.Media.AVProVideo
|
||||
{
|
||||
public sealed partial class PlatformMediaPlayer
|
||||
{
|
||||
internal partial struct Native
|
||||
{
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_MACOS
|
||||
private const string PluginName = "AVProVideo";
|
||||
#elif AVPRO_VIDEO_PLATFORMMEDIAPLAYER_IPHONE
|
||||
private const string PluginName = "__Internal";
|
||||
#elif AVPRO_VIDEO_PLATFORMMEDIAPLAYER_ANDROID
|
||||
private const string PluginName = "AVProVideo2Native";
|
||||
#elif AVPRO_VIDEO_PLATFORMMEDIAPLAYER_OPENHARMONY
|
||||
private const string PluginName = "avprovideolib";
|
||||
#endif
|
||||
internal const int kAVPPlayerRenderEventId = 0x5d5ac000;
|
||||
internal const int kAVPPlayerRenderEventMask = 0x7ffff000;
|
||||
internal const int kAVPPlayerRenderEventTypeMask = 0x00000f00;
|
||||
internal const int kAVPPlayerRenderEventTypeShift = 8;
|
||||
internal const int kAVPPlayerRenderEventDataPlayerIDMask = 0xffff;
|
||||
internal const int kAVPPlayerRenderEventDataPlayerIDShift = 0;
|
||||
internal const int kAVPPlayerRenderEventDataOptionsMask = 0xff;
|
||||
internal const int kAVPPlayerRenderEventDataOptionsShift = 16;
|
||||
|
||||
internal enum AVPPluginRenderEvent: int
|
||||
{
|
||||
None,
|
||||
PlayerSetup,
|
||||
PlayerRender,
|
||||
PlayerFreeResources,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerRenderEventPlayerSetupFlags: int
|
||||
{
|
||||
AndroidUseOESFastPath = 1 << 0,
|
||||
LinearColourSpace = 1 << 1,
|
||||
GenerateMipmaps = 1 << 2,
|
||||
#if AVPRO_VIDEO_XR_COMPOSITION_LAYERS
|
||||
XRCompositionLayer = 1 << 3,
|
||||
#endif
|
||||
}
|
||||
|
||||
// Video settings
|
||||
|
||||
internal enum AVPPlayerVideoAPI: int
|
||||
{
|
||||
// Apple - just included for completeness
|
||||
AVFoundation,
|
||||
|
||||
// Android - Matches Android.VideoApi
|
||||
MediaPlayer = Android.VideoApi.MediaPlayer,
|
||||
ExoPlayer = Android.VideoApi.ExoPlayer,
|
||||
}
|
||||
|
||||
internal enum AVPPlayerVideoOutputMode: int
|
||||
{
|
||||
// Default output mode, to a texture
|
||||
Texture,
|
||||
|
||||
// Android - XR composition layer
|
||||
#if AVPRO_VIDEO_XR_COMPOSITION_LAYERS
|
||||
XRCompositionLayer = Android.VideoOutputMode.XRCompositionLayer
|
||||
#endif
|
||||
}
|
||||
|
||||
internal enum AVPPlayerVideoPixelFormat: int
|
||||
{
|
||||
Invalid,
|
||||
Bgra,
|
||||
YCbCr420
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerFeatureFlags: int
|
||||
{
|
||||
Caching = 1 << 0,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerVideoOutputSettingsFlags: int
|
||||
{
|
||||
None = 0,
|
||||
LinearColorSpace = 1 << 0,
|
||||
GenerateMipmaps = 1 << 1,
|
||||
PreferSoftwareDecoder = 1 << 2,
|
||||
ForceEnableMediaCodecAsynchronousQueueing = 1 << 3,
|
||||
AllowUnsupportedVideoTrackVariants = 1 << 4,
|
||||
}
|
||||
|
||||
// Audio settings
|
||||
|
||||
internal enum AVPPlayerAudioOutputMode : int
|
||||
{
|
||||
SystemDirect,
|
||||
Unity,
|
||||
SystemDirectWithCapture,
|
||||
FacebookAudio360,
|
||||
}
|
||||
|
||||
// Network settings
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerNetworkSettingsFlags : int
|
||||
{
|
||||
None = 0,
|
||||
PlayWithoutBuffering = 1 << 0,
|
||||
UseSinglePlayerItem = 1 << 1,
|
||||
ForceStartHighestBitrate = 1 << 2,
|
||||
ForceRtpTCP = 1 << 3,
|
||||
PrioritizeTimeOverSize = 1 << 4,
|
||||
}
|
||||
|
||||
// NOTE: The layout of this structure is important - if adding anything put it at the end, make sure alignment is 4 bytes and DO NOT USE bool
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerSettings
|
||||
{
|
||||
// Video
|
||||
internal AVPPlayerVideoAPI videoApi;
|
||||
internal AVPPlayerVideoPixelFormat pixelFormat;
|
||||
internal AVPPlayerVideoOutputSettingsFlags videoFlags;
|
||||
internal float preferredMaximumResolution_width;
|
||||
internal float preferredMaximumResolution_height;
|
||||
internal float maximumPlaybackRate;
|
||||
|
||||
// Audio
|
||||
internal AVPPlayerAudioOutputMode audioOutputMode;
|
||||
internal int sampleRate;
|
||||
internal int bufferLength;
|
||||
internal int audioFlags;
|
||||
internal Audio360ChannelMode audio360Channels;
|
||||
internal int audio360LatencyMS;
|
||||
|
||||
// Network
|
||||
internal double preferredPeakBitRate;
|
||||
internal double preferredForwardBufferDuration;
|
||||
internal AVPPlayerNetworkSettingsFlags networkFlags;
|
||||
internal int minBufferMs;
|
||||
internal int maxBufferMs;
|
||||
internal int bufferForPlaybackMs;
|
||||
internal int bufferForPlaybackAfterRebufferMs;
|
||||
}
|
||||
|
||||
internal enum AVPPlayerOpenOptionsForceFileFormat: int
|
||||
{
|
||||
Unknown,
|
||||
HLS,
|
||||
DASH,
|
||||
SmoothStreaming
|
||||
};
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerOpenOptionsFlags: int
|
||||
{
|
||||
None = 0,
|
||||
};
|
||||
|
||||
// NOTE: The layout of this structure is important - if adding anything put it at the end, make sure alignment is 4 bytes and DO NOT USE bool
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerOpenOptions
|
||||
{
|
||||
internal long fileOffset;
|
||||
internal AVPPlayerOpenOptionsForceFileFormat forceFileFormat;
|
||||
internal AVPPlayerOpenOptionsFlags flags;
|
||||
};
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerStatus : int
|
||||
{
|
||||
Unknown = 0,
|
||||
ReadyToPlay = 1 << 0,
|
||||
Playing = 1 << 1,
|
||||
Paused = 1 << 2,
|
||||
Finished = 1 << 3,
|
||||
Seeking = 1 << 4,
|
||||
Buffering = 1 << 5,
|
||||
Stalled = 1 << 6,
|
||||
ExternalPlaybackActive = 1 << 7,
|
||||
Cached = 1 << 8,
|
||||
FinishedSeeking = 1 << 9,
|
||||
|
||||
UpdatedAssetInfo = 1 << 16,
|
||||
UpdatedTexture = 1 << 17,
|
||||
UpdatedBufferedTimeRanges = 1 << 18,
|
||||
UpdatedSeekableTimeRanges = 1 << 19,
|
||||
UpdatedText = 1 << 20,
|
||||
UpdatedTextureTransform = 1 << 21,
|
||||
UpdatedTimedMetadata = 1 << 22,
|
||||
|
||||
HasVideo = 1 << 24,
|
||||
HasAudio = 1 << 25,
|
||||
HasText = 1 << 26,
|
||||
HasMetadata = 1 << 27,
|
||||
HasVariants = 1 << 28,
|
||||
|
||||
Failed = 1 << 31
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerFlags : int
|
||||
{
|
||||
None = 0,
|
||||
Looping = 1 << 0,
|
||||
Muted = 1 << 1,
|
||||
AllowExternalPlayback = 1 << 2,
|
||||
ResumePlayback = 1 << 16, // iOS only, resumes playback after audio session route change
|
||||
Dirty = 1 << 31
|
||||
}
|
||||
|
||||
internal enum AVPPlayerExternalPlaybackVideoGravity : int
|
||||
{
|
||||
Resize,
|
||||
ResizeAspect,
|
||||
ResizeAspectFill
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerSize
|
||||
{
|
||||
internal float width;
|
||||
internal float height;
|
||||
public static readonly AVPPlayerSize Zero = new ()
|
||||
{
|
||||
width = 0.0f,
|
||||
height = 0.0f
|
||||
};
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPAffineTransform
|
||||
{
|
||||
internal float a;
|
||||
internal float b;
|
||||
internal float c;
|
||||
internal float d;
|
||||
internal float tx;
|
||||
internal float ty;
|
||||
|
||||
public static readonly AVPAffineTransform Identity = new()
|
||||
{
|
||||
a = 1.0f,
|
||||
b = 0.0f,
|
||||
c = 0.0f,
|
||||
d = 1.0f,
|
||||
tx = 0.0f,
|
||||
ty = 0.0f
|
||||
};
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{{ {a}, {b}, {c}, {d}, {tx}, {ty} }}";
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerAssetFlags : int
|
||||
{
|
||||
None = 0,
|
||||
CompatibleWithAirPlay = 1 << 0,
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerAssetInfo
|
||||
{
|
||||
internal double duration;
|
||||
internal AVPPlayerSize dimensions;
|
||||
internal float frameRate;
|
||||
internal int videoTrackCount;
|
||||
internal int audioTrackCount;
|
||||
internal int textTrackCount;
|
||||
internal int variantCount;
|
||||
internal AVPPlayerAssetFlags flags;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerTrackFlags: int
|
||||
{
|
||||
Default = 1 << 0,
|
||||
}
|
||||
|
||||
internal enum AVPPlayerVideoTrackStereoMode: int
|
||||
{
|
||||
Unknown = -1,
|
||||
Monoscopic,
|
||||
StereoscopicTopBottom,
|
||||
StereoscopicLeftRight,
|
||||
StereoscopicCustom,
|
||||
StereoscopicRightLeft,
|
||||
StereoscopicMultiviewLeftPrimary,
|
||||
StereoscopicMultiviewRightPrimary,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerVideoTrackFlags: int
|
||||
{
|
||||
HasAlpha = 1 << 0,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerVideoTrackInfo
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)] internal string name;
|
||||
[MarshalAs(UnmanagedType.LPWStr)] internal string language;
|
||||
internal int trackId;
|
||||
internal float estimatedDataRate;
|
||||
internal uint codecSubtype;
|
||||
internal AVPPlayerTrackFlags flags;
|
||||
|
||||
internal AVPPlayerSize dimensions;
|
||||
internal float frameRate;
|
||||
internal AVPAffineTransform transform;
|
||||
internal AVPPlayerVideoTrackStereoMode stereoMode;
|
||||
internal int bitsPerComponent;
|
||||
internal AVPPlayerVideoTrackFlags videoTrackFlags;
|
||||
|
||||
internal Matrix4x4 yCbCrTransform;
|
||||
|
||||
public static readonly AVPPlayerVideoTrackInfo Default = new()
|
||||
{
|
||||
name = null,
|
||||
language = null,
|
||||
trackId = -1,
|
||||
estimatedDataRate = 0,
|
||||
codecSubtype = 0,
|
||||
flags = 0,
|
||||
dimensions = AVPPlayerSize.Zero,
|
||||
frameRate = 0.0f,
|
||||
transform = AVPAffineTransform.Identity,
|
||||
stereoMode = AVPPlayerVideoTrackStereoMode.Unknown,
|
||||
bitsPerComponent = 0,
|
||||
videoTrackFlags = 0,
|
||||
yCbCrTransform = Matrix4x4.identity
|
||||
};
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerAudioTrackInfo
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)] internal string name;
|
||||
[MarshalAs(UnmanagedType.LPWStr)] internal string language;
|
||||
internal int trackId;
|
||||
internal float estimatedDataRate;
|
||||
internal uint codecSubtype;
|
||||
internal AVPPlayerTrackFlags flags;
|
||||
|
||||
internal double sampleRate;
|
||||
internal uint channelCount;
|
||||
internal uint channelLayoutTag;
|
||||
internal AudioChannelMaskFlags channelBitmap;
|
||||
|
||||
public static readonly AVPPlayerAudioTrackInfo Default = new()
|
||||
{
|
||||
name = null,
|
||||
language = null,
|
||||
trackId = -1,
|
||||
estimatedDataRate = 0,
|
||||
codecSubtype = 0,
|
||||
flags = 0,
|
||||
sampleRate = 0.0,
|
||||
channelCount = 0,
|
||||
channelLayoutTag = 0,
|
||||
channelBitmap = AudioChannelMaskFlags.Unspecified
|
||||
};
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerTextTrackInfo
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)] internal string name;
|
||||
[MarshalAs(UnmanagedType.LPWStr)] internal string language;
|
||||
internal int trackId;
|
||||
internal float estimatedDataRate;
|
||||
internal uint codecSubtype;
|
||||
internal AVPPlayerTrackFlags flags;
|
||||
|
||||
public static readonly AVPPlayerTextTrackInfo Default = new()
|
||||
{
|
||||
name = null,
|
||||
language = null,
|
||||
trackId = -1,
|
||||
estimatedDataRate = 0,
|
||||
codecSubtype = 0,
|
||||
flags = 0
|
||||
};
|
||||
}
|
||||
|
||||
internal enum AVPPlayerVideoRange : int
|
||||
{
|
||||
SDR,
|
||||
HLG,
|
||||
PQ
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerVariantFlags: int
|
||||
{
|
||||
Default = 1 << 0,
|
||||
Unsupported = 1 << 1,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerVariantInfo
|
||||
{
|
||||
// Video
|
||||
internal int averageDataRate;
|
||||
internal int peakDataRate;
|
||||
internal CodecType videoCodecType;
|
||||
internal float frameRate;
|
||||
internal AVPPlayerSize dimensions;
|
||||
internal AVPPlayerVideoRange videoRange;
|
||||
|
||||
// Audio
|
||||
internal CodecType audioCodecType;
|
||||
|
||||
// Flags
|
||||
internal AVPPlayerVariantFlags flags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerTimeRange
|
||||
{
|
||||
internal double start;
|
||||
internal double duration;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerState
|
||||
{
|
||||
internal AVPPlayerStatus status;
|
||||
internal double currentTime;
|
||||
internal double currentDate;
|
||||
internal int selectedVideoTrack;
|
||||
internal int selectedAudioTrack;
|
||||
internal int selectedTextTrack;
|
||||
internal int bufferedTimeRangesCount;
|
||||
internal int seekableTimeRangesCount;
|
||||
internal int audioCaptureBufferedSamplesCount;
|
||||
internal int selectedVariant;
|
||||
}
|
||||
|
||||
internal enum AVPPlayerTextureFormat: int
|
||||
{
|
||||
Unknown,
|
||||
BGRA8,
|
||||
R8,
|
||||
RG8,
|
||||
BC1,
|
||||
BC3,
|
||||
BC4,
|
||||
BC5,
|
||||
BC7,
|
||||
BGR10A2,
|
||||
R16,
|
||||
RG16,
|
||||
BGR10XR,
|
||||
RGBA16Float,
|
||||
AndroidOES,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerTexturePlane
|
||||
{
|
||||
internal IntPtr plane;
|
||||
internal int width;
|
||||
internal int height;
|
||||
internal AVPPlayerTextureFormat textureFormat;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum AVPPlayerTextureFlags: int
|
||||
{
|
||||
None = 0,
|
||||
Flipped = 1 << 0,
|
||||
Linear = 1 << 1,
|
||||
Mipmapped = 1 << 2,
|
||||
YCbCr = 1 << 3,
|
||||
}
|
||||
|
||||
internal enum AVPPlayerTextureYCbCrMatrix: int
|
||||
{
|
||||
Identity,
|
||||
ITU_R_601,
|
||||
ITU_R_709,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerTexture
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
|
||||
internal AVPPlayerTexturePlane[] planes;
|
||||
internal long itemTime;
|
||||
internal int frameCounter;
|
||||
internal int planeCount;
|
||||
internal AVPPlayerTextureFlags flags;
|
||||
internal AVPPlayerTextureYCbCrMatrix YCbCrMatrix;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerText
|
||||
{
|
||||
internal IntPtr buffer;
|
||||
internal long itemTime;
|
||||
internal int length;
|
||||
internal int sequence;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AVPPlayerTimedMetadata
|
||||
{
|
||||
internal IntPtr buffer;
|
||||
internal long itemTime;
|
||||
internal int length;
|
||||
}
|
||||
|
||||
internal enum AVPPlayerTrackType : int
|
||||
{
|
||||
Video,
|
||||
Audio,
|
||||
Text
|
||||
}
|
||||
|
||||
internal static string GetPluginVersion()
|
||||
{
|
||||
return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(AVPPluginGetVersionStringPointer());
|
||||
}
|
||||
|
||||
#if AVPRO_VIDEO_PLATFORMMEDIAPLAYER_IPHONE
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPUnityRegisterPlugin(IntPtr fn);
|
||||
|
||||
delegate void UnityRegisterPluginDelegate(IntPtr loadFn, IntPtr unloadFn);
|
||||
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
private const string UnityRegisterPluginEntryPoint = "UnityRegisterPlugin";
|
||||
#else
|
||||
private const string UnityRegisterPluginEntryPoint = "UnityRegisterRenderingPluginV5";
|
||||
#endif
|
||||
|
||||
[DllImport(PluginName, EntryPoint = UnityRegisterPluginEntryPoint)]
|
||||
[AOT.MonoPInvokeCallback(typeof(UnityRegisterPluginDelegate))]
|
||||
internal static extern void UnityRegisterPlugin(IntPtr loadFn, IntPtr unloadFn);
|
||||
|
||||
internal static void AVPPluginBootstrap()
|
||||
{
|
||||
UnityRegisterPluginDelegate unityRegisterPluginDelegate = UnityRegisterPlugin;
|
||||
IntPtr pFn = Marshal.GetFunctionPointerForDelegate(unityRegisterPluginDelegate);
|
||||
AVPUnityRegisterPlugin(pFn);
|
||||
}
|
||||
#else
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPluginBootstrap();
|
||||
#endif
|
||||
#elif AVPRO_VIDEO_PLATFORMMEDIAPLAYER_ANDROID
|
||||
internal static void AVPPluginBootstrap()
|
||||
{
|
||||
AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
|
||||
if (activityClass != null)
|
||||
{
|
||||
AndroidJavaObject activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
|
||||
if (activityContext != null)
|
||||
{
|
||||
AndroidJavaObject avProVideoManager = new AndroidJavaObject("com.renderheads.AVPro.Video.Manager");
|
||||
if (avProVideoManager != null)
|
||||
{
|
||||
avProVideoManager.CallStatic("SetContext", activityContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Handle failure?
|
||||
}
|
||||
#elif AVPRO_VIDEO_PLATFORMMEDIAPLAYER_OPENHARMONY
|
||||
internal static void AVPPluginBootstrap()
|
||||
{
|
||||
Debug.Log("UNITY_OPENHARMONY: Calling Bootstrap");
|
||||
OpenHarmonyJSClass openHarmonyJSClass = new OpenHarmonyJSClass("Manager");
|
||||
openHarmonyJSClass.CallStatic( "Bootstrap" );
|
||||
}
|
||||
#endif
|
||||
|
||||
[DllImport(PluginName)]
|
||||
private static extern IntPtr AVPPluginGetVersionStringPointer();
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern IntPtr AVPPluginGetRenderEventFunction();
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern IntPtr AVPPluginMakePlayer(AVPPlayerSettings settings);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerRelease(IntPtr player);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern AVPPlayerFeatureFlags AVPPlayerGetSupportedFeatures(IntPtr player);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerUpdate(IntPtr _player);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetState(IntPtr player, ref AVPPlayerState state);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetFlags(IntPtr player, int flags);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetAssetInfo(IntPtr player, ref AVPPlayerAssetInfo info);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetVideoTrackInfo(IntPtr player, int index, ref AVPPlayerVideoTrackInfo info);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetAudioTrackInfo(IntPtr player, int index, ref AVPPlayerAudioTrackInfo info);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetTextTrackInfo(IntPtr player, int index, ref AVPPlayerTextTrackInfo info);
|
||||
|
||||
[DllImport( PluginName )]
|
||||
internal static extern void AVPPlayerGetVariantInfo(IntPtr player, int index, ref AVPPlayerVariantInfo info);
|
||||
|
||||
[DllImport( PluginName )]
|
||||
internal static extern void AVPPlayerSelectVariant(IntPtr player, int index);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetBufferedTimeRanges(IntPtr player, AVPPlayerTimeRange[] ranges, int count);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetSeekableTimeRanges(IntPtr player, AVPPlayerTimeRange[] ranges, int count);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetTexture(IntPtr player, ref AVPPlayerTexture texture);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetText(IntPtr player, ref AVPPlayerText text);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerGetTimedMetadata(IntPtr player, ref AVPPlayerTimedMetadata timedMetadata);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetPlayerSettings(IntPtr player, AVPPlayerSettings settings);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal static extern bool AVPPlayerOpenURL(IntPtr player, string url, string headers, AVPPlayerOpenOptions options);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerClose(IntPtr player);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern int AVPPlayerGetAudio(IntPtr player, float[] buffer, int length);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetAudioHeadRotation(IntPtr _player, float[] rotation);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetPositionTrackingEnabled(IntPtr _player, bool enabled);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetAudioFocusEnabled(IntPtr _player, bool enabled);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetAudioFocusProperties(IntPtr _player, float offFocusLevel, float widthDegrees);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetAudioFocusRotation(IntPtr _player, float[] rotation);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerResetAudioFocus(IntPtr _player);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetRate(IntPtr player, float rate);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetVolume(IntPtr player, float volume);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetExternalPlaybackVideoGravity(IntPtr player, AVPPlayerExternalPlaybackVideoGravity gravity);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSeek(IntPtr player, double toTime, double toleranceBefore, double toleranceAfter);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetKeyServerAuthToken(IntPtr player, string token);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetKeyServerURL(IntPtr player, string url);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
internal static extern void AVPPlayerSetDecryptionKey(IntPtr player, byte[] key, int length);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
internal static extern bool AVPPlayerSetTrack(IntPtr player, AVPPlayerTrackType type, int index);
|
||||
|
||||
public struct MediaCachingOptions
|
||||
{
|
||||
public double minimumRequiredBitRate;
|
||||
public float minimumRequiredResolution_width;
|
||||
public float minimumRequiredResolution_height;
|
||||
public string title;
|
||||
public IntPtr artwork;
|
||||
public int artworkLength;
|
||||
}
|
||||
|
||||
[DllImport(PluginName)]
|
||||
public static extern void AVPPlayerCacheMediaForURL(IntPtr player, string url, string headers, MediaCachingOptions options);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
public static extern void AVPPlayerCancelDownloadOfMediaForURL(IntPtr player, string url);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
public static extern void AVPPlayerPauseDownloadOfMediaForURL(IntPtr player, string url);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
public static extern void AVPPlayerResumeDownloadOfMediaForURL(IntPtr player, string url);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
public static extern void AVPPlayerRemoveCachedMediaForURL(IntPtr player, string url);
|
||||
|
||||
[DllImport(PluginName)]
|
||||
public static extern int AVPPlayerGetCachedMediaStatusForURL(IntPtr player, string url, ref float progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bf374b5848b649e6b3840fe1dc03cd2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f68628a1ef6349648e502d1c66b5114
|
||||
timeCreated: 1547113004
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,241 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2015-2024 RenderHeads Ltd. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || (!UNITY_EDITOR && (UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS || UNITY_ANDROID || UNITY_OPENHARMONY)))
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RenderHeads.Media.AVProVideo
|
||||
{
|
||||
internal static class PlatformMediaPlayerExtensions
|
||||
{
|
||||
// AVPPlayerStatus
|
||||
|
||||
internal static bool IsReadyToPlay(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.ReadyToPlay) == PlatformMediaPlayer.Native.AVPPlayerStatus.ReadyToPlay;
|
||||
}
|
||||
|
||||
internal static bool IsPlaying(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.Playing) == PlatformMediaPlayer.Native.AVPPlayerStatus.Playing;
|
||||
}
|
||||
|
||||
internal static bool IsPaused(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.Paused) == PlatformMediaPlayer.Native.AVPPlayerStatus.Paused;
|
||||
}
|
||||
|
||||
internal static bool IsFinished(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.Finished) == PlatformMediaPlayer.Native.AVPPlayerStatus.Finished;
|
||||
}
|
||||
|
||||
internal static bool IsSeeking(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.Seeking) == PlatformMediaPlayer.Native.AVPPlayerStatus.Seeking;
|
||||
}
|
||||
|
||||
internal static bool IsBuffering(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.Buffering) == PlatformMediaPlayer.Native.AVPPlayerStatus.Buffering;
|
||||
}
|
||||
|
||||
internal static bool IsStalled(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.Stalled) == PlatformMediaPlayer.Native.AVPPlayerStatus.Stalled;
|
||||
}
|
||||
|
||||
internal static bool IsExternalPlaybackActive(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.ExternalPlaybackActive) == PlatformMediaPlayer.Native.AVPPlayerStatus.ExternalPlaybackActive;
|
||||
}
|
||||
|
||||
internal static bool IsCached(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.Cached) == PlatformMediaPlayer.Native.AVPPlayerStatus.Cached;
|
||||
}
|
||||
|
||||
internal static bool HasFinishedSeeking(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.FinishedSeeking) == PlatformMediaPlayer.Native.AVPPlayerStatus.FinishedSeeking;
|
||||
}
|
||||
|
||||
internal static bool HasUpdatedAssetInfo(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedAssetInfo) == PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedAssetInfo;
|
||||
}
|
||||
|
||||
internal static bool HasUpdatedTexture(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedTexture) == PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedTexture;
|
||||
}
|
||||
|
||||
internal static bool HasUpdatedTextureTransform(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedTextureTransform) == PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedTextureTransform;
|
||||
}
|
||||
|
||||
internal static bool HasUpdatedBufferedTimeRanges(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedBufferedTimeRanges) == PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedBufferedTimeRanges;
|
||||
}
|
||||
|
||||
internal static bool HasUpdatedSeekableTimeRanges(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedSeekableTimeRanges) == PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedSeekableTimeRanges;
|
||||
}
|
||||
|
||||
internal static bool HasUpdatedText(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedText) == PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedText;
|
||||
}
|
||||
|
||||
internal static bool HasUpdatedTimedMetaData(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedTimedMetadata) == PlatformMediaPlayer.Native.AVPPlayerStatus.UpdatedTimedMetadata;
|
||||
}
|
||||
|
||||
internal static bool HasVideo(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.HasVideo) == PlatformMediaPlayer.Native.AVPPlayerStatus.HasVideo;
|
||||
}
|
||||
|
||||
internal static bool HasAudio(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.HasAudio) == PlatformMediaPlayer.Native.AVPPlayerStatus.HasAudio;
|
||||
}
|
||||
|
||||
internal static bool HasText(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.HasText) == PlatformMediaPlayer.Native.AVPPlayerStatus.HasText;
|
||||
}
|
||||
|
||||
internal static bool HasMetadata(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.HasMetadata) == PlatformMediaPlayer.Native.AVPPlayerStatus.HasMetadata;
|
||||
}
|
||||
|
||||
internal static bool HasFailed(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.Failed) == PlatformMediaPlayer.Native.AVPPlayerStatus.Failed;
|
||||
}
|
||||
|
||||
internal static bool HasVariants(this PlatformMediaPlayer.Native.AVPPlayerStatus status)
|
||||
{
|
||||
return (status & PlatformMediaPlayer.Native.AVPPlayerStatus.HasVariants) == PlatformMediaPlayer.Native.AVPPlayerStatus.HasVariants;
|
||||
}
|
||||
|
||||
// AVPPlayerFlags
|
||||
|
||||
internal static bool IsLooping(this PlatformMediaPlayer.Native.AVPPlayerFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerFlags.Looping) == PlatformMediaPlayer.Native.AVPPlayerFlags.Looping;
|
||||
}
|
||||
|
||||
internal static PlatformMediaPlayer.Native.AVPPlayerFlags SetLooping(this PlatformMediaPlayer.Native.AVPPlayerFlags flags, bool b)
|
||||
{
|
||||
if (flags.IsLooping() ^ b)
|
||||
{
|
||||
flags = (b ? flags | PlatformMediaPlayer.Native.AVPPlayerFlags.Looping
|
||||
: flags & ~PlatformMediaPlayer.Native.AVPPlayerFlags.Looping) | PlatformMediaPlayer.Native.AVPPlayerFlags.Dirty;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
internal static bool IsMuted(this PlatformMediaPlayer.Native.AVPPlayerFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerFlags.Muted) == PlatformMediaPlayer.Native.AVPPlayerFlags.Muted;
|
||||
}
|
||||
|
||||
internal static PlatformMediaPlayer.Native.AVPPlayerFlags SetMuted(this PlatformMediaPlayer.Native.AVPPlayerFlags flags, bool b)
|
||||
{
|
||||
if (flags.IsMuted() ^ b)
|
||||
{
|
||||
flags = (b ? flags | PlatformMediaPlayer.Native.AVPPlayerFlags.Muted
|
||||
: flags & ~PlatformMediaPlayer.Native.AVPPlayerFlags.Muted) | PlatformMediaPlayer.Native.AVPPlayerFlags.Dirty;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
internal static bool IsExternalPlaybackAllowed(this PlatformMediaPlayer.Native.AVPPlayerFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerFlags.AllowExternalPlayback) == PlatformMediaPlayer.Native.AVPPlayerFlags.AllowExternalPlayback;
|
||||
}
|
||||
|
||||
internal static PlatformMediaPlayer.Native.AVPPlayerFlags SetAllowExternalPlayback(this PlatformMediaPlayer.Native.AVPPlayerFlags flags, bool b)
|
||||
{
|
||||
if (flags.IsExternalPlaybackAllowed() ^ b)
|
||||
{
|
||||
flags = (b ? flags | PlatformMediaPlayer.Native.AVPPlayerFlags.AllowExternalPlayback
|
||||
: flags & ~PlatformMediaPlayer.Native.AVPPlayerFlags.AllowExternalPlayback) | PlatformMediaPlayer.Native.AVPPlayerFlags.Dirty;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
internal static bool ResumePlayback(this PlatformMediaPlayer.Native.AVPPlayerFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerFlags.ResumePlayback) == PlatformMediaPlayer.Native.AVPPlayerFlags.ResumePlayback;
|
||||
}
|
||||
|
||||
internal static PlatformMediaPlayer.Native.AVPPlayerFlags SetResumePlayback(this PlatformMediaPlayer.Native.AVPPlayerFlags flags, bool b)
|
||||
{
|
||||
if (flags.ResumePlayback() ^ b)
|
||||
{
|
||||
flags = (b ? flags | PlatformMediaPlayer.Native.AVPPlayerFlags.ResumePlayback
|
||||
: flags & ~PlatformMediaPlayer.Native.AVPPlayerFlags.ResumePlayback) | PlatformMediaPlayer.Native.AVPPlayerFlags.Dirty;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
internal static bool IsDirty(this PlatformMediaPlayer.Native.AVPPlayerFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerFlags.Dirty) == PlatformMediaPlayer.Native.AVPPlayerFlags.Dirty;
|
||||
}
|
||||
|
||||
internal static PlatformMediaPlayer.Native.AVPPlayerFlags SetDirty(this PlatformMediaPlayer.Native.AVPPlayerFlags flags, bool b)
|
||||
{
|
||||
if (flags.IsDirty() ^ b)
|
||||
{
|
||||
flags = b ? flags | PlatformMediaPlayer.Native.AVPPlayerFlags.Dirty : flags & ~PlatformMediaPlayer.Native.AVPPlayerFlags.Dirty;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
// MARK: AVPPlayerAssetFlags
|
||||
|
||||
internal static bool IsCompatibleWithAirPlay(this PlatformMediaPlayer.Native.AVPPlayerAssetFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerAssetFlags.CompatibleWithAirPlay) == PlatformMediaPlayer.Native.AVPPlayerAssetFlags.CompatibleWithAirPlay;
|
||||
}
|
||||
|
||||
// MARK: AVPPlayerTrackFlags
|
||||
|
||||
internal static bool IsDefault(this PlatformMediaPlayer.Native.AVPPlayerTrackFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerTrackFlags.Default) == PlatformMediaPlayer.Native.AVPPlayerTrackFlags.Default;
|
||||
}
|
||||
|
||||
// AVPPlayerTextureFlags
|
||||
|
||||
internal static bool IsFlipped(this PlatformMediaPlayer.Native.AVPPlayerTextureFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerTextureFlags.Flipped) == PlatformMediaPlayer.Native.AVPPlayerTextureFlags.Flipped;
|
||||
}
|
||||
|
||||
internal static bool IsLinear(this PlatformMediaPlayer.Native.AVPPlayerTextureFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerTextureFlags.Linear) == PlatformMediaPlayer.Native.AVPPlayerTextureFlags.Linear;
|
||||
}
|
||||
|
||||
internal static bool IsMipmapped(this PlatformMediaPlayer.Native.AVPPlayerTextureFlags flags)
|
||||
{
|
||||
return (flags & PlatformMediaPlayer.Native.AVPPlayerTextureFlags.Mipmapped) == PlatformMediaPlayer.Native.AVPPlayerTextureFlags.Mipmapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e27ea5523e11f44c09e8d368eb1f2983
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,930 @@
|
||||
//#define AVPRO_WEBGL_USE_RENDERTEXTURE
|
||||
// NOTE: We only allow this script to compile in editor so we can easily check for compilation issues
|
||||
#if (UNITY_EDITOR || UNITY_WEBGL)
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2015-2021 RenderHeads Ltd. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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, int externalLibrary);
|
||||
|
||||
[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 AVPPlayerGetVideoTrackCount(int player);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern int AVPPlayerGetAudioTrackCount(int player);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern int AVPPlayerGetTextTrackCount(int player);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern bool AVPPlayerSetActiveVideoTrack(int player, int trackId);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern bool AVPPlayerSetActiveAudioTrack(int player, int trackId);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern bool AVPPlayerSetActiveTextTrack(int player, int trackId);
|
||||
|
||||
[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, double time, bool fast);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern double AVPPlayerGetCurrentTime(int player);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern float AVPPlayerGetDuration(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 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);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void AVPPlayerCreateVideoTexture(int textureId);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void AVPPlayerDestroyVideoTexture(int textureId);
|
||||
|
||||
[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 double AVPPlayerGetTimeRangeStart(int id, int timeRangeIndex);
|
||||
[DllImport("__Internal")]
|
||||
private static extern double AVPPlayerGetTimeRangeEnd(int id, int timeRangeIndex);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern string AVPPlayerGetVideoTrackName(int player, int trackIndex);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern string AVPPlayerGetAudioTrackName(int player, int trackIndex);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern string AVPPlayerGetTextTrackName(int player, int trackIndex);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern string AVPPlayerGetVideoTrackLanguage(int player, int trackIndex);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern string AVPPlayerGetAudioTrackLanguage(int player, int trackIndex);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern string AVPPlayerGetTextTrackLanguage(int player, int trackIndex);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern bool AVPPlayerIsVideoTrackActive(int player, int trackIndex);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern bool AVPPlayerIsAudioTrackActive(int player, int trackIndex);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern bool AVPPlayerIsTextTrackActive(int player, int trackIndex);
|
||||
|
||||
private WebGL.ExternalLibrary _externalLibrary = WebGL.ExternalLibrary.None;
|
||||
private int _playerIndex = -1;
|
||||
private int _playerID = -1;
|
||||
|
||||
#if AVPRO_WEBGL_USE_RENDERTEXTURE
|
||||
private RenderTexture _texture = null;
|
||||
#else
|
||||
private Texture2D _texture = null;
|
||||
#endif
|
||||
|
||||
private int _width = 0;
|
||||
private int _height = 0;
|
||||
private int _cachedVideoTrackCount = 0;
|
||||
private int _cachedAudioTrackCount = 0;
|
||||
private int _cachedTextTrackCount = 0;
|
||||
private bool _isDirtyVideoTracks = false;
|
||||
private bool _isDirtyAudioTracks = false;
|
||||
private bool _isDirtyTextTracks = false;
|
||||
private bool _useTextureMips = false;
|
||||
private System.IntPtr _cachedTextureNativePtr = System.IntPtr.Zero;
|
||||
|
||||
private static bool _isWebGL1 = false;
|
||||
|
||||
public static bool InitialisePlatform()
|
||||
{
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
_isWebGL1 = false;
|
||||
#else
|
||||
_isWebGL1 = (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.OpenGLES2);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
public WebGLMediaPlayer(MediaPlayer.OptionsWebGL options)
|
||||
{
|
||||
SetOptions(options);
|
||||
}
|
||||
|
||||
public void SetOptions(MediaPlayer.OptionsWebGL options)
|
||||
{
|
||||
_externalLibrary = options.externalLibrary;
|
||||
_useTextureMips = options.useTextureMips;
|
||||
}
|
||||
|
||||
public override string GetVersion()
|
||||
{
|
||||
return "3.1.0";
|
||||
}
|
||||
|
||||
public override string GetExpectedVersion()
|
||||
{
|
||||
return GetVersion();
|
||||
}
|
||||
|
||||
public override bool OpenMedia(string path, long offset, string httpHeader, MediaHints mediaHints, int forceFileFormat = 0, bool startWithHighestBitrate = false)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (path.StartsWith("http://") ||
|
||||
path.StartsWith("https://") ||
|
||||
path.StartsWith("file://") ||
|
||||
path.StartsWith("blob:") ||
|
||||
path.StartsWith("chrome-extension://"))
|
||||
{
|
||||
int[] idValues = new int[2];
|
||||
idValues[0] = -1;
|
||||
AVPPlayerInsertVideoElement(path, idValues, (int)_externalLibrary);
|
||||
{
|
||||
int playerIndex = idValues[0];
|
||||
_playerID = idValues[1];
|
||||
|
||||
if (playerIndex > -1)
|
||||
{
|
||||
_playerIndex = playerIndex;
|
||||
_mediaHints = mediaHints;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[AVProVideo] Unknown URL protocol");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void CloseMedia()
|
||||
{
|
||||
if (_playerIndex != -1)
|
||||
{
|
||||
Pause();
|
||||
|
||||
_width = 0;
|
||||
_height = 0;
|
||||
_cachedVideoTrackCount = 0;
|
||||
_cachedAudioTrackCount = 0;
|
||||
_cachedTextTrackCount = 0;
|
||||
_isDirtyVideoTracks = false;
|
||||
_isDirtyAudioTracks = false;
|
||||
_isDirtyTextTracks = false;
|
||||
|
||||
AVPPlayerClose(_playerIndex);
|
||||
|
||||
if (_texture != null)
|
||||
{
|
||||
DestroyTexture();
|
||||
}
|
||||
|
||||
_playerIndex = -1;
|
||||
_playerID = -1;
|
||||
|
||||
base.CloseMedia();
|
||||
}
|
||||
}
|
||||
|
||||
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 Seek(double time)
|
||||
{
|
||||
// Debug.Assert(_playerIndex != -1, "no player Seek");
|
||||
AVPPlayerSeekToTime(_playerIndex, time, false);
|
||||
}
|
||||
|
||||
public override void SeekFast(double time)
|
||||
{
|
||||
// Debug.Assert(_playerIndex != -1, "no player SeekFast");
|
||||
AVPPlayerSeekToTime(_playerIndex, time, true);
|
||||
}
|
||||
|
||||
public override double GetCurrentTime()
|
||||
{
|
||||
//Debug.Assert(_player != -1, "no player GetCurrentTime");
|
||||
double result = 0.0;
|
||||
if (_playerIndex != -1)
|
||||
{
|
||||
result = AVPPlayerGetCurrentTime(_playerIndex);
|
||||
}
|
||||
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 double GetDuration()
|
||||
{
|
||||
//Debug.Assert(_player != -1, "no player GetDuration");
|
||||
double result = 0.0;
|
||||
if (_playerIndex != -1)
|
||||
{
|
||||
result = AVPPlayerGetDuration(_playerIndex);
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
|
||||
internal override StereoPacking InternalGetTextureStereoPacking()
|
||||
{
|
||||
return StereoPacking.Unknown;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsMipMapGenerationSupported(int videoWidth, int videoHeight)
|
||||
{
|
||||
if (!_isWebGL1 || (Mathf.IsPowerOfTwo(videoWidth) && Mathf.IsPowerOfTwo(videoHeight)))
|
||||
{
|
||||
// Mip generation only supported in WebGL 2.0, or WebGL 1.0 when using power-of-two textures
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void CreateTexture()
|
||||
{
|
||||
//Debug.Log("creating texture " + _width + " X " + _height);
|
||||
|
||||
#if AVPRO_WEBGL_USE_RENDERTEXTURE
|
||||
_texture = new RenderTexture(_width, _height, 0, RenderTextureFormat.Default);
|
||||
_texture.autoGenerateMips = false;
|
||||
_texture.useMipMap = (_useTextureMips && IsMipMapGenerationSupported(_width, _height));
|
||||
_texture.Create();
|
||||
_cachedTextureNativePtr = _texture.GetNativeTexturePtr();
|
||||
#else
|
||||
int textureId = 80000 + _playerIndex;
|
||||
_cachedTextureNativePtr = new System.IntPtr(textureId);
|
||||
AVPPlayerCreateVideoTexture(textureId);
|
||||
// TODO: add support for mip generation
|
||||
_texture = Texture2D.CreateExternalTexture(_width, _height, TextureFormat.RGBA32, false, false, _cachedTextureNativePtr);
|
||||
if (_useTextureMips)
|
||||
{
|
||||
Debug.LogWarning("[AVProVideo] Texture Mips not yet implemented in this WebGL rendering path");
|
||||
}
|
||||
//Debug.Log("created texture1 " + _texture);
|
||||
//Debug.Log("created texture2 " + _texture.GetNativeTexturePtr().ToInt32());
|
||||
#endif
|
||||
|
||||
ApplyTextureProperties(_texture);
|
||||
|
||||
bool initTexture = true;
|
||||
#if AVPRO_WEBGL_USE_RENDERTEXTURE
|
||||
// Textures in WebGL 2.0 don't require texImage2D as they are already recreated with texStorage2D
|
||||
initTexture = _isWebGL1;
|
||||
#endif
|
||||
AVPPlayerFetchVideoTexture(_playerIndex, _cachedTextureNativePtr, initTexture);
|
||||
}
|
||||
|
||||
private void DestroyTexture()
|
||||
{
|
||||
// Have to update with zero to release Metal textures!
|
||||
//_texture.UpdateExternalTexture(0);
|
||||
if (_texture != null)
|
||||
{
|
||||
#if AVPRO_WEBGL_USE_RENDERTEXTURE
|
||||
RenderTexture.Destroy(_texture);
|
||||
#else
|
||||
Texture2D.Destroy(_texture);
|
||||
AVPPlayerDestroyVideoTexture(_cachedTextureNativePtr.ToInt32());
|
||||
#endif
|
||||
_texture = null;
|
||||
}
|
||||
_cachedTextureNativePtr = System.IntPtr.Zero;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if(_playerID >= 0) // CheckPlayer's index and update it
|
||||
{
|
||||
_playerIndex = AVPPlayerUpdatePlayerIndex(_playerID);
|
||||
}
|
||||
|
||||
if(_playerIndex >= 0)
|
||||
{
|
||||
CheckTracksDirty();
|
||||
UpdateTracks();
|
||||
UpdateTextCue();
|
||||
UpdateSubtitles();
|
||||
UpdateLastErrorCode();
|
||||
|
||||
if (AVPPlayerReady(_playerIndex))
|
||||
{
|
||||
UpdateTimeRanges();
|
||||
if (AVPPlayerHasVideo(_playerIndex))
|
||||
{
|
||||
_width = AVPPlayerWidth(_playerIndex);
|
||||
_height = AVPPlayerHeight(_playerIndex);
|
||||
|
||||
if (_texture != null && (_texture.width != _width || _texture.height != _height))
|
||||
{
|
||||
DestroyTexture();
|
||||
}
|
||||
|
||||
if (_texture == null && _width > 0 && _height > 0)
|
||||
{
|
||||
CreateTexture();
|
||||
}
|
||||
|
||||
// Update the texture
|
||||
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);
|
||||
|
||||
#if AVPRO_WEBGL_USE_RENDERTEXTURE
|
||||
if (_texture.useMipMap)
|
||||
{
|
||||
_texture.GenerateMips();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UpdateDisplayFrameRate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckTracksDirty()
|
||||
{
|
||||
_isDirtyVideoTracks = false;
|
||||
_isDirtyAudioTracks = false;
|
||||
_isDirtyTextTracks = false;
|
||||
|
||||
// TODO: replace this crude polling check with events, or only do it once metadataReady
|
||||
// Need to add event support as tracks can be added via HTML (especially text)
|
||||
int videoTrackCount = AVPPlayerGetVideoTrackCount(_playerIndex);
|
||||
int audioTrackCount = AVPPlayerGetAudioTrackCount(_playerIndex);
|
||||
int textTrackCount = AVPPlayerGetTextTrackCount(_playerIndex);
|
||||
|
||||
_isDirtyVideoTracks = (_cachedVideoTrackCount != videoTrackCount);
|
||||
_isDirtyAudioTracks = (_cachedAudioTrackCount != audioTrackCount);
|
||||
_isDirtyTextTracks = ( _cachedTextTrackCount != textTrackCount);
|
||||
|
||||
_cachedVideoTrackCount = videoTrackCount;
|
||||
_cachedAudioTrackCount = audioTrackCount;
|
||||
_cachedTextTrackCount = textTrackCount;
|
||||
}
|
||||
|
||||
private void UpdateTimeRanges()
|
||||
{
|
||||
{
|
||||
int rangeCount = AVPPlayerGetNumBufferedTimeRanges(_playerIndex);
|
||||
if (rangeCount != _bufferedTimes.Count)
|
||||
{
|
||||
_bufferedTimes._ranges = new TimeRange[rangeCount];
|
||||
}
|
||||
for (int i = 0; i < rangeCount; i++)
|
||||
{
|
||||
double startTime = AVPPlayerGetTimeRangeStart(_playerIndex, i);
|
||||
double endTime = AVPPlayerGetTimeRangeEnd(_playerIndex, i);
|
||||
_bufferedTimes._ranges[i] = new TimeRange(startTime, endTime - startTime);
|
||||
}
|
||||
_bufferedTimes.CalculateRange();
|
||||
}
|
||||
|
||||
{
|
||||
double duration = GetDuration();
|
||||
if (duration > 0.0)
|
||||
{
|
||||
_seekableTimes._ranges = new TimeRange[1];
|
||||
_seekableTimes._ranges[0] = new TimeRange(0.0, duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
_seekableTimes._ranges = new TimeRange[0];
|
||||
}
|
||||
_seekableTimes.CalculateRange();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
CloseMedia();
|
||||
}
|
||||
|
||||
public override bool IsPlaybackStalled()
|
||||
{
|
||||
bool result = false;
|
||||
if (_playerIndex > -1)
|
||||
{
|
||||
result = AVPPlayerIsPlaybackStalled(_playerIndex) && IsPlaying();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Tracks
|
||||
internal override int InternalGetTrackCount(TrackType trackType)
|
||||
{
|
||||
int result = 0;
|
||||
switch (trackType)
|
||||
{
|
||||
case TrackType.Video:
|
||||
result = AVPPlayerGetVideoTrackCount(_playerIndex);
|
||||
break;
|
||||
case TrackType.Audio:
|
||||
result = AVPPlayerGetAudioTrackCount(_playerIndex);
|
||||
break;
|
||||
case TrackType.Text:
|
||||
result = AVPPlayerGetTextTrackCount(_playerIndex);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal override bool InternalIsChangedTracks(TrackType trackType)
|
||||
{
|
||||
bool result = false;
|
||||
switch (trackType)
|
||||
{
|
||||
case TrackType.Video:
|
||||
result = _isDirtyVideoTracks;
|
||||
break;
|
||||
case TrackType.Audio:
|
||||
result = _isDirtyAudioTracks;
|
||||
break;
|
||||
case TrackType.Text:
|
||||
result = _isDirtyTextTracks;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal override bool InternalSetActiveTrack(TrackType trackType, int trackId)
|
||||
{
|
||||
bool result = false;
|
||||
switch (trackType)
|
||||
{
|
||||
case TrackType.Video:
|
||||
result = AVPPlayerSetActiveVideoTrack(_playerIndex, trackId);
|
||||
break;
|
||||
case TrackType.Audio:
|
||||
result = AVPPlayerSetActiveAudioTrack(_playerIndex, trackId);
|
||||
break;
|
||||
case TrackType.Text:
|
||||
result = AVPPlayerSetActiveTextTrack(_playerIndex, trackId);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal override TrackBase InternalGetTrackInfo(TrackType trackType, int trackIndex, ref bool isActiveTrack)
|
||||
{
|
||||
TrackBase result = null;
|
||||
|
||||
switch (trackType)
|
||||
{
|
||||
case TrackType.Video:
|
||||
{
|
||||
string trackName = AVPPlayerGetVideoTrackName(_playerIndex, trackIndex);
|
||||
string trackLanguage = AVPPlayerGetVideoTrackLanguage(_playerIndex, trackIndex);
|
||||
bool isActive = AVPPlayerIsVideoTrackActive(_playerIndex, trackIndex);
|
||||
result = new VideoTrack(trackIndex, trackName, trackLanguage, isActive);
|
||||
break;
|
||||
}
|
||||
case TrackType.Audio:
|
||||
{
|
||||
string trackName = AVPPlayerGetAudioTrackName(_playerIndex, trackIndex);
|
||||
string trackLanguage = AVPPlayerGetAudioTrackLanguage(_playerIndex, trackIndex);
|
||||
bool isActive = AVPPlayerIsAudioTrackActive(_playerIndex, trackIndex);
|
||||
result = new AudioTrack(trackIndex, trackName, trackLanguage, isActive);
|
||||
break;
|
||||
}
|
||||
case TrackType.Text:
|
||||
{
|
||||
string trackName = AVPPlayerGetTextTrackName(_playerIndex, trackIndex);
|
||||
string trackLanguage = AVPPlayerGetTextTrackLanguage(_playerIndex, trackIndex);
|
||||
bool isActive = AVPPlayerIsTextTrackActive(_playerIndex, trackIndex);
|
||||
result = new TextTrack(trackIndex, trackName, trackLanguage, isActive);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Text Cue stub methods
|
||||
internal override bool InternalIsChangedTextCue() { return false; }
|
||||
internal override string InternalGetCurrentTextCue() { return string.Empty; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c044ff13d5570e64a8156bc718b3cfec
|
||||
timeCreated: 1468230219
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f3c954eb61392a4193295a8376bd8db
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,5 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2015-2025 RenderHeads Ltd. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This file is intentionally blank
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b36cc2d6962ce34e86c5a83a0de6d4a
|
||||
timeCreated: 1630292296
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,973 @@
|
||||
//#define AVPROVIDEO_WINDOWS_UNIFIED_DLLS // DEV FEATURE: are we using new unified (DS + MF + WRT) Windows DLLs?
|
||||
//
|
||||
// NOTE: We only allow this script to compile in editor so we can easily check for compilation issues
|
||||
#if ((UNITY_EDITOR || (UNITY_STANDALONE_WIN || UNITY_WSA_10_0)) && !AVPROVIDEO_WINDOWS_UNIFIED_DLLS)
|
||||
|
||||
#if UNITY_WSA_10 || ENABLE_IL2CPP
|
||||
#define AVPROVIDEO_MARSHAL_RETURN_BOOL
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2018-2021 RenderHeads Ltd. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace RenderHeads.Media.AVProVideo
|
||||
{
|
||||
public enum PlaybackState
|
||||
{
|
||||
None = 0,
|
||||
Opening = 1,
|
||||
Buffering = 2, // Replace with Stalled and add Buffering as State 64??
|
||||
Playing = 3,
|
||||
Paused = 4,
|
||||
StateMask = 7,
|
||||
|
||||
Seeking = 32,
|
||||
}
|
||||
|
||||
public partial class WindowsRtMediaPlayer : BaseMediaPlayer
|
||||
{
|
||||
private bool _isMediaLoaded = false;
|
||||
private bool _isLooping = false;
|
||||
private float _volume = 1.0f;
|
||||
private bool _use10BitTextures = false;
|
||||
private bool _useLowLiveLatency = false;
|
||||
|
||||
public WindowsRtMediaPlayer(MediaPlayer.OptionsWindows options) : base()
|
||||
{
|
||||
_playerDescription = "WinRT";
|
||||
|
||||
SetOptions(options);
|
||||
|
||||
for (int i = 0; i < _eyeTextures.Length; i++)
|
||||
{
|
||||
_eyeTextures[i] = new EyeTexture();
|
||||
}
|
||||
}
|
||||
|
||||
public WindowsRtMediaPlayer(MediaPlayer.OptionsWindowsUWP options) : base()
|
||||
{
|
||||
_playerDescription = "WinRT";
|
||||
_use10BitTextures = options.use10BitTextures;
|
||||
_useLowLiveLatency = options.useLowLiveLatency;
|
||||
for (int i = 0; i < _eyeTextures.Length; i++)
|
||||
{
|
||||
_eyeTextures[i] = new EyeTexture();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetOptions(MediaPlayer.OptionsWindows options)
|
||||
{
|
||||
_use10BitTextures = options.use10BitTextures;
|
||||
_useLowLiveLatency = options.useLowLiveLatency;
|
||||
}
|
||||
|
||||
public override bool CanPlay()
|
||||
{
|
||||
return HasMetaData();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
CloseMedia();
|
||||
if (_playerInstance != System.IntPtr.Zero)
|
||||
{
|
||||
Native.DestroyPlayer(_playerInstance); _playerInstance = System.IntPtr.Zero;
|
||||
Native.IssueRenderThreadEvent_FreeAllTextures();
|
||||
}
|
||||
for (int i = 0; i < _eyeTextures.Length; i++)
|
||||
{
|
||||
_eyeTextures[i].Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool PlayerSupportsLinearColorSpace()
|
||||
{
|
||||
// The current player doesn't support rendering to SRGB textures
|
||||
return false;
|
||||
}
|
||||
|
||||
public override double GetCurrentTime()
|
||||
{
|
||||
return Native.GetCurrentPosition(_playerInstance);
|
||||
}
|
||||
|
||||
public override double GetDuration()
|
||||
{
|
||||
return Native.GetDuration(_playerInstance);
|
||||
}
|
||||
|
||||
public override float GetPlaybackRate()
|
||||
{
|
||||
return Native.GetPlaybackRate(_playerInstance);
|
||||
}
|
||||
|
||||
public override Texture GetTexture(int index = 0)
|
||||
{
|
||||
Texture result = null;
|
||||
if (_frameTimeStamp > 0 && index < _eyeTextures.Length)
|
||||
{
|
||||
result = _eyeTextures[index].texture;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override int GetTextureCount()
|
||||
{
|
||||
if (_eyeTextures[1].texture != null)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override int GetTextureFrameCount()
|
||||
{
|
||||
return (int)_frameTimeStamp;
|
||||
}
|
||||
|
||||
internal override StereoPacking InternalGetTextureStereoPacking()
|
||||
{
|
||||
/// [MOZ] Windows plugin internal stereo packing enum is now out of date and doesn't take into account
|
||||
/// the changes required for supporting MV-HEVC on visionOS and Android.
|
||||
int value = Native.GetStereoPacking(_playerInstance);
|
||||
|
||||
StereoPacking stereoPacking;
|
||||
switch (value)
|
||||
{
|
||||
case 0: // None
|
||||
stereoPacking = StereoPacking.Monoscopic;
|
||||
break;
|
||||
|
||||
case 1: // TopBottom
|
||||
stereoPacking = StereoPacking.TopBottom;
|
||||
break;
|
||||
|
||||
case 2: // LeftRight
|
||||
stereoPacking = StereoPacking.LeftRight;
|
||||
break;
|
||||
|
||||
case 3: // CustomUV
|
||||
stereoPacking = StereoPacking.CustomUV;
|
||||
break;
|
||||
|
||||
case 4: // TwoTextures
|
||||
stereoPacking = StereoPacking.MultiviewLeftPrimary;
|
||||
break;
|
||||
|
||||
default:
|
||||
stereoPacking = StereoPacking.Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
return stereoPacking;
|
||||
}
|
||||
|
||||
public override string GetVersion()
|
||||
{
|
||||
return _version;
|
||||
}
|
||||
|
||||
public override string GetExpectedVersion()
|
||||
{
|
||||
return Helper.ExpectedPluginVersion.WinRT;
|
||||
}
|
||||
|
||||
public override float GetVideoFrameRate()
|
||||
{
|
||||
float result = 0f;
|
||||
Native.VideoTrack videoTrack;
|
||||
if (Native.GetActiveVideoTrackInfo(_playerInstance, out videoTrack))
|
||||
{
|
||||
result = videoTrack.frameRate;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override int GetVideoWidth()
|
||||
{
|
||||
int result = 0;
|
||||
if (_eyeTextures[0].texture)
|
||||
{
|
||||
result = _eyeTextures[0].texture.width;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override int GetVideoHeight()
|
||||
{
|
||||
int result = 0;
|
||||
if (_eyeTextures[0].texture)
|
||||
{
|
||||
result = _eyeTextures[0].texture.height;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override float GetVolume()
|
||||
{
|
||||
return _volume;//Native.GetAudioVolume(_playerInstance);
|
||||
}
|
||||
|
||||
public override void SetBalance(float balance)
|
||||
{
|
||||
Native.SetAudioBalance(_playerInstance, balance);
|
||||
}
|
||||
|
||||
public override float GetBalance()
|
||||
{
|
||||
return Native.GetAudioBalance(_playerInstance);
|
||||
}
|
||||
|
||||
public override bool HasAudio()
|
||||
{
|
||||
return _audioTracks.Count > 0;
|
||||
}
|
||||
|
||||
public override bool HasMetaData()
|
||||
{
|
||||
return Native.GetDuration(_playerInstance) > 0f;
|
||||
}
|
||||
|
||||
public override bool HasVideo()
|
||||
{
|
||||
return _videoTracks.Count > 0;
|
||||
}
|
||||
|
||||
public override bool IsBuffering()
|
||||
{
|
||||
return ((Native.GetPlaybackState(_playerInstance) & PlaybackState.StateMask) == PlaybackState.Buffering);
|
||||
}
|
||||
|
||||
public override bool IsFinished()
|
||||
{
|
||||
bool result = false;
|
||||
if (IsPaused() && !IsSeeking() && GetCurrentTime() >= GetDuration())
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool IsLooping()
|
||||
{
|
||||
return _isLooping;//Native.IsLooping(_playerInstance);
|
||||
}
|
||||
|
||||
public override bool IsMuted()
|
||||
{
|
||||
return Native.IsAudioMuted(_playerInstance);
|
||||
}
|
||||
|
||||
public override bool IsPaused()
|
||||
{
|
||||
return ((Native.GetPlaybackState(_playerInstance) & PlaybackState.StateMask) == PlaybackState.Paused);
|
||||
}
|
||||
|
||||
public override bool IsPlaying()
|
||||
{
|
||||
return ((Native.GetPlaybackState(_playerInstance) & PlaybackState.StateMask) == PlaybackState.Playing);
|
||||
}
|
||||
|
||||
public override bool IsSeeking()
|
||||
{
|
||||
return ((Native.GetPlaybackState(_playerInstance) & PlaybackState.Seeking) != 0);
|
||||
}
|
||||
|
||||
public override void MuteAudio(bool bMuted)
|
||||
{
|
||||
Native.SetAudioMuted(_playerInstance, bMuted);
|
||||
}
|
||||
|
||||
// TODO: replace all these options with a structure
|
||||
public override bool OpenMedia(string path, long offset, string httpHeader, MediaHints mediaHints, int forceFileFormat = 0, bool startWithHighestBitrate = false)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// RJT NOTE: Commented out as already called by 'InternalOpenMedia()' which calls this function
|
||||
// CloseMedia();
|
||||
|
||||
if (_playerInstance == System.IntPtr.Zero)
|
||||
{
|
||||
_playerInstance = Native.CreatePlayer();
|
||||
|
||||
// Force setting any auth data as it wouldn't have been set without a _playerInstance
|
||||
AuthenticationData = _nextAuthData;
|
||||
}
|
||||
if (_playerInstance != System.IntPtr.Zero)
|
||||
{
|
||||
result = Native.OpenMedia(_playerInstance, path, httpHeader, (FileFormat)forceFileFormat, startWithHighestBitrate, _use10BitTextures);
|
||||
if (result)
|
||||
{
|
||||
if (_useLowLiveLatency)
|
||||
{
|
||||
Native.SetLiveOffset(_playerInstance, 0.0);
|
||||
}
|
||||
|
||||
// RJT NOTE: Other platforms create their native instances earlier than 'OpenMedia()' and set looping at that
|
||||
// point which Windows misses, so make sure once we have an instance we pass the looping flag down retrospectively
|
||||
// - https://github.com/RenderHeads/UnityPlugin-AVProVideo/issues/1913
|
||||
// - Same now with volume: https://github.com/RenderHeads/UnityPlugin-AVProVideo/issues/1916
|
||||
Native.SetLooping(_playerInstance, _isLooping);
|
||||
Native.SetAudioVolume(_playerInstance, _volume);
|
||||
}
|
||||
_mediaHints = mediaHints;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void CloseMedia()
|
||||
{
|
||||
// NOTE: This unloads the current video, but the texture should remain
|
||||
_isMediaLoaded = false;
|
||||
_isLooping = false;
|
||||
_volume = 1.0f;
|
||||
Native.CloseMedia(_playerInstance);
|
||||
|
||||
base.CloseMedia();
|
||||
}
|
||||
|
||||
public override void Pause()
|
||||
{
|
||||
Native.Pause(_playerInstance);
|
||||
}
|
||||
|
||||
public override void Play()
|
||||
{
|
||||
Native.Play(_playerInstance);
|
||||
}
|
||||
|
||||
public override void Render()
|
||||
{
|
||||
Native.IssueRenderThreadEvent_UpdateAllTextures();
|
||||
}
|
||||
|
||||
private void Update_Textures()
|
||||
{
|
||||
// See if there is a new frame ready
|
||||
{
|
||||
System.IntPtr texturePointerLeft = System.IntPtr.Zero;
|
||||
System.IntPtr texturePointerRight = System.IntPtr.Zero;
|
||||
ulong frameTimeStamp = 0;
|
||||
int width, height;
|
||||
if (Native.GetLatestFrame(_playerInstance, out texturePointerLeft, out texturePointerRight, out frameTimeStamp, out width, out height))
|
||||
{
|
||||
bool isFrameUpdated = false;
|
||||
bool isNewFrameTime = (frameTimeStamp > _frameTimeStamp) || (_frameTimeStamp == 0 && frameTimeStamp == 0);
|
||||
for (int i = 0; i < _eyeTextures.Length; i++)
|
||||
{
|
||||
EyeTexture eyeTexture = _eyeTextures[i];
|
||||
System.IntPtr texturePointer = texturePointerLeft;
|
||||
if (i == 1)
|
||||
{
|
||||
texturePointer = texturePointerRight;
|
||||
}
|
||||
|
||||
bool isNewFrameSpecs = (eyeTexture.texture != null && (texturePointer == IntPtr.Zero || eyeTexture.texture.width != width || eyeTexture.texture.height != height));
|
||||
//Debug.Log("tex? " + i + " " + width + " " + height + " " + (eyeTexture.texture != null) + " " + texturePointer.ToString() + " " + frameTimeStamp);
|
||||
|
||||
// Check whether the latest frame is newer than the one we got last time
|
||||
if (isNewFrameTime || isNewFrameSpecs)
|
||||
{
|
||||
if (isNewFrameSpecs)
|
||||
{
|
||||
eyeTexture.Dispose();
|
||||
// TODO: blit from the old texture to the new texture before destroying?
|
||||
}
|
||||
|
||||
/// Switch to the latest texture pointer
|
||||
if (eyeTexture.texture != null)
|
||||
{
|
||||
// TODO: check whether UpdateExternalTexture resets the sampling filter to POINT - it seems to in Unity 5.6.6
|
||||
if (eyeTexture.nativePointer != texturePointer)
|
||||
{
|
||||
eyeTexture.texture.UpdateExternalTexture(texturePointer);
|
||||
eyeTexture.nativePointer = texturePointer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (texturePointer != IntPtr.Zero)
|
||||
{
|
||||
// RJT NOTE: See notes in 'WindowsMediaPlayer::UpdateTexture()' re: 'isLinear'
|
||||
bool isLinear = (/*!_supportsLinearColorSpace*/true && (QualitySettings.activeColorSpace == ColorSpace.Linear));
|
||||
eyeTexture.texture = Texture2D.CreateExternalTexture(width, height, TextureFormat.BGRA32, false, isLinear, texturePointer);
|
||||
if (eyeTexture.texture != null)
|
||||
{
|
||||
eyeTexture.texture.name = "AVProVideo";
|
||||
eyeTexture.nativePointer = texturePointer;
|
||||
ApplyTextureProperties(eyeTexture.texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[AVProVideo] Failed to create texture");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isFrameUpdated = true;
|
||||
}
|
||||
}
|
||||
if (isFrameUpdated)
|
||||
{
|
||||
_frameTimeStamp = frameTimeStamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AuthData _nextAuthData = new AuthData();
|
||||
|
||||
public AuthData AuthenticationData
|
||||
{
|
||||
get
|
||||
{
|
||||
return _nextAuthData;
|
||||
}
|
||||
set
|
||||
{
|
||||
_nextAuthData = value;
|
||||
Native.SetNextAuthData(_playerInstance, _nextAuthData);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool RequiresVerticalFlip()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Seek(double time)
|
||||
{
|
||||
Native.SeekParams seekParams = new Native.SeekParams();
|
||||
seekParams.timeSeconds = time;
|
||||
seekParams.mode = Native.SeekMode.Accurate;
|
||||
Native.Seek(_playerInstance, ref seekParams);
|
||||
}
|
||||
|
||||
public override void SeekFast(double time)
|
||||
{
|
||||
// Keyframe seeking is not supported on this platform
|
||||
Seek(time);
|
||||
}
|
||||
|
||||
public override void SetLooping(bool bLooping)
|
||||
{
|
||||
_isLooping = bLooping;
|
||||
Native.SetLooping(_playerInstance, _isLooping);
|
||||
}
|
||||
|
||||
public override void SetPlaybackRate(float rate)
|
||||
{
|
||||
// Clamp rate as WinRT doesn't seem to be able to handle negative rate
|
||||
rate = Mathf.Max(0f, rate);
|
||||
Native.SetPlaybackRate(_playerInstance, rate);
|
||||
}
|
||||
|
||||
public override void SetVolume(float volume)
|
||||
{
|
||||
_volume = volume;
|
||||
Native.SetAudioVolume(_playerInstance, _volume);
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
Pause();
|
||||
}
|
||||
|
||||
private void UpdateTimeRanges()
|
||||
{
|
||||
UpdateTimeRange(ref _seekableTimes._ranges, Native.TimeRangeTypes.Seekable);
|
||||
UpdateTimeRange(ref _bufferedTimes._ranges, Native.TimeRangeTypes.Buffered);
|
||||
_seekableTimes.CalculateRange();
|
||||
_bufferedTimes.CalculateRange();
|
||||
}
|
||||
|
||||
private void UpdateTimeRange(ref TimeRange[] range, Native.TimeRangeTypes timeRangeType)
|
||||
{
|
||||
int newCount = Native.GetTimeRanges(_playerInstance, range, range.Length, timeRangeType);
|
||||
if (newCount != range.Length)
|
||||
{
|
||||
range = new TimeRange[newCount];
|
||||
Native.GetTimeRanges(_playerInstance, range, range.Length, timeRangeType);
|
||||
}
|
||||
}
|
||||
|
||||
public override System.DateTime GetProgramDateTime()
|
||||
{
|
||||
double seconds = Native.GetCurrentDateTimeSecondsSince1970(_playerInstance);
|
||||
return Helper.ConvertSecondsSince1970ToDateTime(seconds);
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
Native.Update(_playerInstance);
|
||||
UpdateTracks();
|
||||
UpdateTextCue();
|
||||
|
||||
_lastError = (ErrorCode)Native.GetLastErrorCode(_playerInstance);
|
||||
|
||||
UpdateTimeRanges();
|
||||
UpdateSubtitles();
|
||||
Update_Textures();
|
||||
UpdateDisplayFrameRate();
|
||||
|
||||
if (!_isMediaLoaded)
|
||||
{
|
||||
if (HasVideo() && _eyeTextures[0].texture != null)
|
||||
{
|
||||
Native.VideoTrack videoTrack;
|
||||
if (Native.GetActiveVideoTrackInfo(_playerInstance, out videoTrack))
|
||||
{
|
||||
Helper.LogInfo("Using playback path: " + _playerDescription + " (" + videoTrack.frameWidth + "x" + videoTrack.frameHeight + "@" + videoTrack.frameRate.ToString("F2") + ")");
|
||||
_isMediaLoaded = true;
|
||||
}
|
||||
}
|
||||
else if (HasAudio() && !HasVideo())
|
||||
{
|
||||
Helper.LogInfo("Using playback path: " + _playerDescription);
|
||||
_isMediaLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*public override void SetKeyServerURL(string url)
|
||||
{
|
||||
_nextAuthData.URL = url;
|
||||
AuthenticationData = _nextAuthData;
|
||||
}*/
|
||||
|
||||
public override void SetKeyServerAuthToken(string token)
|
||||
{
|
||||
_nextAuthData.Token = token;
|
||||
AuthenticationData = _nextAuthData;
|
||||
}
|
||||
|
||||
public override void SetOverrideDecryptionKey(byte[] key)
|
||||
{
|
||||
_nextAuthData.KeyBytes = key;
|
||||
AuthenticationData = _nextAuthData;
|
||||
}
|
||||
}
|
||||
|
||||
// Tracks
|
||||
public sealed partial class WindowsRtMediaPlayer
|
||||
{
|
||||
internal override bool InternalSetActiveTrack(TrackType trackType, int trackUid)
|
||||
{
|
||||
return Native.SetActiveTrack(_playerInstance, trackType, trackUid);
|
||||
}
|
||||
|
||||
// Has it changed since the last frame 'tick'
|
||||
internal override bool InternalIsChangedTracks(TrackType trackType)
|
||||
{
|
||||
return Native.IsChangedTracks(_playerInstance, trackType);
|
||||
}
|
||||
|
||||
internal override int InternalGetTrackCount(TrackType trackType)
|
||||
{
|
||||
return Native.GetTrackCount(_playerInstance, trackType);
|
||||
}
|
||||
|
||||
internal override TrackBase InternalGetTrackInfo(TrackType trackType, int trackIndex, ref bool isActiveTrack)
|
||||
{
|
||||
TrackBase result = null;
|
||||
StringBuilder name = new StringBuilder(128);
|
||||
StringBuilder language = new StringBuilder(16);
|
||||
int uid = -1;
|
||||
if (Native.GetTrackInfo(_playerInstance, trackType, trackIndex, ref uid, ref isActiveTrack, name, name.Capacity, language, language.Capacity))
|
||||
{
|
||||
if (trackType == TrackType.Video)
|
||||
{
|
||||
result = new VideoTrack(uid, name.ToString(), language.ToString(), false);
|
||||
}
|
||||
else if (trackType == TrackType.Audio)
|
||||
{
|
||||
result = new AudioTrack(uid, name.ToString(), language.ToString(), false);
|
||||
}
|
||||
else if (trackType == TrackType.Text)
|
||||
{
|
||||
result = new TextTrack(uid, name.ToString(), language.ToString(), false);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private partial struct Native
|
||||
{
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public static extern bool IsChangedTracks(System.IntPtr instance, TrackType trackType);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern int GetTrackCount(System.IntPtr instance, TrackType trackType);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public static extern bool GetTrackInfo(System.IntPtr instance, TrackType trackType, int index, ref int uid,
|
||||
ref bool isActive,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int maxNameLength,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] StringBuilder language, int maxLanguageLength);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public static extern bool SetActiveTrack(System.IntPtr instance, TrackType trackType, int trackUid);
|
||||
}
|
||||
}
|
||||
|
||||
// Text Cue
|
||||
public sealed partial class WindowsRtMediaPlayer
|
||||
{
|
||||
// Has it changed since the last frame 'tick'
|
||||
internal override bool InternalIsChangedTextCue()
|
||||
{
|
||||
return Native.IsChangedTextCue(_playerInstance);
|
||||
}
|
||||
|
||||
internal override string InternalGetCurrentTextCue()
|
||||
{
|
||||
string result = null;
|
||||
System.IntPtr ptr = Native.GetCurrentTextCue(_playerInstance);
|
||||
if (ptr != System.IntPtr.Zero)
|
||||
{
|
||||
result = System.Runtime.InteropServices.Marshal.PtrToStringUni(ptr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private partial struct Native
|
||||
{
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
public static extern bool IsChangedTextCue(System.IntPtr instance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern System.IntPtr GetCurrentTextCue(System.IntPtr instance);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class WindowsRtMediaPlayer
|
||||
{
|
||||
private partial struct Native
|
||||
{
|
||||
[DllImport("AVProVideoWinRT", EntryPoint = "GetPluginVersion")]
|
||||
private static extern System.IntPtr GetPluginVersionStringPointer();
|
||||
|
||||
public static string GetPluginVersion()
|
||||
{
|
||||
return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(GetPluginVersionStringPointer());
|
||||
}
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern System.IntPtr CreatePlayer();
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void DestroyPlayer(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
#if AVPROVIDEO_MARSHAL_RETURN_BOOL
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
#endif
|
||||
public static extern bool OpenMedia(System.IntPtr playerInstance, [MarshalAs(UnmanagedType.LPWStr)] string filePath,
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string httpHeader, FileFormat overrideFileFormat,
|
||||
bool startWithHighestBitrate, bool use10BitTextures);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void CloseMedia(System.IntPtr playerInstance);
|
||||
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void Pause(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void Play(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void SetAudioVolume(System.IntPtr playerInstance, float volume);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void SetAudioBalance(System.IntPtr playerInstance, float balance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void SetPlaybackRate(System.IntPtr playerInstance, float rate);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void SetAudioMuted(System.IntPtr playerInstance, bool muted);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern float GetAudioVolume(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
#if AVPROVIDEO_MARSHAL_RETURN_BOOL
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
#endif
|
||||
public static extern bool IsAudioMuted(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern float GetAudioBalance(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern float GetPlaybackRate(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void SetLooping(System.IntPtr playerInstance, bool looping);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
#if AVPROVIDEO_MARSHAL_RETURN_BOOL
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
#endif
|
||||
public static extern bool IsLooping(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern int GetLastErrorCode(System.IntPtr playerInstance);
|
||||
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void Update(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern double GetDuration(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern int GetStereoPacking(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern double GetCurrentPosition(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
#if AVPROVIDEO_MARSHAL_RETURN_BOOL
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
#endif
|
||||
public static extern bool GetLatestFrame(System.IntPtr playerInstance, out System.IntPtr leftEyeTexturePointer, out System.IntPtr rightEyeTexturePointer, out ulong frameTimeStamp, out int width, out int height);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern PlaybackState GetPlaybackState(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
#if AVPROVIDEO_MARSHAL_RETURN_BOOL
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
#endif
|
||||
public static extern bool GetActiveVideoTrackInfo(System.IntPtr playerInstance, out VideoTrack videoTrack);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
#if AVPROVIDEO_MARSHAL_RETURN_BOOL
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
#endif
|
||||
public static extern bool GetActiveAudioTrackInfo(System.IntPtr playerInstance, out AudioTrack audioTrack);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern double GetCurrentDateTimeSecondsSince1970(System.IntPtr playerInstance);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void SetLiveOffset(System.IntPtr playerInstance, double seconds);
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void DebugValues(System.IntPtr playerInstance, out int isD3D, out int isUnityD3D, out int isTexture, out int isSharedTexture, out int isSurface);
|
||||
|
||||
public enum SeekMode
|
||||
{
|
||||
Fast = 0,
|
||||
Accurate = 1,
|
||||
// TODO: Add Fast_Before and Fast_After
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct VideoTrack
|
||||
{
|
||||
public int trackIndex;
|
||||
public int frameWidth;
|
||||
public int frameHeight;
|
||||
public float frameRate;
|
||||
public uint averageBitRate;
|
||||
//public string trackName;
|
||||
// TODO: add index, language, name, bitrate, codec etc
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct AudioTrack
|
||||
{
|
||||
public int trackIndex;
|
||||
public uint channelCount;
|
||||
public uint sampleRate;
|
||||
public uint bitsPerSample;
|
||||
public uint averageBitRate;
|
||||
//public string trackName;
|
||||
// TODO: add index, language, name, bitrate, codec etc
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct SeekParams
|
||||
{
|
||||
public double timeSeconds;
|
||||
public SeekMode mode;
|
||||
// TODO: add min-max thresholds
|
||||
}
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern void Seek(System.IntPtr playerInstance, ref SeekParams seekParams);
|
||||
|
||||
public static void SetNextAuthData(System.IntPtr playerInstance, RenderHeads.Media.AVProVideo.AuthData srcAuthData)
|
||||
{
|
||||
Native.AuthData ad = new Native.AuthData();
|
||||
ad.url = string.IsNullOrEmpty(srcAuthData.URL) ? null : srcAuthData.URL;
|
||||
ad.token = string.IsNullOrEmpty(srcAuthData.Token) ? null : srcAuthData.Token;
|
||||
if (srcAuthData.KeyBytes != null && srcAuthData.KeyBytes.Length > 0)
|
||||
{
|
||||
ad.keyBytes = Marshal.AllocHGlobal(srcAuthData.KeyBytes.Length);
|
||||
Marshal.Copy(srcAuthData.KeyBytes, 0, ad.keyBytes, srcAuthData.KeyBytes.Length);
|
||||
ad.keyBytesLength = srcAuthData.KeyBytes.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
ad.keyBytes = System.IntPtr.Zero;
|
||||
ad.keyBytesLength = 0;
|
||||
}
|
||||
|
||||
SetNextAuthData(playerInstance, ref ad);
|
||||
|
||||
if (ad.keyBytes != System.IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(ad.keyBytes);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct AuthData
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string url;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string token;
|
||||
|
||||
public System.IntPtr keyBytes;
|
||||
public int keyBytesLength;
|
||||
};
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
private static extern void SetNextAuthData(System.IntPtr playerInstance, ref AuthData authData);
|
||||
|
||||
internal enum TimeRangeTypes
|
||||
{
|
||||
Seekable = 0,
|
||||
Buffered = 1,
|
||||
}
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern int GetTimeRanges(System.IntPtr playerInstance, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] TimeRange[] ranges, int rangeCount, TimeRangeTypes timeRangeType);
|
||||
|
||||
// RJT TODO: Clean this up to better match non-WinRT
|
||||
|
||||
[DllImport("AVProVideoWinRT")]
|
||||
public static extern System.IntPtr GetRenderEventFunc();
|
||||
|
||||
private static System.IntPtr _nativeFunction_UnityRenderEvent;
|
||||
public static void IssueRenderThreadEvent_UpdateAllTextures()
|
||||
{
|
||||
if (_nativeFunction_UnityRenderEvent == System.IntPtr.Zero)
|
||||
{
|
||||
_nativeFunction_UnityRenderEvent = Native.GetRenderEventFunc();
|
||||
}
|
||||
if (_nativeFunction_UnityRenderEvent != System.IntPtr.Zero)
|
||||
{
|
||||
GL.IssuePluginEvent(_nativeFunction_UnityRenderEvent, /*(int)Native.RenderThreadEvent.UpdateAllTextures*/1);
|
||||
}
|
||||
}
|
||||
|
||||
public static void IssueRenderThreadEvent_FreeAllTextures()
|
||||
{
|
||||
if (_nativeFunction_UnityRenderEvent == System.IntPtr.Zero)
|
||||
{
|
||||
_nativeFunction_UnityRenderEvent = Native.GetRenderEventFunc();
|
||||
}
|
||||
if (_nativeFunction_UnityRenderEvent != System.IntPtr.Zero)
|
||||
{
|
||||
GL.IssuePluginEvent(_nativeFunction_UnityRenderEvent, /*(int)Native.RenderThreadEvent.FreeTextures*/2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed partial class WindowsRtMediaPlayer
|
||||
{
|
||||
private static bool _isInitialised = false;
|
||||
private static string _version = "Plug-in not yet initialised";
|
||||
|
||||
private ulong _frameTimeStamp;
|
||||
private System.IntPtr _playerInstance;
|
||||
|
||||
class EyeTexture
|
||||
{
|
||||
public Texture2D texture = null;
|
||||
public System.IntPtr nativePointer = System.IntPtr.Zero;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
if (Application.isPlaying) { Texture2D.Destroy(texture); }
|
||||
else { Texture2D.DestroyImmediate(texture); }
|
||||
texture = null;
|
||||
}
|
||||
nativePointer = System.IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private EyeTexture[] _eyeTextures = new EyeTexture[2];
|
||||
|
||||
public static bool InitialisePlatform()
|
||||
{
|
||||
if (!_isInitialised)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if !UNITY_2019_3_OR_NEWER
|
||||
if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D12)
|
||||
{
|
||||
Debug.LogError("[AVProVideo] Direct3D 12 is not supported until Unity 2019.3");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Null ||
|
||||
SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D11 ||
|
||||
SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D12)
|
||||
{
|
||||
/*if (!Native.Init(QualitySettings.activeColorSpace == ColorSpace.Linear))
|
||||
{
|
||||
Debug.LogError("[AVProVideo] Failing to initialise platform");
|
||||
}
|
||||
else*/
|
||||
{
|
||||
_isInitialised = true;
|
||||
_version = Native.GetPluginVersion();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[AVProVideo] Only Direct3D 11 and 12 are supported, graphicsDeviceType not supported: " + SystemInfo.graphicsDeviceType);
|
||||
}
|
||||
}
|
||||
catch (System.DllNotFoundException e)
|
||||
{
|
||||
Debug.LogError("[AVProVideo] Failed to load DLL. " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return _isInitialised;
|
||||
}
|
||||
|
||||
public static void DeinitPlatform()
|
||||
{
|
||||
//Native.Deinit();
|
||||
_isInitialised = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b04c4ad4a3b8c44a98a08ea2ae71a6d
|
||||
timeCreated: 1541807235
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user