強化された axmol エンジンのビデオ再生 - Linux (Ubuntu) ビデオ再生のサポート

導入

「axmol エンジンのビデオ再生の強化 - Android ビデオ再生のサポート」に引き続き、この記事では主に有名な Linux ディストリビューションでのUbuntuビデオ レンダリングからテクスチャ再生までをサポートする方法について説明します。特に指定がない限り、Linux以下の説明におけるすべての参照はUbuntu Linuxバージョンを指しますUbuntu 22.04+

なぜ開発するのか

著者が Android ビデオ テクスチャのレンダリングを正常に完了した後、axmol エンジンでサポートされている唯一のプラットフォーム (macos、windows、ios/tvos、android、linux) が Linux だったので、ついでに Linux もサポートしないのはどうだろうと考えました。

研究

libvlc調査の結果、Linux の優れたプレーヤーの中で、VLCは LGPL-2.1 認証 (ソース コードを変更せずにダイナミック ライブラリの形式で無料で商用利用) を提供していることが判明したため、統合することlibvlcがより良い解決策となります。

達成方法

これは依然として axmol を実装するインターフェースですが、として をMediaEngine使用しますlibvlcbackend

  1. libvlc開発パッケージをインストールする

    sudo apt install libvlc-dev libvlccore-dev vlc
    

    このうち とlibvlc-devlibvlccore-devコンパイルと接続に必要で、vlc実際のインストールはプレーヤーとプラグイン.soをインストールすることです。プレーヤーは必要ありませんが、プラグインは実行に必要です。そうしないとビデオが再生されません。デコードされた。
    ヒント: プラグインの読み込みに関する隠されたルール:

    • デフォルトでは、libvlc_newAPI を呼び出すと、libvlc はライブラリが配置されているディレクトリlibvlc.soからビデオの再生に必要なデコード プラグインを検索します。インストールするとプラグインが正しいパスに配置されますlibvlccore.sopluginsvlc
    • 環境変数を介して:プラグインをロードするパス VLC_PLUGIN_PATHを指定します。libvlc
      • Linux はsetenvAPI 経由で動的に設定できます。setenv("VLC_PLUGIN_PATH", "/path/to/vlc/plugins", true);
      • Windows は API を通じて設定できます_putenv_sが、特別な注意はlibvlc.dllとの c ランタイム ライブラリに基づいて決定する必要がありますlibvlccore.dll。公式のプリコンパイルされた libvlc ライブラリは libvlc を使用しますmsvcrt。つまり、win10 システムでは直接呼び出し_putenv_sは無効です。_putenv_s通常は直接呼び出しが設定されます環境変数が異なる C ランタイム ライブラリと共存するucrt場合、メモリは分離されます。両方のランタイム ライブラリを有効にしたい場合は、次のように設定できます。msvcrtucrtbased/ucrtbase
        _putenv_s("VLC_PLUGIN_PATH", R"(D:\dev\axmol\thirdparty\vlc\win\lib\plugins)");
        
        HMODULE hmsvcrt = GetModuleHandleW(L"msvcrt.dll");
        auto msvcrt_getenv = (decltype(getenv)*)GetProcAddress(hmsvcrt, "getenv");
        
        if (msvcrt_getenv)
        {
                  
                  
            auto msvcrt_putenv_s = (decltype(_putenv_s)*)GetProcAddress(hmsvcrt, "_putenv_s");
            if (msvcrt_putenv_s)
                msvcrt_putenv_s("VLC_PLUGIN_PATH", R"(D:\dev\axmol\thirdparty\vlc\win\lib\plugins)");
        }
        
  2. MediaEngine再生、一時停止などのコア機能、登録コールバック (メディア イベント、ビデオ NV12 フレーム イベント) およびその他の機能を実装するコードを作成します。

  3. VLC(インターネット上の主にRGBA)でデコードされたNV12ビデオデータの取得方法については、この記事ではキーコードのみを掲載しています

    libvlcロック コールバックで、書き込み用にこのビデオ データ フレームのメモリをロックします。

    static constexpr auto VLC_OUTPUT_FORMAT = ax::MEVideoPixelFormat::NV12;
    
    void* VlcMediaEngine::libvlc_video_lock(void* data, void** p_pixels)
    {
          
          
        VlcMediaEngine* mediaEngine = static_cast<VlcMediaEngine*>(data);
    
        auto& bufferDim    = mediaEngine->_videoDim;
        auto& outputBuffer = mediaEngine->_frameBuffer1;
        mediaEngine->_frameBuffer1Mtx.lock();
        if constexpr (VLC_OUTPUT_FORMAT == ax::MEVideoPixelFormat::NV12)
        {
          
          
            outputBuffer.resize_fit(bufferDim.x * bufferDim.y + (bufferDim.x * bufferDim.y >> 1));  // NV12
            p_pixels[0] = outputBuffer.data();
            p_pixels[1] = outputBuffer.data() + (bufferDim.x * bufferDim.y);
        }
        else if constexpr (VLC_OUTPUT_FORMAT == ax::MEVideoPixelFormat::YUY2)
        {
          
          
            outputBuffer.resize_fit(bufferDim.x * bufferDim.y + ((bufferDim.x >> 1) * bufferDim.y * 4));  // YUY2
            p_pixels[0] = outputBuffer.data();
        }
        else
        {
          
          
            outputBuffer.resize_fit(bufferDim.x * bufferDim.y * 4);  // RGBA32
            p_pixels[0] = outputBuffer.data();
        }
        return nullptr;
    }
    void VlcMediaEngine::libvlc_video_unlock(void* data, void* id, void* const* p_pixels)
    {
          
          
        VlcMediaEngine* mediaEngine = static_cast<VlcMediaEngine*>(data);
        mediaEngine->_frameBuffer1Mtx.unlock();
        ++mediaEngine->_frameIndex;
        assert(id == nullptr);
    }
    

    libvlcコールバック モードの書式設定を使用する場合、NV12 では 2 番目plane( pitchbytesPerRow) とlines(ビデオの予想レンダリング高さ/2)を指定する必要があることに注意してください。

    unsigned int VlcMediaEngine::libvlc_video_format_setup(void** opaque,
                                                           char* chroma,  // forcc, refer to:vlc_fourcc.h
                                                           unsigned* width,
                                                           unsigned* height,
                                                           unsigned* pitches,
                                                           unsigned* lines)
    {
          
          
        // refer to: vmem.c:Open https://github.com/videolan/vlc/blob/3.0.18/modules/video_output/vmem.c#L150
        // future: 4.0: will be widths, heights:
        // https://github.com/videolan/vlc/blob/master/modules/video_output/vmem.c#L156
        VlcMediaEngine* mediaEngine = static_cast<VlcMediaEngine*>(*opaque);
    
        // vlc tell us the original codecDim(ALIGNED)
        mediaEngine->_codecDim.set(width[0], height[0]);
    
        // tell vlc we want render as video size
        width[0]  = mediaEngine->_videoDim.x;
        height[0] = mediaEngine->_videoDim.y;
    
        // plane0
        pitches[0] = width[0];   // bytesPerRow
        lines[0]   = height[0];  // rows
    
    #    if LIBVLC_VERSION_MAJOR >= 4
        mediaEngine->_videoDim.set(width[1], height[1]);
    #    endif
    
        int num_of_plane = 1;
    
        if constexpr (VLC_OUTPUT_FORMAT == ax::MEVideoPixelFormat::NV12)
        {
          
          
            memcpy(chroma, "NV12", 4);
    
            // plane1
            pitches[1] = mediaEngine->_videoDim.x;       // bytesPerRow
            lines[1]   = mediaEngine->_videoDim.y >> 1;  // rows
    
            num_of_plane = 2;
        }
        else if constexpr (VLC_OUTPUT_FORMAT == ax::MEVideoPixelFormat::YUY2)
        {
          
          
            memcpy(chroma, "YUY2", 4);
            pitches[0] = width[0] * 2;  // bytesPerRow
        }
        else
        {
          
          
            memcpy(chroma, "RGBA", 4);
            pitches[0] = width[0] * 4;  // bytesPerRow
        }
    
        // return the number of picture buffers allocated, 0 indicates failure
        return num_of_plane;
    }
    

操作と注意事項

axmolエンジンの最新のソース コードをダウンロードしてUbuntu 22.04+、システムでコンパイルして実行します。ビデオの再生時にデコードできない問題が発生した場合は、ubuntu扩展组件次のコマンドを使用してインストールしてください。

sudo apt install ubuntu-restricted-extras

結論

それ以来、axmol エンジンは、ui::MediaPlayerすべてのプラットフォームでビデオ テクスチャのレンダリングと再生をサポートしています。これは、エンジン内で動作するだけでなく、作成された bgfx ビデオ再生サンプルのように、独立してコンパイルすることもできる、再設計されたフレームワークのMediaEngine恩恵も受けています。axmol著者による: bgfx -axplay
さらに、libvlcそれ自体がクロスプラットフォームであるため、この記事の実装は、VlcMediaEngine次のような簡単な構成後に他のプラットフォームでも実行できます。Windows

おすすめ

転載: blog.csdn.net/xyzzf/article/details/131176345