先々週から定期的にTwitterでブツブツ言っている件です。過去に何度か取り上げているMediaCaptureですが、少し問題を見つけました。
デバイスによって症状が異なるかと思いますが、MacBook Pro with Retina displayを使っていて、SetPreviewRotationメソッドを使ってカメラプレビューを回転させると表示がおかしくなります。
プレビューを開始するのは、この方法を使えば、簡単に実装することが可能です。参考にしてみてください。
MediaCaptureには、SetPreviewRotationメソッドというものがあり、カメラプレビューを回転させることができます。例えば、270度回転させたい場合は、以下のように回転角度を指定します。
var capture = new MediaCapture(); await capture.InitializeAsync(); captureElement.Source = capture; // カメラプレビューを270度回転させる capture.SetPreviewRotation(VideoRotation.Clockwise270Degrees); // プレビューを開始します await capture.StartPreviewAsync();
Windowsシミュレータ上で、上記のサンプルコードを実行してみました。
色差情報がおかしくなる(カメラデバイス固有?)
カメラデバイス(ドライバ?)固有の問題ですが、色差情報がおかしくなる現象が確認できています。
回転させてカメラプレビューした場合
SetPreviewRotation(VideoRotation.Clockwise270Degrees);を指定した場合、下図のように出力されます。
プレビューを見た感じでは、YUVの色差情報(UV)部分がおかしくなったのではないかと推測できます。
VideoRotation.Clockwise270Degreesだけではなく、VideoRotation.Clockwise90Degreesを指定しても同じように色情報が飛んでしまいました。
通常の方向でカメラプレビューをした場合
SetPreviewRotationメソッドを使っておらず、回転方向を設定しない場合は、下図のように出力されます。
プレビューフレームのサイズがおかしくなる
追記。
こちらは、MacBook Proだけではなく、リファレンスデバイスのSurface RTでも発生する現象です。
通常方向(回転なし)でカメラプレビューさせた場合、期待したサイズでプレビューされます。
SetPreviewRotationメソッドを使って270度回転等させた場合、本来のプレビューサイズである通常方向のサイズと同じサイズで、かつ270度回転させた状態で欲しいのですが、左右に謎の余白ができてしまう現象が発生します。
色差情報がズレるの現象とともに回避するには、まとめに書いている対処法くらいしか思いつきません。
まとめ
現時点での結論としては以下の通りです。
MediaCaptureにはSetPreviewRotationメソッドと言うプレビュー時に回転させるメソッドが存在しますが、このメソッドを使用してカメラプレビューを回転させると、意図しない(上図のように色情報が崩れた)プレビューフレームが出力される可能性があります。
MBPだけの問題かもしれませんが、そうでない可能性もあります。多種多様なデバイスで動いている上に、さらに様々なウェブカメラを後付けもできるため、Windowsが動いているデバイスとカメラデバイスの相性によっても上記のような問題が発生する可能性があります。
なので、面倒臭いことはすべてWindowsに任せてしまえるCameraCaptureUIを使うか、Windowsストアアプリでカメラプレビュー画面を独自実装される場合は、MediaCapture側で回転させるのではなく、CaptureElementの方を回転させた方が良いかもしれません。
僕と同様にMediaCaptureを使った回転処理で意図しない表示になってしまうことがあれば、↓でコメントを頂けると幸いです。
追記 (2013/7/17)
@mntoneさんと「MacBook Proの色差情報はドライバをみないと解決できないねぇ」と話していて、自分には解析が難しいな……と棚上げになりました。
プレビューフレームのサイズがおかしくなる件に関しては、Twitterでぼやいているのを高橋さんに拾ってもらい、いくつか情報を得ることができました。以下、Twitterでのやり取り。
これのやり取りをベースに我らの高橋さんが記事を書いてくれました。
僕がまとめに書いた「CaptureElementを回転させるという解決策の後押し」アンド「Borderを使ったらいいよという具体的な解決策」を提示して頂けました。
……ということなので、縦画面かつフルスクリーンプレビューをしたい場合は、SetPreviewRotationメソッドを使わずにCaptureElement側を回転させるのが良さそうですね。