前言

image.png

CLSCTX_INPROC_SERVER 导入的COM组件,跟当前逻辑共用同一个进程。

image.png
image.png

代码分析

8-5 源码分析-视频处理流程的建立

CapturerTrackSource::Create

H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\examples\peerconnection\client\conductor.cc

  1. static rtc::scoped_refptr<CapturerTrackSource> Create() {
  2. const size_t kWidth = 640;
  3. const size_t kHeight = 480;
  4. const size_t kFps = 30;
  5. std::unique_ptr<webrtc::test::VcmCapturer> capturer;
  6. std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> info(
  7. webrtc::VideoCaptureFactory::CreateDeviceInfo());
  8. if (!info) {
  9. return nullptr;
  10. }
  11. int num_devices = info->NumberOfDevices();
  12. for (int i = 0; i < num_devices; ++i) {
  13. capturer = absl::WrapUnique(
  14. webrtc::test::VcmCapturer::Create(kWidth, kHeight, kFps, i));
  15. if (capturer) {
  16. return new rtc::RefCountedObject<CapturerTrackSource>(
  17. std::move(capturer));
  18. }
  19. }
  20. return nullptr;
  21. }

—-》 capturer = absl::WrapUnique(
webrtc::test::VcmCapturer::Create(kWidth, kHeight, kFps, i));

VcmCapturer::Create

  1. VcmCapturer* VcmCapturer::Create(size_t width,
  2. size_t height,
  3. size_t target_fps,
  4. size_t capture_device_index) {
  5. std::unique_ptr<VcmCapturer> vcm_capturer(new VcmCapturer());
  6. if (!vcm_capturer->Init(width, height, target_fps, capture_device_index)) {
  7. RTC_LOG(LS_WARNING) << "Failed to create VcmCapturer(w = " << width
  8. << ", h = " << height << ", fps = " << target_fps
  9. << ")";
  10. return nullptr;
  11. }
  12. return vcm_capturer.release();
  13. }

—》vcm_capturer->Init(width, height, target_fps, capture_device_index)

VcmCapturer::Init

  1. bool VcmCapturer::Init(size_t width,
  2. size_t height,
  3. size_t target_fps,
  4. size_t capture_device_index) {
  5. std::unique_ptr<VideoCaptureModule::DeviceInfo> device_info(
  6. VideoCaptureFactory::CreateDeviceInfo());
  7. // 获取设备名称
  8. char device_name[256];
  9. char unique_name[256];
  10. if (device_info->GetDeviceName(static_cast<uint32_t>(capture_device_index),
  11. device_name, sizeof(device_name), unique_name,
  12. sizeof(unique_name)) != 0) {
  13. Destroy();
  14. return false;
  15. }
  16. //根据设备名称,创建VideoCaptureModule实例
  17. vcm_ = webrtc::VideoCaptureFactory::Create(unique_name);
  18. if (!vcm_) {
  19. return false;
  20. }
  21. // 创建成功,则传入采集数据回调,当采集到视频数据就会调用回调
  22. vcm_->RegisterCaptureDataCallback(this);
  23. // 获取设备的能力
  24. device_info->GetCapability(vcm_->CurrentDeviceName(), 0, capability_);
  25. // 根据传入参数传入到capability_变量中
  26. capability_.width = static_cast<int32_t>(width);
  27. capability_.height = static_cast<int32_t>(height);
  28. capability_.maxFPS = static_cast<int32_t>(target_fps);
  29. capability_.videoType = VideoType::kI420;
  30. // vcm实例以capability_的值开始采集,此时,设备已经开始工作了。
  31. if (vcm_->StartCapture(capability_) != 0) {
  32. Destroy();
  33. return false;
  34. }
  35. RTC_CHECK(vcm_->CaptureStarted());
  36. return true;
  37. }

—》 vcm_ = webrtc::VideoCaptureFactory::Create(unique_name);

