以下是从相机前置摄像头和后置摄像头录制视频的完整代码。
我需要将重新编码的视频的帧速率设置为30 fps 。这是我尝试了很多事情的重大问题,但没有什么对我有用。这是大约2周,我陷入了这个问题,这是非常紧急。
我在 Samsung Tablet GT-P1000上运行此应用程序,固件版本为2.3.3 GingerBread
代码工作得非常好,它正在录制视频。
主要问题在于代码 mrec.setVideoFrameRate(30);
。
这不应该像它应该的那样工作。帧速率在每个输出文件中都有所不同,有时是10,15或25等。
我需要30 fps的稳定帧速率,就像原生Android相机应用
代码:
package com.cameraApp.www;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
public class StartCamera extends Activity implements Callback, Runnable {
public ProgressDialog progressDialog;
public ProgressDialog progressDialogSave;
public SurfaceHolder surfaceHolder;
public SurfaceView surfaceView;
public Button startRecording = null;
public String SdCardPath = Environment.getExternalStorageDirectory().getPath();
public final static String Directory = "/cameraDirectory";
public static SimpleDateFormat sdf = null;
public static String currentDateandTime = null;
public static String RecordFileName = null;
public String FullFilePath = null;
public Camera mCamera;
boolean recording;
public MediaRecorder mrec = null;
public String cameraTypeString;
public int cameraType;
File video;
ImageView startVideo;
ImageView switchSurface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().getAttributes().windowAnimations = R.style.Fade;
Intent intent = getIntent();
cameraTypeString = intent.getStringExtra("cameraType");
sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
currentDateandTime = sdf.format(new Date());
RecordFileName = "/" + currentDateandTime + ".mp4";
FullFilePath = null;
mrec = new MediaRecorder();
recording = false;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.screenBrightness = 100 / 100.0f;
getWindow().setAttributes(lp);
if(mrec!=null){
mrec.reset();
}
setContentView(R.layout.activity_camera);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
initCameraBack();
startVideo = (ImageView) findViewById(R.id.RecordStart_View);
switchSurface = (ImageView) findViewById(R.id.SwitchCam_View);
}
public void doClick(View view) {
switch (view.getId()) {
case R.id.RecordStart_View:
startORstopRecording();
break;
case R.id.SwitchCam_View:
startFrontCamera();
break;
default:
break;
}
}
@SuppressWarnings("deprecation")
public void initCameraBack() {
surfaceView = (SurfaceView) findViewById(R.id.BackCameraVideoView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void startFrontCamera() {
progressDialog = ProgressDialog.show(StartCamera.this, "In progress","Changing Camera...");
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
run();
}
public void startORstopRecording() {
if (recording) {
try {
progressDialogSave = ProgressDialog.show(StartCamera.this,"In progress", "Saving Video...");
mrec.stop();
} catch (Exception e) {
Log.i("StopRecordingError", e.toString());
}
} else {
try {
startRecording();
recording = true;
switchSurface.setEnabled(false);
switchSurface.setVisibility(View.INVISIBLE);
startVideo.setImageResource(R.drawable.record_stop);
} catch (Exception e) {
Log.i("StartRecordingError", e.toString());
}
}
}
@TargetApi(11)
public void startRecording() {
try{
mCamera.unlock();
}
catch (Exception e){
e.printStackTrace();
}
mrec.setCamera(mCamera);
mrec.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mrec.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mrec.setVideoSize(640, 480);
mrec.setVideoEncodingBitRate(3000000);
mrec.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// MPEG_4_SP
mrec.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
File dir = new File(SdCardPath + Directory);
if (!dir.exists()) {
if (dir.mkdir()) {
Log.v(STORAGE_SERVICE, "Created directory");
} else {
Log.v(STORAGE_SERVICE, "Failed to create Directory");
}
}
FullFilePath = SdCardPath + Directory + RecordFileName;
mrec.setOutputFile(FullFilePath);
mrec.setVideoFrameRate(30);
mrec.setPreviewDisplay(surfaceHolder.getSurface());
try {
mrec.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mrec.start();
}
@TargetApi(9)
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
try {
Parameters p = mCamera.getParameters();
if (p != null) {
p.setPreviewSize(640, 480);
mCamera.setParameters(p);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
} catch (IOException e) {
e.printStackTrace();
}
}
@TargetApi(9)
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (cameraTypeString.equals("back")) // For SDK version 9 and above
{
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
int cameraCount = Camera.getNumberOfCameras();
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
try {
cameraType = camIdx;
} catch (RuntimeException e) {
Toast.makeText(getApplicationContext(),
"CameraStart not available!", Toast.LENGTH_LONG)
.show();
}
}
}
mCamera = Camera.open(cameraType);
} else if (cameraTypeString.equals("front")) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
int cameraCount = Camera.getNumberOfCameras();
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
try {
cameraType = camIdx;
} catch (RuntimeException e) {
Toast.makeText(getApplicationContext(),
"CameraStart not available!", Toast.LENGTH_LONG)
.show();
}
}
}
mCamera = Camera.open(cameraType);
}
else { // For SDK 8 or below
Intent WelcomeScreen = new Intent();
WelcomeScreen.setClass(getBaseContext(), WelcomeScreen.class);
startActivity(WelcomeScreen);
Toast.makeText(getBaseContext(),
"Application doesn't support firmware less than 2.3",
Toast.LENGTH_LONG).show();
}
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
;
mCamera.startPreview();
Parameters p = mCamera.getParameters();
p.setPreviewSize(640, 480);
mCamera.setParameters(p);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
try {
if (mCamera != null) {
try {
mCamera.stopPreview();
} catch (Exception ignore) {
Log.i("SurfaceDestroyedCameraPreview", ignore.getMessage());
}
try {
mCamera.release();
} catch (Exception ignore) {
Log.i("SurfaceDestroyedCameraReleased", ignore.getMessage());
}
mCamera = null;
}
} catch (Exception ex) {
Log.i("SurfaceDestroyed", ex.getMessage());
ex.printStackTrace();
}
}
@Override
protected void onPause() {
try {
if (null != mCamera) {
if (recording == true) {
mrec.stop();
}
mCamera.stopPreview();
mCamera.release();
mCamera = null;
android.os.Process.killProcess(android.os.Process.myPid());
}
} catch (Exception e) {
Log.i("OnPause", e.getMessage());
}
super.onPause();
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (recording == true) {
mrec.stop();
}
mCamera.stopPreview();
mCamera.release();
mCamera = null;
Intent home = new Intent();
home.setClass(getBaseContext(), WelcomeScreen.class);
startActivity(home);
StartCamera.this.finish();
return false;
}
return super.onKeyDown(keyCode, event);
}
@Override
public void run() {
String value;
if (cameraTypeString.equals("back")) {
value = "front";
} else {
value = "back";
}
Intent switchCamera = new Intent();
switchCamera.setClass(getBaseContext(), StartCamera.class);
switchCamera.putExtra("cameraType", value);
startActivity(switchCamera);
StartCamera.this.finish();
}
}