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)的更多相关文章

  1. Android 高速录像(2)

    private void startRecordVideo() { if (index == VIDEO_1080) { if (!supported1080P120Fps) { showToast( ...

  2. Bmob移动后端云服务平台--Android从零開始--(二)android高速入门

    Bmob移动后端云服务平台--Android从零開始--(二)android高速入门 上一篇博文我们简介何为Bmob移动后端服务平台,以及其相关功能和优势. 本文将利用Bmob高速实现简单样例,进一步 ...

  3. android Camera 录像时旋转角度

    录像保存时,旋转角度要与所拍录像时的角度保持一致,否则,看起来就会出现角度不度,巅倒等问题. 一般在开始录像之前会先去初始化录像 initializeRecorder 中会去读取当前的录像或拍照的旋转 ...

  4. 看大师解说Android高速开发框架EasyAndroid

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u010966622/article/details/37601789 前几天做了小应用.感觉小有成就 ...

  5. EasyPlayer实现Android MediaMuxer录像MP4(支持G711/AAC/G726音频)

    本文转自EasyDarwin开源团队John的博客:http://blog.csdn.net/jyt0551/article/details/72787095 Android平台的MediaMuxer ...

  6. android高速开发框架xUtils

    xUtils简单介绍 xUtils 包括了非常多有用的android工具. xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词).拥有更加灵活的ORM,很多其它的事件注解支持且不受 ...

  7. 官方Android Camera2 录像示例--停止录像时崩溃修正

    官方Android 使用Camera2示例项目地址:https://github.com/android/camera-samples 视频录像示例:https://github.com/androi ...

  8. 5.3、Android Studio录像

    Android Monitor允许你从设备中录制一段MP4格式的视频,最长允许3分钟. 录制视频 在硬件设备中录制视频: 1. 打开一个项目 2. 在设备中运行应用 3. 显示Android Moni ...

  9. android高速上手(三)经常使用控件使用

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/wangpeifeng669/article/details/26288387 完毕了android的 ...

随机推荐

  1. B: Break Prime

    题目描述 给定一个素数,试判断能否将该素数写为b3−a3 的形式,a,b皆为非负整数. 输入 多组输入 每行一个素数P (2≤P≤1015)   输出 若可以分解输出a,b(a<b) ,不能输出 ...

  2. python自动化day3-函数、递归、内置函数

    一.什么是函数 修理工===>程序员 具备某一功能的工具===>函数 要想使用工具,需要事先准备好,然后拿来就用且可以重复使用要想用函数,需要先定义,再使用 二.函数基础 1.函数分类 # ...

  3. 主库binlog被purge的情形

    1.演示实验环境 --主库版本: root@(none)>show variables like 'version'; +---------------+-------------------- ...

  4. Java第四次实训作业

    1.编写“电费管理类”及其测试类. 第一步 编写“电费管理”类1)私有属性:上月电表读数.本月电表读数2)构造方法:无参.2个参数3)成员方法:getXXX()方法.setXXX()方法4)成员方法 ...

  5. decode 和 encode 区别

    字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(en ...

  6. 《大数据日知录》读书笔记-ch16机器学习:分布式算法

    计算广告:逻辑回归 千次展示收益eCPM(Effective Cost Per Mille) eCPM= CTR * BidPrice 优化算法 训练数据使用:在线学习(online learning ...

  7. 浅谈C#.NET防止SQL注入式攻击

    1#region 防止sql注入式攻击(可用于UI层控制)  2  3///   4/// 判断字符串中是否有SQL攻击代码  5///   6/// 传入用户提交数据  7/// true-安全:f ...

  8. 前端中用到的图片(png图片)

    作为前端工程师,将设计师的设计稿转化为html页面,其中有一个必不可少的环节就是将psd文件中的一些图片随心所欲的使用,而我们经常用到的就是png图片. 第一部分:基本介绍 首先我们先对比几种图片: ...

  9. table定位

    Table定位 在 web 页面中经常会遇到 table 表格,特别是后台操作页面比较常见.本篇详细讲解 table 表格如何定位. 1.1 table特性 1.table 页面查看源码一般有这几个明 ...

  10. sencha touch list infinite 属性

    sencha touch list 1 默认每一项的高度会自动适应其内容. 2 当每一个 item 的高度都相同且不变时, 设置 itemHeight 为固定值 和 variableHeights 为 ...