WebRTC视频 01 - 视频采集整体架构
WebRTC视频 02 - 视频采集类 VideoCaptureModule
WebRTC视频 03 - 视频采集类 VideoCaptureDS 上篇
WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇
WebRTC视频 05 - 视频采集类 VideoCaptureDS 下篇(本文)
一、前言:
前面介绍了视频数据采集,那么采集到的数据如何上传给上层应用的?本节看看。
二、流程图:

CaptureFilter从Camera采集到数据之后交给SinkFilter;- 通过
SinkFilter获取到数据之后,会调用VideoCaptureImpl的IncomingFrame; - 接着调用
DeliverCapturedFrame,里面会调用RegisterCaptureDataCallback的onFrame,将数据传给onFrame函数; - 接下来再交给
VcmCapturer::OnFrame,里面会交给VideoBroadcaster; VideoBroadcaster::OnFrame会将采集到数据进行分两路,本地渲染和编码器(注意看数据有没有copy);- 还记得本地渲染器和编码器什么时候加入到
VideoBroadcaster当中的吗?本地渲染器是StartLocalRenderer时候加入的,编码器是媒体协商最后一步SetRemoteDescription的时候加入的;
三、代码走读:
首先看看SinkFilter接收数据的地方:
/**
* 接收采集到的视频数据时候,首先会进入到这儿
* @param media_sample:就是采集到的数据
*/
STDMETHODIMP CaptureInputPin::Receive(IMediaSample* media_sample) {
RTC_DCHECK_RUN_ON(&capture_checker_);
// 通过Filter()获取到这个pin所属的filter,也就是sinkFilter
CaptureSinkFilter* const filter = static_cast<CaptureSinkFilter*>(Filter());
if (flushing_.load(std::memory_order_relaxed))
return S_FALSE;
if (runtime_error_.load(std::memory_order_relaxed))
return VFW_E_RUNTIME_ERROR;
// 确保采集线程id已经获得,并给线程起个名字webrtc_video_capture
if (!capture_thread_id_) {
// Make sure we set the thread name only once.
capture_thread_id_ = GetCurrentThreadId();
rtc::SetCurrentThreadName("webrtc_video_capture");
}
// 获取采样属性,看其中是否包含AM_SAMPLE_TYPECHANGED,如果包含了,会做一些处理
AM_SAMPLE2_PROPERTIES sample_props = {
};
GetSampleProperties(media_sample, &sample_props);
// Has the format changed in this sample?
if (sample_props.dwSampleFlags & AM_SAMPLE_TYPECHANGED) {
// Check the derived class accepts the new format.
// This shouldn't fail as the source must call QueryAccept first.
// Note: This will modify resulting_capability_.
// That should be OK as long as resulting_capability_ is only modified
// on this thread while it is running (filter is not stopped), and only
// modified on the main thread when the filter is stopped (i.e. this thread
// is not running).
if (!TranslateMediaTypeToVideoCaptureCapability(sample_props.pMediaType,
&resulting_capability_)) {
// Raise a runtime error if we fail the media type
runtime_error_ = true;
EndOfStream();
Filter()->NotifyEvent(EC_ERRORABORT, VFW_E_TYPE_NOT_ACCEPTED, 0);
return VFW_E_INVALIDMEDIATYPE;
}
}
// 收到数据之后调用这个方法将数据从pin传给filter
filter->ProcessCapturedFrame(sample_props.pbBuffer, sample_props.lActual,
resulting_capability_

最低0.47元/天 解锁文章
7494

被折叠的 条评论
为什么被折叠?



