187 lines
5.7 KiB
C#
187 lines
5.7 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using FairyGUI;
|
|
using RedHotRoast;
|
|
using UnityEngine;
|
|
using UnityEngine.Video;
|
|
|
|
internal class VideoLoadTask
|
|
{
|
|
public Coroutine coroutine;
|
|
public string fileName;
|
|
public bool isCancelled;
|
|
public GLoader loader;
|
|
public Action<VideoPlayer> onComplete;
|
|
public bool play;
|
|
public VideoPlayer player;
|
|
|
|
// loader 绑定的任务 ID
|
|
public string taskId;
|
|
}
|
|
|
|
internal class VideoLoadScheduler
|
|
{
|
|
private const int MaxConcurrent = 1; // 同时加载任务数
|
|
private static readonly Queue<VideoLoadTask> taskQueue = new();
|
|
private static readonly List<VideoLoadTask> runningTasks = new();
|
|
|
|
/// <summary>
|
|
/// 入队视频加载任务
|
|
/// </summary>
|
|
public static void EnqueueLoad(VideoPlayer player, string fileName, GLoader loader, Action<VideoPlayer> onComplete,
|
|
bool play = true)
|
|
{
|
|
// 🔑 检查重复任务
|
|
var isDuplicate = taskQueue.Any(t => t.fileName == fileName && t.loader == loader && !t.isCancelled);
|
|
|
|
if (isDuplicate)
|
|
{
|
|
Debug.LogWarning($"[VideoScheduler] 跳过重复任务: {fileName}, loader={loader.name}");
|
|
return;
|
|
}
|
|
|
|
// 生成唯一 taskId,绑定到 loader
|
|
var taskId = Guid.NewGuid().ToString();
|
|
loader.SetData(taskId);
|
|
|
|
var task = new VideoLoadTask
|
|
{
|
|
fileName = fileName,
|
|
loader = loader,
|
|
onComplete = onComplete,
|
|
play = play,
|
|
player = player,
|
|
taskId = taskId
|
|
};
|
|
|
|
taskQueue.Enqueue(task);
|
|
Debug.Log($"[VideoScheduler] 入队视频: {fileName}, taskId={taskId}, queueCount={taskQueue.Count}");
|
|
|
|
TryStartNext();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 尝试启动队列中的任务
|
|
/// </summary>
|
|
private static void TryStartNext()
|
|
{
|
|
Debug.Log($"[VideoScheduler] TryStartNext 调用,queue={taskQueue.Count}, running={runningTasks.Count}");
|
|
|
|
while (taskQueue.Count > 0 && runningTasks.Count < MaxConcurrent)
|
|
{
|
|
var task = taskQueue.Dequeue();
|
|
|
|
if (task.isCancelled)
|
|
{
|
|
Debug.Log($"[VideoScheduler] 跳过已取消任务: {task.fileName}, taskId={task.taskId}");
|
|
continue;
|
|
}
|
|
|
|
Debug.Log($"[VideoScheduler] 启动任务: {task.fileName}, taskId={task.taskId}");
|
|
var co = CrazyAsyKit.StartCoroutine(LoadVideoToPlayer(task.player, task));
|
|
task.coroutine = co;
|
|
runningTasks.Add(task);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 协程加载视频
|
|
/// </summary>
|
|
private static IEnumerator LoadVideoToPlayer(VideoPlayer player, VideoLoadTask task)
|
|
{
|
|
Debug.Log($"[VideoScheduler] 开始加载视频: {task.fileName}, taskId={task.taskId}");
|
|
|
|
var callbackTriggered = false;
|
|
|
|
yield return LiveVideoManager.LoadVideoToPlayer(player, task.fileName, task.loader, vp =>
|
|
{
|
|
callbackTriggered = true;
|
|
Debug.Log(
|
|
$"[VideoScheduler] 回调触发: {task.fileName}, loader taskId={task.loader.GetData()}, current taskId={task.taskId}");
|
|
|
|
if (task.loader.GetData() != task.taskId)
|
|
{
|
|
Debug.Log($"[VideoScheduler] 任务被覆盖,丢弃: {task.fileName}, taskId={task.taskId}");
|
|
}
|
|
else if (task.isCancelled)
|
|
{
|
|
Debug.Log($"[VideoScheduler] 任务被取消: {task.fileName}, taskId={task.taskId}");
|
|
if (vp != null) vp.Stop();
|
|
task.onComplete?.Invoke(null);
|
|
}
|
|
else
|
|
{
|
|
Debug.Log($"[VideoScheduler] 任务完成: {task.fileName}, taskId={task.taskId}");
|
|
task.onComplete?.Invoke(vp);
|
|
}
|
|
|
|
runningTasks.Remove(task);
|
|
Debug.Log($"[VideoScheduler] 移除任务,剩余: {runningTasks.Count}");
|
|
TryStartNext();
|
|
}, task.play);
|
|
|
|
// 🔴 兜底:防止 TextureHelper 出错导致回调不触发
|
|
if (!callbackTriggered)
|
|
{
|
|
Debug.LogWarning($"[VideoScheduler] ⚠️ 没有回调就结束了,强制移除任务: {task.fileName}, taskId={task.taskId}");
|
|
runningTasks.Remove(task);
|
|
TryStartNext();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 取消某个任务
|
|
/// </summary>
|
|
public static void CancelTask(VideoLoadTask task)
|
|
{
|
|
if (task == null) return;
|
|
task.isCancelled = true;
|
|
if (task.coroutine != null)
|
|
CrazyAsyKit.StopCoroutine(task.coroutine);
|
|
|
|
if (runningTasks.Remove(task))
|
|
Debug.Log($"[VideoScheduler] 取消并移除任务: {task.fileName}, taskId={task.taskId}");
|
|
|
|
// TryStartNext();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清理所有任务
|
|
/// </summary>
|
|
public static void ClearAll()
|
|
{
|
|
// 倒序遍历,避免索引错乱
|
|
for (int i = runningTasks.Count - 1; i >= 0; i--)
|
|
{
|
|
CancelTask(runningTasks[i]);
|
|
}
|
|
|
|
taskQueue.Clear();
|
|
runningTasks.Clear();
|
|
Debug.Log("[VideoScheduler] 所有任务已清理");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 扩展方法:GLoader 绑定当前任务 ID
|
|
/// </summary>
|
|
public static class GLoaderExtensions
|
|
{
|
|
private static readonly Dictionary<GLoader, string> loaderTaskMap = new();
|
|
|
|
public static void SetData(this GLoader loader, string taskId)
|
|
{
|
|
loaderTaskMap[loader] = taskId;
|
|
}
|
|
|
|
public static string GetData(this GLoader loader)
|
|
{
|
|
if (loaderTaskMap.TryGetValue(loader, out var taskId))
|
|
return taskId;
|
|
return null;
|
|
}
|
|
} |