WebRTC 源码分析(三):安卓视频硬编码

 

 

 

  • 数据怎么送进编码器?
  • 怎么从编码器取数据?
  • 如何做流控?

在开始之前,我们先了解一下 MediaCodec 的基本知识。

 

MediaCodec 基础

 

Developer 官网 上的描述已经很清楚了,下面简要总结一下。

 

首先是工作流程:

生产者不断把输入数据送进 codec,消费者则不断消费 codec 的输出数据。

 

接下来是调用流程:

  • 选择编码器:根据 mimeType 和 colorFormat,以及是否为编码器,选择出一个 MediaCodecInfo;
  • 创建编码器:MediaCodec.createByCodecName(codecInfo.getName());
  • 对于 API 21 以上的系统,我们可以选择异步消费输出:mVideoCodec.setCallback;
  • 配置编码器:设置各种编码器参数(MediaFormat),再调用 mVideoCodec.configure(文档也没有明确说 setCallback 应该在 configure 之前,但既然示例是这样写的,我们还是保持这样好了,毕竟相机采集也是踩过坑了的);
  • 对于 API 19 以上的系统,我们可以选择 Surface 输入:mVideoCodec.createInputSurface;
  • 启动编码器:mVideoCodec.start;
  • 输入数据到编码器:输入数据到来时,Surface 输入模式下(提前用 Surface 创建 EGLSurface),调用 GLES API 绘制,最后 eglSwapBuffers 即可;普通模式下我们需要 dequeueInputBuffer、填入数据、queueInputBuffer;
  • 消费编码器输出数据:异步模式下,我们在 onOutputBufferAvailable 中使用 buffer 内的数据,然后 releaseOutputBuffer 即可;同步模式下我们需要 dequeueOutputBuffer、使用 buffer 内的数据、releaseOutputBuffer;
  • 停止并销毁编码器:先告知编码器我们要结束编码,Surface 输入时调用 mVideoCodec.signalEndOfInputStream,普通输入则可以为在 queueInputBuffer 时指定 MediaCodec.BUFFER_FLAG_END_OF_STREAM 这个 flag;告知编码器后我们就可以等到编码器输出的 buffer 带着 MediaCodec.BUFFER_FLAG_END_OF_STREAM 这个 flag 了,等到之后我们调用 mVideoEncoder.release 销毁编码器;

简单了解了 MediaCodec 基础之后,我们就可以开始看看 WebRTC 是怎么做硬编码的了。

 

数据怎么送进编码器?

 

WebRTC 的硬编码封装在 MediaCodecVideoEncoder 类中,只看 Java 代码我们会发现这个类的方法基本都是 package private 的,而且并没有被其他类调用过,一开始我也很疑惑,但当我开始看 native 代码的时候就发现了蹊跷。

 

原来对 MediaCodecVideoEncoder 接口的调用都发生在 native 层,就在 webrtc/sdk/android/src/jni/androidmediaencoder_jni.cc 这个文件中。Java 调用 native 代码想必大家都知道,但 native 代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值