我已经循环了5天试图用FFmpegRecorder实现JavaCV,已经发现我必须使用OpenCvFrameConverter将IplImage连接到框架,我终于设法在流上看到一些视频。但现在问题似乎是音频工作完美而且清晰,但视频显示不正确。
除此之外,当我认为RTMP延迟2-4秒时,流上有大量延迟,超过40秒,
以下是一些代码:
FFmpegFrameRecorder初始化
recorder = new FFmpegFrameRecorder(ffmpeg_link, screenWidth, screenHeight, 1);
recorder.setFormat("flv");
recorder.setSampleRate(44100);
recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_FLV1);// AV_CODEC_ID_FLV1
recorder.setVideoOption("preset", "ultrafast");
recorder.setFrameRate(30);
这是我的SurfaceChanged和PreviewFrame方法
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters camParams = mCamera.getParameters();
List<Camera.Size> sizes = camParams.getSupportedPreviewSizes();
android.hardware.Camera.Size z = getOptimalPreviewSize(sizes, screenWidth, screenHeight);
int imageWidth = z.width;
int imageHeight = z.height;
camParams.setPreviewSize(imageWidth, imageHeight);
mCamera.setParameters(camParams);
for(int[] arr : camParams.getSupportedPreviewFpsRange()){
Log.e(LOG_TAG, "Supported range: " + arr[0] + " - " + arr[1]);
}
Camera.Parameters framerateAttempts = mCamera.getParameters();
camParams.setPreviewFrameRate(frameRate);
Log.v(LOG_TAG,"Preview Framerate: " + camParams.getPreviewFrameRate());
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
mCamera.setDisplayOrientation(90);
}
if(display.getRotation() == Surface.ROTATION_90)
{
}
if(display.getRotation() == Surface.ROTATION_180)
{
}
if(display.getRotation() == Surface.ROTATION_270)
{
mCamera.setDisplayOrientation(180);
}
camParams.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
mCamera.setParameters(framerateAttempts);
startPreview();
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
/* get video data */
if (yuvIplimage != null && recording) {
yuvIplimage.getByteBuffer().put(data);
Log.v(LOG_TAG,"Writing Frame");
try {
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
OpenCVFrameConverter.ToIplImage converterToMat = new OpenCVFrameConverter.ToIplImage();
Frame f = converterToMat.convert(yuvIplimage);
recorder.record(f);
} catch (FFmpegFrameRecorder.Exception e) {
Log.v(LOG_TAG,e.getMessage());
e.printStackTrace();
}
}
}