package cn.jiguang.imui.chatinput.camera;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.media.MediaRecorder;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.TextureView;
import android.widget.RelativeLayout;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import cn.jiguang.imui.chatinput.listener.OnCameraCallbackListener;
@SuppressWarnings("deprecation")
public class CameraOld implements CameraSupport {
private final static String TAG = "CameraOld";
private Camera mCamera;
private TextureView mTextureView;
private File mPhoto;
private Context mContext;
private OnCameraCallbackListener mCameraCallbackListener;
private MediaRecorder mMediaRecorder;
private String mNextVideoAbsolutePath;
private int mCameraId;
private Size mPreviewSize;
private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90;
private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270;
private static SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 0);
ORIENTATIONS.append(Surface.ROTATION_90, 90);
ORIENTATIONS.append(Surface.ROTATION_180, 180);
ORIENTATIONS.append(Surface.ROTATION_270, 270);
}
private boolean mIsFacingBack = true;
public CameraOld(Context context, TextureView textureView) {
this.mContext = context;
this.mTextureView = textureView;
}
@Override
public CameraSupport open(int cameraId, int width, int height, boolean isFacingBack) {
this.mCameraId = cameraId;
this.mCamera = Camera.open(cameraId);
mIsFacingBack = isFacingBack;
Camera.Parameters params = mCamera.getParameters();
/*获取摄像头支持的PictureSize列表*/
List<Size> pictureSizeList = params.getSupportedPictureSizes();
/*从列表中选取合适的分辨率*/
mPreviewSize = getProperSize(pictureSizeList, ((float) width) / height);
if (null != mPreviewSize) {
params.setPictureSize(mPreviewSize.width, mPreviewSize.height);
} else {
mPreviewSize = params.getPictureSize();
}
/*获取摄像头支持的PreviewSize列表*/
List<Size> previewSizeList = params.getSupportedPreviewSizes();
Size preSize = getProperSize(previewSizeList, ((float) width) / height);
if (null != preSize) {
Log.v("CameraOld", preSize.width + "," + preSize.height);
params.setPreviewSize(preSize.width, preSize.height);
}
/*根据选出的PictureSize重新设置SurfaceView大小*/
float w = mPreviewSize.width;
float h = mPreviewSize.height;
mTextureView.setLayoutParams(new RelativeLayout.LayoutParams((int) (height * (w / h)), height));
params.setJpegQuality(100); // 设置照片质量
if (params.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
mCamera.cancelAutoFocus();//只有加上了这一句,才会自动对焦。
params.setPictureFormat(ImageFormat.JPEG);
mCamera.setParameters(params);
try {
mCamera.setPreviewTexture(mTextureView.getSurfaceTexture());
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
return this;
}
@Override
public int getOrientation(int cameraId) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
return info.orientation;
}
@Override
public void release() {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.lock();
mCamera.release();
mCamera = null;
releaseMediaRecorder();
}
@Override
public void setOutputFile(File file) {
this.mPhoto = file;
}
@Override
public void takePicture() {
mCamera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] bytes, Camera camera) {
try {
OutputStream outputStream = new FileOutputStream(mPhoto);
// 前置摄像头水平翻转照片
if (!mIsFacingBack) {
Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
int w = bmp.getWidth();
int h = bmp.getHeight();
Matrix matrix = new Matrix();
matrix.postScale(-1, 1);
Bitmap convertBmp = Bitmap.createBitmap(bmp, 0, 0, w, h, matrix, true);
convertBmp.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
} else {
outputStream.write(bytes);
}
outputStream.close();
if (mCameraCallbackListener != null) {
mCameraCallbackListener.onTakePictureCompleted(mPhoto.getAbsolutePath());
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
@Override
public void setCameraCallbackListener(OnCameraCallbackListener listener) {
mCameraCallbackListener = listener;
}
public static Size getProperSize(List<Size> sizeList, float displayRatio) {
//先对传进来的size列表进行排序
Collections.sort(sizeList, new SizeComparator());
Size result = null;
for (Size size : sizeList) {
float curRatio = ((float) size.width) / size.height;
if (curRatio - displayRatio == 0) {
result = size;
}
}
if (null == result) {
for (Size size : sizeList) {
float curRatio = ((float) size.width) / size.height;
if (curRatio == 3f / 4) {
result = size;
}
}
}
return result;
}
private static class SizeComparator implements Comparator<Camera.Size> {
@Override
public int compare(Size lhs, Size rhs) {
// TODO Auto-generated method stub
if (lhs.width < rhs.width
|| lhs.width == rhs.width && lhs.height < rhs.height) {
return -1;
} else if (!(lhs.width == rhs.width && lhs.height == rhs.height)) {
return 1;
}
return 0;
}
}
public void setUpMediaRecorder() {
if (null == mContext) {
return;
}
Activity activity = (Activity) mContext;
mMediaRecorder = new MediaRecorder();
mCamera.stopPreview();
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mNextVideoAbsolutePath = getVideoFilePath(activity);
mMediaRecorder.setOutputFile(mNextVideoAbsolutePath);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoEncodingBitRate(10000000);
mMediaRecorder.setVideoSize(mPreviewSize.width, mPreviewSize.height);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
switch (getOrientation(mCameraId)) {
case SENSOR_ORIENTATION_DEFAULT_DEGREES:
mMediaRecorder.setOrientationHint(ORIENTATIONS.get(rotation));
break;
case SENSOR_ORIENTATION_INVERSE_DEGREES:
mMediaRecorder.setOrientationHint(rotation);
break;
}
try {
mMediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
private String getVideoFilePath(Context context) {
String fileDir = context.getFilesDir().getAbsolutePath() + "/video";
File destDir = new File(fileDir);
if (!destDir.exists()) {
destDir.mkdirs();
}
return destDir.getAbsolutePath() + "/" + System.currentTimeMillis() + ".mp4";
}
@Override
public void startRecordingVideo() {
try {
setUpMediaRecorder();
mMediaRecorder.start();
} catch (RuntimeException e) {
e.printStackTrace();
Log.e(TAG, "MediaRecorder start error");
releaseMediaRecorder();
}
}
private void releaseMediaRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.release();
mMediaRecorder = null;
}
}
@Override
public void cancelRecordingVideo() {
mMediaRecorder.stop();
mMediaRecorder.reset();
mCamera.startPreview();
if (mNextVideoAbsolutePath != null) {
File file = new File(mNextVideoAbsolutePath);
if (file.exists() && file.isFile()) {
file.delete();
}
}
}
@Override
public String finishRecordingVideo() {
mMediaRecorder.stop();
mMediaRecorder.reset();
if (mCameraCallbackListener != null) {
mCameraCallbackListener.onFinishVideoRecord(mNextVideoAbsolutePath);
}
return mNextVideoAbsolutePath;
}
}