【Unity】WebCamTextureで表示したカメラ映像が真っ黒になった時の対処方

Android

 UnityのWebCamTextureをtextureに設定すると、Android端末のカメラPreviewを表示させることができるのは以前の記事でご紹介しました。

 今回、手持ちのいくつかのAndroid機種でカメラのPreviewを表示させてみていたところ、特定のデバイスでPreviewが表示されず真っ黒な画が表示されることがあったので、その症状と対処方法についてまとめておきたいと思います。

Goal

Android端末でカメラを正しく表示させる!

https://amzn.to/3bd8XOX




症状

 まず、今回確認した端末は以下になります。

  • Docomo Xperia SO-03L
  • Docomo Xperia SO-04J
  • Docomo Xperia SO-04H
  • Xperia Z3 tablet compact

 これらの端末に以下のカメラデバッグアプリをインストールして動きをみてみました。(以下アプリではすでに障害修正済みです)

Google Play で手に入れよう

 すると、Docomo Xperia SO-03L以外の全端末でPreview画面が黒くなり、正しく表示することができませんでした。

 何度かカメラのデバイスを切り替えているうちに黒画面は解消され、以下のように正しく表示されるようになります。

一度正しく表示されればもう二度と黒画面は出なくなる、なかなか厄介な症状でした。

LogCatでログをみる

 Unityのデバッグではどうしてもわからなかったので、Android Device MonitorでLogCatからログを確認してみることにしました。

Android Device Monitor の起動

 Android Device MonitorはAndroid SDKの以下のフォルダに格納されています。
  skdインストールディレクトリ\tools\monitor.bat
 ダブルクリックで以下のような画面が起動してきます。

 上のWindowのNameのところに接続されているデバイスが表示されるので、選択します。すると、下のWindowのLogCatのTabにログが表示されます。Filterをかけてログを見れるようですが、どうもうまく動かないので、All messagesをダンプしてエディタで検索しながらログを確認しました。

ログを解析してみる

 膨大なログが出力されてみる気が失せてきますが、Cameraとかerrorとかそれっぽいキーワードで検索していきます。するとそれっぽいエラーログを見つけました。

E/Camera3-Device(1291): Camera 0: clearStreamingRequest: Device has encountered a serious error

 シリアスなエラーにエンカウンターしたと出ています。ちなみに正しく動作しているSO-03Lでは表示されないことを確認したので、ほぼこれが原因だとあたりを付けます。

 さらにログをさかのぼってみると、

E/camera-hal(924): camera_device.cpp(4230):validateCaptureSettings: Unsupported target fps range (24, 24).
E/camera-hal(924): camera_device.cpp(5924):validateCaptureSettings: validateCaptureSettings failed.
E/camera-hal(924): camera_device.cpp(3189):processRequest: Invalid settings for capture. Device:0 Frame Number:0
E/VendorSomcCamDevSession@3.2-impl(924): processOneCaptureRequest: HAL process_capture_request call failed!
E/Camera3-Device(1291): Camera 0: sendRequestsBatch: RequestThread: Unable to submit capture request 0 to HAL device: Function not implemented (-38)
E/Unity(25685): Camera2: Error opeining CameraDevice 4

 設定しようとしているFPSがrange (24, 24)なので、おそらく24固定で指定されています。そして、このデバイスは24fpsをサポートしていないので、映像をキャプチャする設定に失敗しているようです。SO-03Lはシネマモードでの撮影で24fpsをサポートしているので、エラーとならないようです。納得です。

Unityでフレームレートを設定する

 WebCamTextureでのカメラ初期化で幅高さをリクエストしますが、そこにFPSもリクエストするとこができます。黒画面になっていた初期化コードは以下のようになっていました。

webCam = new WebCamTexture(_cameraName, 960,720);

 ここでは960×720のサイズを指定して初期化している例ですが、FPSは指定していません。よろしくやってくれていると思っていましたが、そうではないようです。30fpsであれば、どんなデバイスでも対応していると思われますので、以下のようにコードを修正しました。

webCam = new WebCamTexture(_cameraName, 960,720,30);

 すると、黒画面となっていた他の全てのAndroid端末で、正しく画が表示されるようになりました。

まとめ

 最初、UnityとAndroidの相性問題かと思い、何度か起動停止を繰り返すと正しく表示できていたことから、スクリプトでPlay、Stopを繰り返すワークアラウンドで乗り越えようと企みましたが、有効ではありませんでした。

 ログを解析するのはしんどい作業ですが、無事解決した時は爽快感が味わえますね。

 ただ、なぜ複数回カメラの起動停止を繰り返すと、表示されるようになっていたのかは現象改善したので、調査せず放置しています。知っている方がいれば教えてもらいたいです。

https://amzn.to/3bd8XOX

コメント