using OpenCVForUnity.CoreModule; using OpenCVForUnity.ImgprocModule; using OpenCVForUnity.UnityUtils; using OpenCVForUnity.VideoioModule; using System; using System.Collections; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; namespace OpenCVForUnityExample { /// /// VideoCapture Example /// An example of playing a video file using the VideoCapture class. /// http://docs.opencv.org/3.2.0/dd/d43/tutorial_py_video_display.html /// public class VideoCaptureExample : MonoBehaviour { /// /// The seek bar slider. /// public Slider seekBarSlider; Slider.SliderEvent defaultSliderEvent = new Slider.SliderEvent(); /// /// The videocapture. /// VideoCapture capture; /// /// The rgb mat. /// Mat rgbMat; /// /// The texture. /// Texture2D texture; /// /// Indicates whether the video is playing. /// bool isPlaying = false; /// /// Indicates whether the video frame needs updating. /// bool shouldUpdateVideoFrame = false; /// /// The prev frame tick count. /// long prevFrameTickCount; /// /// The current frame tick count. /// long currentFrameTickCount; /// /// The FPS monitor. /// FpsMonitor fpsMonitor; /// /// VIDEO_FILENAME /// protected static readonly string VIDEO_FILENAME = "OpenCVForUnity/768x576_mjpeg.mjpeg"; #if UNITY_WEBGL IEnumerator getFilePath_Coroutine; #endif // Use this for initialization void Start() { fpsMonitor = GetComponent(); capture = new VideoCapture(); #if UNITY_WEBGL getFilePath_Coroutine = Utils.getFilePathAsync(VIDEO_FILENAME, (result) => { getFilePath_Coroutine = null; capture.open(result); Initialize(); }); StartCoroutine(getFilePath_Coroutine); #else capture.open(Utils.getFilePath(VIDEO_FILENAME)); Initialize(); #endif } private void Initialize() { rgbMat = new Mat(); if (!capture.isOpened()) { Debug.LogError(VIDEO_FILENAME + " is not opened. Please move from “OpenCVForUnity/StreamingAssets/OpenCVForUnity/” to “Assets/StreamingAssets/OpenCVForUnity/” folder."); } Debug.Log("CAP_PROP_FORMAT: " + capture.get(Videoio.CAP_PROP_FORMAT)); Debug.Log("CAP_PROP_POS_MSEC: " + capture.get(Videoio.CAP_PROP_POS_MSEC)); Debug.Log("CAP_PROP_POS_FRAMES: " + capture.get(Videoio.CAP_PROP_POS_FRAMES)); Debug.Log("CAP_PROP_POS_AVI_RATIO: " + capture.get(Videoio.CAP_PROP_POS_AVI_RATIO)); Debug.Log("CAP_PROP_FRAME_COUNT: " + capture.get(Videoio.CAP_PROP_FRAME_COUNT)); Debug.Log("CAP_PROP_FPS: " + capture.get(Videoio.CAP_PROP_FPS)); Debug.Log("CAP_PROP_FRAME_WIDTH: " + capture.get(Videoio.CAP_PROP_FRAME_WIDTH)); Debug.Log("CAP_PROP_FRAME_HEIGHT: " + capture.get(Videoio.CAP_PROP_FRAME_HEIGHT)); double ext = capture.get(Videoio.CAP_PROP_FOURCC); Debug.Log("CAP_PROP_FOURCC: " + (char)((int)ext & 0XFF) + (char)(((int)ext & 0XFF00) >> 8) + (char)(((int)ext & 0XFF0000) >> 16) + (char)(((int)ext & 0XFF000000) >> 24)); if (fpsMonitor != null) { fpsMonitor.Add("CAP_PROP_FORMAT", capture.get(Videoio.CAP_PROP_FORMAT).ToString()); fpsMonitor.Add("CAP_PROP_POS_MSEC", capture.get(Videoio.CAP_PROP_POS_MSEC).ToString()); fpsMonitor.Add("CAP_PROP_POS_FRAMES", capture.get(Videoio.CAP_PROP_POS_FRAMES).ToString()); fpsMonitor.Add("CAP_PROP_POS_AVI_RATIO", capture.get(Videoio.CAP_PROP_POS_AVI_RATIO).ToString()); fpsMonitor.Add("CAP_PROP_FRAME_COUNT", capture.get(Videoio.CAP_PROP_FRAME_COUNT).ToString()); fpsMonitor.Add("CAP_PROP_FPS", capture.get(Videoio.CAP_PROP_FPS).ToString()); fpsMonitor.Add("CAP_PROP_FRAME_WIDTH", capture.get(Videoio.CAP_PROP_FRAME_WIDTH).ToString()); fpsMonitor.Add("CAP_PROP_FRAME_HEIGHT", capture.get(Videoio.CAP_PROP_FRAME_HEIGHT).ToString()); fpsMonitor.Add("CAP_PROP_FOURCC", "" + (char)((int)ext & 0XFF) + (char)(((int)ext & 0XFF00) >> 8) + (char)(((int)ext & 0XFF0000) >> 16) + (char)(((int)ext & 0XFF000000) >> 24)); fpsMonitor.Add("STATE", ""); } capture.grab(); capture.retrieve(rgbMat); int frameWidth = rgbMat.cols(); int frameHeight = rgbMat.rows(); texture = new Texture2D(frameWidth, frameHeight, TextureFormat.RGB24, false); gameObject.transform.localScale = new Vector3((float)frameWidth, (float)frameHeight, 1); float widthScale = (float)Screen.width / (float)frameWidth; float heightScale = (float)Screen.height / (float)frameHeight; if (widthScale < heightScale) { Camera.main.orthographicSize = ((float)frameWidth * (float)Screen.height / (float)Screen.width) / 2; } else { Camera.main.orthographicSize = (float)frameHeight / 2; } capture.set(Videoio.CAP_PROP_POS_FRAMES, 0); gameObject.GetComponent().material.mainTexture = texture; StartCoroutine("WaitFrameTime"); isPlaying = true; } // Update is called once per frame void Update() { if (isPlaying && shouldUpdateVideoFrame) { shouldUpdateVideoFrame = false; //Loop play if (capture.get(Videoio.CAP_PROP_POS_FRAMES) >= capture.get(Videoio.CAP_PROP_FRAME_COUNT)) capture.set(Videoio.CAP_PROP_POS_FRAMES, 0); if (capture.grab()) { capture.retrieve(rgbMat); Imgproc.cvtColor(rgbMat, rgbMat, Imgproc.COLOR_BGR2RGB); if (fpsMonitor != null) { fpsMonitor.Add("CAP_PROP_POS_MSEC", capture.get(Videoio.CAP_PROP_POS_MSEC).ToString()); fpsMonitor.Add("CAP_PROP_POS_FRAMES", capture.get(Videoio.CAP_PROP_POS_FRAMES).ToString()); fpsMonitor.Add("CAP_PROP_POS_AVI_RATIO", capture.get(Videoio.CAP_PROP_POS_AVI_RATIO).ToString()); fpsMonitor.Add("CAP_PROP_FRAME_COUNT", capture.get(Videoio.CAP_PROP_FRAME_COUNT).ToString()); int msec = (int)Math.Round(1000.0 * (currentFrameTickCount - prevFrameTickCount) / Core.getTickFrequency()); int fps = (int)Math.Round(1000.0 / msec); fpsMonitor.Add("STATE", msec + "ms (" + fps + "fps)"); } Utils.matToTexture2D(rgbMat, texture); var tmp = seekBarSlider.onValueChanged; seekBarSlider.onValueChanged = defaultSliderEvent; seekBarSlider.value = (float)capture.get(Videoio.CAP_PROP_POS_AVI_RATIO); seekBarSlider.onValueChanged = tmp; } } } private IEnumerator WaitFrameTime() { double videoFPS = (capture.get(Videoio.CAP_PROP_FPS) <= 0) ? 10.0 : capture.get(Videoio.CAP_PROP_FPS); float frameTime_sec = (float)(1000.0 / videoFPS / 1000.0); WaitForSeconds wait = new WaitForSeconds(frameTime_sec); prevFrameTickCount = currentFrameTickCount = Core.getTickCount(); capture.grab(); while (true) { if (isPlaying) { shouldUpdateVideoFrame = true; prevFrameTickCount = currentFrameTickCount; currentFrameTickCount = Core.getTickCount(); yield return wait; } else { yield return null; } } } /// /// Raises the destroy event. /// void OnDestroy() { StopCoroutine("WaitFrameTime"); capture.release(); if (rgbMat != null) rgbMat.Dispose(); #if UNITY_WEBGL if (getFilePath_Coroutine != null) { StopCoroutine(getFilePath_Coroutine); ((IDisposable)getFilePath_Coroutine).Dispose(); } #endif } /// /// Raises the back button click event. /// public void OnBackButtonClick() { SceneManager.LoadScene("OpenCVForUnityExample"); } /// /// Raises the play button click event. /// public void OnPlayButtonClick() { isPlaying = true; } /// /// Raises the pause button click event. /// public void OnPauseButtonClick() { isPlaying = false; } /// /// Raises the jump ahead button click event. /// public void OnJumpAheadButtonClick() { int courentFrame = (int)capture.get(Videoio.CAP_PROP_POS_FRAMES) + 50; if (courentFrame >= capture.get(Videoio.CAP_PROP_FRAME_COUNT)) { courentFrame = (int)capture.get(Videoio.CAP_PROP_FRAME_COUNT); } capture.set(Videoio.CAP_PROP_POS_FRAMES, courentFrame); } /// /// Raises the jump back button click event. /// public void OnJumpBackButtonClick() { int courentFrame = (int)capture.get(Videoio.CAP_PROP_POS_FRAMES) - 50; if (courentFrame <= 0) { courentFrame = 0; } capture.set(Videoio.CAP_PROP_POS_FRAMES, courentFrame); } /// /// Raises the seek bar slider value changed event. /// public void OnSeekBarSliderValueChanged() { bool supported = capture.set(Videoio.CAP_PROP_POS_AVI_RATIO, seekBarSlider.value); if (!supported) { capture.set(Videoio.CAP_PROP_POS_FRAMES, (int)(seekBarSlider.value * capture.get(Videoio.CAP_PROP_FRAME_COUNT))); } } } }