前言
CLSCTX_INPROC_SERVER 导入的COM组件,跟当前逻辑共用同一个进程。
代码分析
CapturerTrackSource::Create
H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\examples\peerconnection\client\conductor.cc
static rtc::scoped_refptr<CapturerTrackSource> Create() {
const size_t kWidth = 640;
const size_t kHeight = 480;
const size_t kFps = 30;
std::unique_ptr<webrtc::test::VcmCapturer> capturer;
std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> info(
webrtc::VideoCaptureFactory::CreateDeviceInfo());
if (!info) {
return nullptr;
}
int num_devices = info->NumberOfDevices();
for (int i = 0; i < num_devices; ++i) {
capturer = absl::WrapUnique(
webrtc::test::VcmCapturer::Create(kWidth, kHeight, kFps, i));
if (capturer) {
return new rtc::RefCountedObject<CapturerTrackSource>(
std::move(capturer));
}
}
return nullptr;
}
—-》 capturer = absl::WrapUnique(
webrtc::test::VcmCapturer::Create(kWidth, kHeight, kFps, i));
VcmCapturer::Create
VcmCapturer* VcmCapturer::Create(size_t width,
size_t height,
size_t target_fps,
size_t capture_device_index) {
std::unique_ptr<VcmCapturer> vcm_capturer(new VcmCapturer());
if (!vcm_capturer->Init(width, height, target_fps, capture_device_index)) {
RTC_LOG(LS_WARNING) << "Failed to create VcmCapturer(w = " << width
<< ", h = " << height << ", fps = " << target_fps
<< ")";
return nullptr;
}
return vcm_capturer.release();
}
—》vcm_capturer->Init(width, height, target_fps, capture_device_index)
VcmCapturer::Init
bool VcmCapturer::Init(size_t width,
size_t height,
size_t target_fps,
size_t capture_device_index) {
std::unique_ptr<VideoCaptureModule::DeviceInfo> device_info(
VideoCaptureFactory::CreateDeviceInfo());
// 获取设备名称
char device_name[256];
char unique_name[256];
if (device_info->GetDeviceName(static_cast<uint32_t>(capture_device_index),
device_name, sizeof(device_name), unique_name,
sizeof(unique_name)) != 0) {
Destroy();
return false;
}
//根据设备名称,创建VideoCaptureModule实例
vcm_ = webrtc::VideoCaptureFactory::Create(unique_name);
if (!vcm_) {
return false;
}
// 创建成功,则传入采集数据回调,当采集到视频数据就会调用回调
vcm_->RegisterCaptureDataCallback(this);
// 获取设备的能力
device_info->GetCapability(vcm_->CurrentDeviceName(), 0, capability_);
// 根据传入参数传入到capability_变量中
capability_.width = static_cast<int32_t>(width);
capability_.height = static_cast<int32_t>(height);
capability_.maxFPS = static_cast<int32_t>(target_fps);
capability_.videoType = VideoType::kI420;
// vcm实例以capability_的值开始采集,此时,设备已经开始工作了。
if (vcm_->StartCapture(capability_) != 0) {
Destroy();
return false;
}
RTC_CHECK(vcm_->CaptureStarted());
return true;
}
—》 vcm_ = webrtc::VideoCaptureFactory::Create(unique_name);
VideoCaptureFactory::Create
rtc::scoped_refptr<VideoCaptureModule> VideoCaptureFactory::Create(
const char* deviceUniqueIdUTF8) {
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC)
return nullptr;
#else
return videocapturemodule::VideoCaptureImpl::Create(deviceUniqueIdUTF8);
#endif
—》videocapturemodule::VideoCaptureImpl::Create(deviceUniqueIdUTF8);
VideoCaptureImpl::Create
rtc::scoped_refptr<VideoCaptureModule> VideoCaptureImpl::Create(
const char* device_id) {
if (device_id == nullptr)
return nullptr;
// TODO(tommi): Use Media Foundation implementation for Vista and up.
rtc::scoped_refptr<VideoCaptureDS> capture(
new rtc::RefCountedObject<VideoCaptureDS>());
if (capture->Init(device_id) != 0) {
return nullptr;
}
return capture;
}
VideoCaptureDS::Init
int32_t VideoCaptureDS::Init(const char* deviceUniqueIdUTF8) {
const int32_t nameLength = (int32_t)strlen((char*)deviceUniqueIdUTF8);
if (nameLength > kVideoCaptureUniqueNameLength)
return -1;
// Store the device name
_deviceUniqueId = new (std::nothrow) char[nameLength + 1];
memcpy(_deviceUniqueId, deviceUniqueIdUTF8, nameLength + 1);
if (_dsInfo.Init() != 0)
return -1;
_captureFilter = _dsInfo.GetDeviceFilter(deviceUniqueIdUTF8);
if (!_captureFilter) {
RTC_LOG(LS_INFO) << "Failed to create capture filter.";
return -1;
}
// Get the interface for DirectShow's GraphBuilder
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void**)&_graphBuilder);
if (FAILED(hr)) {
RTC_LOG(LS_INFO) << "Failed to create graph builder.";
return -1;
}
// 获取IID_IMediaControl接口
hr = _graphBuilder->QueryInterface(IID_IMediaControl, (void**)&_mediaControl);
if (FAILED(hr)) {
RTC_LOG(LS_INFO) << "Failed to create media control builder.";
return -1;
}
hr = _graphBuilder->AddFilter(_captureFilter, CAPTURE_FILTER_NAME);
if (FAILED(hr)) {
RTC_LOG(LS_INFO) << "Failed to add the capture device to the graph.";
return -1;
}
_outputCapturePin = GetOutputPin(_captureFilter, PIN_CATEGORY_CAPTURE);
if (!_outputCapturePin) {
RTC_LOG(LS_INFO) << "Failed to get output capture pin";
return -1;
}
// Create the sink filte used for receiving Captured frames.
sink_filter_ = new ComRefCount<CaptureSinkFilter>(this);
hr = _graphBuilder->AddFilter(sink_filter_, SINK_FILTER_NAME);
if (FAILED(hr)) {
RTC_LOG(LS_INFO) << "Failed to add the send filter to the graph.";
return -1;
}
_inputSendPin = GetInputPin(sink_filter_);
if (!_inputSendPin) {
RTC_LOG(LS_INFO) << "Failed to get input send pin";
return -1;
}
// Temporary connect here.
// This is done so that no one else can use the capture device.
if (SetCameraOutput(_requestedCapability) != 0) {
return -1;
}
// 在后面VcmCapturer::Init()中调用vcm_->StartCapture(capability_)的时候,才开始采集。
// H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\test\vcm_capturer.cc
hr = _mediaControl->Pause();
if (FAILED(hr)) {
RTC_LOG(LS_INFO)
<< "Failed to Pause the Capture device. Is it already occupied? " << hr;
return -1;
}
RTC_LOG(LS_INFO) << "Capture device '" << deviceUniqueIdUTF8
<< "' initialized.";
return 0;
}