using UnityEngine; using UnityEngine.UI; using System; using System.Threading.Tasks; using UnityEngine.EventSystems; namespace Hanatric.Unity.Video.FFmpegPlayer { [RequireComponent(typeof(RawImage))] public class FFmpegPlayerBasicRawImage : FFmpegPlayerMono, IPointerDownHandler { private RawImage rawimage; public Image mask; public Image loading; public Text text; public InputField input; public Func> GetConnectUrl; public Color inactiveColor = Color.clear; public bool autoReconnect = true; public float frameUpdateTimeTimeout = 2; public float reconnectWaitTime = 5; public bool loop = false; private float reconnectWaitTimeRemain; private float frameUpdateTimeTimeoutRemain; private string exceptionMsg; private string info; private bool refreshInfo = false; private Material mat; private void Awake() { rawimage = GetComponent(); mat = rawimage.material; reconnectWaitTimeRemain = float.MaxValue; frameUpdateTimeTimeoutRemain = float.MaxValue; input.onEndEdit.AddListener((s) => { input.gameObject.SetActive(false); }); } protected override void Update() { base.Update(); HandleExceptionMsg(); rawimage.color = rawimage.texture ? Color.white : inactiveColor; rawimage.material = rawimage.texture ? mat : null; loading.transform.Rotate(0, 0, -300 * Time.deltaTime); if (refreshInfo) { refreshInfo = false; info = info.Substring(0, info.Length > 2000 ? 2000 : info.Length); input.text = info; } } protected override void BeforeOpenCall() { base.BeforeOpenCall(); exceptionMsg = ""; reconnectWaitTimeRemain = float.MaxValue; text.text = "正在加载/连接"; info = $"[Info] Url:{Url}" + "\r\n" + info; } private void HandleExceptionMsg() { if (!string.IsNullOrWhiteSpace(exceptionMsg)) { text.text = exceptionMsg; exceptionMsg = ""; mask.gameObject.SetActive(true); if (reconnectWaitTimeRemain > reconnectWaitTime) { reconnectWaitTimeRemain = reconnectWaitTime; } } if (reconnectWaitTimeRemain <= reconnectWaitTime) { reconnectWaitTimeRemain -= Time.deltaTime; } if (reconnectWaitTimeRemain < 0) { reconnectWaitTimeRemain = float.MaxValue; if (autoReconnect) { text.text = "正在重新加载/连接"; DoReconnect(); } } frameUpdateTimeTimeoutRemain -= Time.deltaTime; if (frameUpdateTimeTimeoutRemain < 0) { mask.gameObject.SetActive(true); } } private async void DoReconnect() { if (GetConnectUrl != null) { string url = await Task.Run(GetConnectUrl); Url = url; } Reconnect(); } protected override void OnTextureCreatedFunc(Texture2D texture) { base.OnTextureCreatedFunc(texture); rawimage.texture = texture; } public override void OnVideoOpenedInThread() { base.OnVideoOpenedInThread(); info = $"[Info] Width:{Width},Height:{Height},FPStime:{FrameRateFTime}" + "\r\n" + info; refreshInfo = true; } public override void OnExceptionInThread(FFmpegLibMsg msg, int decoderIndex) { base.OnExceptionInThread(msg, decoderIndex); if (msg == FFmpegLibMsg.UrlOpenException) { exceptionMsg = "无法连接或连接超时"; } if (msg == FFmpegLibMsg.UrlBlank || msg == FFmpegLibMsg.UrlError) { exceptionMsg = "URL格式错误"; } if (msg == FFmpegLibMsg.UrlFileNotExist) { exceptionMsg = "文件不存在"; } if (msg == FFmpegLibMsg.EOF) { exceptionMsg = "EOF 流终止"; if (loop) { reconnectWaitTimeRemain = -1; } } if (msg == FFmpegLibMsg.ReadTimeout) { exceptionMsg = "流读取超时"; } if (msg == FFmpegLibMsg.DecoderOverNum) { exceptionMsg = "打开失败"; reconnectWaitTimeRemain = 0.5f; } Debug.Log("[Exception] " + msg.Message + " " + Url); info = "[Exception] " + msg.Message + "\r\n" + info; refreshInfo = true; } protected override void OnTextureRefreshedFunc(Texture2D texture) { base.OnTextureRefreshedFunc(texture); frameUpdateTimeTimeoutRemain = frameUpdateTimeTimeout; mask.gameObject.SetActive(false); } public override void Stop() { base.Stop(); reconnectWaitTimeRemain = float.MaxValue; exceptionMsg = ""; } public void OnPointerDown(PointerEventData eventData) { if (Input.GetMouseButtonDown(1)) { input.gameObject.SetActive(true); input.Select(); } } } }