Raspberry PiでHDMIディスプレイを調査する[EDID/CEC]
- Mzyy94
- Multimedia
- 11 May, 2020
みなさん、テレビやディスプレイに備わるHDMIの情報を確認する必要に迫られることはありませんか? 1年に一度くらいはありますよね。映像がうまく映らなかったり、操作がうまくいかなかったり。 そんな時にパッとHDMIの情報を確認できるようになっておくべく、Raspberry PiとHDMIケーブルで調査できるようになっておきましょう。
はい、今回はRaspberry PiとHDMI EDID/CECの話。
目次
Open 目次
HDMI
HDMIには映像と音声の他に、様々な情報がやり取りされています。 イーサネット通信機能やHDMI入力端子から音声を出力して送り返す(!?)ARCなど、あげたらキリがないほど機能てんこ盛りです。
全ての機能に関する仕様書はHDMI.orgでメンバー登録してライセンス料を払うことで入手できるそうですが、ちょこっとHDMIについて知りたい場合は大袈裟すぎます。 一般人にはWikipediaでも読んで知ったつもりになるくらいで十分です。私もWikipediaで知ったつもりになりました。
このWikipediaの概要に、以下に引用した興味深い一文が掲載されています。
物理層はTMDS (Transition Minimized Differential Signaling)、信号の暗号化はHDCP (High-bandwidth Digital Content Protection)、機器間認証はEDID (Extended display identification data(英語版))、系全体の制御系接続はCEC (Consumer Electronics Control(英語版)) が採用されている。
映像と音声の伝送のほかに、機器間認証はEDIDを、制御系接続はCECを用いているとのことです。ふむふむ。
EDID
Extended Display Identification Data - Wikipedia(英語版)
表まで使って色々と詳しく説明されていますが、噛み砕いてEDIDについて説明すると、ディスプレイの機能について出力機器に伝えるためのメタデータです。 VESAの規格に従って、対応解像度や対応周波数、メーカー名やシリアルナンバーなどが記述されています。
WindowsやmacOSがディスプレイに接続して映像を出力する時、このEDIDに記述されている対応映像情報を元に、映像出力解像度やフレームレートなどが決定されています。 Raspbianも同じくして、接続されたHDMIディスプレイのEDIDを確認しています。
CEC
Consumer Electronics Control - Wikipedia(英語版)
CEC (Consumer Electronics Control) over HDMI - eLinux.org
CECはディスプレイを操作するコントローラーで、機器を制御するものです。 テレビリモコンでAmazon Fire TVを操作したり、テレビの電源に連動してゲーム機がスリープに移行する機能はCECによるものです。
昔紹介したエンターテイメントシステムのKodiもCECをサポートしています。
Wikiにも紹介がありますが、Kodiが直接CECの実装を持っているのではなく、Pulse-EightのlibCECを用いてリモコンでの操作を可能としています。
Pulse-Eight/libcec: USB CEC Adapter communication Library http://libcec.pulse-eight.com/
Raspberry PiのHDMI出力
Raspberry PiのHDMI出力は、ブートローダーであり心臓部でもあるVideoCore(GPU)に直結していることもあって、レジスタ操作によってHDMIの情報にアクセスできるようになっています。
BCM2711 datasheet ARM Peripherals
ただ、画面出力目的ではなくHDMIの調査目的にHDMI出力端子を使うには、VideoCoreの設定をいくつかカスタマイズする必要があります。 設定方法は恒例の**/boot/config.txt**の編集です。
ドキュメントがこちらもRaspberry Pi財団によって用意されているので参照しながら設定していきます。
Video options in config.txt - Raspberry Pi Documentation
HDMIの強制設定
hdmi_drive=2
hdmi_drive
The
hdmi_drive
command allows you to choose between HDMI and DVI output modes.
hdmi_drive result 1 Normal DVI mode (no sound) 2 Normal HDMI mode (sound will be sent if supported and enabled)
引用元: Video options in config.txt - Raspberry Pi Documentation
HDMIはDVIと一部互換のため、DVIとして音声のない映像のみを取り扱う信号をやり取りすることもできます。 今回はHDMI信号としての情報に限って調べるため、ノイズを減らすためにHDMI信号を扱うようにしておきます。
ホットプラグ対応
hdmi_force_hotplug=1
hdmi_force_hotplug
Setting
hdmi_force_hotplug
to1
pretends that the HDMI hotplug signal is asserted, so it appears that a HDMI display is attached. In other words, HDMI output mode will be used, even if no HDMI monitor is detected.
引用元: Video options in config.txt - Raspberry Pi Documentation
抜き差ししていろいろなディスプレイを調査する時や、Raspberry Piが起動してからディスプレイを接続するとき、これを有効にしておく必要があります。
初期CEC無効化
hdmi_ignore_cec_init=1
hdmi_ignore_cec_init
Setting
hdmi_ignore_cec_init
to1
will stop the initial active source message being sent during bootup. This prevents a CEC-enabled TV from coming out of standby and channel-switching when you are rebooting your Raspberry Pi.
引用元: Video options in config.txt - Raspberry Pi Documentation
Raspberry PiのHDMIは、Raspberry Piの起動時にディスプレイにCECの信号を送ってスタンバイから復帰させる機能があります。 HDMI情報の調査目的でRaspberry Piを繋げて起動すると、勝手にCECの信号を送られて困るシチュエーションもあるので、そういう場合にオフにします。
ブースト
config_hdmi_boost
Configures the signal strength of the HDMI interface. The minimum value is
0
and the maximum is11
.The default value for the original Model B and A is
2
. The default value for the Model B+ and all later models is5
.If you are seeing HDMI issues (speckling, interference) then try
7
. Very long HDMI cables may need up to11
, but values this high should not be used unless absolutely necessary.This option is ignored on the Raspberry Pi 4.
引用元: Video options in config.txt - Raspberry Pi Documentation
信号がうまく取れなかったりするときはconfig_hdmi_boost
の値を変えるといいらしい。Raspberry Pi 4では動かないので効果の程はわからないです。
EDID調査
EDIDからディスプレイの情報を取得してみます。
EDIDのダンプ
Raspbianにはtvservice
コマンドが標準で用意されており、HDMI接続機器の情報を取得できます。EDIDのダンプもできます。
シンボリックリンクを経由したものがPATHに通っていますが、VideoCoreのレジスタを叩くためのコマンドであることから、**/opt/vc/bin/**にあります。
そしてドキュメントがRaspberry Pi財団によってWebに公開されています。(manは用意されていない。)
tvservice - Raspberry Pi Documentation
Raspberry Pi起動後に接続したディスプレイに対しては、-d
(ダンプEDID)オプション以外動いてくれません。
まあ-d
オプションが動いてくれれば目的のEDIDのダンプは取れるので、十分です。
HDMIケーブルでRaspberry Piとテレビを繋げてEDIDをダンプしてみます。対象は、1年半前に買った格安65インチ4Kテレビです。 stdoutとかには出力できないので、ファイルに出力してあげます。
pi@raspberrypi:~ $ tvservice -d /tmp/edid.bin
Written 256 bytes to /tmp/edid.bin
出力したEDIDファイルは、以下のようになっています。 これだけ見るとなんのこっちゃわかりませんね。
EDID解析
Raspbianにはtvservice
とセットで同じ場所にedidparser
コマンドがあり、これで先ほどのEDIDファイルを読める形にできます。
このパース結果から、以下のようなテレビの情報が取得できました。
- 画面サイズ: 128x72 cm
- 製品名: TV-monitor
- 推奨映像モード: 3840x2160p @ 60 Hz 594 MHz
- 対応音声フォーマット: 2 channels PCM, 32|44|48 kHz, 16 bits
CEC調査
次はCEC調査です。
先に紹介したlibCECには、クライアント実装としてcec-client
というCLIツールがセットで提供されています。
これを使ってCECの調査ができます。
libCECをビルドするか、sudo apt install cec-utils
でcec-client
が手に入ります。
cec-client
はログ出力がモリモリでうるさいので、-d
オプションで必要なレベルまで下げます。
普段使いは-d 1
です。
typedef enum cec_log_level
{
CEC_LOG_ERROR = 1,
CEC_LOG_WARNING = 2,
CEC_LOG_NOTICE = 4,
CEC_LOG_TRAFFIC = 8,
CEC_LOG_DEBUG = 16,
CEC_LOG_ALL = 31
} cec_log_level;
libcec/cectypes.h#L828-L836 at libcec-5.0.0
コマンドを-s
オプションに続けて標準入力から与えることで、CECの調査ができます。
コマンドの一覧はecho help | cec-client -d 1 -s
でわかります。
接続機器の一覧
echo "scan" | cec-client -d 1 -s
同じディスプレイに繋がっていて、CECの疎通ができるデバイスの一覧をscan
コマンドで列挙できます。
認識されているデバイスを確認することができます。
この列挙されている各デバイスの、device #
の後に続く16進数がバスアドレスです。
テレビのスリープ
echo "standby 0" | cec-client -d 1 -s
テレビのバスアドレスはよっぽどのことがない限り0
なので、アドレス0
に向かってstandby
コマンドを叩けば、ほとんの環境でテレビをスリープできます。
デバイスのスリープ
echo "standby B" | cec-client -d 1 -s
先ほどのscanでバスアドレスB
のNintendo Switchがアクティブなので、スリープさせてみます。
スリープしました。
デバイスの復帰
echo "on 4" | cec-client -d 1 -s
これも指定したバスアドレスの機器をonにできます。 Nintendo SwitchはスリープしたらCECが切断されてしまったので、AppleTVを付けてみました。付きました。
CECの監視
cec-client -m
流れているCECフレームを監視できます。 監視中にリモコンでテレビの画面を消してみました。
>> 0f:36 とトラフィックが流れてきているのがログに現れています。 CECのフレームは送信元4ビット、宛先4ビット、コード8ビット、それに続いて引数がつく形で表されます。 この0f:36は次のように分解できます。
- 送信元アドレス
0
テレビ - 宛先アドレス
f
ブロードキャスト(全体) - コード
36
standby(スタンバイ)
libCECで扱っているコードは、cectypes.hに記載があります。
libcec/cectypes.h at libcec-5.0.0 · Pulse-Eight/libcec
CECフレームの送信
echo "tx 10:04" | cec-client -d 1 -s
データ構造がわかると、CECフレームを生で送って調査したくなりますね。 そんな時に役に立つのが、CECフレームパーサ・ジェネレーターWebアプリケーションのCEC-O-MATIC。 先ほどの監視したフレームのトラフィックもパースできます。
10:04を送ってみました。
- 送信元アドレス
1
Raspberry Pi - 宛先アドレス
0
テレビ - コード
04
on
テレビがつきました。
まとめ
HDMIのEDIDを調査することで、ディスプレイやテレビが対応している映像モードや音声のチャンネル数などがわかります。 映像が映らない時、出力する機器が対応しているモードがないなんてことが稀にありますが、これで確認できますね。
CECの調査では、デバイスと連動してスリープにちゃんと移行しない場合など、どのようなCECフレームがやり取りされているかを確認できます。 また、どのようなフレームを送るとどういった挙動をするのか、動作確認にも使えますね。
これらのツールでみなさん良いHDMI調査ライフを〜