从相机到Unity3D的直播视频

Mic*_*hal 6 c# camera video-streaming unity-game-engine

假设我有一台无线摄像头,我想将视频从实时流式传输到统一.有没有办法实现这个目标?

奖金问题:

  • 那些角度更宽的相机(180,甚至360)
  • 如果这是我希望与之互动的镜头,延迟会有多大问题
  • 除了常规镜头之外,还可以发送更多数据,例如深度感知(使用深度感知相机)吗?
  • 我疯了还是这样做了?

提前致谢

Pro*_*mer 8

我假设这是一台带有以太网端口或Wi-Fi的摄像头,您可以连接到该摄像头并实时流式传输图像.

如果是这样,那么是的,它可以用Unity完成.

如何在没有外部库的情况下完成:

连接相机:

1.使用相机连接到同一本地网络,或者如果支持unpn,您也可以通过互联网连接到它.通常,您需要相机的IP和端口才能执行此操作.假设摄像机IP地址是192.168.1.5,端口号是900.要连接的网址是http://192.168.1.5:900.

有时候,它只是一个以.mjpg.bin结尾的网址,如http://192.168.1.5/mjpg/video.mjpghttp://192.168.1.5/mjpg/video.bin

每个相机都不同.找到网址的唯一方法是阅读其手册.如果手册不可用,请使用其官方应用程序连接到该手册,然后使用Wireshark发现相机Image的URL.的usernamepassword(如果需要)也可在手册中找到.如果没有,请在Google上输入型号,找到您需要的所有信息.

从相机中提取JPEG:

连接到相机时,相机将向您发送无尽的数据.您可以通过此数据扫描并从中检索图像.

2.搜索0xFF后面跟着的JPEG标题0xD8.如果这两个字节彼此相邻,则开始读取字节并继续将它们保存到数组中.您可以使用index(int)变量来计算已接收的字节数.

int counter = 0;
byte[] completeImageByte = new byte[500000];
byte[] receivedBytes = new byte[500000];
receivedBytes[counter] = byteFromCamera;
counter++;
Run Code Online (Sandbox Code Playgroud)

3.从相机读取数据时,检查接下来的两个字节是否是0xFF后面的JPEG页脚0xD9.如果是这样,那么您已收到完整的图像(1帧).

您的图像字节应如下所示:

0xFF 0xD8 someotherbytes(成千上万).....然后 0xFF 0xD9

复制receivedBytescompleteImageByte变量,以便稍后可以使用它来显示图像.将counter变量重置为0.

Buffer.BlockCopy(receivedBytes, 0, completeImageByte, 0, counter);
counter = 0;
Run Code Online (Sandbox Code Playgroud)

将JPEG图像显示在屏幕上:

4.显示图像到屏幕

由于您将每秒接收许多图像,因此我发现显示此效果的最有效方法是使用RawImageComponent.因此,如果您希望在移动设备上运行,请不要使用ImageSprite Renderer为此.

public RawImage screenDisplay;
if(updateFrame){
Texture2D camTexture = new Texture2D(2, 2);
camTexture.LoadImage(completeImageByte);
screenDisplay.texture = camTexture;
}
Run Code Online (Sandbox Code Playgroud)

你只需要camTexture = new Texture2D(2, 2);Start()函数中执行一次.

5回到第2步并继续这样做,直到你想要完全.

用于连接相机的API : .

使用HttpWebRequest如果相机需要认证(用户名和密码).

对于那些不需要身份验证的用户,请使用UnityWebRequest.使用时UnityWebRequest,您必须从中派生自己的类,DownloadHandlerScript否则您的应用程序将崩溃,因为您将不停地接收数据.

从中派生自己的类的示例DownloadHandlerScript:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class CustomWebRequest : DownloadHandlerScript
{    
    // Standard scripted download handler - will allocate memory on each ReceiveData callback
    public CustomWebRequest()
        : base()
    {
    }

    // Pre-allocated scripted download handler
    // Will reuse the supplied byte array to deliver data.
    // Eliminates memory allocation.
    public CustomWebRequest(byte[] buffer)
        : base(buffer)
    {
    }

    // Required by DownloadHandler base class. Called when you address the 'bytes' property.
    protected override byte[] GetData() { return null; }

    // Called once per frame when data has been received from the network.
    protected override bool ReceiveData(byte[] byteFromCamera, int dataLength)
    {
        if (byteFromCamera == null || byteFromCamera.Length < 1)
        {
            //Debug.Log("CustomWebRequest :: ReceiveData - received a null/empty buffer");
            return false;
        }

        //Search of JPEG Image here

        return true;
    }

    // Called when all data has been received from the server and delivered via ReceiveData
    protected override void CompleteContent()
    {
        //Debug.Log("CustomWebRequest :: CompleteContent - DOWNLOAD COMPLETE!");
    }

    // Called when a Content-Length header is received from the server.
    protected override void ReceiveContentLength(int contentLength)
    {
        //Debug.Log(string.Format("CustomWebRequest :: ReceiveContentLength - length {0}", contentLength));
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Test : MonoBehaviour
{

    CustomWebRequest camImage;
    UnityWebRequest webRequest;
    byte[] bytes = new byte[90000];

    void Start()
    {
        string url = "http://camUrl/mjpg/video.mjpg";
        webRequest = new UnityWebRequest(url);
        webRequest.downloadHandler = new CustomWebRequest(bytes);
        webRequest.Send();
    }
}
Run Code Online (Sandbox Code Playgroud)

可以将它们执行步骤2,3,45中的ReceiveData从功能CustomWebRequest的脚本.

控制相机:

摄像机具有平移,旋转,翻转,镜像和执行其他功能的命令.这在每个摄像机中都是不同的,但是对摄像机的URL进行GET/POST请求并提供查询很简单.这些命令可在相机手册中找到.

例如: http://192.168.1.5?pan=50&rotate=90

其他框架:

AForge - 一个免费的框架,可以从相机处理JPEG/MJPESFFMPEG.你必须修改它与团结的工作,你应该,如果你不能做的步骤2,3,45.