WebRTC VideoEngine 本地Video数据处理-Encode

本文详细解析了WebRTC中ViEEncoder如何处理Video数据,包括对象初始化、DeliverFrame方法、编码器配置、编码过程以及编码输出数据的获取。通过VideoSendStream::Config初始化设置,VideoSender::AddVideoFrame添加视频帧,然后进行编码操作,最后通过编码回调处理编码后的数据。
摘要由CSDN通过智能技术生成

前面分析到,video数据由VideoCaptureInput,通过DeliverFrame函数传递到ViEEncoder来进行处理.
这里详细分析ViEEncoder对Video数据的处理过程:

ViEEncoder对象初始化

在End_to_End_tests中的RunTest()中创建的VideoSendStream::Config send_config,并定义pre_encode_callback_,用于对送入Encoder的frame进行预处理

Call::CreateVideoSendStream(send_config, ..)
new VideoSendStream(.., config,..)
new ViEEncoder(.., config.pre_encode_callback, ..)

例如自定义类A,其对象a要使用这一功能,需要按以下方式进行实现:

  • A要继承I420FrameCallback类
  • override FrameCallback方法,实现需要做的预处理,可以自己实现,也可以很容易的就集成现有的图像处理库(opencv .etc)
  • 创建VideoSendStream::Config send_config, 并初始化pre_encode_callback_
  • 根据send_config创建VideoSendStream对象

ViEEncoder::DeliverFrame

将video数据送入编码器

    // Pass frame via preprocessor.
    const int ret = vpm_->PreprocessFrame(video_frame, &decimated_frame);

VideoProcessingModuleImpl::PreprocessFrame
VPMFramePreprocessor::PreprocessFrame

  • resize if needed (VPMSimpleSpatialResampler::ResampleFrame(frame,
    &resampled_frame_))
  • content analysis ( VPMContentAnalysis::ComputeContentMetrics)

对送入编码器的数据进行预处理,在现有的代码中没有相应的实现

  if (pre_encode_callback_) {
    ....
    pre_encode_callback_->FrameCallback(decimated_frame);
  }

将准备好的数据送入编码器:

    vcm_->AddVideoFrame(*output_frame);

调用关系:

VideoCodingModule::AddVideoFrame
VideoCodingModuleImpl::AddVideoFrame
VideoSender::AddVideoFrame

VideoSender::AddVideoFrame

编码器以及编码参数配置

编码器初始化流程及参数配置:
编码器初始化流程及参数配置

创建Config信息:
所有的编码器选择,编码器参数,编码输出数据的callback函数都是在这里进行配置的

VideoSendStream::Config send_config

  • EncoderSettings(payload_name,payload_type, VideoEncoder对象(选择对应的encode类型(H264)))
  • Rtp(max_packet_size, RtpExtension, NackConfig, FecConfig, Rtx())
  • send_transport //Transport for outgoing packets.
  • LoadObserver* overuse_callback, 当前系统的负载情况,根据incoming capture frame的jitter计算
  • I420FrameCallback*
  • EncodedFrameObserver* post_encode_callback,编码输出帧的处理
  • VideoRenderer* local_renderer,Renderer for local preview
  • VideoCaptureInput* Input(),video数据输入

VideoEncoderConfig encoder_config

  • vector< VideoStream > streams 视频流的常规参数配置(width, height, framerate, bitrate(min/max/target), qp )

创建Encoder,参考EndToEndTest中的实现

  rtc::scoped_ptr< VideoEncoder > encoder(
      VideoEncoder::Create(VideoEncoder::kVp8));
  //根据需要传入不同的参数,初始化不同的encoder
  //VP8Encoder::Create();
  send_config_.encoder_settings.encoder = encoder.get();

创建一个VideoEncoder对象,保存在VideoSendStream::Config中通话下面的调用顺序,进行设置:

CreateVideoSendStream(send_config_, ...);
VideoSendStream::VideoSendStream(..., config, ...);
VideoEncoder::RegisterExternalEncoder(
                      config.encoder_settings.encoder, ...);
ViEEncoder::RegisterExternalEncoder(encoder, ...);
VideoCodingModuleImpl::RegisterExternalEncoder(externalEncoder, ...);
VideoSender::RegisterExternalEncoder(externalEncoder, ...);
VCMCodecDataBase::RegisterExternalEncoder(external_encoder, ...);                     

最终保存在VCMCodecDataBase的成员变量external_encoder_中。

初始化VideoSendStream对象
这个对象很重要,所有上行数据的操作都是从这里开始的:

  • ViEEncoder初始化
  • ViEChannel初始化
  • VideoCaptureInput初始化
  • EncodedFrameObserver 编码输出码流问题
    构造函数的具体实现:
VideoSendStream::VideoSendStream(
    int num_cpu_cores,
    ProcessThread* module_process_thread,
    CallStats* call_stats,
    CongestionController* congestion_controller,
    const VideoSendStream::Config& config,
    const VideoEncoderConfig& encoder_config,
    const std::map<uint32_t, RtpState>& suspended_ssrcs)
    : stats_proxy_(Clock::GetRealTimeClock(), config),
      transport_adapter_(config.send_transport),
      encoded_frame_proxy_(config.post_encode_callback),
      config_(config),
      suspended_ssrcs_(suspended_ssrcs),
      m
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值