148 lines
5.3 KiB
C#
148 lines
5.3 KiB
C#
/*----------------------------------------------------------------
|
||
// 多 RawImage + 多 Decoder、同时只播一路时:共用一份 UI 材质,仅当前激活 Decoder 写贴图与参数。
|
||
//----------------------------------------------------------------*/
|
||
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// 与多个 <see cref="LeviathanVideoDecoder"/> 配合:全组共用<strong>一个</strong> <see cref="Material"/> 实例,
|
||
/// 任意时刻只有 <see cref="ActivateDecoder"/> 指定的那一路会把它赋到自己的 RawImage 并更新 Y/U/V。
|
||
/// 要求:各解码器的 <see cref="LeviathanVideoDecoderBase.AlphaType"/> 与控制器上配置的 Shared Alpha Type 一致(同一套 Shader)。
|
||
/// </summary>
|
||
public class LeviathanVideoSharedMaterialController : MonoBehaviour
|
||
{
|
||
private static Shader FindShaderForAlphaType(LeviathanVideoDecoderBase.PlayAlphaType alphaType)
|
||
{
|
||
string name = alphaType switch
|
||
{
|
||
LeviathanVideoDecoderBase.PlayAlphaType.RightSide => "LeviathanVideo/YUV420P_Alpha_Right",
|
||
LeviathanVideoDecoderBase.PlayAlphaType.BottomSide => "LeviathanVideo/YUV420P_Alpha_Bottom",
|
||
LeviathanVideoDecoderBase.PlayAlphaType.ChromaKey => "LeviathanVideo/YUV420P_ChromaKey",
|
||
_ => "LeviathanVideo/YUV420P",
|
||
};
|
||
return Shader.Find(name);
|
||
}
|
||
|
||
[SerializeField]
|
||
[Tooltip("共用材质使用的 Alpha/Shader 类型,须与各 Decoder 的 Alpha Type 一致")]
|
||
private LeviathanVideoDecoderBase.PlayAlphaType _sharedAlphaType = LeviathanVideoDecoderBase.PlayAlphaType.ChromaKey;
|
||
|
||
[SerializeField]
|
||
[Tooltip("可选:用工程里的材质做模板 Instantiate;为空则按 Shared Alpha Type 从 Shader 创建")]
|
||
private Material _materialTemplate;
|
||
|
||
private Material _sharedMaterial;
|
||
private LeviathanVideoDecoder _activeDecoder;
|
||
|
||
/// <summary>当前独占共用材质的解码器;无则为 null。</summary>
|
||
public LeviathanVideoDecoder ActiveDecoder => _activeDecoder;
|
||
|
||
/// <summary>共用材质实例(只读,勿在外部 Dispose)。</summary>
|
||
public Material SharedMaterial
|
||
{
|
||
get
|
||
{
|
||
EnsureSharedMaterial();
|
||
return _sharedMaterial;
|
||
}
|
||
}
|
||
|
||
private void EnsureSharedMaterial()
|
||
{
|
||
if (_sharedMaterial != null)
|
||
return;
|
||
|
||
if (_materialTemplate != null)
|
||
{
|
||
_sharedMaterial = new Material(_materialTemplate);
|
||
return;
|
||
}
|
||
|
||
var sh = FindShaderForAlphaType(_sharedAlphaType);
|
||
if (sh == null)
|
||
{
|
||
LeviathanLogConfig.LogError(nameof(LeviathanVideoSharedMaterialController),
|
||
$"无法创建共用材质:Shader 未找到(AlphaType={_sharedAlphaType})");
|
||
return;
|
||
}
|
||
|
||
_sharedMaterial = new Material(sh);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将共用材质交给指定解码器;可选停止上一路。
|
||
/// </summary>
|
||
/// <param name="decoder">若为 null,则仅解绑当前路并清空激活项</param>
|
||
/// <param name="stopPreviousDecoder">为 true 时对上一路调用 <see cref="LeviathanVideoDecoderBase.Stop"/></param>
|
||
public void ActivateDecoder(LeviathanVideoDecoder decoder, bool stopPreviousDecoder = true)
|
||
{
|
||
EnsureSharedMaterial();
|
||
if (_sharedMaterial == null)
|
||
return;
|
||
|
||
if (_activeDecoder == decoder)
|
||
{
|
||
if (decoder != null)
|
||
decoder.RefreshSharedMaterialDisplay();
|
||
return;
|
||
}
|
||
|
||
if (_activeDecoder != null)
|
||
{
|
||
if (stopPreviousDecoder)
|
||
_activeDecoder.Stop();
|
||
_activeDecoder.UnbindSharedMaterialController();
|
||
_activeDecoder = null;
|
||
}
|
||
|
||
if (decoder == null)
|
||
return;
|
||
|
||
if (decoder.AlphaType != _sharedAlphaType)
|
||
{
|
||
LeviathanLogConfig.LogError(nameof(LeviathanVideoSharedMaterialController),
|
||
$"ActivateDecoder: 解码器 AlphaType={decoder.AlphaType} 与控制器 {_sharedAlphaType} 不一致,拒绝绑定。请统一 Inspector 中的 Alpha Type。");
|
||
return;
|
||
}
|
||
|
||
_activeDecoder = decoder;
|
||
_activeDecoder.BindToSharedMaterialController(this, _sharedMaterial);
|
||
_activeDecoder.RefreshSharedMaterialDisplay();
|
||
}
|
||
|
||
/// <summary>解绑当前解码器并停止播放(共用材质仍保留在控制器上)。</summary>
|
||
public void DeactivateCurrent(bool stopDecoder = true)
|
||
{
|
||
if (_activeDecoder == null)
|
||
return;
|
||
if (stopDecoder)
|
||
_activeDecoder.Stop();
|
||
_activeDecoder.UnbindSharedMaterialController();
|
||
_activeDecoder = null;
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
if (_activeDecoder != null)
|
||
{
|
||
_activeDecoder.UnbindSharedMaterialController();
|
||
_activeDecoder = null;
|
||
}
|
||
|
||
if (_sharedMaterial != null)
|
||
{
|
||
Destroy(_sharedMaterial);
|
||
_sharedMaterial = null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解码器销毁或主动 <see cref="LeviathanVideoDecoder.UnbindSharedMaterialController"/> 时调用,清除激活引用。
|
||
/// </summary>
|
||
public void NotifyDecoderReleased(LeviathanVideoDecoder decoder)
|
||
{
|
||
if (_activeDecoder == decoder)
|
||
_activeDecoder = null;
|
||
}
|
||
}
|