Android 高速录像(1)
package com.kirin.voltage.activity;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.kirin.voltage.R;
import com.kirin.voltage.util.CompareSizesByArea;
import com.kirin.voltage.util.LogUtil;
import com.kirin.voltage.util.SharedPreferencesUtils;
import com.kirin.voltage.view.AutoFitTextureView;
import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCaptureSession.StateCallback;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureRequest.Builder;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Range;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.PopupWindow;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;
public class RecordActivity extends Activity implements View.OnClickListener {
private static final int VIDEO_1080 = 0x0;
private static final int VIDEO_4K = 0x1;
private static final int VIDEO_NORMAL = 0x2;
private static final String INDEX = "INDEX";
private static final String TAG = RecordActivity.class.getSimpleName();
private static final SparseIntArray DEFAULT_ORIENTATION = new SparseIntArray();
static {
DEFAULT_ORIENTATION.append(Surface.ROTATION_0, 90);
DEFAULT_ORIENTATION.append(Surface.ROTATION_90, 0);
DEFAULT_ORIENTATION.append(Surface.ROTATION_180, 270);
DEFAULT_ORIENTATION.append(Surface.ROTATION_270, 180);
}
private CameraCaptureSession mPreviewSession;
private CaptureRequest.Builder mPreviewBuilder;
private CameraConstrainedHighSpeedCaptureSession mPreviewSessionHighSpeed;
private String mFilePath;
private boolean supportedNormal;
private boolean supported4K;
private boolean supported1080P120Fps;
private boolean isRecording = false;
private int index;
private Size size4K, size1080P, size320x240, videoSize, mPreviewSize;;
private AutoFitTextureView mTextureView;
private Button btn_record;
private ImageButton ibtn_info;
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
startPreview();
// mCameraOpenCloseLock.release();
if (null != mTextureView) {
configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
}
}
@Override
public void onError(CameraDevice camera, int error) {
// mCameraOpenCloseLock.release();
camera.close();
mCameraDevice = null;
}
@Override
public void onDisconnected(CameraDevice camera) {
// mCameraOpenCloseLock.release();
camera.close();
mCameraDevice = null;
}
};
private TextureView.SurfaceTextureListener textureListener = new SurfaceTextureListener() {
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
configureTransform(width, height);
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return true;
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
openCamera(width, height);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record_video);
mTextureView = (AutoFitTextureView) findViewById(R.id.textureview);
btn_record = (Button) findViewById(R.id.btn_record);
ibtn_info = (ImageButton) findViewById(R.id.ibtn_info);
btn_record.setOnClickListener(this);
ibtn_info.setOnClickListener(this);
index = SharedPreferencesUtils.getInt(this, INDEX, VIDEO_NORMAL);
size1080P = new Size(1920, 1080);
size320x240 = new Size(320, 240);
size4K = new Size(3840, 2160);
switch (index) {
case VIDEO_1080:
videoSize = size1080P;
break;
case VIDEO_4K:
videoSize = size4K;
break;
case VIDEO_NORMAL:
videoSize = size320x240;
break;
}
}
@Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if (mTextureView.isAvailable()) {
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
} else {
mTextureView.setSurfaceTextureListener(textureListener);
}
}
private void openCamera(int width, int height) {
CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
try {
String cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
availableFpsRange = map.getHighSpeedVideoFpsRangesFor(size1080P);
Size[] highSpeedVideoSizes = map.getHighSpeedVideoSizes();
if (highSpeedVideoSizes != null) {
if (Arrays.asList(highSpeedVideoSizes).contains(size1080P)) {
Range<Integer>[] ranges = map.getHighSpeedVideoFpsRangesFor(size1080P);
if (ranges != null) {
for (Range<Integer> r : ranges) {
if (r.contains(120)) {
supported1080P120Fps = true;
break;
}
}
}
}
}
Size[] outputSizes = map.getOutputSizes(MediaRecorder.class);
if (outputSizes != null) {
for (Size s : outputSizes) {
if (s.equals(size320x240)) {
supportedNormal = true;
} else if (s.equals(size4K)) {
supported4K = true;
}
}
}
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height, videoSize);
int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
} else {
mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
}
configureTransform(width, height);
mMediaRecorder = new MediaRecorder();
manager.openCamera(cameraId, mStateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
LogUtil.e(TAG, "openCamera : " + e);
}
}
private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
List<Size> bigEnough = new ArrayList<Size>();
int w = aspectRatio.getWidth();
int h = aspectRatio.getHeight();
for (Size option : choices) {
if (option.getHeight() == option.getWidth() * h / w && option.getWidth() <= width
&& option.getHeight() <= height) {
bigEnough.add(option);
}
}
if (bigEnough.size() > 0) {
return Collections.max(bigEnough, new CompareSizesByArea());
} else {
LogUtil.e(TAG, "Couldn't find any suitable preview size");
return choices[0];
}
}
protected void onDestroy() {
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
if (mMediaRecorder != null) {
mMediaRecorder.release();
mMediaRecorder.reset();
mMediaRecorder = null;
}
super.onDestroy();
};
private void configureTransform(int width, int height) {
if (null == mTextureView) {
return;
}
int rotation = getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, width, height);
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max((float) height / mPreviewSize.getHeight(), (float) height / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}
mTextureView.setTransform(matrix);
}
@Override
protected void onPause() {
// 处理界面,停止录制
if (isRecording) {
stopRecordingVideoOnPause();
}
closeCamera();
stopBackgroundThread();
super.onPause();
}
@Override
public void onClick(View v) {
// 处理点击事件
switch (v.getId()) {
case R.id.btn_record:
if (isRecording) {
stopRecordVideo();
} else {
startRecordVideo();
}
break;
case R.id.ibtn_info:
showChoices();
break;
default:
break;
}
}
Android 高速录像(1)的更多相关文章
- Android 高速录像(2)
private void startRecordVideo() { if (index == VIDEO_1080) { if (!supported1080P120Fps) { showToast( ...
- Bmob移动后端云服务平台--Android从零開始--(二)android高速入门
Bmob移动后端云服务平台--Android从零開始--(二)android高速入门 上一篇博文我们简介何为Bmob移动后端服务平台,以及其相关功能和优势. 本文将利用Bmob高速实现简单样例,进一步 ...
- android Camera 录像时旋转角度
录像保存时,旋转角度要与所拍录像时的角度保持一致,否则,看起来就会出现角度不度,巅倒等问题. 一般在开始录像之前会先去初始化录像 initializeRecorder 中会去读取当前的录像或拍照的旋转 ...
- 看大师解说Android高速开发框架EasyAndroid
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u010966622/article/details/37601789 前几天做了小应用.感觉小有成就 ...
- EasyPlayer实现Android MediaMuxer录像MP4(支持G711/AAC/G726音频)
本文转自EasyDarwin开源团队John的博客:http://blog.csdn.net/jyt0551/article/details/72787095 Android平台的MediaMuxer ...
- android高速开发框架xUtils
xUtils简单介绍 xUtils 包括了非常多有用的android工具. xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词).拥有更加灵活的ORM,很多其它的事件注解支持且不受 ...
- 官方Android Camera2 录像示例--停止录像时崩溃修正
官方Android 使用Camera2示例项目地址:https://github.com/android/camera-samples 视频录像示例:https://github.com/androi ...
- 5.3、Android Studio录像
Android Monitor允许你从设备中录制一段MP4格式的视频,最长允许3分钟. 录制视频 在硬件设备中录制视频: 1. 打开一个项目 2. 在设备中运行应用 3. 显示Android Moni ...
- android高速上手(三)经常使用控件使用
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/wangpeifeng669/article/details/26288387 完毕了android的 ...
随机推荐
- JAVA中 this关键字的用法
this 在类中就是代表当前对象,可以通过 this 关键字完成当前对象的成员属性.成员方法和构造方法的调用. 那么何时用 this? 当在定义类中的方法时,如果需要调用该类对象,就可以用 this来 ...
- iis上部署本地数据库LocalDB的方法
1. iis应用程序池的标识设置为"ApplicationPoolIdentify"(比较安全) 2. 不要将数据库物理文件保存在网站的物理路径内,因为iis应用程序池的标识为Ap ...
- 4.nginx动静分离
动静分离,就是将css.js.jpg等静态资源和jsp等动态资源分开处理,以此提高服务器响应速度,提高性能. 核心就是区分动态和静态资源 图片转自:https://www.cnblogs.com/xi ...
- epoll_wait 返回值学习以及epoll使用学习
https://blog.csdn.net/analogous_love/article/details/88721574
- (转)PXE+kickstart无人值守安装CentOS 7
kickstart+cobbler系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 本文是PXE+kickstart无人值守安装CentOS ...
- 使用express创建node服务器的两种方法及区别
使用express创建node服务器有两种方法,如下所示: 方法一: var express = require('express'); var app = express(); app.listen ...
- vue-webpack项目中调试的问题
在使用devtools的过程中,可以使用debugger.
- MVC目录规范
入口程序 单一入口机制,单一入口指在一个web应用程序中,所有的请求都是指向一个脚本文件,例如我们经常看到某一个网站所有的页面都是index.php??xxxx这样的形式.所有对使用程序的访问都是必须 ...
- xamarin for android webservice
首先新建一个空网站,添加一个webservice服务.然后在UserWebService.cs类里编写对外服务的方法 [WebMethod] public string IsCorret(string ...
- HTTP 状态代码之汇总+理解
这里有百度百科的介绍,还挺全的. 下面是在开发过程中遇到过的各种码,自己的问题自己的原因,同码不同错,贱笑贱笑. HTTP 406 Not Acceptable 这个错误的原因,是由于框架使用了`Sp ...