C# VideoPlayer (Unity层)
↓
C++ VideoPlugin (Native Plugin接口层)
↓
C++ VideoPlayer (播放器控制层)
↓
C++ AVPlayer (解码层,基于FFmpeg)
gvpCreate
创建播放器实例,注册事件回调。VideoPlayer
对象。AVPlayer
,设置渲染、音频、事件等回调。GL.IssuePluginEvent(EVENT_INIT)
触发C++层初始化渲染资源(如纹理)。gvpPrepare(id, url, decodeType)
传入视频URL和解码类型。stream_open
),准备解码线程。gvpPlay(id)
开始播放。AVPlayer::play()
。Update()
中通过 GL.IssuePluginEvent(EVENT_RENDER)
触发C++层渲染。stop()
、destroy()
,停止解码、释放资源。GL.IssuePluginEvent(EVENT_CLEAR)
触发C++层清理。onNativeEvent
)通知C#层状态变更(准备就绪、播放完成、出错等)。GL.IssuePluginEvent
实现。Unity自定义视频播放器通过C#-C++多层架构,结合FFmpeg解码和平台渲染/音频API,实现了高性能、强兼容的视频播放。核心流程包括初始化、解码、渲染、事件回调和资源管理。工程上需关注多线程同步、帧缓存、异常处理和平台适配。
下面我将继续深入,从以下几个方面详细展开:
[DllImport]
调用C++接口(如gvpCreate
、gvpPrepare
、gvpPlay
等)GL.IssuePluginEvent
与C++渲染线程同步Texture2D.CreateExternalTexture
或NativeTexturePtr
与C++层共享纹理GL.IssuePluginEvent
确保纹理更新在Unity渲染线程执行,避免多线程冲突SynchronizationContext
派发到主线程// C#层
void Start() {
gvpCreate(playerType, OnNativeEvent);
GL.IssuePluginEvent(EVENT_INIT);
gvpPrepare(id, url, decodeType);
}
void OnNativeEvent(EventType type) {
if (type == READY) {
gvpPlay(id);
} else if (type == COMPLETED || type == ERROR) {
gvpStop(id);
gvpDestroy(id);
}
}
void Update() {
GL.IssuePluginEvent(EVENT_RENDER);
}
// C++层
void VideoPlayer::init() {
createNativeTexture();
}
void VideoPlayer::prepare(const char* url) {
avPlayer->setDataSource(url);
avPlayer->prepare();
}
void AVPlayer::decodeLoop() {
while (!eof) {
decodeFrame();
pushFrameToQueue();
}
notifyEvent(COMPLETED);
}
void VideoPlayer::render() {
Frame* frame = getLatestFrame();
uploadToTexture(frame);
}
C# VideoPlayer
|
| gvpCreate/Prepare/Play/Stop/Destroy
v
C++ VideoPlugin
|
| 创建/管理播放器对象
v
C++ VideoPlayer
|
| 控制解码、渲染、音频、事件
v
C++ AVPlayer (FFmpeg)
|
| 解码音视频帧,推送到VideoPlayer
v
帧缓存队列 <----> 纹理/音频设备
|
| 事件回调
v
C# VideoPlayer
Unity自定义视频播放器的核心在于C#与C++多层协作,FFmpeg高效解码,Native Texture高效渲染,音视频同步与事件回调机制健全。工程实现需关注多线程同步、平台适配、性能优化和异常容错。
下面我将继续深入,补充更具体的实现细节和工程建议,尤其关注你可能关心的接口设计、Native Texture集成、音视频同步、音频输出、异常处理等方面。
// 1. 创建播放器
[DllImport("GalaxyVideoPlugin")]
public static extern int gvpCreate(int playerType, NativeEventCallback callback);
// 2. 初始化渲染资源
[DllImport("GalaxyVideoPlugin")]
public static extern void gvpInit(int id);
// 3. 准备视频
[DllImport("GalaxyVideoPlugin")]
public static extern void gvpPrepare(int id, string url, int decodeType);
// 4. 播放/暂停/停止
[DllImport("GalaxyVideoPlugin")]
public static extern void gvpPlay(int id);
[DllImport("GalaxyVideoPlugin")]
public static extern void gvpPause(int id);
[DllImport("GalaxyVideoPlugin")]
public static extern void gvpStop(int id);
// 5. 清理资源
[DllImport("GalaxyVideoPlugin")]
public static extern void gvpDestroy(int id);
// 6. 渲染帧同步
[DllImport("GalaxyVideoPlugin")]
public static extern void gvpRender(int id);
// 7. 事件回调
public delegate void NativeEventCallback(int id, int eventType, int param1, int param2);
// C接口暴露给C#
extern "C" {
int gvpCreate(int playerType, NativeEventCallback callback);
void gvpInit(int id);
void gvpPrepare(int id, const char* url, int decodeType);
void gvpPlay(int id);
void gvpPause(int id);
void gvpStop(int id);
void gvpDestroy(int id);
void gvpRender(int id);
}
Texture2D.CreateExternalTexture
或Texture2D.UpdateExternalTexture
将原生纹理包装为Unity可用的Texture2D。IntPtr GetNativeTexturePtr(int id)
。Update()
或OnPostRender()
中调用GL.IssuePluginEvent
,确保纹理更新在Unity渲染线程执行。// C#侧
IntPtr nativeTex = GetNativeTexturePtr(id);
Texture2D unityTex = Texture2D.CreateExternalTexture(width, height, TextureFormat.RGBA32, false, false, nativeTex);
// 解码线程
while (running) {
Frame* frame = decodeNextFrame();
videoQueue.push(frame);
}
// 渲染线程
double audioClock = getAudioClock();
while (!videoQueue.empty()) {
Frame* frame = videoQueue.front();
if (frame->pts <= audioClock) {
renderFrame(frame);
videoQueue.pop();
} else {
break;
}
}
AudioClip.SetData
或OnAudioFilterRead
播放。sequenceDiagram
participant C# as C# VideoPlayer
participant C++ as C++ VideoPlugin
participant VP as C++ VideoPlayer
participant AV as C++ AVPlayer
C#->>C++: gvpCreate
C++->>VP: new VideoPlayer
VP->>AV: new AVPlayer
C#->>C++: gvpInit
C++->>VP: init()
C#->>C++: gvpPrepare(url)
C++->>VP: prepare(url)
VP->>AV: setDataSource, prepare
AV->>AV: stream_open
AV-->>C#: onNativeEvent(READY)
C#->>C++: gvpPlay
C++->>VP: play()
VP->>AV: play()
AV->>VP: decodeLoop (push frames)
C#->>C++: gvpRender (每帧)
C++->>VP: render()
VP->>C#: commitTextures
AV-->>C#: onNativeEvent(COMPLETED/ERROR)
C#->>C++: gvpStop/gvpDestroy
C++->>VP: stop/destroy
Unity自定义视频播放器的高效实现,关键在于C#与C++层清晰分工、接口简洁、Native Texture高效渲染、音视频同步精准、事件回调健壮、异常处理完善。工程上需关注多线程、平台适配、性能与内存优化。