美文网首页Android音视频Android技术简化开发
Android音视频开发——MedCodec实现屏幕录制编码成H

Android音视频开发——MedCodec实现屏幕录制编码成H

作者: Peakmain | 来源:发表于2021-08-25 18:18 被阅读0次

    前言

    基本知识

    • 主要用到的服务是系统服务的MEDIA_PROJECTION_SERVICE
     private lateinit var mMediaProjectionManager: MediaProjectionManager
       mMediaProjectionManager =
                getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
    
      val intent: Intent = mMediaProjectionManager.createScreenCaptureIntent()
      startActivityForResult(intent, screenRequestCode)
    
    • 获取开启屏幕录制之后的数据
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
            if (requestCode == screenRequestCode && resultCode == Activity.RESULT_OK) {
                mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data)
                //开始编码
            }
        }
    
    
    • 屏幕数据怎么给Medcodec呢?


      问题.png

      解决办法:Medcodec提供一个场地,MediaProjection把数据放到那个场地,如下图


      解决办法.png

    实现编码

    代码很简单,主要几个方法

    • createEncoderByType创建编码器
    • configure:配置信息,我们需要配置帧率,码率,I帧等等
    • createInputSurface:创建场地
    • createVirtualDisplay:数据放到场地上去
    • 我们前篇文章讲Android音视频开发——MediaCodec播放H264视频的时候,提供给MediaCodec的左边的源数据是本地的H264视频文件,这里我们的源数据是我们的屏幕录制的数据,所以我们不需要像MediaCodec传入数据,只需要获取数据就可以了
      image.png
        private fun initMediaCodec() {
            mMediaCodec = MediaCodec.createEncoderByType("video/avc")
            //配置信息
            val format = MediaFormat.createVideoFormat(
                "video/avc",
                SizeUtils.screenWidth,
                SizeUtils.screenHeight
            )
            format.setInteger(
                MediaFormat.KEY_COLOR_FORMAT,
                MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface
            )
    
            format.setInteger(MediaFormat.KEY_FRAME_RATE, 15)
            //码率,码率越高,字节越长,视频就越清晰
            format.setInteger(MediaFormat.KEY_BIT_RATE, 400_000)
            //2s一个I帧
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2)
            //CONFIGURE_FLAG_ENCODE:表示编码
            mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
            //创建一个场地
            val surface = mMediaCodec.createInputSurface()
            mHandler = Handler(mHandlerThread.looper)
            mHandler.post {
                mMediaCodec.start()
                mMediaProjection.createVirtualDisplay(
                    "screen_codec",
                    SizeUtils.screenWidth,
                    SizeUtils.screenHeight,
                    1,
                    DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
                    surface,
                    null, null
                )
                //此时有了源数据,就可以取出数据进行编码
                val bufferInfo = MediaCodec.BufferInfo()
                while (true) {
                    val outIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 10000)
                    if (outIndex >= 0) {
                        //这是dsp的数据,无法直接使用
                        val byteBuffer = mMediaCodec.getOutputBuffer(outIndex)
                        val outData = ByteArray(bufferInfo.size)
                        byteBuffer.get(outData)
                        FileUtils.writeBytes(outData, "codec.h264")
                        FileUtils.writeContent(outData, "codec.txt")
                        mMediaCodec.releaseOutputBuffer(outIndex, false)
                    }
                }
            }
    
        }
    
    • 编码后的文件分析


      image.png

    相关文章

      网友评论

        本文标题:Android音视频开发——MedCodec实现屏幕录制编码成H

        本文链接:https://www.haomeiwen.com/subject/ajreiltx.html