Ho modificato il metodo di questa onPreviewFrame Open Source Android Touch-To-Record library prendere recepire e ridimensionare un frame catturato.
Ho definito "yuvIplImage" come segue nel mio metodo setCameraParams().
IplImage yuvIplImage = IplImage.create(mPreviewSize.height, mPreviewSize.width, opencv_core.IPL_DEPTH_8U, 2);
Questo è il mio metodo 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);
}
}
Questo codice utilizza un metodo "YUV_NV21_TO_BGR", che ho trovato da questo link
Fondamentalmente questo metodo viene utilizzato per risolvere, che Chiamo come, "Il problema del Green Devil su Android". Puoi vedere altri sviluppatori Android che affrontano lo stesso problema su altri thread SO. Prima di aggiungere il metodo "YUV_NV21_TO_BGR" quando ho appena preso la trasposizione di YuvIplImage, ancora più importante una combinazione di trasposizione, flip (con o senza ridimensionamento), c'era un output verdastro nel video risultante. Questo metodo "YUV_NV21_TO_BGR" ha salvato il giorno. Grazie a @David Han dall'alto thread dei gruppi di google.
Inoltre, dovresti sapere che tutta questa elaborazione (trasporre, capovolgere e ridimensionare), in onPreviewFrame, richiede molto tempo e ti fa perdere molto tempo nella frequenza dei fotogrammi al secondo (FPS). Quando ho usato questo codice, all'interno del metodo onPreviewFrame, l'FPS risultante del video registrato era sceso a 3 fotogrammi/sec da 30 fps.
Vorrei consigliare di non utilizzare questo approccio. Piuttosto si può andare per l'elaborazione post-registrazione (trasporre, capovolgere e ridimensionare) del file video utilizzando JavaCV in un AsyncTask. Spero che questo ti aiuti.
ridurre la risoluzione – cxphong