[Kinesis Video Streams] Raspberry Piでh.264エンコードをする3種類の方法

2020.02.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

Kinesis Video Streamsへ動画を送信する場合、メディア形式は、h.264又は、h.265である必要があります。

このため、GStreamerのパイプライン等、どこかの段階で、エンコードを組み込む必要があります。

今回は、Raspberry Pi で送信する場合に利用可能な、3種類のh.264エンコードについて確認してみました。

2 環境

確認に使用した環境は、Model 4B と Raspberry Piの公式カメラ V2です。

OSは、昨年9月の最新版(Raspbian GNU/Linux 10 (buster) 2019-09-26-raspbian-buster-full.img です。

$ cat /proc/cpuinfo  | grep Revision
Revision    : c03112

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:    10
Codename:   buster

$ uname -a
Linux raspberrypi 4.19.75-v7l+ #1270 SMP Tue Sep 24 18:51:41 BST 2019 armv7l GNU/Linux

以降の作業は、環境変数で認証情報とリージョンを設定した状態で行っています。

export AWS_DEFAULT_REGION=ap-northeast-1
export AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxx

また、デバイスはdevice=/dev/video0(v4l2srcでのデフォルト)で認識されてます。

3 ソフトウエアによるエンコード

x264encは、GStreamerでデフォルトで提供されるソフトウエアエンコーダーです。
参考: https://gstreamer.freedesktop.org/documentation/x264/index.html?gi-language=c

x264encを使用した場合のコマンドは以下のようになります。

$ gst-launch-1.0 -v v4l2src ! videoconvert ! video/x-raw,format=I420,width=640,height=480,framerate=30/1 ! x264enc  bframes=0 key-int-max=45 bitrate=500 tune=zerolatency ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

CPUの負荷は、結構上がっている事が分かります。

$ vmstat 3 100
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 3710104  19236 113028    0    0     0     0   36   46  0  0 100  0  0
 0  0      0 3710104  19236 113028    0    0     0     0   29   36  0  0 100  0  0
 0  0      0 3710072  19236 113028    0    0     0     5   38   46  0  0 100  0  0
 2  0      0 3693624  19912 124376    0    0  3823   313  429  649  2  2 93  3  0
 0  0      0 3684184  19908 125020    0    0   228    15 1544 1969 23  2 75  0  0
 0  0      0 3684208  19908 125020    0    0     0    12 1955 2658 35  1 64  0  0
 0  0      0 3684144  19908 125020    0    0     0     0 1826 2519 33  2 65  0  0
 0  0      0 3684112  19908 125020    0    0     0     0 1874 2723 35  1 64  0  0
 0  0      0 3684080  19908 125020    0    0     0     0 1885 2779 34  1 65  0  0

この方法では、ちょっと古いRaspberry Piなどでは、安定した送信は、無理があるかも知れません。

4 ハードウエアによるエンコード

omxh264encは、RaspberryPiに実装されているハードウエアエンコーダーを使用するエレメントです。

omxが利用可能かどうかは、以下のように確認することが出来ます。

$ gst-inspect-1.0 | grep omx
libav:  avenc_h264_omx: libav OpenMAX IL H.264 video encoder encoder
omx:  omxhdmiaudiosink: OpenMAX HDMI Audio Sink
omx:  omxanalogaudiosink: OpenMAX Analog Audio Sink
omx:  omxh264enc: OpenMAX H.264 Video Encoder
omx:  omxvc1dec: OpenMAX WMV Video Decoder
omx:  omxmjpegdec: OpenMAX MJPEG Video Decoder
omx:  omxvp8dec: OpenMAX VP8 Video Decoder
omx:  omxtheoradec: OpenMAX Theora Video Decoder
omx:  omxh264dec: OpenMAX H.264 Video Decoder
omx:  omxh263dec: OpenMAX H.263 Video Decoder
omx:  omxmpeg4videodec: OpenMAX MPEG4 Video Decoder
omx:  omxmpeg2videodec: OpenMAX MPEG2 Video Decoder

使用する場合のコマンドは以下のとおりです。

$ gst-launch-1.0 -v v4l2src ! videoconvert ! video/x-raw,format=I420,width=640,height=480,framerate=30/1 ! omxh264enc periodicty-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

CPUの負荷は、殆ど上がっておらず、安定した送信が可能です。

$ vmstat 3 100
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 3696132  19924 126356    0    0     0     0   24   28  0  0 100  0  0
 0  0      0 3696132  19928 126352    0    0     0     4   31   42  0  0 100  0  0
 0  0      0 3696132  19928 126352    0    0     0     0   24   29  0  0 100  0  0
 1  0      0 3691244  19928 126356    0    0     0     0  517  748  1  1 98  0  0
 0  0      0 3690660  19928 126356    0    0     0     0 1221 2016  1  2 98  0  0
 0  0      0 3690660  19936 126356    0    0     0     4  978 1696  1  1 98  0  0

5 カメラによるエンコード

カメラによっては、h.264のエンコーダーが組み込まれているものがあります。

今回使用している、 「Raspberry Pi 公式カメラ V2」も、その一つで、各種のフォーマットに対応しており、H264も確認できます。

$ v4l2-ctl -d /dev/video0 --list-formats
ioctl: VIDIOC_ENUM_FMT
    Type: Video Capture

    [0]: 'YU12' (Planar YUV 4:2:0)
    [1]: 'YUYV' (YUYV 4:2:2)
    [2]: 'RGB3' (24-bit RGB 8-8-8)
    [3]: 'JPEG' (JFIF JPEG, compressed)
    [4]: 'H264' (H.264, compressed)
    [5]: 'MJPG' (Motion-JPEG, compressed)
    [6]: 'YVYU' (YVYU 4:2:2)
    [7]: 'VYUY' (VYUY 4:2:2)
    [8]: 'UYVY' (UYVY 4:2:2)
    [9]: 'NV12' (Y/CbCr 4:2:0)
    [10]: 'BGR3' (24-bit BGR 8-8-8)
    [11]: 'YV12' (Planar YVU 4:2:0)
    [12]: 'NV21' (Y/CrCb 4:2:0)
    [13]: 'BGR4' (32-bit BGRA/X 8-8-8-8)

v4l2srcは、h.264の入力も処理できるので、下記のように使用することが可能です。

gst-launch-1.0 -e v4l2src ! video/x-h264, width=640, height=480, framerate=30/1 ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

この場合も、CPUへの負荷は殆どないため、安定した送信が可能です。

$ vmstat 3 100
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 3488288  29232 215692    0    0    17     1   58   75  1  0 99  0  0
 0  0      0 3493172  29232 215692    0    0     0     0  132  126  0  0 100  0  0
 0  0      0 3493172  29240 215692    0    0     0    12   83  100  0  0 100  0  0
 0  0      0 3493172  29240 215692    0    0     0     0   41   47  0  0 100  0  0
 0  0      0 3487656  29248 215692    0    0     0    11 1037 1082  2  2 96  0  0
 0  0      0 3487624  29248 215692    0    0     0     1 1350 1285  0  1 99  0  0
 0  0      0 3487576  29248 215692    0    0     0     0 1848 1826  1  1 98  0  0
 1  0      0 3487448  29248 215692    0    0     0     0 1159 1179  1  1 98  0  0
 0  0      0 3487352  29248 215692    0    0     0     0 1398 1229  1  1 98  0  0

6 その他

(1) カメラのモード

h.264のエンコードを使用するかどうかなど、カメラのモードは、GStreamer側から変更されます。 v4l2-ctl -allで、カメラの状態を確認出来ますが、Raspiのハードウエアエンコードを使用した直後に出力です。

$ v4l2-ctl --all
(略)
Format Video Capture:
    Width/Height      : 640/480
    Pixel Format      : 'YU12' (Planar YUV 4:2:0)
    Field             : None
    Bytes per Line    : 640
    Size Image        : 460800
    Colorspace        : SMPTE 170M
    Transfer Function : Default (maps to Rec. 709)
    YCbCr/HSV Encoding: Default (maps to ITU-R 601)
    Quantization      : Default (maps to Limited Range)
(略)

そして、カメラのエンコードを使用した直後です。

$ v4l2-ctl --all
(略)
Video input : 0 (Camera 0: ok)
Format Video Capture:
    Width/Height      : 640/480
    Pixel Format      : 'H264' (H.264)
    Field             : None
    Bytes per Line    : 0
    Size Image        : 307200
    Colorspace        : SMPTE 170M
    Transfer Function : Default (maps to Rec. 709)
    YCbCr/HSV Encoding: Default (maps to ITU-R 601)
    Quantization      : Default (maps to Full Range)
    Flags             :
(略)

以下のように、v4l2-ctlでモード変更が可能ですが、GStreamerを使用する場合、必要ないと言うことになります。

$ v4l2-ctl --device /dev/video0 --set-fmt-video=width=1280,height=960,pixelformat=1

(2) h.264をソース元にした場合の確認

ソース元からh.264を正常に受け取れているかどうかの切り分けには、下記のようなコマンドが有効かも知れません。

gst-launch-1.0 -e v4l2src device=/dev/video0 ! video/x-h264, width=640, height=488, framerate=30/1 ! avdec_h264 ! xvimagesink sync=false

(3) uvch264srcは諦めました

h.264の入力が、uvch264srcというエレメントで可能だという情報が有ったのですが、今回は、こちらはうまく動作させることが出来ませんでした。

何か必要な処置などがあれば、是非、教えてほしいです。

$ gst-launch-1.0 -v uvch264src device=/dev/video0 ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream
ERROR: from element /GstPipeline:pipeline0/GstUvcH264Src:uvch264src0: Device is not a valid UVC H264 camera

(4) Logicool(logitech) C920

ネット上では、C920からh.264で取得している記事が多数公開されているのですが、残念ながら、最近のものには、実装されていないようです。

手元のC920の出力です。

$ v4l2-ctl -d /dev/video0 --list-formats
ioctl: VIDIOC_ENUM_FMT
    Type: Video Capture

    [0]: 'YUYV' (YUYV 4:2:2)
    [1]: 'MJPG' (Motion-JPEG, compressed)

logitechのページで、以下のアナウンスを確認することができます。


https://www.logitech.com/en-us/video-collaboration/resources/think-tank/articles/article-logitech-and-h264-encoding.html

The result of freeing up in-camera resources and instead focusing 
on delivering better image quality, have been born out in three of 
Logitech’s most popular webcams, the C920, C922 and BRIO.

7 最後に

今回は、Kinesis Video Streamsに送信する場合に必要な、h.264のエンコードについて、確認してみました。 安定した送信のために、ハードウエアによるエンコードをうまく利用する必要があるでしょう。(すいません、当たり前の話ですよね・・・)