快速开始
更新时间:2023-04-17
设置LicenseID(AppId)并初始化播放器
用户在使用SDK之前需要去百度智能云控制台申请并下载.license文件放到自己工程下,并将LicenseID设置给播放器。
LicenseID、包名、证书文件一一对应,所以可能需要按平台设置对应的ID。
using BDCloud.MetaMediaSDK;
#if UNITY_ANDROID
// android
private static string appId = "your-android-license-id";
#elif UNITY_IOS
// ios
private static string appId = "your-ios-license-id";
#endif
private UnityXplayer xplayer;
xplayer = new UnityXplayer(appId);
创建Shader和Material
针对Android和iOS平台,需要选择不同的Shader。
private Shader playerShader = null;
private Material playerMaterial = null;
#if UNITY_ANDROID
playerShader = Shader.Find("Xplayer/AndroidOESShader");
#else
playerShader = Shader.Find("Xplayer/YUVShader");
#endif
playerMaterial = new Material(playerShader);
// 将material设置给你想要显示视频画面的GameObject
private GameObject cube0 = GameObject.Find("Cube0");
if (cube0 != null) {
cube0.GetComponent<Renderer>().material = playerMaterial;
}
设置监听回调
// SEI信息回调
class MyUnityXplayerSEIListener : UnityXplayerSEIListener
{
public override int OnSEI(byte[] buf)
{
Debug.Log("OnSEI");
seiBuf = buf;
return 0;
}
}
// 错误码回调,具体错误码含义参考接口与错误码速查页面
private static int errorCode = 0;
class MyUnityXplayerErrorListener : UnityXplayerErrorListener
{
private UnityXplayer player = null;
public MyUnityXplayerErrorListener(UnityXplayer player)
{
this.player = player;
}
public override int OnError(int _errorCode)
{
Debug.Log("OnError: " + _errorCode);
errorCode = _errorCode;
// 在错误回调中可以自定义处理逻辑,如重新播放
this.player.Stop();
this.player.OpenUrl(this.player.GetUrl());
return 0;
}
}
// 信息码回调,具体信息码含义参考接口与错误码速查页面
class MyUnityXplayerInfoListener : UnityXplayerInfoListener
{
public override int OnInfo(int infoCode)
{
Debug.Log("OnInfo: " + infoCode);
return 0;
}
}
private UnityXplayerSEIListener seiListener = new MyUnityXplayerSEIListener();
private UnityXplayerErrorListener errorListener = new MyUnityXplayerInfoListener();
private UnityXplayerInfoListener infoListener = new MyUnityXplayerErrorListener(xplayer);
创建Android平台的显示Surface
对于Android平台,需要提前在渲染线程创建Surface用于绘制视频内容
#if UNITY_ANDROID
GL.IssuePluginEvent(RenderThreadHandlePtr, CREATE_SURFACE_INTERNAL);
#endif
传入URL并开始播放
xplayer.OpenUrl(url);
在Update事件函数中渲染上屏并且响应播放监听回调
因为Android平台和iOS平台的渲染机制不同,所以在Update事件函数中也要根据平台做不同的处理。
void Update()
{
// 在iOS平台上,渲染基于Y纹理和UV纹理
#if UNITY_IOS || UNITY_STANDALONE_OSX
GL.IssuePluginEvent(UnityXplayerCPP.UnityRenderEvent(xplayer.GetPlayer(), METAL_LOCK));
if (texY == null) {
IntPtr ytex = (IntPtr)xplayer.GetYTex(yTexWidth, yTexHeight);
if (ytex != IntPtr.Zero && ytex != null) {
texY = Texture2D.CreateExternalTexture (Marshal.ReadInt32(yTexWidth), Marshal.ReadInt32(yTexHeight), TextureFormat.R8, false, false, ytex);
}
}
if (texUV == null) {
IntPtr uvtex = (IntPtr)xplayer.GetUVTex(uvTexWidth, uvTexHeight);
if (uvtex != IntPtr.Zero && uvtex != null) {
texUV = Texture2D.CreateExternalTexture (Marshal.ReadInt32(uvTexWidth), Marshal.ReadInt32(uvTexHeight), TextureFormat.RG16, false, false, uvtex);
}
}
if (texY != null && texUV != null) {
IntPtr ytex = (IntPtr)xplayer.GetYTex(yTexWidth, yTexHeight);
IntPtr uvtex = (IntPtr)xplayer.GetUVTex(uvTexWidth, uvTexHeight);
if (ytex != IntPtr.Zero && ytex != null && uvtex != IntPtr.Zero && uvtex != null) {
texY.UpdateExternalTexture (ytex);
texUV.UpdateExternalTexture (uvtex);
foreach (Renderer renderer in rendererList)
{
if (renderer != null) {
renderer.sharedMaterial.SetTexture("_YTex", texY);
renderer.sharedMaterial.SetTexture("_UVTex", texUV);
renderer.sharedMaterial.SetInt("_Type", 3);
}
}
int width = Marshal.ReadInt32(yTexWidth);
int height = Marshal.ReadInt32(yTexHeight);
if (renderTexture != null && playerMaterial != null)
{
playerMaterial.SetTexture("_YTex", texY);
playerMaterial.SetTexture("_UVTex", texUV);
playerMaterial.SetInt("_Type", 3);
// 判断尺寸发生变化
if (renderTexture.width != width || renderTexture.height != height)
{
renderTexture.Release();
renderTexture.width = width;
renderTexture.height = height;
}
Graphics.Blit(null, renderTexture, playerMaterial);
}
}
}
#elif UNITY_ANDROID
// 在Android平台上渲染基于OES纹理
GL.IssuePluginEvent(RenderThreadHandlePtr, UPDATE_TEX);
if (texOES == null) {
int oestex = xplayer.GetOesTex();
if (oestex > 0) {
yTexWidth = xplayer.GetVideoWidth();
yTexHeight = xplayer.GetVideoHeight();
texOES = Texture2D.CreateExternalTexture (yTexWidth, yTexHeight,
TextureFormat.RGBA32, false, false, new System.IntPtr(oestex));
}
}
if (texOES != null) {
int oestex = xplayer.GetOesTex();
if (oestex > 0) {
yTexWidth = xplayer.GetVideoWidth();
yTexHeight = xplayer.GetVideoHeight();
if (texOES.width != yTexWidth || texOES.height != yTexHeight) {
texOES = Texture2D.CreateExternalTexture (yTexWidth, yTexHeight,
TextureFormat.RGBA32, false, false, new System.IntPtr(oestex));
}
texOES.UpdateExternalTexture (new System.IntPtr(oestex));
foreach (Renderer renderer in rendererList)
{
if (renderer != null) {
renderer.sharedMaterial.SetTexture("_MainTex", texOES);
}
}
if (renderTexture != null && playerMaterial != null)
{
playerMaterial.SetTexture("_MainTex", texOES);
// 判断尺寸发生变化
if (renderTexture.width != yTexWidth || renderTexture.height != yTexHeight)
{
renderTexture.Release();
renderTexture.width = yTexWidth;
renderTexture.height = yTexHeight;
}
Graphics.Blit(null, renderTexture, playerMaterial);
}
}
}
#endif
// 处理SEI回调
byte[] seiBuf = xplayer.GetSEI();
if (seiBuf != null) {
if(seiListener != null){
seiListener.OnSEI(seiBuf);
}
}
// 处理错误回调
int errorCode = xplayer.GetErrorCode();
if (errorCode != 0)
{
if (errorListener != null)
{
errorListener.OnError(errorCode);
}
}
// 处理事件回调
int infoCode = xplayer.GetInfo();
if (infoCode != 0)
{
if (infoListener != null)
{
infoListener.OnInfo(infoCode);
}
}
}
播放控制
暂停播放
xplayer.Pause();
恢复播放
xplayer.Resume();
进度SEEK
xplayer.SeekTo(time);
倍速播放
xplayer.SetSpeed(speed);
循环播放
xplayer.SetLooping(looping);
音量设置
xplayer.SetVolume(volume);
停止播放并释放资源
xplayer.Stop()
以上流程在Demo工程的DebugUI.cs
和Player.cs
中进行了详细的展示,可以参考。
Player.cs
对常见的播放功能进行了封装,适用于不需要太多自定义功能的开发者直接使用。