您的位置:首页 > 移动开发 > Android开发

Camera进阶,自定义拍照录像界面

2016-01-08 09:18 701 查看
Camera 官方指南,英语不太好,翻译有可能不准确,见谅 o(^▽^)o

自定义拍照,录像项目 下载地址

上一篇:初识Camera,调用系统拍照录像程序

在项目中创建一个自定义拍照录像界面的一般步骤

找到并使用摄像头

检查摄像头是否存在,并去使用它

创建一个预览类

通过继承SurfaceView类和实现SurfaceHolder接口去创建一个摄像头预览类,该类能实时的把摄像头拍摄的界面展示出来

创建一个预览布局

一旦一创建了预览类,那么你就可以创建一个布局,里面包含有该预览类和相关的操作控件

设置捕获监听器

为你的界面操作控件设置监听方法,当你操作的时(比如按一个按钮)会捕获到图片或视频。

捕获并保存文件

把你捕获到的图片或视频输出并保存起来

释放摄像头

当你使用完摄像头后,要在适当的位置释放摄像头

ps:摄像头是共有资源,你必须小心的去使用它,避免当其他程序也想去使用它的时候起冲突

警告:当你不需要使用Camera的时候,一定要通过camera.release()方法去释放Camera,如果你不去释放摄像头,那么当其他程序去请求摄像头资源时会失败,可能导致程序崩溃

检测摄像头硬件

通过使用packageManager.hasSystemFeature()方法去检测摄像头是否存在,具体代码如下

/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}


android机器可能有多个摄像头,比如一般的手机都有前置摄像头和后置摄像头。在Android2.3(API Level 9)和之后的版本中,你可以通过方法camera.getNumberOfCameras()方法去获取机器的摄像头个数。

访问摄像头

通过Camera.open()方法去访问摄像头(需要捕获异常),具体代码如下

/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}


警告:一定要捕获异常。否则当摄像头被使用或者没有摄像头时,你的程序会崩溃

当你的程序运行在Android 2.3(API Level 9)或者更高的版本上,你可以通过使用Camera.open(int)去访问指定的摄像头

检查摄像头功能

当你获取到摄像头后,你可以通过camera.getParameters()方法获取Camera.Parameters对象,进一步的获取关于摄像头使用功能的信息。

当系统版本是Android 2.3(API Level 9)或者更高时,可以使用camera.getCameraInfo()去判断使用的是那个摄像头和图片的方向

创建一个预览类

为了使用户能有效地拍照或录像,用户必须能够看到摄像头拍摄的图像。一个预览类是一个SurfaceView,它必须能够通过摄像头实时的显示图片。

下面是一段示例代码,写的是创建一个基本的摄像头预览类,包含了一个View布局。这个类实现了SurfaceHolder.Callback,回掉事件是为了捕获视图的创建和销毁,这需要分派摄像头预览输入。

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;

public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;

// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}

public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.

if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}

// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}

// set preview size and make any resize, rotate or
// reformatting changes here

// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();

} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}


如果你想设置预览界面大小,你需要在surfaceChanged()方法中设置。当你设置预览大小时,你必须通过getSupportedPreviewSizes()方法获取值,不能设置任意值,设置的方法是setPreviewSize();

布局中设置预览界面

示例代码如下,其中FrameLayout打算集合摄像头预览类

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="@+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>

<Button
android:id="@+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>


我们需要在manifest文件中设置Activity的方向去匹配摄像头的预览界面

<activity android:name=".CameraActivity"
android:label="@string/app_name"

android:screenOrientation="landscape">
<!-- configure this activity to use landscape orientation -->

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>


ps:在Android2.2(API Level 8)以后,我们可以通过setDisplayOrientation()方法去设置预览画面的旋转角度。设置地方是在surfaceChanged()方法内,设置前我们需要调用camera.stopPreview(),设置结束后需要调用camera.startPreview()

在Activity中,我们需要添加预览类到FrameLayout元素中,具体代码如下

public class CameraActivity extends Activity {

private Camera mCamera;
private CameraPreview mPreview;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// Create an instance of Camera
mCamera = getCameraInstance();//上面有方法内容

// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(id.camera_preview);
preview.addView(mPreview);
}
}


捕获图片

当你创建了一个预览类,并且去使用它,那么你就可以在你的程序里开始捕获图片了。

使用camera.takePicture()方法去检索图片。这个方法有三个参数,从摄像头获取数据。为了获取JPEG格式的数据,你必须实现Camera.PictureCallback接口去获取数据并写入文件中。下面的示例就是简单的一个实现Camera.PictureCallback接口并保存从摄像头获取的图片的例子

