#if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN
#define UNITY_PLATFORM_SUPPORTS_LINEAR
#elif UNITY_IOS || UNITY_ANDROID
#if UNITY_5_5_OR_NEWER || (UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 && !UNITY_5_3 && !UNITY_5_4)
#define UNITY_PLATFORM_SUPPORTS_LINEAR
#endif
#endif
using UnityEngine;
using System.Collections.Generic;
#if NETFX_CORE
using Windows.Storage.Streams;
#endif
//-----------------------------------------------------------------------------
// Copyright 2015-2018 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo
{
///
/// Base class for all platform specific MediaPlayers
///
public abstract class BaseMediaPlayer : IMediaPlayer, IMediaControl, IMediaInfo, IMediaProducer, IMediaSubtitles, System.IDisposable
{
public abstract string GetVersion();
public abstract bool OpenVideoFromFile(string path, long offset, string httpHeaderJson, uint sourceSamplerate = 0, uint sourceChannels = 0, int forceFileFormat = 0);
#if NETFX_CORE
public virtual bool OpenVideoFromFile(IRandomAccessStream ras, string path, long offset, string httpHeaderJson, uint sourceSamplerate = 0, uint sourceChannels = 0){return false;}
#endif
public virtual bool OpenVideoFromBuffer(byte[] buffer) { return false; }
public virtual bool StartOpenVideoFromBuffer(ulong length) { return false; }
public virtual bool AddChunkToVideoBuffer(byte[] chunk, ulong offset, ulong length) { return false; }
public virtual bool EndOpenVideoFromBuffer() { return false; }
public virtual void CloseVideo()
{
_stallDetectionTimer = 0f;
_stallDetectionFrame = 0;
_lastError = ErrorCode.None;
}
public abstract void SetLooping(bool bLooping);
public abstract bool IsLooping();
public abstract bool HasMetaData();
public abstract bool CanPlay();
public abstract void Play();
public abstract void Pause();
public abstract void Stop();
public abstract void Rewind();
public abstract void Seek(float timeMs);
public abstract void SeekFast(float timeMs);
public virtual void SeekWithTolerance(float timeMs, float beforeMs, float afterMs) { Seek(timeMs); }
public abstract float GetCurrentTimeMs();
public virtual double GetCurrentDateTimeSecondsSince1970() { return 0.0; }
public virtual TimeRange[] GetSeekableTimeRanges() { return _seekableTimeRanges; }
public abstract float GetPlaybackRate();
public abstract void SetPlaybackRate(float rate);
public abstract float GetDurationMs();
public abstract int GetVideoWidth();
public abstract int GetVideoHeight();
public virtual Rect GetCropRect() { return new Rect(0f, 0f, 0f, 0f); }
public abstract float GetVideoDisplayRate();
public abstract bool HasAudio();
public abstract bool HasVideo();
public abstract bool IsSeeking();
public abstract bool IsPlaying();
public abstract bool IsPaused();
public abstract bool IsFinished();
public abstract bool IsBuffering();
public virtual bool WaitForNextFrame(Camera dummyCamera, int previousFrameCount) { return false; }
public virtual int GetTextureCount() { return 1; }
public abstract Texture GetTexture(int index = 0);
public abstract int GetTextureFrameCount();
public virtual bool SupportsTextureFrameCount() { return true; }
public virtual long GetTextureTimeStamp() { return long.MinValue; }
public abstract bool RequiresVerticalFlip();
public virtual float[] GetTextureTransform() { return new float[] { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }; }
public abstract void MuteAudio(bool bMuted);
public abstract bool IsMuted();
public abstract void SetVolume(float volume);
public virtual void SetBalance(float balance) { }
public abstract float GetVolume();
public virtual float GetBalance() { return 0f; }
public abstract int GetAudioTrackCount();
public virtual string GetAudioTrackId(int index) { return index.ToString(); }
public abstract int GetCurrentAudioTrack();
public abstract void SetAudioTrack(int index);
public abstract string GetCurrentAudioTrackId();
public abstract int GetCurrentAudioTrackBitrate();
public virtual int GetNumAudioChannels() { return -1; }
public virtual void SetAudioHeadRotation(Quaternion q) { }
public virtual void ResetAudioHeadRotation() { }
public virtual void SetAudioChannelMode(Audio360ChannelMode channelMode) { }
public virtual void SetAudioFocusEnabled(bool enabled) { }
public virtual void SetAudioFocusProperties(float offFocusLevel, float widthDegrees) { }
public virtual void SetAudioFocusRotation(Quaternion q) { }
public virtual void ResetAudioFocus() { }
public abstract int GetVideoTrackCount();
public virtual string GetVideoTrackId(int index) { return index.ToString(); }
public abstract int GetCurrentVideoTrack();
public abstract void SetVideoTrack(int index);
public abstract string GetCurrentVideoTrackId();
public abstract int GetCurrentVideoTrackBitrate();
public abstract float GetVideoFrameRate();
public virtual long GetEstimatedTotalBandwidthUsed() { return -1; }
public abstract float GetBufferingProgress();
public abstract void Update();
public abstract void Render();
public abstract void Dispose();
public ErrorCode GetLastError()
{
return _lastError;
}
public virtual long GetLastExtendedErrorCode()
{
return 0;
}
public string GetPlayerDescription()
{
return _playerDescription;
}
public virtual bool PlayerSupportsLinearColorSpace()
{
#if UNITY_PLATFORM_SUPPORTS_LINEAR
return true;
#else
return false;
#endif
}
public virtual int GetBufferedTimeRangeCount() { return 0; }
public virtual bool GetBufferedTimeRange(int index, ref float startTimeMs, ref float endTimeMs) { return false; }
protected string _playerDescription = string.Empty;
protected ErrorCode _lastError = ErrorCode.None;
protected FilterMode _defaultTextureFilterMode = FilterMode.Bilinear;
protected TextureWrapMode _defaultTextureWrapMode = TextureWrapMode.Clamp;
protected int _defaultTextureAnisoLevel = 1;
protected TimeRange[] _seekableTimeRanges = new TimeRange[0];
public void SetTextureProperties(FilterMode filterMode = FilterMode.Bilinear, TextureWrapMode wrapMode = TextureWrapMode.Clamp, int anisoLevel = 0)
{
_defaultTextureFilterMode = filterMode;
_defaultTextureWrapMode = wrapMode;
_defaultTextureAnisoLevel = anisoLevel;
for (int i = 0; i < GetTextureCount(); ++i)
ApplyTextureProperties(GetTexture(i));
}
protected virtual void ApplyTextureProperties(Texture texture)
{
if (texture != null)
{
texture.filterMode = _defaultTextureFilterMode;
texture.wrapMode = _defaultTextureWrapMode;
texture.anisoLevel = _defaultTextureAnisoLevel;
}
}
public virtual void GrabAudio(float[] buffer, int floatCount, int channelCount)
{
}
protected bool IsExpectingNewVideoFrame()
{
if (HasVideo())
{
// If we're playing then we expect a new frame
if (!IsFinished() && (!IsPaused() || IsPlaying()))
{
// NOTE: if a new frame isn't available then we could either be seeking or stalled
return true;
}
}
return false;
}
public virtual bool IsPlaybackStalled()
{
const float StallDetectionDuration = 0.75f;
// Manually detect stalled video if the platform doesn't have native support to detect it
if (SupportsTextureFrameCount() && IsExpectingNewVideoFrame())
{
int frameCount = GetTextureFrameCount();
if (frameCount != _stallDetectionFrame)
{
_stallDetectionTimer = 0f;
_stallDetectionFrame = frameCount;
}
else
{
_stallDetectionTimer += Time.deltaTime;
}
return (_stallDetectionTimer > StallDetectionDuration);
}
else
{
_stallDetectionTimer = 0f;
}
return false;
}
private float _stallDetectionTimer;
private int _stallDetectionFrame;
protected List _subtitles;
protected Subtitle _currentSubtitle;
public bool LoadSubtitlesSRT(string data)
{
if (string.IsNullOrEmpty(data))
{
// Disable subtitles
_subtitles = null;
_currentSubtitle = null;
}
else
{
_subtitles = Helper.LoadSubtitlesSRT(data);
_currentSubtitle = null;
}
return (_subtitles != null);
}
public virtual void UpdateSubtitles()
{
if (_subtitles != null)
{
float time = GetCurrentTimeMs();
// TODO: implement a more effecient subtitle index searcher
int searchIndex = 0;
if (_currentSubtitle != null)
{
if (!_currentSubtitle.IsTime(time))
{
if (time > _currentSubtitle.timeEndMs)
{
searchIndex = _currentSubtitle.index + 1;
}
_currentSubtitle = null;
}
}
if (_currentSubtitle == null)
{
for (int i = searchIndex; i < _subtitles.Count; i++)
{
if (_subtitles[i].IsTime(time))
{
_currentSubtitle = _subtitles[i];
break;
}
}
}
}
}
public virtual int GetSubtitleIndex()
{
int result = -1;
if (_currentSubtitle != null)
{
result = _currentSubtitle.index;
}
return result;
}
public virtual string GetSubtitleText()
{
string result = string.Empty;
if (_currentSubtitle != null)
{
result = _currentSubtitle.text;
}
return result;
}
public virtual void OnEnable()
{
}
}
}