概要
前回、KurentoでMCU接続のGroup Callを行うサンプルを作成しましたが、Kurento標準のCompositeMixerエレメントでは、レイアウトのパターンが決まっていて自由に配置する事ができませんでした。このレイアウトを変更するためには、独自のKurentoエレメントを作成する必要があります。
そこで今回は新規にKuretno Moduleを作成し、CompositeMixerエレメントと同じ機能を持つCustomMixerという名前のエレメントを追加して動作させてみます。CustomMixerを変更して、オリジナルのレイアウトに変更する作業は次回に行います。
独自Kurento Moduleとエレメント追加&動作確認は、以下の手順で行っていきます。
-
Module作成ツールのインストール
-
Module作成ツールを使って雛形を作る
-
既存のコードをベースにElement本体を作る
-
ビルド環境を整える
-
ビルドをする
-
debパッケージの作成とインストール
-
JAVA Client用ライブラリの作成とインストール
-
動作確認
Module作成ツールのインストール
Kurento Moduleの作成作業は、kurento-media-serverを動作させるUbuntuマシンにログインして行います。
まずは、作業用ディレクトリを作っておきます。
cd
mkdir work
cd work
自作エレメントの作成の際に参照するので、オリジナルのkurento−elementsのソースを取得しておきます。
git clone https://github.com/Kurento/kms-elements.git
cd kms-elements
git checkout 6.16.0
cd ..
Kurento Moduleを自作するときには、kurento-module-scaffoldというツールを使います。kurento-module-scaffoldはkurento-media-server-devというパッケージに入っているのでインストールします。
sudo apt update && apt install -y kurento-media-server-dev
Module作成ツールを使って独自のModuleを作る
kurento-module-scaffoldを使って新しいmodule("MyModule")を作成します。一番目の引数にmodule名(Module名はCamelCaseで指定する必要あり)2番目の引数に出力ディレクトリを指定します。3番目の引数を与えるとOpenCV用のフィルタモジュールを作成しますが、ここではGstermer用のモジュールを作成するので何も指定せずに実行します。
kurento-module-scaffold MyModule .
このコマンドにより、my-moduleフォルダが作成されて、モジュールのソースコード一式がそのフォルダの中に作成されます。
cd my-module
MyModuleのソースコードは、以下のようなフォルダ構成になっています。
my-module (ルート)
|-- src
| |-- gst-plugins ... Kurento Media Server内に生成されるCustomMixerの本体のソースコード
| |-- server
| |-- implementation ... Kurento ClientからCustomMixerを呼び出すAPIのコード
| |-- interface ... CustomMixerモジュールの記述ファイル(.kmf)
|-- debianパッケージを生成するためのフォルダ
ソースコードの雛形が作成されました。
既存のコードをベースにElementを作る
ここからMyModuleの中にCustomMixer Elementを作成していきます。エレメントのコードを0から作るのは大変なので、標準のKurento-elementsモジュールに含まれるCompositeMixerをコピーして作成します。
src/server/inferfaceフォルダ内のモジュール記述ファイル(xxx.kmd.json)に作成するelementの情報を記述します。雛形を作成した段階で、src/server/interfaceフォルダの中に、mymodule.MyModule.kmd.jsonというファイルがあるので、ファイル名をmymodule.CustomMixer.kmd.jsonに変更します。
mv src/server/interface/mymodule.MyModule.kmd.json src/server/interface/mymodule.CustomMixer.kmd.json
mymodule.CustomMixer.kmd.jsonの内容をオリジナルのCompositeMixerの記述ファイル(kms-elements/src/server/interface/elements.Composite.kmd.json)を参考に以下の通りに書き換えます。
{
"remoteClasses": [
{
"name": "CustomMixer",
"extends": "Hub",
"doc": "CustomMixer interface. Documentation about the module",
"constructor": {
"doc": "Create an element",
"params": [
{
"name": "mediaPipeline",
"doc": "the parent :rom:cls:`MediaPipeline`",
"type": "MediaPipeline",
"final": true
}
]
}
}
]
}
このファイルでは作成するエレメントの名前、親クラス、説明、パラメータなどを記述します。記述ファイルを作成したら、cmakeを実行するとAPIを作成するコード(C++)を src/server/implementation/objectフォルダの中に自動生成します。ここでは、プロジェクトのルートフォルダの下に"build"フォルダを作成してcmake ..
を実行します。
mkdir build
cd build
cmake ..
cd ..
これで、src/server/implementation/objectの中にCustomMixerImpl.cpp
と CustomMixerImpl.hpp
ができました。
ls src/server/implementation/objects/
> CustomMixerImpl.cpp CustomMixerImpl.hpp
APIを生成するコードが自動生成されたのですが、一部不完全なので追記が必要な箇所があります。親クラスのコンストラクタを呼び出すコードをCompositeMixerのコードに従って追記します。CustomMixerImpl.cpp
のコード21行目から25行目までのCustomMixerImplコンストラクタのコードを以下のコードに置き換えて、親クラスのコンストラクタが呼ばれるように書き換えます。
#define FACTORY_NAME "custommixer"
CustomMixerImpl::CustomMixerImpl (const boost::property_tree::ptree &conf, std::shared_ptr<MediaPipeline> mediaPipeline)
: HubImpl (conf, std::dynamic_pointer_cast<MediaObjectImpl> (mediaPipeline), FACTORY_NAME)
{
}
以上で新しいエレメントのためのKurento APIを作成するコードができました。
次にCustomMixerの処理の内容を記述します。オリジナルのCompositeMixerをベースに、kmscompositemixer.cの中の"COMPOSITE"の文字列を"CUSTOM"に置換します。全部大文字、先頭大文字、全部小文字の3パターンとも書き換えて、src/gst-plugin/gstcustommixer.cとして書き込みます。以下のコマンドをプロジェクトのルートディレクトリで実行します。
sed -e 's/COMPOSITE/CUSTOM/g' -e 's/Composite/Custom/g' -e 's/composite/custom/g' ../kms-elements/src/gst-plugins/kmscompositemixer.c > src/gst-plugins/gstcustommixer.c
ヘッダーファイルも同様に作成します。
sed -e 's/COMPOSITE/CUSTOM/g' -e 's/Composite/Custom/g' -e 's/composite/custom/g' ../kms-elements/src/gst-plugins/kmscompositemixer.h > src/gst-plugins/gstcustommixer.h
gstcustommixer.cppファイルの先頭部分を編集してgstcustommixer.hをincludeするように修正します。
// kmscustommixer.h から gstcustommixer.hに変更する
#include "gstcustommixer.h"
同様にmymodule.cファイルの先頭部分を編集してgstcustommixer.hをincludeするように修正します。
// gstmymodule.h から gstcustommixer.hに変更する
#include "gstcustommixer.h"
さらにmymodule.cファイルのinit()関数から呼び出されるCustomMixer エレメントの初期化関数を書き換えます。
static gboolean
init (GstPlugin *plugin)
{
// gst_my_module_plugin_initからkms_custom_mixer_plugin_initに変更
if (!kms_custom_mixer_plugin_init (plugin))
return FALSE;
return TRUE;
}
src/gst-pluginsフォルダの中に、gstmymodule.cppとgstmymodule.hのファイルがありますが、これは自動生成された中身のないフィルタエレメントのコードで不要なので削除しても構いません。
エレメントのコードの作成は以上です。
ビルド環境を整える
kurentoのヘッダーファイルと、ライブラリがリンクできるようにプロジェクトのルートフォルダにある.CMakeLists.txt
の51行目の# Generate file "config.h"
の直前に以下の2行を追記します。
include(GenericFind)
generic_find(LIBNAME KmsGstCommons REQUIRED)
src/gst-plugins/CMakeLists.txt を修正して、kurentoのヘッダーファイルとライブラリの設定を追記します。またソースコードとしてgstcustommixer.cとgstcustommixer.hを指定します。
include_directories(
${GSTREAMER_INCLUDE_DIRS}
${GSTREAMER_VIDEO_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${OPENCV_INCLUDE_DIRS}
${KmsGstCommons_INCLUDE_DIRS} # 行追加
)
set(MY_MODULE_SOURCES
mymodule.c
gstcustommixer.h # gstcustommixer.hを指定
gstcustommixer.c # gstcustommixer.cを指定
)
add_library(mymodule MODULE ${MY_MODULE_SOURCES})
if(SANITIZERS_ENABLED)
add_sanitizers(mymodule)
endif()
target_link_libraries(mymodule
${GSTREAMER_LIBRARIES}
${GSTREAMER_VIDEO_LIBRARIES}
${OPENCV_LIBRARIES}
${KmsGstCommons_LIBRARIES} # 行追加
)
install(
TARGETS mymodule
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_GST_PLUGINS_DIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
ビルドをする
ここで、ビルドディレクトリを作ってcmake ..
を実行すると、コードが自動生成されてmakeできるようになり、makeします。
cd build
cmake ..
make
ビルドしてできたモジュールのライブラリ(libmymodule.so)がbuild/srcディレクトリの中に作成されました。
debパッケージの作成とインストール
モジュールのライブラリをkurento-media-serverが起動時に読み込んで実行できるようにするためにdebianパッケージを作成します。
プロジェクトのルートフォルダに戻って、debパッケージのビルドツールがインストールされていなければインストールします。
cd ..
sudo apt update && sudo apt install --no-install-recommends --yes dpkg-dev
ルートディレクトリでパッケージを作成します。
dpkg-buildpackage -us -uc
これで、作成したライブラリのdebパッケージができました。生成されたdebパッケージはルートフォルダの親フォルダにあります。
ls ../*.deb
../my-module-dev_0.0.1~rc1_amd64.deb ../my-module_0.0.1~rc1_amd64.deb
パッケージをkurento-media-serverが動作するUbuntuにインストールします。
sudo dpkg -i ../my-module_0.0.1~rc1_amd64.deb
インストールできたかどうかは kurento-media-server
を -v
オプション付きで起動するとわかります。
$ kurento-media-server -v
Kurento Media Server version: 6.16.0
Found modules:
'core' version 6.16.0
'elements' version 6.16.0
'filters' version 6.16.0
'mymodule' version 0.0.1~1.g13fd0d5
作成したモジュールが無事にkurento-media-serverに読み込まれるようになりました。
JAVA Client用ライブラリの作成とインストール
Java Client用のライブラリを作成します。このライブラリを読み込ませるとKurento Client ApplicationからMyModule内のCustomMixerを呼び出して使用することができるようになります。
cd build
cmake .. -DGENERATE_JAVA_CLIENT_PROJECT=TRUE
make java
ビルド終了後、build/java/target
ディレクトリの下にcustommixer-0.0.1-SNAPSHOT.jar
ファイルが作成されました。
このファイルは、kurento-clientから、kurento-media-serverのCustomMixerを作成・制御するためのAPIを含むライブラリです。kurento-clientを動作させるマシンにインストールする必要がありますので、このファイルをMacにコピーしてローカルのmvnリポジトリにインストールします。
Macの任意のディレクトリで以下を実行します。
scp <username>@<kuernto host IP>:~/work/my-module/build/java/target/mymodule-0.0.1-SNAPSHOT.jar .
mvn install:install-file \
-Dfile=./mymodule-0.0.1-SNAPSHOT.jar \
-DgroupId=org.kurento.module \
-DartifactId=mymodule \
-Dversion=0.0.1-SNAPSHOT \
-Dpackaging=jar \
-DgeneratePom=true
動作確認
これを前回作ったkurento-group-call-mcuで動かして試してみましょう。
kurento-group-call-mcuプロジェクトのルートディレクトリにあるpom.xmlの<dependencies>
の項目に以下を追記します。
<dependency>
<groupId>org.kurento.module</groupId>
<artifactId>mymodule</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
javaのコードを今回作成したCustomMixerを使うように修正します。
room.javaのソースコードでImportするモージュール名を以下の様にComposteからCustomMixerに変更し、
-import org.kurento.client.Composite;
+import org.kurento.module.mymodule.CustomMixer;
以下room.java中のComposteクラスをCustomMixerクラスに置き換えます。(3箇所くらい)
Ubuntu 側でkurento-media-serverを起動してからKurento Clientを起動します。
# Ubuntuマシンで実行
GST_DEBUG="1,Kurento*:5,custommixer*:5" kurento-media-server
環境変数GST_DEBUG
に上記の様にデバッグオプションを指定してから起動すると、kurento-media-serverとKurentoClient間のメッセージのやり取りを確認することができます。ログを解析すると、CustomMixerが呼び出されていることを確認することができます。
Mac側
# Macで実行
cd kurento-group-call-mcu
./start.sh
macのブラウザからlocalhost:8443
にアクセスして前回作った標準のComposite による画面合成と全く同様に動くとこを確認できればOKです。
まとめ
新規にKuretno Moduleを作成し、CompositeMixerエレメントと同じ機能を持つCustomMixerという名前のエレメントを追加して動作させてみました。次回はCustomMixerを変更して、独自のレイアウトに変更する作業を行います。
ここまでのソースコードはこちらでダウンロードできます。