Unity中基于SDL获取显微镜视频流RGB原始数据并解析的问题
解析显微镜视频流并在Unity中显示
我通过SDL库获取到了显微镜的视频流frameData数据,但不知道如何解析这些数据,生成Unity可使用的视频内容。相关代码如下:
public class CameraStreamManager : MonoBehaviour { private Thread cameraThread; private bool isRunning = false; private SLcamNet.NetCamera _camera; private Texture2D videoTexture; public RawImage videoImage; private List<NetInfo> _infos; private CameraInfo _cameraInfo; private SDLPanel sdlPanel; private Task _task; private int width = 1920; private int height = 1080; private bool frameReady = false; public void InitializeCamera() { SLcamNet.NetCamera.InitNet(); _infos = SLcamNet.NetCamera.SearchAvailableCameras(); if (_infos.Count < 1) { Thread.Sleep(100); _infos = SLcamNet.NetCamera.SearchAvailableCameras(); } } public void OpenCamera() { sdlPanel?.Dispose(); sdlPanel = new SDLPanel { Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right }; Debug.LogError("_infos>>>> " + _infos.Count); if (_infos.Count < 1) { Thread.Sleep(100); _infos = SLcamNet.NetCamera.SearchAvailableCameras(); return; } CameraSettings settings = new CameraSettings { netInfo = _infos[0], resolution = new CameraResolution(1920, 1080), streamFormat = StreamFormat.kMJPEG, pixFormat = PixFormat.kRGBA8888, rcMode = "cbr", quality = "high", frameRate = 25, bitrate = 86000, keyFrameInterval = 90 }; settings.netInfo.Username = "admin"; settings.netInfo.Password = "123456"; _camera = SLcamNet.NetCamera.Create(settings.netInfo.Model); _camera.SetCameraSettings(settings); _camera.Login(); _cameraInfo = _camera.GetNetCameraAllInfo(); _camera.Open(); isRunning = true; _task = Task.Run(() => StartCameraCapture()); } private void StartCameraCapture() { Task.Run(() => { Thread.Sleep(500); IntPtr frameDataPtr = IntPtr.Zero; while (isRunning) { try { if (!_camera.GetVideoFrameData(ref frameDataPtr)) continue; SLcamNet.l_md_data_t frameData = SLcamNet.l_md_data_t.FromIntPtr(frameDataPtr); Debug.LogError("frameData>>>>>" + frameData.p_rgb); } catch (Exception ex) { Debug.LogError($"Error in StartCameraCapture: {ex.Message}"); } } }); } private void OnApplicationQuit() { isRunning = false; _task = null; if (sdlPanel != null) { sdlPanel.Dispose(true); sdlPanel = null; } _camera?.Close(); } }
解析与显示实现方案
你的代码已经拿到了帧数据指针frameData.p_rgb,结合Unity的纹理系统,只需完成数据复制→主线程更新纹理两个核心步骤,即可实现实时视频显示:
1. 新增线程安全数据缓存变量
在类中添加用于缓存帧数据的线程安全变量:
private byte[] frameBuffer; private object bufferLock = new object();
2. 初始化Texture2D
在OpenCamera方法中,相机启动后初始化与分辨率匹配的Texture2D,并绑定到RawImage:
// 在_camera.Open()之后添加 videoTexture = new Texture2D(width, height, TextureFormat.RGBA32, false); videoImage.texture = videoTexture;
3. 子线程复制帧数据
修改StartCameraCapture中的帧处理逻辑,将非托管指针的RGBA数据复制到托管数组,标记帧就绪状态:
private void StartCameraCapture() { Task.Run(() => { Thread.Sleep(500); IntPtr frameDataPtr = IntPtr.Zero; while (isRunning) { try { if (!_camera.GetVideoFrameData(ref frameDataPtr)) continue; SLcamNet.l_md_data_t frameData = SLcamNet.l_md_data_t.FromIntPtr(frameDataPtr); int dataLength = width * height * 4; // RGBA8888每个像素4字节 lock(bufferLock) { if(frameBuffer == null || frameBuffer.Length != dataLength) { frameBuffer = new byte[dataLength]; } // 从非托管内存复制数据到托管数组 System.Runtime.InteropServices.Marshal.Copy(frameData.p_rgb, frameBuffer, 0, dataLength); frameReady = true; } // 关键:记得调用SDK的帧释放方法(根据SDK文档调整) // _camera.ReleaseVideoFrameData(frameDataPtr); } catch (Exception ex) { Debug.LogError($"Error in StartCameraCapture: {ex.Message}"); } } }); }
4. 主线程更新纹理
添加Update方法,在主线程中检测帧就绪状态,更新Texture2D:
private void Update() { if(frameReady) { lock(bufferLock) { videoTexture.LoadRawTextureData(frameBuffer); videoTexture.Apply(); frameReady = false; } } }
关键注意事项
- 线程安全:Unity的Texture操作必须在主线程执行,子线程仅负责数据复制,绝对不能直接修改Texture
- 内存释放:务必调用SDK提供的帧数据释放方法(注释中的
ReleaseVideoFrameData),避免内存泄漏 - 格式匹配:确保
TextureFormat.RGBA32与相机设置的PixFormat.kRGBA8888完全匹配,否则会出现画面错乱 - 分辨率适配:如果相机分辨率动态变化,需要重新创建Texture2D和frameBuffer
内容的提问来源于stack exchange,提问作者jindeus ye
相关产品推荐
相关产品推荐

