/******** main.cc ********/
wWinMain()
wnd()
PeerConnectionClient client;//用于信令处理相关
rtc::scoped_refptr conductor(new rtc::RefCountedObject(&client, &wnd));
while((gm = ::GetMessage(&msg, NULL, 0, 0)) != 0 && gm != -1)
if (!wnd.PreTranslateMessage(&msg))
::TranslateMessage(&msg);
::DispatchMessage(&msg);
wnd.PreTranslateMessage(&msg)
if (msg->message == WM_CHAR)
if (msg->wParam == VK_TAB)
HandleTabbing()
else if (msg->wParam == VK_RETURN)
OnDefaultAction();
else if (msg->wParam == VK_ESCAPE)
if (ui_ == STREAMING)
callback_->DisconnectFromCurrentPeer();
else
callback_->DisconnectFromServer();
else if (msg->hwnd == NULL && msg->message == UI_THREAD_CALLBACK)
callback_->UIThreadCallback(static_cast(msg->wParam),
reinterpret_cast(msg->lParam));
switch (msg_id)
case SEND_MESSAGE_TO_PEER:
client_->SendToPeer(peer_id_, *msg)
sprintfn(headers, sizeof(headers),
"POST /message?peer_id=%i&to=%i HTTP/1.0\r\n"
"Content-Length: %i\r\n"
"Content-Type: text/plain\r\n"
"\r\n", my_id_, peer_id, message.length());
onconnect_data_ = headers;
onconnect_data_ += message;
ConnectControlSocket()
control_socket_->Connect(server_address_);//触发连接事件,在回调函数中进行数据发送
case NEW_STREAM_ADDED:
webrtc::MediaStreamInterface* stream =
reinterpret_cast(data);
webrtc::VideoTrackVector tracks = stream->GetVideoTracks();
webrtc::VideoTrackInterface* track = tracks[0];
main_wnd_->StartRemoteRenderer(track);
remote_renderer_.reset(new VideoRenderer(this, remote_video)
rendered_track_->AddRenderer(this);
case STREAM_REMOVED:
webrtc::MediaStreamInterface* stream =
reinterpret_cast(data);
stream->Release();
/******** InitSocketSignals()注册的回调函数 ********/
OnConnect
socket->Send(onconnect_data_.c_str(), onconnect_data_.length())
OnHangingGetConnect
sprintfn(buffer, sizeof(buffer),"GET /wait?peer_id=%i HTTP/1.0\r\n\r\n", my_id_);
int len = static_cast(strlen(buffer));
int sent = socket->Send(buffer, len);
OnRead
ReadIntoBuffer
ParseServerResponse
if (ParseEntry(control_data_.substr(pos, eol - pos),
&name, &id, &connected) && id != my_id_)
callback_->OnPeerConnected(id, name);
callback_->OnSignedIn();
hanging_get_->Connect(server_address_)
OnHangingGetRead
ReadIntoBuffer()
int bytes = socket->Recv(buffer, sizeof(buffer))
GetHeaderValue()
ParseServerResponse()
GetHeaderValue
if (my_id_ == static_cast(peer_id))
if (ParseEntry(notification_data_.substr(pos), &name, &id, &connected))
callback_->OnPeerConnected(id, name);
main_wnd_->SwitchToPeerList(client_->peers());
AddListBoxItem()
LRESULT index = ::SendMessageA(listbox, LB_ADDSTRING, 0,
reinterpret_cast(str.c_str()));
::SendMessageA(listbox, LB_SETITEMDATA, index, item_data);
LayoutPeerListUI(true);
::GetClientRect(wnd_, &rc);
::MoveWindow(listbox_, 0, 0, rc.right, rc.bottom, TRUE);
::ShowWindow(listbox_, SW_SHOWNA);
::SetFocus(listbox_);
else
OnMessageFromPeer
callback_->OnMessageFromPeer(peer_id, message);
InitializePeerConnection()
reader.parse(message, jmessage)//接收为offer, answer, candidate信息
rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName, &type);
if (!type.empty()) //接收的是offer或者answer
webrtc::SessionDescriptionInterface* session_description(
webrtc::CreateSessionDescription(type, sdp, &error));
peer_connection_->SetRemoteDescription(
DummySetSessionDescriptionObserver::Create(), session_description);
if (session_description->type() == webrtc::SessionDescriptionInterface::kOffer)
peer_connection_->CreateAnswer(this, NULL);//接收到offer就创建answer
else //接收则为candidate
rtc::scoped_ptr candidate(
webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp, &error));
peer_connection_->AddIceCandidate(candidate.get())//添加候选信息
/******** main_wnd.cc ********/
WndProc()
OnMessage()
switch (msg)
case WM_PAINT:
OnPaint();//绘制窗体
return true;
case WM_COMMAND:
if (button_ == reinterpret_cast(lp))
if (BN_CLICKED == HIWORD(wp)) //单击按钮
OnDefaultAction();
else if (listbox_ == reinterpret_cast(lp))
if (LBN_DBLCLK == HIWORD(wp)) //双击列表框
OnDefaultAction();
return true;
OnDefaultAction()
if (ui_ == CONNECT_TO_SERVER) //点击的是连接到服务器按钮
callback_->StartLogin(server, port)//如:http://192.168.1.123:8888/sign_in?id_name
client_->Connect(server, port, GetPeerName())
DoConnect()
InitSocketSignals();//设置了些回调函数
control_socket_->SignalCloseEvent.connect(this,&PeerConnectionClient::OnClose);
hanging_get_->SignalCloseEvent.connect(this,&PeerConnectionClient::OnClose);
control_socket_->SignalConnectEvent.connect(this,&PeerConnectionClient::OnConnect);
hanging_get_->SignalConnectEvent.connect(this,&PeerConnectionClient::OnHangingGetConnect);
control_socket_->SignalReadEvent.connect(this,&PeerConnectionClient::OnRead);
hanging_get_->SignalReadEvent.connect(this,&PeerConnectionClient::OnHangingGetRead);
sprintfn(buffer, sizeof(buffer),"GET /sign_in?%s HTTP/1.0\r\n\r\n", client_name_.c_str());
ConnectControlSocket();
control_socket_->Connect(server_address_);//control_socket_为异步套接字
else if (ui_ == LIST_PEERS) //双击的是列表框
callback_->ConnectToPeer(peer_id);
InitializePeerConnection()
peer_connection_factory_ = webrtc::CreatePeerConnectionFactory();
CreatePeerConnection(DTLS_ON)
webrtc::PeerConnectionInterface::RTCConfiguration config;
webrtc::PeerConnectionInterface::IceServer server;
server.uri = GetPeerConnectionString();//stun server和turn server地址
config.servers.push_back(server);
webrtc::FakeConstraints constraints;
if (dtls) //使用srtp协议进行传输
constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,"true");
else //使用rtp协议进行传输
constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,"false");
peer_connection_ = peer_connection_factory_->CreatePeerConnection(
config, &constraints, NULL, NULL, this);
AddStreams();
rtc::scoped_refptr audio_track(
peer_connection_factory_->CreateAudioTrack(
kAudioLabel, peer_connection_factory_->CreateAudioSource(NULL)));
rtc::scoped_refptr video_track(
peer_connection_factory_->CreateVideoTrack(
kVideoLabel,peer_connection_factory_->CreateVideoSource(
OpenVideoCaptureDevice(),NULL))); //打开摄像头
main_wnd_->StartLocalRenderer(video_track);
local_renderer_.reset(new VideoRenderer(handle(), 1, 1, local_video));
rendered_track_->AddRenderer(this);
rtc::scoped_refptr stream =
peer_connection_factory_->CreateLocalMediaStream(kStreamLabel);
stream->AddTrack(audio_track);
stream->AddTrack(video_track);
peer_connection_->AddStream(stream)
main_wnd_->SwitchToStreamingUI();
LayoutConnectUI(false);
CalculateWindowSizeForText()
::GetClientRect(wnd_, &rc)
::MoveWindow()
::SetWindowText()
::ShowWindow()
LayoutPeerListUI(false);
::GetClientRect(wnd_, &rc);
::MoveWindow(listbox_, 0, 0, rc.right, rc.bottom, TRUE);
::ShowWindow(listbox_, SW_SHOWNA);
peer_connection_->CreateOffer(this, NULL);
/*CreateSessionDescriptionObserver复写函数*/
OnSuccess() //CreateOffer或者CreateAnswer成功
peer_connection_->SetLocalDescription(DummySetSessionDescriptionObserver::Create(), desc);
Json::StyledWriter writer;
Json::Value jmessage;
jmessage[kSessionDescriptionTypeName] = desc->type(); //kSessionDescriptionTypeName[] = "type";
jmessage[kSessionDescriptionSdpName] = sdp; //kSessionDescriptionSdpName[] = "sdp";
SendMessage(writer.write(jmessage));
main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, msg);
::PostThreadMessage(ui_thread_id_, UI_THREAD_CALLBACK,
static_cast(msg_id), reinterpret_cast(data));
/******** Conductor.cc ********/
class Conductor
: public webrtc::PeerConnectionObserver,
public webrtc::CreateSessionDescriptionObserver,
public PeerConnectionClientObserver,
public MainWndCallback
Conductor
client_->RegisterObserver(this);
main_wnd->RegisterObserver(this);
/*PeerConnectionObserver复写函数*/
OnAddStream
stream->AddRef();
main_wnd_->QueueUIThreadCallback(NEW_STREAM_ADDED, stream);
::PostThreadMessage(ui_thread_id_, UI_THREAD_CALLBACK,
static_cast(msg_id), reinterpret_cast(data));
OnRemoveStream
stream->AddRef();
main_wnd_->QueueUIThreadCallback(STREAM_REMOVED,stream);
::PostThreadMessage(ui_thread_id_, UI_THREAD_CALLBACK,
static_cast(msg_id), reinterpret_cast(data));
OnIceCandidate
jmessage[kCandidateSdpMidName] = candidate->sdp_mid();
jmessage[kCandidateSdpMlineIndexName] = candidate->sdp_mline_index();
jmessage[kCandidateSdpName] = sdp;
SendMessage(writer.write(jmessage));
main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, msg);
/*VideoRenderer复写函数*/
SetSize
image_.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
RenderFrame
const cricket::VideoFrame* frame = video_frame->GetCopyWithRotationApplied();
SetSize(static_cast(frame->GetWidth()), static_cast(frame->GetHeight()));
rame->ConvertToRgbBuffer(cricket::FOURCC_ARGB,
image_.get(),
bmi_.bmiHeader.biSizeImage,
bmi_.bmiHeader.biWidth *
bmi_.bmiHeader.biBitCount / 8);