webrtc入门五-android视频采集流程

606 阅读2分钟

写在前面,

本人android开发。入门webrtc还是从android入口进入比较友好。
最近的当然是音视频采集模块。今天看下视频采集模块。
先上一张图:scrum流程.png

简单介绍下这张图 1.CameraEnumerator提供获取camera名称、判断camera朝向、获取CaptureFormat、createCapturer方法;
#createCapturer通过这个方法获取VideoCapturer;这个方法有两个重构方法,三个参数分别代表deviceName(摄像头名称)、CameraEventsHandler(摄像头打开、关闭、报错、首帧、断开、卡住)、fixedRotation:以固定旋转角度,
#如果传-1,那么根据设备朝向+摄像头的角度
#有值,那么根据值+摄像头的角度
#最后再取余360,把这个值作为VideoFrame的rotation;
#摄像头的角度,前置默认是逆时针旋转270°,前置默认90°
2.VideoCapturer提供initialize、start\stopCapture、changeCaptureFormat、dispose、isScreencast方法;
#initialize:入参是SurfaceTextureHelper(这个下面再单独介绍)、CapturerObserver:提供视频视频捕获开始、停止和VideoFrame的回调;
#startCapture:入参是捕获的videoframe的宽、高和帧率;
这个方法判断了如果没有initialize则抛出RuntimeException异常,此外使用了stateLock来做多线程同步。在子线程用createCameraSession,创建CameraSession。如果10s后没有开启摄像头则在主线程抛出异常;

3.SurfaceTextureHelper
#通过opengles提供采集的videoframe的修改的SurfaceTexture,主要是旋转矩阵和时间戳。
#这里有个要注意的点是在构造SurfaceTextureHelper时,设置了SurfaceTexture.OnFrameAvailableListener:

setOnFrameAvailableListener(surfaceTexture, (SurfaceTexture st) -> {
  if (hasPendingTexture) {
    Logging.d(TAG, "A frame is already pending, dropping frame.");
  }
  hasPendingTexture = true;
  tryDeliverTextureFrame();
}, handler);

在Frame回调时tryDeliverTextureFrame方法会创建并回调VideoFrame给VideoSink;的onFrame方法;我们可以对帧进行处理;
这里Frame还会通过VideoCapture在initialize时传入的CapturerObserver,通知给VideoSource

@Override
public void onFrameCaptured(VideoFrame frame) {
  final VideoProcessor.FrameAdaptationParameters parameters =
      nativeAndroidVideoTrackSource.adaptFrame(frame);
 synchronized (videoProcessorLock) {
    if (videoProcessor != null) {
      videoProcessor.onFrameCaptured(frame, parameters);
 return;  }
  }
  VideoFrame adaptedFrame = VideoProcessor.applyFrameAdaptationParameters(frame, parameters);
 if (adaptedFrame != null) {
    nativeAndroidVideoTrackSource.onFrameCaptured(adaptedFrame);
  adaptedFrame.release();
  }
}

在这里nativeAndroidVideoTrackSource.onFrameCaptured回调给了webrtc的jni层。采集流程到这里就结束了,下面是渲染、发送,我们下面再继续分析;
¥简单总结下:CapturerObserver在两个地方有注册回调,一个是VideoCapture(这是个接口),另一个是VideoSource
#提供释放opengl资源的release方法;
4.CameraSession这个逻辑在Camera1Session和Camera2Session不一致,因为我们支持的版本是5.0以上,所以我只看了Camera2Session。
构造方法中调用了:
#start():通过摄像头提供的参数获取采集参数并开启摄像头;
#openCamera()方法是通过android系统的Context.CAMERA_SERVICE的openCamera方式实现的,这是个异步方法,我们通过传入CameraStateCallback获取摄像头开启的回调。在onOpened回调中CameraDevice.createCaptureSession并注册CaptureSessionCallback回调,同时new一个Surface作为相机buffer的消费者。可以简单的理解为把videoFrame通过opengles绘制到Surface上;

对于屏幕分享,没有上面的Emulator,直接new一个ScreenCapturerAndroid,其他方法基本和VideoCapturer一样