我正在构建一个简单的录音机应用程序。我想在开始录制时动态调整SurfaceView的大小。例如,当用户在设置活动中预先将视频分辨率设置为4:3比例并单击“开始录制”按钮时,我希望SurfaceView将其宽度和高度更改为4:3比例。因此,当按下录制按钮时,SurfaceView会更改其大小。
当应用程序没有录制任何内容时,我可以调整SurfaceView的大小,但是当我尝试在视频录制开始之前更改它时,它会调整视图的大小但是录制没有正确完成(当我完成录制时会抛出stopFailed错误。)< / p>
我希望我的应用程序调整SurfaceView的大小并立即开始录制。在用户按下录制按钮之前!
这是我的代码。
MainActivity.java
private boolean prepRecorder() {
mRecorder = new MediaRecorder();
CamcorderProfile profile = getCurrentProfile();
Camera.Parameters parameters = mCamera.getParameters();
parameters = setContinuesFocusMode(parameters);
Camera.Size desiredSize = null, optimalPreviewSize = null;
if (mVideoSizeIndex != -1) {
List<Camera.Size> supportedVidSizes = parameters.getSupportedVideoSizes();
if (mVideoSizeIndex < supportedVidSizes.size()) {
desiredSize = supportedVidSizes.get(mVideoSizeIndex);
optimalPreviewSize = mSurface.getOptimalPreviewSize(
parameters.getSupportedPreviewSizes(), desiredSize.width, desiredSize.height);
Point screenSize = getScreenSize();
mSurface.resizePreview(optimalPreviewSize.width, optimalPreviewSize.height, screenSize.x, screenSize.y);
parameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
}
} else {
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
}
mCamera.setParameters(parameters);
mCamera.unlock();
mRecorder.setCamera(mCamera);
mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setProfile(profile);
mRecorder.setPreviewDisplay(mSurface.getHolder().getSurface());
mVideoPath = getMediaPath();
if (mVideoPath != null) {
mRecorder.setOutputFile(mVideoPath);
} else {
return false;
}
if (desiredSize != null) {
mRecorder.setVideoSize(desiredSize.width, desiredSize.height);
} else {
mRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
}
// Orientation adjustment stuff.....
mTrackerThread = new VideoFileTrackerThread(new Handler(), this, mVideoPath);
mTrackerThread.start();
mTrackerThread.prepareHandler();
mTrackerThread.triggerHandler();
try {
mRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
VideoSurfaceView.java
public void resizePreview(int desiredWidth, int desiredHeight, int screenWidth, int screenHeight) {
float videoProportion = (float) desiredWidth / (float) desiredHeight;
float screenProportion = (float) screenWidth / screenHeight;
ViewGroup.LayoutParams lp = this.getLayoutParams();
if (videoProportion > screenProportion) {
lp.width = screenWidth;
lp.height = (int) ((float) screenWidth / videoProportion);
} else {
lp.width = (int) (videoProportion * (float) screenHeight);
lp.height = screenHeight;
}
this.setLayoutParams(lp);
}
public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.2;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
if (size.width == w && size.height == h) {
optimalSize = size;
return optimalSize;
}
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
当我在应用未录制时运行resizePreview()
方法时,它会完美地改变视图;但是当我按下录制按钮时运行它时,会暂停UI一段时间,并且视频输出无法正确保存。主线程是否可能过载?
提前致谢。
答案 0 :(得分:1)
我解决了。这是因为在调整视图大小时调用了onSurfaceChanged()
方法。我删除了mCamera.stopPreview(),mCamera.setPreviewDisplay()和mCamera.startPreview(),现在它工作正常。