前言

  这个博客本来是用来详细介绍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配合录制视频(暂时有异常抛出,无法使用)的更多相关文章

  1. Android 开发 MediaRecorder使用Camera1配合录制视频

    前言 MediaRecorder可以不依靠Camera API 实现视频的录制,但是如果需要切换摄像头/设置对焦/选择分辨率等等就需要Camera来参与配合录制视频.这篇博客将介绍使用Camera1来 ...

  2. Android 开发 MediaRecorder视频录制入门

    前言 MediaRecorder是Android SDK提供用于录制音视频,关于音频的录制在我另一篇博客里已经介绍.传送门: https://www.cnblogs.com/guanxinjing/p ...

  3. Android切换前后置摄像头并录制视频

    项目需要对微信的视频模块也看了一下,在此就对这块进行了一个开发.首先给出效果图 首先给出java代码 /** * RecordActivity.java * 版权所有(C) 2013 * 创建:cui ...

  4. Android 开发 MediaRecorder音频录制

    前言 MediaRecorder类是Android sdk提供的一个专门用于音视频录制,一般利用手机麦克风采集音频和摄像头采集图像.这个类是属于简单的音频录制类,录制音频简单容易但是对音频流的控制也比 ...

  5. 【Android】 Android实现录音、播音、录制视频功能

    智能手机操作系统IOS与Android平分天下(PS:WP与其他的直接无视了),而Android的免费招来了一大堆厂商分分向Android示好,故Android可能会有“较好”的前景. Android ...

  6. 【Android Developers Training】 49. 轻松录制视频

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  7. Android自定义view之仿微信录制视频按钮

    本文章只写了个类似微信的录制视频的按钮,效果图如下:             一.主要的功能: 1.长按显示进度条,单击事件,录制完成回调 2.最大时间和最小时间控制 3.进度条宽度,颜色设置 二.实 ...

  8. Android开发 MediaPlayer入门_播放本地视频

    前言 MediaPlayer,可以播放视频/音频,并且它支持本地和网络文件的播放.本片博客作为入门教程,先以最通俗的方式解释播放文件本地视频.(如果你嫌MediaPlayer还是太麻烦可以试试选择Vi ...

  9. 【转】Android开发笔记(序)写在前面的目录

    原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经 ...

随机推荐

  1. C 函数指针详解

    一 通常的函数调用    一个通常的函数调用的例子://自行包含头文件 void MyFun(int x); //此处的申明也可写成:void MyFun( int ); int main(int a ...

  2. servlet的xml配置详解

    <?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns ...

  3. 【CF516D】Drazil and Morning Exercise

    题目 首先我们知道,在树上距离一个点最远的点一定是直径的两个端点之一 首先两遍\(\rm dfs\)把直径求出来,定义\(d(u)\)表示点\(u\)距离其最远点的距离,有了直径我们就能求出\(d\) ...

  4. uoj21 【UR #1】缩进优化

    题目 题意简介明了,需要找到一个\(T\),最小化 \[\sum_{i=1}^n\left \lfloor \frac{a_i}{T} \right \rfloor+\sum_{i=1}^na_i\% ...

  5. pytorch clamp 与clamp_区别

    pytorch clamp 与clamp_ ,有下划线的表示修改并付给自身,无下划线的表示需要返回处理后的值,比如: h = k.clamp(min=0) #将结果存入h,k保留原值 k.clamp_ ...

  6. 2018-12-1-WPF-修改-ItemContainerStyle-鼠标移动到未选中项效果和选中项背景

    title author date CreateTime categories WPF 修改 ItemContainerStyle 鼠标移动到未选中项效果和选中项背景 lindexi 2018-12- ...

  7. 解决VS2012新建MVC4等项目时,收到此模板加载程序集“NuGet.VisualStudio.Interop…”的错误

    1.错误如图所示: 2.不管是VS2012,还是2013如果开始没安装Nuget包都或报这个错,因为VS2012就已经全面切换到使用NuGet这个第三方开源工具来管理项目包和引用模块了,使用VS201 ...

  8. mysql的几种启动方式

    mysql的四种启动方式: 1.mysqld 启动mysql服务器:./mysqld --defaults-file=/etc/my.cnf --user=root 客户端连接: mysql --de ...

  9. ES相关信息

    漫画版原理介绍 搜索引擎的核心:倒排索引 elasticsearch 基于Lucene的,封装成一个restful的api,通过api就可进行操作(Lucene是一个apache开放源代码的全文检索引 ...

  10. [转]nginx简易教程

    安装 nginx官网下载地址 发布版本分为 Linux 和 windows 版本. 也可以下载源码,编译后运行. 从源代码编译 Nginx 把源码解压缩之后,在终端里运行如下命令: $ ./confi ...