WebRTC-Android 源码导读(四):VideoCRE 与内存抖动优化

前面三篇中,我们依次分析了 WebRTC Android 的视频采集视频渲染视频硬编码,Live Streaming 视频的前段就已经全了。WebRTC 是个宝,初窥这部分代码时就被它的 Capturer 类的设计惊艳到了,仔细品鉴后越发佩服起来,里面简直填了太多坑了,如此宝贝,如不能为我所用,岂非一大憾事!而前三篇的解读,正是为了今天能将其剥离出来所做的铺垫,现在就有请我们今天的主角——VideoCRE, _Video Capture, Render and Encode_——闪亮登场。

VideoCRE 结构

我们当然可以直接使用 Capturer/Renderer/Encoder,但如果能将它们进行一定的封装,让基本的需求实现起来更加简单,岂不妙哉。

下面介绍一下 VideoCRE 的结构:

  • 视频数据由 VideoCapturer 采集,例如 Camera1Capturer
  • VideoCapturerSurfaceTextureHelper 等由 VideoSource 类管理;
  • VideoCapturer 采集到的数据会回调给 VideoCapturer.CapturerObserverVideoSink 实现了该接口;
  • VideoSink 会把数据发送给多个 VideoRenderer.Callbacks,例如 SurfaceViewRenderer 负责预览,HwAvcEncoder 负责视频编码;
  • HwAvcEncoder 则会把编码后的数据发送给多个 MediaCodecCallback,例如由 Streamer 进行网络传输实现直播功能,Mp4Recorder 负责本地录制;

同一路视频数据可以被多路消费,例如预览、低码率编码、高码率编码,而同一路编码数据,也可以被多路消费,例如推流、存文件。

VideoCRE 使用

demo 工程里实现了高低码率两路本地 MP4 录制功能,下面我们看看如何一步步实现这个功能。

首先是配置参数,标清和高清:

VideoConfig config = VideoConfig.builder()
        .previewWidth(1280)
        .previewHeight(720)
        .outputWidth(448)
        .outputHeight(800)
        .fps(30)
        .outputBitrate(800)
        .build();
VideoConfig hdConfig = VideoConfig.builder()
        .previewWidth(1280)
        .previewHeight(720)
        .outputWidth(720)
        .outputHeight(1280)
        .fps(30)
        .outputBitrate(2000)
        .build();

接下来是创建 VideoCapturer

VideoCapturer capturer = createVideoCapturer();

private VideoCapturer createVideoCapturer() {
    switch (MainActivity.sVideoSource) {
        case VideoSource.SOURCE_CAMERA1:
            return VideoCapturers.createCamera1Capturer(true);
        case VideoSource.SOURCE_CAMERA2:
            return VideoCapturers.createCamera2Capturer(this);
        default:
            return null;
    }
}

准备 Renderer 和 Encoder:

mVideoView = (SurfaceViewRenderer) findViewById(R.id.mVideoView1);
try {
    String filename = "video_source_record_" + System.currentTimeMillis();
    mMp4Recorder = new Mp4Recorder(
            new File(Environment.getExternalStorageDirectory(), filename + ".mp4"));
    mHdMp4Recorder = new Mp4Recorder(
            new File(Environment.getExternalStorageDirectory(), filename + "-hd.mp4"));
} catch (IOException e) {
    e.printStackTrace();
    Toast.makeText(this, "start Mp4Recorder fail!", Toast.LENGTH_SHORT).show();
    finish();
    return;
}
mHwAvcEncoder = new HwAvcEncoder(config, mMp4Recorder);
mHdHwAvcEncoder = new HwAvcEncoder(hdConfig, mHdMp4Recorder);

创建 VideoSinkVideoSourceVideoSource 也需要视频配置,但只需要使用预览尺寸、帧率,所以用 config 或者 hdConfig 都可以:

top Created with Sketch.