導入
「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
使用します。libvlc
backend
-
libvlc開発パッケージをインストールする
sudo apt install libvlc-dev libvlccore-dev vlc
このうち と
libvlc-dev
はlibvlccore-dev
コンパイルと接続に必要で、vlc
実際のインストールはプレーヤーとプラグイン.soをインストールすることです。プレーヤーは必要ありませんが、プラグインは実行に必要です。そうしないとビデオが再生されません。デコードされた。
ヒント: プラグインの読み込みに関する隠されたルール:- デフォルトでは、
libvlc_new
API を呼び出すと、libvlc はライブラリが配置されているディレクトリlibvlc.so
からビデオの再生に必要なデコード プラグインを検索します。インストールするとプラグインが正しいパスに配置されますlibvlccore.so
plugins
vlc
- 環境変数を介して:プラグインをロードするパス
VLC_PLUGIN_PATH
を指定します。libvlc
- Linux は
setenv
API 経由で動的に設定できます。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
場合、メモリは分離されます。両方のランタイム ライブラリを有効にしたい場合は、次のように設定できます。msvcrt
ucrtbased/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)"); }
- Linux は
- デフォルトでは、
-
MediaEngine
再生、一時停止などのコア機能、登録コールバック (メディア イベント、ビデオ NV12 フレーム イベント) およびその他の機能を実装するコードを作成します。 -
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
(pitch
bytesPerRow) と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