I would like to create a very simple video controller to set the frame of a video. I created a value slider to scroll forward and backwards on the timeline of the video.
The script provided runs flawlessly on a Mac but has incredibly much lag on Windows.
Sometimes it register the value that is set and jumps to it on the video, sometimes it doesn't... It is complacently random. (Also the windows computer has a lot better hardware)
Any suggestion regarding what could be the problem on Windows would be greatly appreciated as I have to run this on Windows computer.
The video is H264 format and has no audio.
I tried changing the value with PingPong
setFrame = Mathf.RoundToInt(Mathf.PingPong(Time.time*frameCount, 156));
It works if the frameCount is smaller than 5.
I am using UnityEngine.Video;
[Range(1,156)]
public int setFrame=1;
public int frameCount;
void Start()
{
Debug.Log("SetTime" + video.canSetTime);
Debug.Log("SetSkip" + video.canSetSkipOnDrop);
Debug.Log("TimeRef" + video.timeReference);
frameCount = video.frameCount;
}
void Update()
{
if (video.frame >= 0)
{
video.Pause();
video.frame = setFrame;
//Debug.Log(video.frame);
}
}
No error messages.
Modern video compression, with H264 being a most known example, is based on encoding just a difference between the current frame and a previous one. A decoder (on the native c++ side) can be imagined as a black box that is feed with a binary encoded stream and splits frames one by one. A process of going to a random frame involves first seeking to a last 'fully encoded frame', picture it as a JPG that's added once in a while for consistency. Than the decoder needs to decode every frame in between in order to provide you with the actual frame you requested - and last fully encoded frame might be seconds away in the past, the amount of frames to decode before you can seek to the one you actually want can be in the hundreds range, there's no way the decoder will be able to instantly jump to a given frame, which your code is requesting.
If with 5 frames it just about keeps up - its not bad actually.
If you want to do funkier stuff (like ping-pong) you can subscribe to a VideoPlayer.frameReady event, its a good time to swap RenderTextures,and buffer them - you can have almost instant access to RenderTextures in video memory. You burn memory quite quickly, but for 156 frames (as stated in the question) at a reasonable resolution it will be orders of magnitude faster than requesting each frame from the player