private PictureCallback mPicture = new PictureCallback() {

@Override
public void onPictureTaken(byte[] data, Camera camera) {

File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: " +
e.getMessage());
return;
}

try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};


通过Camera.takePicture()方法去出发捕获图片操作,代码如下

// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);


警告:当你的程序不需要使用Camera的时候,要记得通过Camera.release()方法去释放Camera资源

捕获视频

视频捕捉镜头使用Android框架需要仔细的管理对象,并配合MediaRecorder类。当你通过Camera录制视频时,你不仅需要使用Camera.open()和Camera.release(),同事还必须使用Camera.lock()和Camera.unlock()管理MediaRecorder去访问摄像头

ps:从Android 4.0(API Level 14)开始,Camera.lock()和Camera.unlocak会自动的去管理

不像照相,捕获视频需要正确的步骤。

捕获视频步骤

获取摄像头

使用Camera.open()去获取一个摄像头对象

连接预览界面

准备一个摄像头实时预览界面,通过Camera.setPreviewDisplay去链接SurfaceView

开始预览

通过Camera.startPreview()方法去预览摄像头图片

开始录制视频

a. 解锁摄像头

通过Camera.unlock()解锁摄像头去使用MediaRecorder

b. 配置MediaRecorder属性(详细属性参考MediaRecorder文档

1. setCamera()
设置摄像头
2. setAudioSource()
设置音频源,使用MediaRecorder.AudioSource.CAMCORDER
3. setVideoSource()
设置视频源,使用MediaRecorder.VideoSource.CAMERA
4. 设置视频编码和输出格式
在Android2.2(API Level 8)和更高版本上,使用CamcorderProfile.get()得到一个实例并通过MediaRecorder.setProfile方法去设置。在2.2以前的版本,你必须设置视频的输出以及编码格式。
a. setOutputFormat()
设置输出格式,指定默认或者MediaRecorder.OutputFormat.MPEG_4
b. setAudioEncoder()
设置音频编码格式,指定默认或者MediaRecorder.AudioEncoder.AMR_NB
c. setVideoEncoder()
设置视频编码格式,指定默认或者MediaRecorder.VideoEncoder.MPEG_4_SP
5. setOutputFile()
设置输出文件
6. setPreviewDisplay()
设置SurfaceView预览界面


c. 准备MediaRecorder

通过mediaRecorder.prepare()方法去根据配置准备MediaRecorder

d. 启动MediaRecorder

通过mediaRecorder.start()开始录制视频

停止视频录制

a. 停止MediaRecorder

通过mediaRecorder.stop()停止录制视频

b. 重置MediaRecorder

通过mediaRecorder.reset()移除MediaRecorder的相关设置

c. 释放MediaRecorder

通过mediaRecorder.release()方法释放MediaRecorder

d. 锁定摄像头

通过camera.lock()锁定摄像头,以便未来的MediaRecorder会话去使用它

停止预览

当Activity停止使用Camera时,通过camera.stopPreview()方法停止预览

释放Camera

通过camera.release()方法释放Camera,使其他程序能够使用它

提示:如果你的程序去录制视频,设置 setRecordingHint(true)可以优先启动你的预览界面,这个设置能够帮助减少启动录制时所花费的时间。

注意:你可以跳过之前几步去使用一个不带预览的MediaRecorder,但是不建议这样做,因为通常用户都希望能边预览边录制。

设置MediaRecorder属性

当你使用MediaRecorder录制视频的时候,你必须通过MediaRecorder.prepare()方法去检测可能的属性并去设置。

示例代码如下

private boolean prepareVideoRecorder(){

mCamera = getCameraInstance();
mMediaRecorder = new MediaRecorder();

// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);

// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

// Step 4: Set output file
mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());

// Step 5: Set the preview output
mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());

// Step 6: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}


Android 2.2 (API Level 8)版本以前,你必须设置输出格式和编码格式参数,代替CamcorderProfile.

// Step 3: Set output format and encoding (for versions prior to API Level 8)
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);  mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);


下面这些视频录制属性系统给的是默认值,你也可以在你的项目中去改变这些设置

setVideoEncodingBitRate()
setVideoSize()
setVideoFrameRate()
setAudioEncodingBitRate()
setAudioChannels()
setAudioSamplingRate()


开始和停止MediaRecorder

当你开始或停止视屏录制的时候,你需要按照下面的步骤进行

1. 使用camera.unlock()解锁Camera

2. 配置MediaRecorder相关属性

3. 使用mediaRecorder.start()开始录制

4. 录制中

5. 使用mediaRecorder.stop()停止录制

6. 使用mediaRecorder.release()释放MediaRecorder资源

7. 使用camera.lock()锁定Camear

ps:当你完成一个视频录制后,不要去释放Camera,否则你的预览会停止

