串联整个音视频录制流程,完成音视频的采集、编码、封包成 mp4 输出

音频采集:AudioRecord
视频采集:Camera预览回调YUV数据
编码:MediaCodec
合成封包MP4:MediaMuxer

首先确定几条线程处理任务
1.audioThread 音频采集和编码
2.videoThread 视频编码
3.muxerThread 合成

示例代码:Kotlin

所有详细代码已上传github,后面会给出地址,示例Activity是Camera1PreviewActivity

代码中少了一些验证,比如设备支持预览的格式,这在之前的文章提到过,要注意自己的设备是否支持该设置。

在最后,会写出容易出现的问题,代码运行不正确的时候,可以对照下,是否
犯了这些错误

1.初始化和打开相机

预览界面用的SurfaceView,通过前面的学习应该知道相机预览,就不多说

  private fun initView() {
        surfaceView = findViewById(com.example.mediastudyproject.R.id.surface_view)
        surfaceView.holder.addCallback(object : SurfaceHolder.Callback2 {
            override fun surfaceRedrawNeeded(holder: SurfaceHolder?) {
            }

            override fun surfaceChanged(
                holder: SurfaceHolder?,
                format: Int,
                width: Int,
                height: Int
            ) {
                isSurfaceAvailiable = true
                this@Camera1PreviewActivity.holder = holder
            }

            override fun surfaceDestroyed(holder: SurfaceHolder?) {
                isSurfaceAvailiable = false
                mCamera?.stopPreview()
                //这里要把之前设置的预览回调取消,不然关闭app,camera释放了,但是还在回调,会报异常
                mCamera?.setPreviewCallback(null)
                mCamera?.release()
                mCamera = null
            }

            override fun surfaceCreated(holder: SurfaceHolder?) {
                isSurfaceAvailiable = true
                this@Camera1PreviewActivity.holder = holder
                thread {
                	//打开相机
                    openCamera(Camera.CameraInfo.CAMERA_FACING_BACK)
                }
            }
        })
    }

相机参数设置

 /**
     * 初始化并打开相机,我这里默认打开的后置摄像头
     */
    private fun openCamera(cameraId: Int) {
        mCamera = Camera.open(cameraId)
        mCamera?.run {
            setPreviewDisplay(holder)
            setDisplayOrientation(WindowDegree.getDegree(this@Camera1PreviewActivity))

            var cameraInfo = Camera.CameraInfo()
            Camera.getCameraInfo(cameraId, cameraInfo)
            Log.i("camera1", "相机方向 ${cameraInfo.orientation}")


            val parameters = parameters

            parameters?.run {

                //自动曝光结果给我爆一团黑,不能忍 自己设置
                exposureCompensation = maxExposureCompensation

                //自动白平衡
                autoWhiteBalanceLock = isAutoWhiteBalanceLockSupported


                //设置预览大小
                appropriatePreviewSizes = getAppropriatePreviewSizes(parameters)
                setPreviewSize(appropriatePreviewSizes?.width!!, appropriatePreviewSizes?.height!!)

                //设置对焦模式
                val supportedFocusModes = supportedFocusModes
                if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                	//设置自动对焦,启动自动对焦是通过Camera的autoFocus方法实现
                	//如果要连续对焦,这个方法要多次调用,这里就没有调用autoFocus
                	//想要连续对焦的可以自己实现,通过Handler连续发送消息就行
                    focusMode = Camera.Parameters.FOCUS_MODE_AUTO
                }
                previewFormat = ImageFormat.NV21
            }

			//相机资源回收的时候,注意setPreviewCallBack(null),将回调移除
            setPreviewCallback { data, camera ->
            	//isRecording是一个开启录制的标志,回调帧数据存放在集合中等待编码器编码
                if (isRecording) {
                    if (data != null) {
                        Log.i("camera1", "获
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值