123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Events;
- namespace RenderHeads.Media.AVProVideo
- {
- public class Resampler
- {
- public Resampler(MediaPlayer player, string name, int bufferSize = 2, Resampler.ResampleMode resampleMode = Resampler.ResampleMode.LINEAR)
- {
- this._bufferSize = Mathf.Max(2, bufferSize);
- if (player.Info != null)
- {
- this._elapsedTimeSinceBase = (float)this._bufferSize / player.Info.GetVideoFrameRate();
- }
- player.Events.AddListener(new UnityAction<MediaPlayer, MediaPlayerEvent.EventType, ErrorCode>(this.OnVideoEvent));
- this._mediaPlayer = player;
- Shader shader = Shader.Find("AVProVideo/BlendFrames");
- if (shader != null)
- {
- this._blendMat = new Material(shader);
- this._propT = Shader.PropertyToID("_t");
- this._propAfterTex = Shader.PropertyToID("_AfterTex");
- }
- else
- {
- Debug.LogError("[AVProVideo] Failed to find BlendFrames shader");
- }
- this._resampleMode = resampleMode;
- this._name = name;
- Debug.Log("[AVProVideo] Resampler " + this._name + " started");
- }
- public int DroppedFrames
- {
- get
- {
- return this._droppedFrames;
- }
- }
- public int FrameDisplayedTimer
- {
- get
- {
- return this._frameDisplayedTimer;
- }
- }
- public long BaseTimestamp
- {
- get
- {
- return this._baseTimestamp;
- }
- set
- {
- this._baseTimestamp = value;
- }
- }
- public float ElapsedTimeSinceBase
- {
- get
- {
- return this._elapsedTimeSinceBase;
- }
- set
- {
- this._elapsedTimeSinceBase = value;
- }
- }
- public float LastT { get; private set; }
- public long TextureTimeStamp { get; private set; }
- public void OnVideoEvent(MediaPlayer mp, MediaPlayerEvent.EventType et, ErrorCode errorCode)
- {
- if (et != MediaPlayerEvent.EventType.MetaDataReady)
- {
- if (et == MediaPlayerEvent.EventType.Closing)
- {
- this.Reset();
- }
- }
- else
- {
- this._elapsedTimeSinceBase = (float)this._bufferSize / this._mediaPlayer.Info.GetVideoFrameRate();
- }
- }
- public Texture[] OutputTexture
- {
- get
- {
- return this._outputTexture;
- }
- }
- public void Reset()
- {
- this._lastTimeStamp = -1L;
- this._baseTimestamp = 0L;
- this.InvalidateBuffer();
- }
- public void Release()
- {
- this.ReleaseRenderTextures();
- if (this._blendMat != null)
- {
- UnityEngine.Object.Destroy(this._blendMat);
- }
- }
- private void ReleaseRenderTextures()
- {
- for (int i = 0; i < this._buffer.Count; i++)
- {
- for (int j = 0; j < this._buffer[i].Length; j++)
- {
- if (this._buffer[i][j].texture != null)
- {
- RenderTexture.ReleaseTemporary(this._buffer[i][j].texture);
- this._buffer[i][j].texture = null;
- }
- }
- if (this._outputTexture != null && this._outputTexture[i] != null)
- {
- RenderTexture.ReleaseTemporary(this._outputTexture[i]);
- }
- }
- this._outputTexture = null;
- }
- private void ConstructRenderTextures()
- {
- this.ReleaseRenderTextures();
- this._buffer.Clear();
- this._outputTexture = new RenderTexture[this._mediaPlayer.TextureProducer.GetTextureCount()];
- for (int i = 0; i < this._mediaPlayer.TextureProducer.GetTextureCount(); i++)
- {
- Texture texture = this._mediaPlayer.TextureProducer.GetTexture(i);
- this._buffer.Add(new Resampler.TimestampedRenderTexture[this._bufferSize]);
- for (int j = 0; j < this._bufferSize; j++)
- {
- this._buffer[i][j] = new Resampler.TimestampedRenderTexture();
- }
- for (int k = 0; k < this._buffer[i].Length; k++)
- {
- this._buffer[i][k].texture = RenderTexture.GetTemporary(texture.width, texture.height, 0);
- this._buffer[i][k].timestamp = 0L;
- this._buffer[i][k].used = false;
- }
- this._outputTexture[i] = RenderTexture.GetTemporary(texture.width, texture.height, 0);
- }
- }
- private bool CheckRenderTexturesValid()
- {
- for (int i = 0; i < this._mediaPlayer.TextureProducer.GetTextureCount(); i++)
- {
- Texture texture = this._mediaPlayer.TextureProducer.GetTexture(i);
- for (int j = 0; j < this._buffer.Count; j++)
- {
- if (this._buffer[i][j].texture == null || this._buffer[i][j].texture.width != texture.width || this._buffer[i][j].texture.height != texture.height)
- {
- return false;
- }
- }
- if (this._outputTexture == null || this._outputTexture[i] == null || this._outputTexture[i].width != texture.width || this._outputTexture[i].height != texture.height)
- {
- return false;
- }
- }
- return true;
- }
- private int FindBeforeFrameIndex(int frameIdx)
- {
- if (frameIdx >= this._buffer.Count)
- {
- return -1;
- }
- int num = -1;
- float num2 = float.MaxValue;
- int num3 = -1;
- float num4 = float.MaxValue;
- for (int i = 0; i < this._buffer[frameIdx].Length; i++)
- {
- if (this._buffer[frameIdx][i].used)
- {
- float num5 = (float)(this._buffer[frameIdx][i].timestamp - this._baseTimestamp) / 1E+07f;
- if (num5 < num4)
- {
- num3 = i;
- num4 = num5;
- }
- float num6 = this._elapsedTimeSinceBase - num5;
- if (num6 >= 0f && num6 < num2)
- {
- num2 = num6;
- num = i;
- }
- }
- }
- if (num >= 0)
- {
- return num;
- }
- if (num3 < 0)
- {
- return -1;
- }
- return num3;
- }
- private int findClosestFrame(int frameIdx)
- {
- if (frameIdx >= this._buffer.Count)
- {
- return -1;
- }
- int result = -1;
- float num = float.MaxValue;
- for (int i = 0; i < this._buffer[frameIdx].Length; i++)
- {
- if (this._buffer[frameIdx][i].used)
- {
- float num2 = (float)(this._buffer[frameIdx][i].timestamp - this._baseTimestamp) / 1E+07f;
- float num3 = Mathf.Abs(this._elapsedTimeSinceBase - num2);
- if (num3 < num)
- {
- result = i;
- num = num3;
- }
- }
- }
- return result;
- }
- private void PointUpdate()
- {
- for (int i = 0; i < this._buffer.Count; i++)
- {
- int num = this.findClosestFrame(i);
- if (num >= 0)
- {
- this._outputTexture[i].DiscardContents();
- Graphics.Blit(this._buffer[i][num].texture, this._outputTexture[i]);
- this._currentDisplayedTimestamp = this._buffer[i][num].timestamp;
- }
- }
- }
- private void SampleFrame(int frameIdx, int bufferIdx)
- {
- this._outputTexture[bufferIdx].DiscardContents();
- Graphics.Blit(this._buffer[bufferIdx][frameIdx].texture, this._outputTexture[bufferIdx]);
- this.TextureTimeStamp = this._buffer[bufferIdx][frameIdx].timestamp;
- this._currentDisplayedTimestamp = this._buffer[bufferIdx][frameIdx].timestamp;
- }
- private void SampleFrames(int bufferIdx, int frameIdx1, int frameIdx2, float t)
- {
- this._blendMat.SetFloat(this._propT, t);
- this._blendMat.SetTexture(this._propAfterTex, this._buffer[bufferIdx][frameIdx2].texture);
- this._outputTexture[bufferIdx].DiscardContents();
- Graphics.Blit(this._buffer[bufferIdx][frameIdx1].texture, this._outputTexture[bufferIdx], this._blendMat);
- this.TextureTimeStamp = (long)Mathf.Lerp((float)this._buffer[bufferIdx][frameIdx1].timestamp, (float)this._buffer[bufferIdx][frameIdx2].timestamp, t);
- this._currentDisplayedTimestamp = this._buffer[bufferIdx][frameIdx1].timestamp;
- }
- private void LinearUpdate()
- {
- for (int i = 0; i < this._buffer.Count; i++)
- {
- int num = this.FindBeforeFrameIndex(i);
- if (num >= 0)
- {
- float num2 = (float)(this._buffer[i][num].timestamp - this._baseTimestamp) / 1E+07f;
- if (num2 > this._elapsedTimeSinceBase)
- {
- this.SampleFrame(num, i);
- this.LastT = -1f;
- }
- else
- {
- int num3 = (num + 1) % this._buffer[i].Length;
- float num4 = (float)(this._buffer[i][num3].timestamp - this._baseTimestamp) / 1E+07f;
- if (num4 < num2)
- {
- this.SampleFrame(num, i);
- this.LastT = 2f;
- }
- else
- {
- float num5 = num4 - num2;
- float num6 = (this._elapsedTimeSinceBase - num2) / num5;
- this.SampleFrames(i, num, num3, num6);
- this.LastT = num6;
- }
- }
- }
- }
- }
- private void InvalidateBuffer()
- {
- this._elapsedTimeSinceBase = (float)(this._bufferSize / 2) / this._mediaPlayer.Info.GetVideoFrameRate();
- for (int i = 0; i < this._buffer.Count; i++)
- {
- for (int j = 0; j < this._buffer[i].Length; j++)
- {
- this._buffer[i][j].used = false;
- }
- }
- this._start = (this._end = 0);
- }
- public void Update()
- {
- if (this._mediaPlayer.TextureProducer == null)
- {
- return;
- }
- if (this._mediaPlayer.TextureProducer == null || this._mediaPlayer.TextureProducer.GetTexture(0) == null)
- {
- return;
- }
- if (!this.CheckRenderTexturesValid())
- {
- this.ConstructRenderTextures();
- }
- long textureTimeStamp = this._mediaPlayer.TextureProducer.GetTextureTimeStamp();
- if (textureTimeStamp != this._lastTimeStamp)
- {
- float num = Mathf.Abs((float)(textureTimeStamp - this._lastTimeStamp));
- float num2 = 1E+07f * (1f / this._mediaPlayer.Info.GetVideoFrameRate());
- if (num > num2 * 1.1f && num < num2 * 3.1f)
- {
- this._droppedFrames += (int)((double)((num - num2) / num2) + 0.5);
- }
- this._lastTimeStamp = textureTimeStamp;
- }
- long textureTimeStamp2 = this._mediaPlayer.TextureProducer.GetTextureTimeStamp();
- bool flag = !this._mediaPlayer.Control.IsSeeking();
- if (this._start != this._end || this._buffer[0][this._end].used)
- {
- int num3 = (this._end + this._buffer[0].Length - 1) % this._buffer[0].Length;
- if (textureTimeStamp2 == this._buffer[0][num3].timestamp)
- {
- flag = false;
- }
- }
- if (flag)
- {
- if (this._start == this._end && !this._buffer[0][this._end].used)
- {
- this._baseTimestamp = textureTimeStamp2;
- }
- if (this._end == this._start && this._buffer[0][this._end].used)
- {
- this._start = (this._start + 1) % this._buffer[0].Length;
- }
- for (int i = 0; i < this._mediaPlayer.TextureProducer.GetTextureCount(); i++)
- {
- Texture texture = this._mediaPlayer.TextureProducer.GetTexture(i);
- this._buffer[i][this._end].texture.DiscardContents();
- Graphics.Blit(texture, this._buffer[i][this._end].texture);
- this._buffer[i][this._end].timestamp = textureTimeStamp2;
- this._buffer[i][this._end].used = true;
- }
- this._end = (this._end + 1) % this._buffer[0].Length;
- }
- bool flag2 = this._start != this._end || !this._buffer[0][this._end].used;
- if (flag2)
- {
- for (int j = 0; j < this._buffer.Count; j++)
- {
- this._outputTexture[j].DiscardContents();
- Graphics.Blit(this._buffer[j][this._start].texture, this._outputTexture[j]);
- this._currentDisplayedTimestamp = this._buffer[j][this._start].timestamp;
- }
- }
- if (this._mediaPlayer.Control.IsPaused())
- {
- this.InvalidateBuffer();
- }
- if (flag2)
- {
- return;
- }
- if (this._mediaPlayer.Control.IsPlaying() && !this._mediaPlayer.Control.IsFinished())
- {
- long num4 = this._buffer[0][(this._start + this._bufferSize / 2) % this._bufferSize].timestamp - this._baseTimestamp;
- double num5 = (double)Mathf.Abs((float)((double)this._elapsedTimeSinceBase * 10000000.0) - (float)num4);
- double num6 = (double)((float)(this._buffer[0].Length / 2) / this._mediaPlayer.Info.GetVideoFrameRate() * 1E+07f);
- if (num5 > num6)
- {
- this._elapsedTimeSinceBase = (float)num4 / 1E+07f;
- }
- if (this._resampleMode == Resampler.ResampleMode.POINT)
- {
- this.PointUpdate();
- }
- else if (this._resampleMode == Resampler.ResampleMode.LINEAR)
- {
- this.LinearUpdate();
- }
- this._elapsedTimeSinceBase += Time.unscaledDeltaTime;
- }
- }
- public void UpdateTimestamp()
- {
- if (this._lastDisplayedTimestamp != this._currentDisplayedTimestamp)
- {
- this._lastDisplayedTimestamp = this._currentDisplayedTimestamp;
- this._frameDisplayedTimer = 0;
- }
- this._frameDisplayedTimer++;
- }
- private List<Resampler.TimestampedRenderTexture[]> _buffer = new List<Resampler.TimestampedRenderTexture[]>();
- private MediaPlayer _mediaPlayer;
- private RenderTexture[] _outputTexture;
- private int _start;
- private int _end;
- private int _bufferSize;
- private long _baseTimestamp;
- private float _elapsedTimeSinceBase;
- private Material _blendMat;
- private Resampler.ResampleMode _resampleMode;
- private string _name = string.Empty;
- private long _lastTimeStamp = -1L;
- private int _droppedFrames;
- private long _lastDisplayedTimestamp;
- private int _frameDisplayedTimer;
- private long _currentDisplayedTimestamp;
- private const string ShaderPropT = "_t";
- private const string ShaderPropAftertex = "_AfterTex";
- private int _propAfterTex;
- private int _propT;
- private class TimestampedRenderTexture
- {
- public RenderTexture texture;
- public long timestamp;
- public bool used;
- }
- public enum ResampleMode
- {
- POINT,
- LINEAR
- }
- }
- }
|