代码如下:

private boolean isRecording = false;

// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isRecording) {
// stop recording and release camera
mMediaRecorder.stop();  // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
mCamera.lock();         // take camera access back from MediaRecorder

// inform the user that recording has stopped
setCaptureButtonText("Capture");
isRecording = false;
} else {
// initialize video camera
if (prepareVideoRecorder()) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();

// inform the user that recording has started
setCaptureButtonText("Stop");
isRecording = true;
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
// inform user
}
}
}
}
);


释放Camera

Camera是一个公用的资源,要及时的去释放掉。下面的代码会告诉你在什么时候释放掉Camera资源最合适

public class CameraActivity extends Activity {
private Camera mCamera;
private SurfaceView mPreview;
private MediaRecorder mMediaRecorder;

...

@Override
protected void onPause() {
super.onPause();
releaseMediaRecorder();       // if you are using MediaRecorder, release it first
releaseCamera();              // release the camera immediately on pause event
}

private void releaseMediaRecorder(){
if (mMediaRecorder != null) {
mMediaRecorder.reset();   // clear recorder configuration
mMediaRecorder.release(); // release the recorder object
mMediaRecorder = null;
mCamera.lock();           // lock camera for later use
}
}

private void releaseCamera(){
if (mCamera != null){
mCamera.release();        // release the camera for other applications
mCamera = null;
}
}
}


保存多媒体文件

当我们要保存图片或视频文件到外部存储器(SD Card)中的时候,我们要确保系统有空余空间,并且能够访问这些文件。

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)

这个方法返回的是标准的,共享的,被推荐的使用保存图片或视频的位置。这个目录是共享的(公共),所以其他应用程序可以在这个位置上很容易地发现,阅读、更改和删除文件保存。如果您的应用程序用户卸载,媒体文件保存到这个位置不会被删除。为了避免干扰用户现有的图片和视频,你应该在这个目录上为应用程序创建子目录的媒体文件。

ps:该方法适用于Android 2.2 (API Level 8) 或更高版本的,当你的机器低于这个版本,你需要使用Environment.getExternalStorageDirectory()

Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)

这个方法返回一个标准的关联你应用的位置去保存图片或视频。当你应用卸载时,保存在这个位置上的文件也会被移除。

下面的代码讲述的是当你通过Intent或者是自定义Camera APP去请求设备Camera时,如何创建一个文件或者Uri路径去保存多媒体文件

public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}

/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.

File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.

// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}

// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}

return mediaFile;
}


更多关于文件保存的内容,请看 Data Storage

Camera功能

android支持很多camera功能,比如图片格式,闪光模式,聚焦功能等等。大多相机可以通过Camera.Parameters进行访问和设置这些功能。这些功能包含在下面几种:

Metering and focus areas

Face detection

Time lapse video

更多Camera.Parameters类的介绍请参照文档

下面的表主要介绍各个API版本对应得功能

功能API Level描述
Face Detection14人脸识别,识别一张图片中的人脸,并为它们聚焦,计量和白平衡
Metering Areas14指定一个或多个区域去计量白平衡
White Balance Lock14停止或启动自动白平衡调整
Focus Areas14一张图片内设置一个或多个区域去使用焦点
Exposure Lock14停止或启动自动曝光调整
Video Snapshot14在拍摄视频时拍照(帧抓取)
Time Lapse Video11设置延迟帧录制去录制一个时间流逝视频
Multiple Cameras9支持多个摄像头,包含前置摄像头和后置摄像头
Focus Distance9聚焦点到摄像头的距离
Zoom8设置图片放大率
Exposure Compensation8增加或减少曝光度
GPS Data5图片中包含或省略地理位置信息
White Balance5设置白平衡模式,从而影响捕获的图像的颜色值
Focus Mode5设置相机的聚焦模式,自动,固定,宏观和无穷
Scene Mode5特定场景模式设置,夜晚,海滩,雪和烛光场景
JPEG Quality5JPEG图像压缩水平,增加或减少图像的输出文件质量和大小
Flash Mode5开启,关闭闪光灯,或者使用自动设置
Color Effects5捕获的图像的颜色效果,黑白色,墨色调或底色。
Anti-Banding5减少由于JPEG压缩条带的颜色渐变的影响
Picture Format1图片文件格式
Picture Size1图片的像素尺寸
ps:这些功能并不适用于所有的机器,当你用这些功能的时候要去检测这些功能是否可用

检测功能可用性

下面代码展示的是如何去获取Camera.Parameters,并检测相机是否支持自动对焦功能

// get Camera parameters
Camera.Parameters params = mCamera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
// Autofocus mode is supported
}


