Android开发 MediaRecorder使用Camera2配合录制视频(暂时有异常抛出,无法使用)
前言
这个博客本来是用来详细介绍MediaRecorder与Camera2,但是出乎预料之外,在获取mMediaRecorder.getSurface();的时候无论如何都是报错的,报错为Surface没有初始化.我查阅了相当多网址甚至在国外网址上查看都没查到问题如何解决(问题查到了都没给出解决办法).所以下面的代码只做临时记录后续将继续看看此问题到底怎么解决.后续看看google官网文档怎么搞的
代码部分
package demo.yt.com.demo; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
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.DisplayMetrics;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button; import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; public class MedioRecorderCamera2Activity extends AppCompatActivity {
private static final String TAG = MedioRecorderCamera2Activity.class.getSimpleName();
private Button mBtnStatr,mBtnFinish;
private TextureView mTextureView;
private CameraManager mCameraManager;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCameraCaptureSession;
private CameraDevice.StateCallback mCameraDeviceStateCallback;
private CameraCaptureSession.StateCallback mSessionStateCallback;
private CameraCaptureSession.CaptureCallback mSessionCaptureCallback;
private CaptureRequest.Builder mPreviewCaptureRequest;
private CaptureRequest.Builder mRecorderCaptureRequest;
private MediaRecorder mMediaRecorder;
private String mCurrentSelectCamera;
private Handler mChildHandler; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_medio_recorder_camera2);
mTextureView = findViewById(R.id.textureview);
mBtnStatr = findViewById(R.id.btn_start);
mBtnFinish = findViewById(R.id.btn_finish);
initClickListener();
initChildHandler();
initTextureViewStateListener();
initMediaRecorder();
initCameraDeviceStateCallback();
initSessionStateCallback();
initSessionCaptureCallback(); } private void initClickListener(){
mBtnStatr.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
config();
startRecorder(); }
});
mBtnFinish.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopRecorder(); }
});
} private void initTextureViewStateListener(){
mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
initCameraManager();
selectCamera();
openCamera(); } @Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { } @Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
} @Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) { }
});
} private void initChildHandler(){
HandlerThread handlerThread = new HandlerThread("Camera2Demo");
handlerThread.start();
mChildHandler = new Handler(handlerThread.getLooper());
} private void initMediaRecorder(){
mMediaRecorder = new MediaRecorder();
} private void configMediaRecorder(){
File file = new File(getExternalCacheDir(),"demo.mp4");
if (file.exists()){
file.delete();
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
mMediaRecorder.setVideoEncodingBitRate(8*1024*1920);
mMediaRecorder.setVideoFrameRate(30);
Size size = getMatchingSize2();
mMediaRecorder.setVideoSize(size.getWidth(),size.getHeight());
mMediaRecorder.setOrientationHint(90);
Surface surface = new Surface(mTextureView.getSurfaceTexture());
mMediaRecorder.setPreviewDisplay(surface);
mMediaRecorder.setOutputFile(file.getAbsolutePath());
try {
mMediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
} } private void config(){
try {
mCameraCaptureSession.stopRepeating();
mCameraCaptureSession.close();
mCameraCaptureSession = null;
} catch (CameraAccessException e) {
e.printStackTrace();
}
configMediaRecorder();
Size cameraSize = getMatchingSize2();
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(cameraSize.getWidth(),cameraSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
Surface recorderSurface = mMediaRecorder.getSurface();
try {
mPreviewCaptureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewCaptureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewCaptureRequest.addTarget(previewSurface);
mPreviewCaptureRequest.addTarget(recorderSurface);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface,recorderSurface),mSessionStateCallback,mChildHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
} } private void startRecorder(){
mMediaRecorder.start(); } private void stopRecorder(){
mMediaRecorder.stop();
mMediaRecorder.reset();
configMediaRecorder(); } private void initCameraManager(){
mCameraManager = (CameraManager)getSystemService(Context.CAMERA_SERVICE); } private void selectCamera(){
if (mCameraManager != null) {
Log.e(TAG, "selectCamera: CameraManager is null"); }
try {
String[] cameraIdList = mCameraManager.getCameraIdList();
if (cameraIdList.length == 0){
Log.e(TAG, "selectCamera: cameraIdList length is 0");
}
for (String cameraId : cameraIdList){
CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing == CameraCharacteristics.LENS_FACING_BACK){
mCurrentSelectCamera = cameraId; }
} } catch (CameraAccessException e) {
e.printStackTrace();
}
} private void initCameraDeviceStateCallback(){
mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
try {
mCameraDevice = camera;
Size cameraSize = getMatchingSize2();
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(cameraSize.getWidth(),cameraSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
mPreviewCaptureRequest = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewCaptureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewCaptureRequest.addTarget(previewSurface);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface),mSessionStateCallback,mChildHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
} } @Override
public void onDisconnected(@NonNull CameraDevice camera) { } @Override
public void onError(@NonNull CameraDevice camera, int error) { }
};
} private void initSessionStateCallback(){
mSessionStateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
mCameraCaptureSession = session;
try {
mCameraCaptureSession.setRepeatingRequest(mPreviewCaptureRequest.build(),mSessionCaptureCallback,mChildHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
} } @Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) { }
};
} private void initSessionCaptureCallback(){
mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
} @Override
public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
super.onCaptureProgressed(session, request, partialResult);
} @Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
} @Override
public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
super.onCaptureFailed(session, request, failure);
}
};
} @SuppressLint("MissingPermission")
private void openCamera(){
try {
mCameraManager.openCamera(mCurrentSelectCamera,mCameraDeviceStateCallback,mChildHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
} private Size getMatchingSize2(){
Size selectSize = null;
try {
CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics(mCurrentSelectCamera);
StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] sizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); //因为我这里是将预览铺满屏幕,所以直接获取屏幕分辨率
int deviceWidth = displayMetrics.widthPixels; //屏幕分辨率宽
int deviceHeigh = displayMetrics.heightPixels; //屏幕分辨率高
Log.e(TAG, "getMatchingSize2: 屏幕密度宽度="+deviceWidth);
Log.e(TAG, "getMatchingSize2: 屏幕密度高度="+deviceHeigh );
/**
* 循环40次,让宽度范围从最小逐步增加,找到最符合屏幕宽度的分辨率,
* 你要是不放心那就增加循环,肯定会找到一个分辨率,不会出现此方法返回一个null的Size的情况
* ,但是循环越大后获取的分辨率就越不匹配
*/
for (int j = 1; j < 41; j++) {
for (int i = 0; i < sizes.length; i++) { //遍历所有Size
Size itemSize = sizes[i];
Log.e(TAG,"当前itemSize 宽="+itemSize.getWidth()+"高="+itemSize.getHeight());
//判断当前Size高度小于屏幕宽度+j*5 && 判断当前Size高度大于屏幕宽度-j*5 && 判断当前Size宽度小于当前屏幕高度
if (itemSize.getHeight() < (deviceWidth + j*5) && itemSize.getHeight() > (deviceWidth - j*5)) {
if (selectSize != null){ //如果之前已经找到一个匹配的宽度
if (Math.abs(deviceHeigh-itemSize.getWidth()) < Math.abs(deviceHeigh - selectSize.getWidth())){ //求绝对值算出最接近设备高度的尺寸
selectSize = itemSize;
continue;
}
}else {
selectSize = itemSize;
} }
}
if (selectSize != null){ //如果不等于null 说明已经找到了 跳出循环
break;
}
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
Log.e(TAG, "getMatchingSize2: 选择的分辨率宽度="+selectSize.getWidth());
Log.e(TAG, "getMatchingSize2: 选择的分辨率高度="+selectSize.getHeight());
return selectSize;
} }
Android开发 MediaRecorder使用Camera2配合录制视频(暂时有异常抛出,无法使用)的更多相关文章
- Android 开发 MediaRecorder使用Camera1配合录制视频
前言 MediaRecorder可以不依靠Camera API 实现视频的录制,但是如果需要切换摄像头/设置对焦/选择分辨率等等就需要Camera来参与配合录制视频.这篇博客将介绍使用Camera1来 ...
- Android 开发 MediaRecorder视频录制入门
前言 MediaRecorder是Android SDK提供用于录制音视频,关于音频的录制在我另一篇博客里已经介绍.传送门: https://www.cnblogs.com/guanxinjing/p ...
- Android切换前后置摄像头并录制视频
项目需要对微信的视频模块也看了一下,在此就对这块进行了一个开发.首先给出效果图 首先给出java代码 /** * RecordActivity.java * 版权所有(C) 2013 * 创建:cui ...
- Android 开发 MediaRecorder音频录制
前言 MediaRecorder类是Android sdk提供的一个专门用于音视频录制,一般利用手机麦克风采集音频和摄像头采集图像.这个类是属于简单的音频录制类,录制音频简单容易但是对音频流的控制也比 ...
- 【Android】 Android实现录音、播音、录制视频功能
智能手机操作系统IOS与Android平分天下(PS:WP与其他的直接无视了),而Android的免费招来了一大堆厂商分分向Android示好,故Android可能会有“较好”的前景. Android ...
- 【Android Developers Training】 49. 轻松录制视频
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- Android自定义view之仿微信录制视频按钮
本文章只写了个类似微信的录制视频的按钮,效果图如下: 一.主要的功能: 1.长按显示进度条,单击事件,录制完成回调 2.最大时间和最小时间控制 3.进度条宽度,颜色设置 二.实 ...
- Android开发 MediaPlayer入门_播放本地视频
前言 MediaPlayer,可以播放视频/音频,并且它支持本地和网络文件的播放.本片博客作为入门教程,先以最通俗的方式解释播放文件本地视频.(如果你嫌MediaPlayer还是太麻烦可以试试选择Vi ...
- 【转】Android开发笔记(序)写在前面的目录
原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经 ...
随机推荐
- mysql最新版与mysql5.6的兼容问题
最近公司在给别的企业打了一个项目,在公司本地使用的是mysql 5.6,但是搭建的项目的mysql版本是最新版5.7以后吧,所以有些sql在执行上出了一点问题 目前发现的是: 1: 在5.6版本下先o ...
- Python3 From Zero——{最初的意识:005~文件和I/O}
一.输出重定向到文件 >>> with open('/home/f/py_script/passwd', 'rt+') as f1: ... print('Hello Dog!', ...
- css样式高级技巧-选择器
用<div>元素为网页 在编写样式表时,我们经常要用div元素来包装内容: <div> <p>Here are two paragraphs of content& ...
- Python匹马行天下之初识python!
python的发展史 1989年,被称为龟叔的Guido在为ABC语言写插件时,产生了写一个简洁又实用的编程语言的想法,并开始着手编写.因为其喜欢Monty Python喜剧团,所以将其命名为pyth ...
- scrapy的使用-scrapy shell
进入 该目录下执行scrapy shell 文件, 在命令行可执行该文件中链接的xpath语法,和BeautifulSoup语法.
- 面向XX程序设计到底是个啥
面向过程编程:面向(对着)-->过程(流程步骤)-->编程(码代码) IPO是啥 input(输入)-->process(过程处理)-->output(输出) 未来码代码的目的 ...
- 【POJ】1182 食物链
这是<挑战设计程序竞赛>中的例题. 题目链接:http://poj.org/problem?id=1182 题意:中文题面.不赘述. 题解: 代码: //带权并查集 #include< ...
- Activiti学习笔记11 — 判断节点的使用
一. 创建流程 <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns=" ...
- OC开发系列-@property和@synthesize
property和synthesize 创建一个Person类.提供成员属性的_age和_height的setter和getter方法. #import <Foundation/Foundati ...
- grunt完整的配置demo
const path = require('path') const fs = require('fs'); module.exports = function (grunt) { grunt.reg ...