2011年2月3日木曜日

AndroidのonPreviewFrame()に渡されるformatが仕様と違う件

 Camera.PreviewCallback#onPreviewFrame(byte[] data, Camera camera)に渡されるデータは、デフォルトでYCbCr_420_SP (NV21)であるとReferenceに書いてある。検索してみると、この前提で書かれているサンプルもたくさんある。
  http://developer.android.com/reference/android/hardware/Camera.PreviewCallback.html

 しかし、SDKをここ数日使ってみたところ、どうも違うっぽい。実際にはYUV422SP(NV16)が来ている。Camera.Parameters#getPreviewFormat()は0x10(NV16)を返すし、data.lengthはY planeの2倍のサイズだし、NV16である前提でRGBに変換してみると、一応まともな画になる。逆に、NV21のつもりで変換すると、色がズレズレになってしまう。Issue 823のコメント22↓がまさにソレ。
  http://code.google.com/p/android/issues/detail?id=823#c22

 実機のカメラがLSIの都合でYUV422SPになるのはあり得るけど、エミュレータがこれではイカンですね。仕様が間違いなのか、実装が間違いなのか。RGB_565を指定してもまともに動かない、getSupportedPreviewFormats()を呼ぶとアプリが死ぬ等、PreviewFormatまわりは相当にひどい出来。まともにテストしてないね。