って今更Nexus7って話でも無いやろってのは置いといて^^;
GitHubで公開している内蔵カメラの映像と内蔵マイクからの音声をMediaCodecを使ってMP4動画ファイルとして出力するサンプルAudioVideoRecordingSampleにNexus7でのアスペクト比不具合のworkaroundを追加して更新しました。
ついでにAndroidStudioのプロジェクトにしてしまったので一見大改造にも見えますが大した違いはありません。
Nexus7でのカメラプレビューのアスペクト比不具合
これについては以前の記事にいっぱい書いたので詳しくはこちらをどうぞ。
で原因は今もって理解不能ですが、Camera.Parameters#setPictureSizeを使って静止画用のサイズを設定すれば回避できるようです。
と言っても自分で見つけたわけではありません(^^)v。自慢することではないけどWebRTCのソースを眺めてて気がついただけです。これはきっと中の人のしわざっぽいな。
今回の修正では次のようなコードを追加しました。
1 2 3 |
// 指定したサイズ(width,height)に最も近い静止画撮影用映像サイズを選択する final Camera.Size pictureSize = getClosestSupportedSize(params.getSupportedPictureSizes(), width, height); params.setPictureSize(pictureSize.width, pictureSize.height); |
これだけであんなに苦労したNexus7(2013)のアスペクト比の不具合が解消するなんてぇ〜\(^o^)/
ついでに指定したサイズにもっとも近い映像サイズ選択のコードも追加しています。
何も考えずにコードを書くとCamera.Parameters#.getSupportedPreviewSizes()を使ってサポートする映像サイズを取得してループして欲しいサイズに最も近いのを選ぶって事になると思いますが、JavaのComparatorというインターフェースを使うと自前でループさせずにスッキリ?とかけます。
例えば次のようなメソッドを作ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
private static Camera.Size getClosestSupportedSize(final List<Camera.Size> supportedSizes, final int requestedWidth, final int requestedHeight) { return (Camera.Size)Collections.min(supportedSizes, new Comparator<Camera.Size>() { private int diff(final Camera.Size size) { return Math.abs(requestedWidth - size.width) + Math.abs(requestedHeight - size.height); } @Override public int compare(final Camera.Size lhs, final Camera.Size rhs) { return diff(lhs) - diff(rhs); } }); } |
後は次のように呼び出せば桶^^
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
... Camera mCamera = Camera.open(CAMERA_ID); ... final Camera.Parameters params = mCamera.getParameters(); ... // 指定したサイズ(width,height)に最も近いプレビュー用映像サイズを選択する final Camera.Size closestSize = getClosestSupportedSize(params.getSupportedPreviewSizes(), width, height); params.setPreviewSize(closestSize.width, closestSize.height); // 指定したサイズ(width,height)に最も近い静止画撮影用映像サイズを選択する final Camera.Size pictureSize = getClosestSupportedSize(params.getSupportedPictureSizes(), width, height); params.setPictureSize(pictureSize.width, pictureSize.height); ... // 実際のプレビュー映像サイズを確認する final Camera.Size previewSize = mCamera.getParameters().getPreviewSize(); Log.i(TAG, String.format("previewSize(%d, %d)", previewSize.width, previewSize.height)); ... final SurfaceTexture st = {プレビュー表示用のSurfaceTextureの取得メソッド} st.setDefaultBufferSize(previewSize.width, previewSize.height); mCamera.setPreviewTexture(st); |
今回は単純に映像サイズの縦横の差の絶対値の和を基準に選択するようになっていますが、アスペクト比が同じなものを優先するようにしたりとか色々応用は可能だと思います。
ちなみにこのComparator、普通はListをソートしたりする時に使いますがこんなこともできるんですねぇ^^
放ったらかしにしてる続き物の記事がまだ他にいくつもあるにもかかわらずしょうもないのを書いてしまったm(_ _)m
ということで今回はおしまい。お疲れ様でした。