前言

image.png
三大部分:
MainWin:处理界面相关内容,创建窗口,渲染界面,切换界面等;
conductor:调用native webrtc api,处理音视频通信;包括协调MainWin和peer_connection_client两部分工作。
peer_connection_client: 用于处理信令的发送接收

image.png

wWinMain入口函数

  1. int PASCAL wWinMain(HINSTANCE instance,
  2. HINSTANCE prev_instance,
  3. wchar_t* cmd_line,
  4. int cmd_show) {
  5. // socket的初始化
  6. rtc::WinsockInitializer winsock_init;
  7. rtc::PhysicalSocketServer ss;
  8. // 线程
  9. rtc::AutoSocketServerThread main_thread(&ss);
  10. // 命令行解析相关
  11. WindowsCommandLineArguments win_args;
  12. int argc = win_args.argc();
  13. char** argv = win_args.argv();
  14. absl::ParseCommandLine(argc, argv);
  15. // InitFieldTrialsFromString stores the char*, so the char array must outlive
  16. // the application.
  17. const std::string forced_field_trials =
  18. absl::GetFlag(FLAGS_force_fieldtrials);
  19. webrtc::field_trial::InitFieldTrialsFromString(forced_field_trials.c_str());
  20. // Abort if the user specifies a port that is outside the allowed
  21. // range [1, 65535].
  22. if ((absl::GetFlag(FLAGS_port) < 1) || (absl::GetFlag(FLAGS_port) > 65535)) {
  23. printf("Error: %i is not a valid port.\n", absl::GetFlag(FLAGS_port));
  24. return -1;
  25. }
  26. // 创建窗口
  27. const std::string server = absl::GetFlag(FLAGS_server);
  28. MainWnd wnd(server.c_str(), absl::GetFlag(FLAGS_port),
  29. absl::GetFlag(FLAGS_autoconnect), absl::GetFlag(FLAGS_autocall));
  30. // 注册窗口类,创建窗口,显示窗口
  31. if (!wnd.Create()) {
  32. RTC_DCHECK_NOTREACHED();
  33. return -1;
  34. }
  35. // 初始化ssl
  36. rtc::InitializeSSL();
  37. // 创建PeerConnectionClient对象,用于处理信令发送接收
  38. PeerConnectionClient client;
  39. // 创建Conductor对象,协调PeerConnectionClient对象和主窗口wnd的工作
  40. auto conductor = rtc::make_ref_counted<Conductor>(&client, &wnd);
  41. // Main loop.
  42. MSG msg;
  43. BOOL gm;
  44. while ((gm = ::GetMessage(&msg, NULL, 0, 0)) != 0 && gm != -1) {
  45. if (!wnd.PreTranslateMessage(&msg)) {
  46. ::TranslateMessage(&msg);
  47. ::DispatchMessage(&msg);
  48. }
  49. }
  50. // 客户端的关闭操作
  51. if (conductor->connection_active() || client.is_connected()) {
  52. while ((conductor->connection_active() || client.is_connected()) &&
  53. (gm = ::GetMessage(&msg, NULL, 0, 0)) != 0 && gm != -1) {
  54. if (!wnd.PreTranslateMessage(&msg)) {
  55. ::TranslateMessage(&msg);
  56. ::DispatchMessage(&msg);
  57. }
  58. }
  59. }
  60. // 清理ssl
  61. rtc::CleanupSSL();
  62. return 0;
  63. }

创建窗口

  1. bool MainWnd::Create() {
  2. RTC_DCHECK(wnd_ == NULL);
  3. // 注册窗口类
  4. if (!RegisterWindowClass())
  5. return false;
  6. ui_thread_id_ = ::GetCurrentThreadId();
  7. // 创建窗口
  8. wnd_ =
  9. ::CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, kClassName, L"WebRTC",
  10. WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
  11. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  12. CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), this);
  13. ::SendMessage(wnd_, WM_SETFONT, reinterpret_cast<WPARAM>(GetDefaultFont()),
  14. TRUE);
  15. // 创建主窗口
  16. CreateChildWindows();
  17. // 切换到连接界面
  18. SwitchToConnectUI();
  19. return wnd_ != NULL;
  20. }
  21. bool MainWnd::RegisterWindowClass() {
  22. if (wnd_class_)
  23. return true;
  24. WNDCLASSEXW wcex = {sizeof(WNDCLASSEX)};
  25. wcex.style = CS_DBLCLKS;
  26. wcex.hInstance = GetModuleHandle(NULL);
  27. wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
  28. wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);
  29. wcex.lpfnWndProc = &WndProc; // 绑定消息处理
  30. wcex.lpszClassName = kClassName;
  31. wnd_class_ = ::RegisterClassExW(&wcex);
  32. RTC_DCHECK(wnd_class_ != 0);
  33. return wnd_class_ != 0;
  34. }
  35. void MainWnd::SwitchToConnectUI() {
  36. RTC_DCHECK(IsWindow());
  37. // 隐藏连接列表
  38. LayoutPeerListUI(false);
  39. ui_ = CONNECT_TO_SERVER;
  40. // 显示连接界面
  41. LayoutConnectUI(true);
  42. ::SetFocus(edit1_);
  43. if (auto_connect_)
  44. ::PostMessage(button_, BM_CLICK, 0, 0);
  45. }

处理消息

  1. LRESULT CALLBACK MainWnd::WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
  2. MainWnd* me =
  3. reinterpret_cast<MainWnd*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
  4. if (!me && WM_CREATE == msg) {
  5. CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lp);
  6. me = reinterpret_cast<MainWnd*>(cs->lpCreateParams);
  7. me->wnd_ = hwnd;
  8. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(me));
  9. }
  10. LRESULT result = 0;
  11. if (me) {
  12. void* prev_nested_msg = me->nested_msg_;
  13. me->nested_msg_ = &msg;
  14. bool handled = me->OnMessage(msg, wp, lp, &result);
  15. if (WM_NCDESTROY == msg) {
  16. me->destroyed_ = true;
  17. } else if (!handled) {
  18. result = ::DefWindowProc(hwnd, msg, wp, lp);
  19. }
  20. if (me->destroyed_ && prev_nested_msg == NULL) {
  21. me->OnDestroyed();
  22. me->wnd_ = NULL;
  23. me->destroyed_ = false;
  24. }
  25. me->nested_msg_ = prev_nested_msg;
  26. } else {
  27. result = ::DefWindowProc(hwnd, msg, wp, lp);
  28. }
  29. return result;
  30. }

后面都是调用到OnMessage函数处理。
bool MainWnd::OnMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT* result)

image.png