前言
源码分析
Conductor::AddTracks
void Conductor::AddTracks() {
**
// 创建视频设备
rtc::scoped_refptr<CapturerTrackSource> video_device =
CapturerTrackSource::Create();
****
}
—》 CapturerTrackSource::Create();
CapturerTrackSource::Create
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));
}
}
}
—》 webrtc::VideoCaptureFactory::CreateDeviceInfo());
VideoCaptureFactory::CreateDeviceInfo
VideoCaptureModule::DeviceInfo* VideoCaptureFactory::CreateDeviceInfo() {
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC)
return nullptr;
#else
return videocapturemodule::VideoCaptureImpl::CreateDeviceInfo();
#endif
}
—》videocapturemodule::VideoCaptureImpl::CreateDeviceInfo();
VideoCaptureModule::DeviceInfo* VideoCaptureImpl::CreateDeviceInfo() {
// TODO(tommi): Use the Media Foundation version on Vista and up.
return DeviceInfoDS::Create();
}
DeviceInfoDS::Create
// static
DeviceInfoDS* DeviceInfoDS::Create() {
DeviceInfoDS* dsInfo = new DeviceInfoDS();
if (!dsInfo || dsInfo->Init() != 0) {
delete dsInfo;
dsInfo = NULL;
}
return dsInfo;
}
DeviceInfoDS::DeviceInfoDS()
DeviceInfoDS::DeviceInfoDS()
: _dsDevEnum(NULL),
_dsMonikerDevEnum(NULL),
_CoUninitializeIsRequired(true) {
// 1) Initialize the COM library (make Windows load the DLLs).
//
// CoInitializeEx must be called at least once, and is usually called only
// once, for each thread that uses the COM library. Multiple calls to
// CoInitializeEx by the same thread are allowed as long as they pass the same
// concurrency flag, but subsequent valid calls return S_FALSE. To close the
// COM library gracefully on a thread, each successful call to CoInitializeEx,
// including any call that returns S_FALSE, must be balanced by a
// corresponding call to CoUninitialize.
//
/*Apartment-threading, while allowing for multiple threads of execution,
serializes all incoming calls by requiring that calls to methods of objects
created by this thread always run on the same thread the apartment/thread
that created them. In addition, calls can arrive only at message-queue
boundaries (i.e., only during a PeekMessage, SendMessage, DispatchMessage,
etc.). Because of this serialization, it is not typically necessary to write
concurrency control into the code for the object, other than to avoid calls
to PeekMessage and SendMessage during processing that must not be interrupted
by other method invocations or calls to other objects in the same
apartment/thread.*/
/// CoInitializeEx(NULL, COINIT_APARTMENTTHREADED ); //|
/// COINIT_SPEED_OVER_MEMORY
HRESULT hr = CoInitializeEx(
NULL, COINIT_MULTITHREADED); // Use COINIT_MULTITHREADED since Voice
// Engine uses COINIT_MULTITHREADED
if (FAILED(hr)) {
// Avoid calling CoUninitialize() since CoInitializeEx() failed.
_CoUninitializeIsRequired = FALSE;
if (hr == RPC_E_CHANGED_MODE) {
// Calling thread has already initialized COM to be used in a
// single-threaded apartment (STA). We are then prevented from using STA.
// Details: hr = 0x80010106 <=> "Cannot change thread mode after it is
// set".
//
RTC_DLOG(LS_INFO) << __FUNCTION__
<< ": CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)"
" => RPC_E_CHANGED_MODE, error 0x"
<< rtc::ToHex(hr);
}
}
}
DeviceInfoDS::Init()
int32_t DeviceInfoDS::Init() {
// 创建SystemDeviceEnum的com组件
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void**)&_dsDevEnum);
if (hr != NOERROR) {
RTC_LOG(LS_INFO) << "Failed to create CLSID_SystemDeviceEnum, error 0x"
<< rtc::ToHex(hr);
return -1;
}
return 0;
}