UnityでRTSPビデオストリーミング再生


はじめに

RTSP配信された映像をUnityでストリーミングしたい場合があります。
しかし、Unityには標準でRTSP再生をサポートしているコンポーネントはありません。
今回はgujadot氏のRTSP_Unity_Pluginを用いてUnityにおいてRTSPストリーミングを導入する方法を解説します。

用いるソフトウェア

実装手順

DLL生成編

  1. Visual StudioにVisual C++をインストールしておく。
  2. FFmpegのダウンロードページにアクセスする。dev/shareの両方をダウンロード。
  3. RTSP_Unity_Pluginをダウンロード。RTSPUnityPlugin.vcxproj(VC++ Project)をVisual Studioで開く。
  4. プロジェクトフォルダ内にffmpegフォルダを作成する。以下のような構成になる。
  5. 作成したffmpeg以下にffmpeg/include、ffmpeg/libの2フォルダを作成する。
    各フォルダに次の通り、ダウンロードしたFFmpegの内容をコピーする。
    ffmpeg/include <- copy <- FFmpeg/win64-dev/include
    ffmpeg/lib <- copy <- FFmpeg/win64-dev/lib と FFmpeg/win64-shared/bin
  6. Visual StudioのエクスプローラからRTSPUnityPluginのプロパティを開く。
  7. [構成プロパティ]-[C/C++]-[全般] を開く。
  8. [追加のインクルードディレクトリ]に以下を入力。

    $(SolutionDir)\ffmpeg\include;%(AdditionalIncludeDirectories)
    
  9. [追加の#usingディレクトリ]に以下を入力。

    $(SolutionDir)\ffmpeg\lib
    
  10. [構成プロパティ]-[リンカー]-[全般] を開く。

  11. [追加のライブラリディレクトリ]に以下を入力。

    $(SolutionDir)\ffmpeg\lib;%(AdditionalLibraryDirectories)
    
  12. [構成プロパティ]-[デバッグ] を開く。

  13. [コマンド]に以下を入力。

    $(TargetPath)
    
  14. [構成プロパティ]-[リンカー]-[入力] を開く。

  15. [追加の依存ファイル]に以下を入力。

    avcodec.lib
    avdevice.lib
    avfilter.lib
    avformat.lib
    avutil.lib
    postproc.lib
    swresample.lib
    swscale.lib
    
  16. [構成プロパティ]-[ビルドイベント]-[リンク前のイベント] を開く。

  17. [コマンドライン]に以下を入力。

    copy "$(SolutionDir)ffmpeg\lib\avcodec-57.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\avdevice-57.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\avfilter-6.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\avformat-57.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\avutil-55.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\postproc-54.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\swresample-2.dll" "$(TargetDir)"
    copy "$(SolutionDir)ffmpeg\lib\swscale-4.dll" "$(TargetDir)"
    
  18. ビルドする。

以上の手順を踏むと、build\x64\Release\RTSPUnityPlugin.dllが生成されます。

Unity編

DLLの配置

上記の手順で生成されたReleaseフォルダをAssets/Plugins下に配置する。

オブジェクトへの適用

ストリームしたいマテリアルのオブジェクトに次のスクリプトをアタッチする。
(setRTSPTexture.cs)

setRTSPTexture.cs
using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;


public class SetRTSPTexture : MonoBehaviour {

    [DllImport("RTSPUnityPlugin")]
    private static extern void SetTimeFromUnity(float t);
    [DllImport("RTSPUnityPlugin")]
    private static extern IntPtr GetRenderEventFunc();
    [DllImport("RTSPUnityPlugin")]
    private static extern void SetTextureAsRTSPSink(string rtsp_uri,System.IntPtr texture, int h, int w);


    public string g_rtspUri = "rtsp://localhost:8554/stream";

    IEnumerator Start()
    {
        CreateTextureAndPassToPlugin();
        yield return StartCoroutine("CallPluginAtEndOfFrames");
    }

    private void CreateTextureAndPassToPlugin()
    {
        // Create a texture
        Texture2D tex = new Texture2D(256, 256, TextureFormat.RGBA32, false);
        // Set point filtering just so we can see the pixels clearly
        tex.filterMode = FilterMode.Point;
        // Call Apply() so it's actually uploaded to the GPU
        tex.Apply();

        // Set texture onto our material
        GetComponent<Renderer>().material.mainTexture = tex;

        // Pass texture pointer to the plugin
        SetTextureAsRTSPSink(g_rtspUri, tex.GetNativeTexturePtr(), tex.width, tex.height);
    }

    private IEnumerator CallPluginAtEndOfFrames()
    {
        while (true)
        {
            // Wait until all frame rendering is done
            yield return new WaitForEndOfFrame();

            // Set time for the plugin
            SetTimeFromUnity(Time.timeSinceLevelLoad);

            // Issue a plugin event with arbitrary integer identifier.
            // The plugin can distinguish between different
            // things it needs to do based on this ID.
            // For our simple plugin, it does not matter which ID we pass here.
            GL.IssuePluginEvent(GetRenderEventFunc(), 1);
        }
    }
}

これでUnityを実行すると、RTSPを受信してオブジェクトのテクスチャで再生されます。

最後に

このプラグインを用いればTHETAなどのネットワークカメラから映像をライブ配信できるので、Unityでビデオチャットのような面白い機能が実現できそうです。素晴らしいプラグインを提供してくださったgujadot氏に感謝!