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. 世界最大BT服务器本周死了三回 海盗湾要凉凉?

    想當初,我是受到BT網站海盜灣的啟發,開發了一個DHT下載網站:http://www.ibmid.com,有一段時間通宵編程,理解此個協議. 海盗湾(The Pirate Bay)是世界上最大的 BT ...

  2. Java 的 List 与 Scala 的 Seq 相互转换

    1. List 转 Seq: List<String> tmpList = new ArrayList<>(); tmpList.add("abc"); S ...

  3. Centos7 安装node(8版本)

    最简洁的命令 yum -y update yum -y install gcc make gcc-c++ openssl-devel wget vim(后面两个如果没有再选择安装) cd /usr/l ...

  4. js的跨域问题和解决办法

    我们在开发中,经常会遇到跨域请求数据问题,那么什么是跨域呢?跨域就是js在不用域之间的数据传输或者通信,比如你在使用ajax从另外一个域请求数据,或者你的页面引入了iframe,要从iframe中获取 ...

  5. Leo-io 的C语言实现简单五子棋游戏观后感

    源代码: /************************************************************** ** 文 件 名:wuziqi.cpp ** 功    能:扫 ...

  6. Restful API学习笔记

    之前关于这个概念在网上看了一些,看完似懂非懂,模模糊糊,发现专业术语或者说书面表达的形式对于理解这种十分抽象的概念还是低效了点. 书面文档方面看了以下几个: 理解本真的REST架构风格 1. 要深入理 ...

  7. JavaScript 刷题一

    最近读<JavaScirpt编程精解>,想把里面的三个大的程序实现,现在记录下来. 问题一: 从下面这封信中,emily奶奶每封信的结尾都会用同样的格式注明哪只猫出生了,哪只猫死去了.现要 ...

  8. Python时间time模块介绍

    一.明确时间元组 二.测试代码#!/usr/bin/env python # -- coding: utf-8 --' """ 时间模块,time的相关操作与测试 &qu ...

  9. 常见Http协议响应码

    总体总结: 1XX:信息相应类,表示接受到请求并且继续处理 2XX:处理成功响应类,表示动作被成功的接收.理解和接受 3XX:重定向响应类,为了完成指定的动作,必须完成进一步处理和操作 4XX:客户端 ...

  10. Missy

    毕业两年了,非常怀念大学生活.有时间还想回去看看,为什么我的眼里常含着泪水,因为我对这片土地爱的深沉. 你问我大学时最后悔的事情是什么,可能是没有对她说 I like you 吧,至今偶尔也会想起她. ...