安卓端获取摄像头原始数据
package com.example.previewcamera;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import com.example.camera.R;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
@SuppressWarnings("deprecation")
public class CameraPreviewActivity extends Activity implements Camera.PreviewCallback{
private Camera mCamera;
private SurfaceView surface_cam;
private SurfaceHolder mSurfaceHolder;
private boolean is_writed;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preview);
is_writed = false;
surface_cam = (SurfaceView) findViewById(R.id.surface_cam);
initSurfaceView();
}
private Camera getCamera() {
Camera camera = null;
int cameraId = 0; // or 1 // findCamera(false);
try {
if (cameraId == 1) {
camera = Camera.open(cameraId);
} else if (cameraId == 0) {
camera = Camera.open(0);
}
} catch (Exception e) {
camera = null;
}
Camera.Parameters parameters = camera.getParameters();
int width = 640;
int height = 480;
parameters.setPreviewSize(width, height);
parameters.setPictureSize(width, height);
// android.graphics.ImageFormat.NV21 默认格式
// parameters.setPreviewFormat(android.graphics.ImageFormat.NV21);
camera.setParameters(parameters);
int pre_format;
parameters = camera.getParameters();
pre_format = parameters.getPreviewFormat();
Log.i("Camera", "[getCamera]" + pre_format); // 17
if(android.graphics.ImageFormat.NV21 == pre_format) {
Log.i("Camera", "[getCamera]NV21");
}
Log.i("Camera", "[getCamera]NV21:" + android.graphics.ImageFormat.NV21);
Log.i("Camera", "[getCamera]YUY2:" + android.graphics.ImageFormat.YUY2);
Log.i("Camera", "[getCamera]NV16:" + android.graphics.ImageFormat.NV16);
Log.i("Camera", "[getCamera]JPEG:" + android.graphics.ImageFormat.JPEG);
return camera;
}
private void initSurfaceView() {
mSurfaceHolder = surface_cam.getHolder();
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
mCamera = getCamera();
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
try {
// mCamera, mSurfaceHolder
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.setPreviewCallback(CameraPreviewActivity.this);
mCamera.startPreview();
} catch (IOException e) {
}
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();// 停掉摄像头的预览
mCamera.release();
mCamera = null;
}
}
});
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// 460800 = 640x480x3/2 出来的是 nv21
Log.v("JAVA", "yuv : " + data.length);
if(false == is_writed) {
is_writed = true;
try {
FileOutputStream out;
out = new FileOutputStream("/storage/sdcard/java_nv21.yuv");
out.write(data, 0, data.length);
out.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
布局增加显示控件
<SurfaceView
android:id="@+id/surface_cam"
android:layout_width="640dp"
android:layout_height="480dp"
/>
对应权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
输出 YUV 格式分析
出来的摄像头数据这里保持的系统默认配置 ImageFormat.NV21.
这里保持着 2 个 Y , 1 个 U,1 个 V 的比例。
Y个数 640x480, U个数 640x480/4, V个数 640x480/4.
即 U 和 V 的个数加起来, 刚好为 Y 总数的一半.
格式如下
Y | Y | Y | Y | Y | Y | Y | Y |
Y | Y | Y | Y | Y | Y | Y | Y |
V | U | V | U | V | U | V | U |