如何让视频有camera
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何让视频有camera相关的知识,希望对你有一定的参考价值。
参考技术A 音视频开发(四):Camera视频采集 原创2022-04-07 14:16:11
音视频开发老舅
码龄1年
关注
目录
Camera基础知识
视频采集的流程
遇到的问题和常见的坑(重点)
一、 Camera基础知识
Camera 有几个重要的基础概念。
facing相机的方向,一般后置摄像头和前置摄像头。
Orientation:相机采集图片的角度,摄像头的传感器在手机中是横向的,在预览的时候根据Camera的预览方向进行顺时针旋转对应角度进行设置即可正常预览。如果不正确设置会导致预览时出现倒立、镜像等问题。把预览的图片保存为相册也要单独设置方向,注意这个方向和预览方向互不相干。
预览图片的大小 预览容器的大小和摄像头支持的图片预览的图片大小,如果设置了Camera不支持的预览大小,会导致黑屏。
可以设置帧回调然后,在每一帧中进行业务处理,比如,人脸识别等功能
Camera预览的图片格式有NV21 YUV420sp等
Camera需要一个容器把的Surface显示在屏幕上,一般SurfaceView,TextureView等。
二、视频采集的流程
通过SurfaceView拿到SurfaceHolder,然后设置addCallback回调,当Surface创建、销毁、改变时触发对应的回调,在其中可以进行Camera的初始化以及参数设置。音视频开发知识点导图:https://docs.qq.com/doc/DQm1VTHBlQmdmTlN2
通过new Camera(cameralId)生成一个对象。然后Camera.getParams获取到相关的参数,可以把重要的或者说比较关系的parmas打印出来,比如说支持多少个摄像头、支持的预览图片的大小、每个摄像头的方向等信息。可以根据需要设置对应的参数,比如图片的格式、图片的预览大小等。当然有一个必须要设置的就是Camera的预览展示方向,否则预览的到图片和正常的方向不一致。
可以设置Camera的setPreviewCallback获取每一帧的回调,根据需要设置处理,开始预览startPreview以及帧回调的处理
摄像头的切换
如果出发Camera的切换,需要把前一个Camera释放,重新生成和设置Camera切换预览
和Activity生命周期的关系,这个是由SurfaceView决定的,当页面可见时(onResume)创建或重新创建,页面不可见时(onPause)销毁释放
本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓
具体实现如下
SurfaceView的设置
private SurfaceHolder mSurfaceHolder;
private void initSurfaceView()
mSurfaceHolder = surfaceview.getHolder();
mSurfaceHolder.addCallback(new SurfaceHolder.Callback()
@Override
public void surfaceCreated(SurfaceHolder holder)
Log.d(TAG, "surfaceCreated: ");
handleSurfaceCreated();
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
@Override
public void surfaceDestroyed(SurfaceHolder holder)
Log.d(TAG, "surfaceDestroyed: ");
handleSurfaceDestroyed();
);
private void handleSurfaceDestroyed()
releaseCamera();
mSurfaceHolder = null;
Log.i(TAG, "handleSurfaceDestroyed: ");
private void handleSurfaceCreated()
Log.i(TAG, "handleSurfaceCreated: start");
if (mSurfaceHolder == null)
mSurfaceHolder = surfaceview.getHolder();
if (mCamera == null)
initCamera(curCameraId);
try
//问题2:页面重新打开后SurfaceView的内容黑屏
//Camera is being used after Camera.release() was called
//在surfaceDestroyed时调用了Camera的release 但是没有设置为null,
//--》如何解耦合,把生命周期相关的方法和Camera的生命周期绑定而不时在回调中处理,方便业务实现
//onResume--》surfaceCreated
//onPause--》surfaceDestroyed
mCamera.setPreviewDisplay(mSurfaceHolder);
catch (IOException e)
e.printStackTrace();
Log.e(TAG, "handleSurfaceCreated: " + e.getMessage());
startPreview();
Log.i(TAG, "handleSurfaceCreated: end");
private void startPreview()
// mCamera.setPreviewCallback(new Camera.PreviewCallback()
// @Override
// public void onPreviewFrame(byte[] data, Camera camera)
// Log.i(TAG, "onPreviewFrame: setPreviewCallback");
//
// );
//问题:很多时候,不仅仅要预览,在预览视频的时候,希望能做一些检测,比如人脸检测等。这就需要获得预览帧视频,该如何做呐?
mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback()
@Override
public void onPreviewFrame(byte[] data, Camera camera)
Log.i(TAG, "onPreviewFrame: setOneShotPreviewCallback");
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null);
ByteArrayOutputStream os = new ByteArrayOutputStream(data.length);
if(!yuvImage.compressToJpeg(new Rect(0,0,previewSize.width,previewSize.height),100,os))
Log.e(TAG, "onPreviewFrame: compressToJpeg error" );
return;
byte[] bytes = os.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
//这里的处理方式是简单的把预览的一帧图保存下。如果需要做人脸别或者其他操作,可以拿到这个bitmap进行分析处理
//我们可以通过找出这张图片发现预览保存的图片的方向是不对的,还是Camera的原始方向,需要旋转一定角度才可以。
if(curCameraId == Camera.CameraInfo.CAMERA_FACING_BACK)
bitmap = BitmapUtils.rotate(bitmap,90);
else
bitmap = BitmapUtils.mirror(BitmapUtils.rotate(bitmap,270));
FileUtils.saveBitmapToFile(bitmap,"oneShot.jpg");
);
// mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback()
// @Override
// public void onPreviewFrame(byte[] data, Camera camera)
// Log.i(TAG, "onPreviewFrame: setPreviewCallbackWithBuffer");
//
// );
以上是关于如何让视频有camera的主要内容,如果未能解决你的问题,请参考以下文章