前言
三大部分:
MainWin:处理界面相关内容,创建窗口,渲染界面,切换界面等;
conductor:调用native webrtc api,处理音视频通信;包括协调MainWin和peer_connection_client两部分工作。
peer_connection_client: 用于处理信令的发送接收
wWinMain入口函数
int PASCAL wWinMain(HINSTANCE instance,
HINSTANCE prev_instance,
wchar_t* cmd_line,
int cmd_show) {
// socket的初始化
rtc::WinsockInitializer winsock_init;
rtc::PhysicalSocketServer ss;
// 线程
rtc::AutoSocketServerThread main_thread(&ss);
// 命令行解析相关
WindowsCommandLineArguments win_args;
int argc = win_args.argc();
char** argv = win_args.argv();
absl::ParseCommandLine(argc, argv);
// InitFieldTrialsFromString stores the char*, so the char array must outlive
// the application.
const std::string forced_field_trials =
absl::GetFlag(FLAGS_force_fieldtrials);
webrtc::field_trial::InitFieldTrialsFromString(forced_field_trials.c_str());
// Abort if the user specifies a port that is outside the allowed
// range [1, 65535].
if ((absl::GetFlag(FLAGS_port) < 1) || (absl::GetFlag(FLAGS_port) > 65535)) {
printf("Error: %i is not a valid port.\n", absl::GetFlag(FLAGS_port));
return -1;
}
// 创建窗口
const std::string server = absl::GetFlag(FLAGS_server);
MainWnd wnd(server.c_str(), absl::GetFlag(FLAGS_port),
absl::GetFlag(FLAGS_autoconnect), absl::GetFlag(FLAGS_autocall));
// 注册窗口类,创建窗口,显示窗口
if (!wnd.Create()) {
RTC_DCHECK_NOTREACHED();
return -1;
}
// 初始化ssl
rtc::InitializeSSL();
// 创建PeerConnectionClient对象,用于处理信令发送接收
PeerConnectionClient client;
// 创建Conductor对象,协调PeerConnectionClient对象和主窗口wnd的工作
auto conductor = rtc::make_ref_counted<Conductor>(&client, &wnd);
// Main loop.
MSG msg;
BOOL gm;
while ((gm = ::GetMessage(&msg, NULL, 0, 0)) != 0 && gm != -1) {
if (!wnd.PreTranslateMessage(&msg)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
// 客户端的关闭操作
if (conductor->connection_active() || client.is_connected()) {
while ((conductor->connection_active() || client.is_connected()) &&
(gm = ::GetMessage(&msg, NULL, 0, 0)) != 0 && gm != -1) {
if (!wnd.PreTranslateMessage(&msg)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
}
// 清理ssl
rtc::CleanupSSL();
return 0;
}
创建窗口
bool MainWnd::Create() {
RTC_DCHECK(wnd_ == NULL);
// 注册窗口类
if (!RegisterWindowClass())
return false;
ui_thread_id_ = ::GetCurrentThreadId();
// 创建窗口
wnd_ =
::CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, kClassName, L"WebRTC",
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), this);
::SendMessage(wnd_, WM_SETFONT, reinterpret_cast<WPARAM>(GetDefaultFont()),
TRUE);
// 创建主窗口
CreateChildWindows();
// 切换到连接界面
SwitchToConnectUI();
return wnd_ != NULL;
}
bool MainWnd::RegisterWindowClass() {
if (wnd_class_)
return true;
WNDCLASSEXW wcex = {sizeof(WNDCLASSEX)};
wcex.style = CS_DBLCLKS;
wcex.hInstance = GetModuleHandle(NULL);
wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wcex.lpfnWndProc = &WndProc; // 绑定消息处理
wcex.lpszClassName = kClassName;
wnd_class_ = ::RegisterClassExW(&wcex);
RTC_DCHECK(wnd_class_ != 0);
return wnd_class_ != 0;
}
void MainWnd::SwitchToConnectUI() {
RTC_DCHECK(IsWindow());
// 隐藏连接列表
LayoutPeerListUI(false);
ui_ = CONNECT_TO_SERVER;
// 显示连接界面
LayoutConnectUI(true);
::SetFocus(edit1_);
if (auto_connect_)
::PostMessage(button_, BM_CLICK, 0, 0);
}
处理消息
LRESULT CALLBACK MainWnd::WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
MainWnd* me =
reinterpret_cast<MainWnd*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (!me && WM_CREATE == msg) {
CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lp);
me = reinterpret_cast<MainWnd*>(cs->lpCreateParams);
me->wnd_ = hwnd;
::SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(me));
}
LRESULT result = 0;
if (me) {
void* prev_nested_msg = me->nested_msg_;
me->nested_msg_ = &msg;
bool handled = me->OnMessage(msg, wp, lp, &result);
if (WM_NCDESTROY == msg) {
me->destroyed_ = true;
} else if (!handled) {
result = ::DefWindowProc(hwnd, msg, wp, lp);
}
if (me->destroyed_ && prev_nested_msg == NULL) {
me->OnDestroyed();
me->wnd_ = NULL;
me->destroyed_ = false;
}
me->nested_msg_ = prev_nested_msg;
} else {
result = ::DefWindowProc(hwnd, msg, wp, lp);
}
return result;
}
后面都是调用到OnMessage函数处理。
bool MainWnd::OnMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT* result)