Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

go言語でカメラ映像配信を受信してみる

前回、gstreamingを用いたrtpでのカメラ映像の配信・受信を行いました。
ですが、前回の方法ですとコマンドベースでの動作でした。
elsammit-beginnerblg.hatenablog.com

今度はgo言語でrtpで送信されたデータを受信してみたいと思います!!
go言語でgstreamingを実施するにあたって、gocv用います。
gocvのインストール手順はこちらを参考ください。
elsammit-beginnerblg.hatenablog.com



■環境

・OS:Ubuntu16.04
・Go言語バージョン:go1.11.5 linux/amd64
・gocvバージョン:0.24.0

■事前準備

gocvを用いるにあたり、デフォルトだとgstreamerがOFF(無効)になっているようです。
このため、gstreamerを有効にする必要があり、再度ビルドしなおす必要があります。

まずはgstreamerを有効にするために設定を変更します。
gocv.io/x/gocv配下に格納された"travis_build_opencv.sh"を変更・追加します。

cmake -D WITH_IPP=${GRAPHICAL} \
      -D WITH_OPENGL=${GRAPHICAL} \
      -D WITH_QT=${GRAPHICAL} \
      -D BUILD_EXAMPLES=OFF \
      -D BUILD_TESTS=OFF \
      -D BUILD_PERF_TESTS=OFF  \
      -D BUILD_opencv_java=OFF \
      -D BUILD_opencv_python=OFF \
      -D BUILD_opencv_python2=OFF \
      -D BUILD_opencv_python3=OFF \
      -D OPENCV_GENERATE_PKGCONFIG=ON \
      -D CMAKE_INSTALL_PREFIX=$HOME/usr \
      -D OPENCV_ENABLE_NONFREE=ON \
      -D WITH_FFMPEG=OFF \        ←OFFに変更.
      -D WITH_GTK=ON \        ←追加.
      -D WITH_GSTREAMER=ON \  ←追加.
      -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-${OPENCV_VERSION}/modules ..
-D WITH_FFMPEG=OFF

は不要かもしれませんが、、、
どうやら、FFMPEGとGSTREAMERが両方ONになっていると動作不安定になるとのことで念のため。

修正変更したら、

sudo make install

を実行してgocvのビルドとインストールを行います。

インストール成功したら動作確認!!

■動作確認

では動作確認を行います。
まずはこちらのコードを実行。

package main

import (
	"fmt"
	"gocv.io/x/gocv"
)

func main() {
	test := "videotestsrc ! videoconvert ! appsink"
	webcam, _ := gocv.OpenVideoCapture(test)
	window := gocv.NewWindow("Hello")
	img := gocv.NewMat()

	for {
		if ok := webcam.Read(&img); !ok {
			fmt.Printf("cannot read device \n")
			return
		}
		if img.Empty() {
			continue
		}
		window.IMShow(img)
		if window.WaitKey(1) >= 0 {
			break
		}
	}
}

こちらの映像が表示されればOKです。
f:id:Elsammit:20201206221940g:plain

こちらのコードですが、OpenVideoCaptureに与えるデータを

test := "videotestsrc ! videoconvert ! appsink"

としており、gstreamerで用意?されたテスト動画をinputとして与えています。
後は、

 webcam.Read(&img)

でフレーム映像を取得、

window.IMShow(img)

で映像表示しております。

この

test := "videotestsrc ! videoconvert ! appsink"

を、

test := "v4l2src! videoconvert ! appsink"

に置き換えればカメラ映像を表示させることが出来ます。

■rtp配信動画受信

セットアップが出来たので、本題のrtp配信動画を扱っていきます。
まずは、送信されてきた動画データの受信です。
まずはコードから。

package main

import (
	"fmt"
	"gocv.io/x/gocv"
)

func main() {
	test := "udpsrc port=5005 ! application/x-rtp,media=video,encoding-name=H264 ! queue ! rtph264depay ! avdec_h264 ! videoconvert ! appsink"
	webcam, _ := gocv.OpenVideoCapture(test)
	window := gocv.NewWindow("Hello")
	img := gocv.NewMat()

	for {
		if ok := webcam.Read(&img); !ok {
			fmt.Printf("cannot read device \n")
			return
		}
		if img.Empty() {
			continue
		}
		window.IMShow(img)
		if window.WaitKey(1) >= 0 {
			break
		}
	}
}

先ほどの動作確認とほぼほぼ同じコードで実現できますw。
異なる点は、

test := "udpsrc port=5005 ! application/x-rtp,media=video,encoding-name=H264 ! queue ! rtph264depay ! avdec_h264 ! videoconvert ! appsink"

で、データ受信先を

udpsrc port=5005

に変更し、エンコード

application/x-rtp,media=video,encoding-name=H264 ! queue ! rtph264depay ! avdec_h264 ! videoconvert

としている点です。
前回のrtp受信コマンドで用いたコードをそのまま入力すれば実行できます。

事前に、

gst-launch-1.0 -v videotestsrc ! videoscale ! video/x-raw,width=160,height=120 ! videorate ! video/x-raw,framerate=100/1 ! x264enc ! rtph264pay ! udpsink host=127.0.0.1 port=5005 sync=false

を実行し、先ほどのコードを実行すると、
f:id:Elsammit:20201206221940g:plain
が表示されるかと思います。

■最後に

go言語でgstreamerを用いた映像受信方法についてまとめました。
送信側はただいま勉強中。