このオープン ソースの Android Touch-To-Record ライブラリの onPreviewFrame メソッドを変更して、キャプチャしたフレームの転置とサイズ変更を行いました。
setCameraParams() メソッドで次のように「yuvIplImage」を定義しました。
IplImage yuvIplImage = IplImage.create(mPreviewSize.height, mPreviewSize.width, opencv_core.IPL_DEPTH_8U, 2);
これは私の onPreviewFrame() メソッドです:
@Override
public void onPreviewFrame(byte[] data, Camera camera)
{
long frameTimeStamp = 0L;
if(FragmentCamera.mAudioTimestamp == 0L && FragmentCamera.firstTime > 0L)
{
frameTimeStamp = 1000L * (System.currentTimeMillis() - FragmentCamera.firstTime);
}
else if(FragmentCamera.mLastAudioTimestamp == FragmentCamera.mAudioTimestamp)
{
frameTimeStamp = FragmentCamera.mAudioTimestamp + FragmentCamera.frameTime;
}
else
{
long l2 = (System.nanoTime() - FragmentCamera.mAudioTimeRecorded) / 1000L;
frameTimeStamp = l2 + FragmentCamera.mAudioTimestamp;
FragmentCamera.mLastAudioTimestamp = FragmentCamera.mAudioTimestamp;
}
synchronized(FragmentCamera.mVideoRecordLock)
{
if(FragmentCamera.recording && FragmentCamera.rec && lastSavedframe != null && lastSavedframe.getFrameBytesData() != null && yuvIplImage != null)
{
FragmentCamera.mVideoTimestamp += FragmentCamera.frameTime;
if(lastSavedframe.getTimeStamp() > FragmentCamera.mVideoTimestamp)
{
FragmentCamera.mVideoTimestamp = lastSavedframe.getTimeStamp();
}
try
{
yuvIplImage.getByteBuffer().put(lastSavedframe.getFrameBytesData());
IplImage bgrImage = IplImage.create(mPreviewSize.width, mPreviewSize.height, opencv_core.IPL_DEPTH_8U, 4);// In my case, mPreviewSize.width = 1280 and mPreviewSize.height = 720
IplImage transposed = IplImage.create(mPreviewSize.height, mPreviewSize.width, yuvIplImage.depth(), 4);
IplImage squared = IplImage.create(mPreviewSize.height, mPreviewSize.height, yuvIplImage.depth(), 4);
int[] _temp = new int[mPreviewSize.width * mPreviewSize.height];
Util.YUV_NV21_TO_BGR(_temp, data, mPreviewSize.width, mPreviewSize.height);
bgrImage.getIntBuffer().put(_temp);
opencv_core.cvTranspose(bgrImage, transposed);
opencv_core.cvFlip(transposed, transposed, 1);
opencv_core.cvSetImageROI(transposed, opencv_core.cvRect(0, 0, mPreviewSize.height, mPreviewSize.height));
opencv_core.cvCopy(transposed, squared, null);
opencv_core.cvResetImageROI(transposed);
videoRecorder.setTimestamp(lastSavedframe.getTimeStamp());
videoRecorder.record(squared);
}
catch(com.googlecode.javacv.FrameRecorder.Exception e)
{
e.printStackTrace();
}
}
lastSavedframe = new SavedFrames(data, frameTimeStamp);
}
}
このコードは、このリンクから見つけたメソッド「YUV_NV21_TO_BGR」を使用しています
基本的にこの方法は、私が「Android の緑の悪魔の問題」と呼んでいる解決に使用されます。他の SO スレッドで同じ問題に直面している他の Android 開発者を見ることができます。「YUV_NV21_TO_BGR」メソッドを追加する前に、YuvIplImage の転置、さらに重要なことに、転置、反転 (サイズ変更の有無にかかわらず) の組み合わせを行ったときに、結果のビデオに緑がかった出力がありました。この「YUV_NV21_TO_BGR」メソッドは、その日を救いました。上記の Google グループ スレッドの @David Han に感謝します。
また、onPreviewFrame でのこのすべての処理 (転置、反転、およびサイズ変更) には多くの時間がかかり、フレーム/秒 (FPS) レートに非常に深刻な影響を与えることも知っておく必要があります。このコードを onPreviewFrame メソッド内で使用すると、記録されたビデオの FPS は 30fps から 3 フレーム/秒に低下しました。
このアプローチは使用しないことをお勧めします。代わりに、AsyncTask で JavaCV を使用して、ビデオ ファイルのレコーディング後の処理 (転置、反転、およびサイズ変更) を行うことができます。お役に立てれば。