标签:原因 这一 异常 param surf text 优先 简单 fan
surface录制是将摄像头数据通过egl和opengl绘制到编码器surface最后输出到文件的,buffer录制则是更直接,直接将摄像头数据灌输到编码器,让编码器直接编码数据后输出到文件
Camera绑定SurfaceView, 通过onPreviewFrame()得到摄像头数据,再把数据输入到视频编码器MediaCodec中,编码完成后输出编码数据给音视频混合器MediaMuxer,最后由MediaMuxer写入数据到文件。
MediaFormat并非是在编码器prepared的时候自己设定的那个MediaFormat,而一定是在第一次数据output的时候,通过MediaCodec.getOutputFormat()获取到的MediaFormat才是最终的编码格式。一般情况下,这个得到的MediaFormat会和prepared配置的MediaFormat会稍有不同(比如你配置的是4M码率,但是得到的可能是3.9M的码率的视频),这是不同手机,不同厂商rom的编码器问题了,但两者基本差异不大。
在surface录制中我们采用的是GLSurfaceView作为视频数据载体来录制,而在buffer录制中我们是采用SurfaceView作为数据载体来录制。原因是如果采用GLSurfaceView,要得到摄像头的YUV数据会非常的困难,因为通过GLSurfaceView得到的是ARGB数据,要手动的转一遍YUV数据,会有巨大的性能问题。
buffer录制:
初始化摄像头的时候,必须要指定摄像头的数据预览格式为NV21(YUV数据的一种),摄像头初始化完成后绑定SurfaceView,在onPreviewFrame()回调中得到预览的NV21数据,将此数据提供给编码器
//将预览的nv21数据传递给编码器 mVideoEncoder.addFrame(bytes);
mCamera.setPreviewCallback(mPreviewCallback);
mParameters = mCamera.getParameters();
mParameters.setRotation(90);
mParameters.setPreviewFormat(ImageFormat.NV21); // 设置NV21预览格式
编码的原理很简单,摄像头在预览的过程中不断的传入数据过来(addFrame()),编码器中又一个List用于缓存这些视频数据(FrameList),编码器是一个轮询线程,在小于 1000/帧率 的时间间隔内轮询该列表,如果有数据,就取出数据,编码该数据,编码过程为:将NV21帧数据转换为NV12数据,再将NV12数据输入到编码器,此时编码器会自动编码该数据,然后输出编码后的数据(output())到混合器。
此处务必注意的是编码器的配置,编码器的颜色模式在我的代码中使用的是COLOR_FormatYUV420SemiPlanar,这个颜色模式就是NV12的格式,但有些手机可能不支持这个格式,所以小伙伴们需要先检查手机的编码器是否支持该格式,如果不支持该格式就得使用其他的颜色模式。通过MediaCodecInfo.getCapabilitiesForType()可以拿到当前编码器的MediaCodecInfo.CodecCapabilities,它有一个数组变量colorFormats包含的是该编码器支持的颜色模式,需要在这些模式中选择适用的颜色模式(在这篇文章中以COLOR_FormatYUV420SemiPlanar为例,建议小伙伴们如果编码器支持的颜色模式种包含这个模式,优先使用这个模式),因为摄像头拿到的是NV21的数据,所以就需要把NV21数据转为你当前编码器配置的颜色模式
在刚刚推荐的 颜色模式的两篇文章中可以知道NV12对应的数据格式是YYYYUVUVUV,而NV21对应的是YYYYVUVUVU,在代码中是通过NV21toI420SemiPlanar()这个函数来进行转化的。
mediarecorder常见错误:
mCamera.setPreviewTexture(mSurfaceTexture);//注意处,如果没有设置preview,录像会报错.坑1
//请通过parameters.getSupportedPictureSizes();设置拍照图片大小,这一步对于录像来说是非必须的. //parameters.setPictureSize(1920, 1080);
mCamera.unlock();//注意处,一定要调用此方法,否则会崩溃. 坑3
mMediaRecorder.reset();//竟可能在调用其他方法之前,调用reset方法.避免状态异常调用.坑4 mMediaRecorder.setCamera(mCamera);//注意顺序,请注意此方法调用的顺序.调用顺序错了,会崩溃.坑5
//请注意, setVideoSource 和 setAudioSource 一定要比其他方法先调用.否则会崩溃. 坑6
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
视频录制学习
标签:原因 这一 异常 param surf text 优先 简单 fan
原文地址:https://www.cnblogs.com/God-boy1/p/10081205.html