视频录制学习

Posted god-boy1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了视频录制学习相关的知识,希望对你有一定的参考价值。

 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.getSupportedPreviewSizes();设置预览大小,否则设置了一个摄像头不支持大小,将会报错. parameters.setPreviewSize(1920, 1080);//如果设置了一个不支持的大小,会崩溃.坑2

 //请通过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);
 



以上是关于视频录制学习的主要内容,如果未能解决你的问题,请参考以下文章

openCV录制视频

录制的视频主题音量能减吗

OpenHarmony视频录制开发

OpenHarmony视频录制开发

C503怎么删除录制的视频文件?

百度云课程:老杜2020版Java零基础685集(视频采用JDK13录制)