你可以使用上面的方法检测相机的功能, Camera.Parameters提供getSupported…(),is…Supported()和getMax…() 方法去判断这些功能是否支持。

使用Camera功能

大多数Camera功能可以通过Camera.Parameters对象去激活和控制。具体代码如下

// get Camera parameters
Camera.Parameters params = mCamera.getParameters();
// set the focus mode
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// set Camera parameters
mCamera.setParameters(params);


注意:一些相机的特性是无法改变的。特别是当你需要改变预览大小和方向的时候,你需要先停止预览,然后再改变,最后开启预览。Android 4.0(API Level 14)以后改变预览方向不用重启预览

下面的这些相机功能需要更多的代码区实现

Metering and focus areas

Face detection

Time lapse video

Metering and focus areas

在一些摄影场景,自动聚焦和浅计量不能产生预期的结果。从Android 4.0(API Level 14)开始,你的相机应用程序可以提供额外的控制,允许你的应用程序或用户指定区域的图像用于确定焦点或光级设置,并将这些值传递给相机硬件用于捕获图像或视频。

具体代码如下

// Create an instance of Camera
mCamera = getCameraInstance();

// set Camera parameters
Camera.Parameters params = mCamera.getParameters();

if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported
List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();

Rect areaRect1 = new Rect(-100, -100, 100, 100);    // specify an area in center of image
meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60%
Rect areaRect2 = new Rect(800, -1000, 1000, -800);  // specify an area in upper right of image
meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40%
params.setMeteringAreas(meteringAreas);
}

mCamera.setParameters(params);


Camera.Area包含两个属性,Rect代表相机界面的区域,weight比重。

Rect在一个Camera.Area 对象中描述了一个矩形映射在2000 x 2000单元的网格。坐标-1000、-1000代表上角,并1000,1000代表右下角



ps:这个坐标系统的界限总是对应于图像的外边缘可见的相机预览,不随图像缩放。同样,使用Camera.setDisplayOrientation()旋转图片的预览不会重新映射坐标系统。

Face detection

人脸识别技术,Android 4.0(API级别14)框架提供了API识别人脸和计算图片设置使用面部识别技术。

ps:人脸检测功能运行时,setWhiteBalance(String),setFocusAreas(List)andsetMeteringAreas(List)不会受到影响

使用人脸识别功能呢的一般步骤如下

1. 检测相机是否支持人脸识别功能

2. 创建一个人脸识别监听器

3. 添加人脸识别监听器到Camera对象上

4. 预览后启动人脸识别功能

不是所有的设备都支持人脸识别功能,你需要通过getMaxNumDetectedFaces()去检查是否支持该功能

具体事例如下:

Camera.FaceDetectionListener监听器

class MyFaceDetectionListener implements Camera.FaceDetectionListener {

@Override
public void onFaceDetection(Face[] faces, Camera camera) {
if (faces.length > 0){
Log.d("FaceDetection", "face detected: "+ faces.length +
" Face 1 Location X: " + faces[0].rect.centerX() +
"Y: " + faces[0].rect.centerY() );
}
}
}


Camera设置人脸识别监听

mCamera.setFaceDetectionListener(new MyFaceDetectionListener());


启动人脸识别功能

public void startFaceDetection(){
// Try starting Face Detection
Camera.Parameters params = mCamera.getParameters();

// start face detection only *after* preview has started
if (params.getMaxNumDetectedFaces() > 0){
// camera supports face detection, so can start it:
mCamera.startFaceDetection();
}
}


你需要在启动camera预览后再启动人脸识别功能,同时这些功能都需要卸载surfaceChange()方法内

public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();

startFaceDetection(); // start face detection feature

} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

if (mHolder.getSurface() == null){
// preview surface does not exist
Log.d(TAG, "mHolder.getSurface() == null");
return;
}

try {
mCamera.stopPreview();

} catch (Exception e){
// ignore: tried to stop a non-existent preview
Log.d(TAG, "Error stopping camera preview: " + e.getMessage());
}

try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();

startFaceDetection(); // re-start face detection feature

} catch (Exception e){
// ignore: tried to stop a non-existent preview
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}


ps:一定要在startPreview()后启动人脸识别功能

Time lapse video

时间流逝视频允许用户结合几秒钟或几分钟的部分创建一个视频剪辑,该特性使用MediaRecorder记录时间流逝的图像序列。

记录时间流逝视频,你必须配置记录器对象记录正常视频,设置帧每秒捕获到一个低数量和使用时间流逝的质量设置

示例代码

// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));
...
// Step 5.5: Set the video capture rate to a low number
mMediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds


终于写完了,语言不流畅的部分敬请见谅,有些东西我也是模糊的,后续会附加上自己写的demo。o(^▽^)o
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android camera media video