VideoCaptureFactory::Create

  1. rtc::scoped_refptr<VideoCaptureModule> VideoCaptureFactory::Create(
  2. const char* deviceUniqueIdUTF8) {
  3. #if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC)
  4. return nullptr;
  5. #else
  6. return videocapturemodule::VideoCaptureImpl::Create(deviceUniqueIdUTF8);
  7. #endif

—》videocapturemodule::VideoCaptureImpl::Create(deviceUniqueIdUTF8);

VideoCaptureImpl::Create

  1. rtc::scoped_refptr<VideoCaptureModule> VideoCaptureImpl::Create(
  2. const char* device_id) {
  3. if (device_id == nullptr)
  4. return nullptr;
  5. // TODO(tommi): Use Media Foundation implementation for Vista and up.
  6. rtc::scoped_refptr<VideoCaptureDS> capture(
  7. new rtc::RefCountedObject<VideoCaptureDS>());
  8. if (capture->Init(device_id) != 0) {
  9. return nullptr;
  10. }
  11. return capture;
  12. }

—》

VideoCaptureDS::Init

  1. int32_t VideoCaptureDS::Init(const char* deviceUniqueIdUTF8) {
  2. const int32_t nameLength = (int32_t)strlen((char*)deviceUniqueIdUTF8);
  3. if (nameLength > kVideoCaptureUniqueNameLength)
  4. return -1;
  5. // Store the device name
  6. _deviceUniqueId = new (std::nothrow) char[nameLength + 1];
  7. memcpy(_deviceUniqueId, deviceUniqueIdUTF8, nameLength + 1);
  8. if (_dsInfo.Init() != 0)
  9. return -1;
  10. _captureFilter = _dsInfo.GetDeviceFilter(deviceUniqueIdUTF8);
  11. if (!_captureFilter) {
  12. RTC_LOG(LS_INFO) << "Failed to create capture filter.";
  13. return -1;
  14. }
  15. // Get the interface for DirectShow's GraphBuilder
  16. HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
  17. IID_IGraphBuilder, (void**)&_graphBuilder);
  18. if (FAILED(hr)) {
  19. RTC_LOG(LS_INFO) << "Failed to create graph builder.";
  20. return -1;
  21. }
  22. // 获取IID_IMediaControl接口
  23. hr = _graphBuilder->QueryInterface(IID_IMediaControl, (void**)&_mediaControl);
  24. if (FAILED(hr)) {
  25. RTC_LOG(LS_INFO) << "Failed to create media control builder.";
  26. return -1;
  27. }
  28. hr = _graphBuilder->AddFilter(_captureFilter, CAPTURE_FILTER_NAME);
  29. if (FAILED(hr)) {
  30. RTC_LOG(LS_INFO) << "Failed to add the capture device to the graph.";
  31. return -1;
  32. }
  33. _outputCapturePin = GetOutputPin(_captureFilter, PIN_CATEGORY_CAPTURE);
  34. if (!_outputCapturePin) {
  35. RTC_LOG(LS_INFO) << "Failed to get output capture pin";
  36. return -1;
  37. }
  38. // Create the sink filte used for receiving Captured frames.
  39. sink_filter_ = new ComRefCount<CaptureSinkFilter>(this);
  40. hr = _graphBuilder->AddFilter(sink_filter_, SINK_FILTER_NAME);
  41. if (FAILED(hr)) {
  42. RTC_LOG(LS_INFO) << "Failed to add the send filter to the graph.";
  43. return -1;
  44. }
  45. _inputSendPin = GetInputPin(sink_filter_);
  46. if (!_inputSendPin) {
  47. RTC_LOG(LS_INFO) << "Failed to get input send pin";
  48. return -1;
  49. }
  50. // Temporary connect here.
  51. // This is done so that no one else can use the capture device.
  52. if (SetCameraOutput(_requestedCapability) != 0) {
  53. return -1;
  54. }
  55. // 在后面VcmCapturer::Init()中调用vcm_->StartCapture(capability_)的时候,才开始采集。
  56. // H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\test\vcm_capturer.cc
  57. hr = _mediaControl->Pause();
  58. if (FAILED(hr)) {
  59. RTC_LOG(LS_INFO)
  60. << "Failed to Pause the Capture device. Is it already occupied? " << hr;
  61. return -1;
  62. }
  63. RTC_LOG(LS_INFO) << "Capture device '" << deviceUniqueIdUTF8
  64. << "' initialized.";
  65. return 0;
  66. }

image.png