From dd27f8bf0ec6340bf8fbc41db6461aa28b6861ce Mon Sep 17 00:00:00 2001 From: "DESKTOP-4RNDQIC\\29019" <290198252@qq.com> Date: Thu, 21 Oct 2021 19:35:40 +0800 Subject: [PATCH] no message --- client/webrtc_demo/src/MyCapturer.cpp | 64 ++ client/webrtc_demo/src/MyCapturer.h | 41 + client/webrtc_demo/src/conductor.cc | 671 ---------------- client/webrtc_demo/src/conductor.h | 138 ---- client/webrtc_demo/src/cplaywidget.cpp | 1 - client/webrtc_demo/src/defaults.cc | 74 -- client/webrtc_demo/src/defaults.h | 39 - client/webrtc_demo/src/main.cpp | 41 +- client/webrtc_demo/src/main_wnd.cc | 739 ------------------ client/webrtc_demo/src/main_wnd.h | 215 ----- client/webrtc_demo/src/mainwindow.cpp | 137 +++- client/webrtc_demo/src/mainwindow.h | 71 +- .../webrtc_demo/src/peer_connection_client.cc | 603 -------------- .../webrtc_demo/src/peer_connection_client.h | 131 ---- client/webrtc_demo/src/video_capture.cpp | 26 +- client/webrtc_demo/webrtc_demo.pro | 25 +- client/webrtc_demo/webrtc_demo.pro.user | 16 +- 17 files changed, 375 insertions(+), 2657 deletions(-) create mode 100644 client/webrtc_demo/src/MyCapturer.cpp create mode 100644 client/webrtc_demo/src/MyCapturer.h delete mode 100644 client/webrtc_demo/src/conductor.cc delete mode 100644 client/webrtc_demo/src/conductor.h delete mode 100644 client/webrtc_demo/src/defaults.cc delete mode 100644 client/webrtc_demo/src/defaults.h delete mode 100644 client/webrtc_demo/src/main_wnd.cc delete mode 100644 client/webrtc_demo/src/main_wnd.h delete mode 100644 client/webrtc_demo/src/peer_connection_client.cc delete mode 100644 client/webrtc_demo/src/peer_connection_client.h diff --git a/client/webrtc_demo/src/MyCapturer.cpp b/client/webrtc_demo/src/MyCapturer.cpp new file mode 100644 index 0000000..2b7d1c2 --- /dev/null +++ b/client/webrtc_demo/src/MyCapturer.cpp @@ -0,0 +1,64 @@ +#include "MyCapturer.h" +#include "rtc_base/thread.h" +#include + +MyCapturer::MyCapturer() { + +} + +void MyCapturer::startCapturer() { + auto options = webrtc::DesktopCaptureOptions::CreateDefault(); + options.set_allow_directx_capturer(true); + capturer_ = webrtc::DesktopCapturer::CreateScreenCapturer(options); + capturer_->Start(this); + CaptureFrame(); +} + +webrtc::MediaSourceInterface::SourceState MyCapturer::state() const { + return webrtc::MediaSourceInterface::kLive; +} + +bool MyCapturer::remote() const { + return false; +} + +bool MyCapturer::is_screencast() const { + return true; +} + +absl::optional MyCapturer::needs_denoising() const { + return false; +} + +void MyCapturer::OnCaptureResult(webrtc::DesktopCapturer::Result result, + std::unique_ptr frame) { + if (result != webrtc::DesktopCapturer::Result::SUCCESS) + return; + + int width = frame->size().width(); + int height = frame->size().height(); + + if (!i420_buffer_.get() || + i420_buffer_->width() * i420_buffer_->height() < width * height) { + i420_buffer_ = webrtc::I420Buffer::Create(width, height); + } +// libyuv::ConvertToI420(frame->data(), 0, i420_buffer_->MutableDataY(), +// i420_buffer_->StrideY(), i420_buffer_->MutableDataU(), +// i420_buffer_->StrideU(), i420_buffer_->MutableDataV(), +// i420_buffer_->StrideV(), 0, 0, width, height, width, +// height, libyuv::kRotate0, libyuv::FOURCC_ARGB); + + OnFrame(webrtc::VideoFrame(i420_buffer_, 0, 0, webrtc::kVideoRotation_0)); +} + +void MyCapturer::OnMessage(rtc::Message* msg) { + if (msg->message_id == 0) + CaptureFrame(); +} + +void MyCapturer::CaptureFrame() { + capturer_->CaptureFrame(); + +// rtc::Location loc(__FUNCTION__, __FILE__); +// rtc::Thread::Current()->PostDelayed(loc, 33, this, 0); +} diff --git a/client/webrtc_demo/src/MyCapturer.h b/client/webrtc_demo/src/MyCapturer.h new file mode 100644 index 0000000..96a4da1 --- /dev/null +++ b/client/webrtc_demo/src/MyCapturer.h @@ -0,0 +1,41 @@ +#pragma once +/** + *¡¡WindowsÆÁĻ¼ÏñÄ£¿é + */ + +#include +#include +#include +#include +#include "rtc_base/thread.h" +#include "media/base/adapted_video_track_source.h" +#include "rtc_base/message_handler.h" + + +class MyCapturer : public rtc::AdaptedVideoTrackSource, + public rtc::MessageHandler, + public webrtc::DesktopCapturer::Callback { + public: + MyCapturer(); + + void startCapturer(); + + void CaptureFrame(); + + bool is_screencast() const override; + + absl::optional needs_denoising() const override; + + webrtc::MediaSourceInterface::SourceState state() const override; + + bool remote() const override; + + void OnCaptureResult(webrtc::DesktopCapturer::Result result, + std::unique_ptr frame) override; + void OnMessage(rtc::Message* msg) override; + + private: + std::unique_ptr capturer_; + rtc::scoped_refptr i420_buffer_; + //mutable volatile int ref_count_; +}; diff --git a/client/webrtc_demo/src/conductor.cc b/client/webrtc_demo/src/conductor.cc deleted file mode 100644 index 101246d..0000000 --- a/client/webrtc_demo/src/conductor.cc +++ /dev/null @@ -1,671 +0,0 @@ -/* - * Copyright 2012 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "conductor.h" - -#include -#include - -#include -#include -#include - -#include "absl/memory/memory.h" -#include "absl/types/optional.h" -#include "api/audio/audio_mixer.h" -#include "api/audio_codecs/audio_decoder_factory.h" -#include "api/audio_codecs/audio_encoder_factory.h" -#include "api/audio_codecs/builtin_audio_decoder_factory.h" -#include "api/audio_codecs/builtin_audio_encoder_factory.h" -#include "api/audio_options.h" -#include "api/create_peerconnection_factory.h" -#include "api/rtp_sender_interface.h" -#include "api/video_codecs/builtin_video_decoder_factory.h" -#include "api/video_codecs/builtin_video_encoder_factory.h" -#include "api/video_codecs/video_decoder_factory.h" -#include "api/video_codecs/video_encoder_factory.h" -#include "defaults.h" -#include "modules/audio_device/include/audio_device.h" -#include "modules/audio_processing/include/audio_processing.h" -#include "modules/video_capture/video_capture.h" -#include "modules/video_capture/video_capture_factory.h" -#include "p2p/base/port_allocator.h" -#include "pc/video_track_source.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" -#include "rtc_base/ref_counted_object.h" -#include "rtc_base/rtc_certificate_generator.h" -#include "rtc_base/strings/json.h" -#include "test/vcm_capturer.h" - -namespace -{ - // Names used for a IceCandidate JSON object. - const char kCandidateSdpMidName[] = "sdpMid"; - const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex"; - const char kCandidateSdpName[] = "candidate"; - - // Names used for a SessionDescription JSON object. - const char kSessionDescriptionTypeName[] = "type"; - const char kSessionDescriptionSdpName[] = "sdp"; - - class DummySetSessionDescriptionObserver - : public webrtc::SetSessionDescriptionObserver - { - public: - static DummySetSessionDescriptionObserver *Create() - { - return new rtc::RefCountedObject(); - } - virtual void OnSuccess() { RTC_LOG(INFO) << __FUNCTION__; } - virtual void OnFailure(webrtc::RTCError error) - { - RTC_LOG(INFO) << __FUNCTION__ << " " << ToString(error.type()) << ": " - << error.message(); - } - }; - - class CapturerTrackSource : public webrtc::VideoTrackSource - { - public: - static rtc::scoped_refptr Create() - { - const size_t kWidth = 640; - const size_t kHeight = 480; - const size_t kFps = 30; - std::unique_ptr capturer; - std::unique_ptr 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( - std::move(capturer)); - } - } - - return nullptr; - } - - protected: - explicit CapturerTrackSource( - std::unique_ptr capturer) - : VideoTrackSource(/*remote=*/false), capturer_(std::move(capturer)) {} - - private: - rtc::VideoSourceInterface *source() override - { - return capturer_.get(); - } - std::unique_ptr capturer_; - }; - -} // namespace - -Conductor::Conductor(PeerConnectionClient *client, MainWindow *main_wnd) - : peer_id_(-1), loopback_(false), client_(client), main_wnd_(main_wnd) -{ - client_->RegisterObserver(this); - main_wnd->RegisterObserver(this); -} - -Conductor::~Conductor() -{ - RTC_DCHECK(!peer_connection_); -} - -bool Conductor::connection_active() const -{ - return peer_connection_ != nullptr; -} - -void Conductor::Close() -{ - client_->SignOut(); - DeletePeerConnection(); -} - -bool Conductor::InitializePeerConnection() -{ - RTC_DCHECK(!peer_connection_factory_); - RTC_DCHECK(!peer_connection_); - - peer_connection_factory_ = webrtc::CreatePeerConnectionFactory( - nullptr /* network_thread */, nullptr /* worker_thread */, - nullptr /* signaling_thread */, nullptr /* default_adm */, - webrtc::CreateBuiltinAudioEncoderFactory(), - webrtc::CreateBuiltinAudioDecoderFactory(), - webrtc::CreateBuiltinVideoEncoderFactory(), - webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */, - nullptr /* audio_processing */); - - if (!peer_connection_factory_) - { - main_wnd_->MessageBox("Error", "Failed to initialize PeerConnectionFactory", - true); - DeletePeerConnection(); - return false; - } - - if (!CreatePeerConnection(/*dtls=*/true)) - { - main_wnd_->MessageBox("Error", "CreatePeerConnection failed", true); - DeletePeerConnection(); - } - - AddTracks(); - - return peer_connection_ != nullptr; -} - -bool Conductor::ReinitializePeerConnectionForLoopback() -{ - loopback_ = true; - std::vector> senders = - peer_connection_->GetSenders(); - peer_connection_ = nullptr; - if (CreatePeerConnection(/*dtls=*/false)) - { - for (const auto &sender : senders) - { - peer_connection_->AddTrack(sender->track(), sender->stream_ids()); - } - peer_connection_->CreateOffer( - this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions()); - } - return peer_connection_ != nullptr; -} - -bool Conductor::CreatePeerConnection(bool dtls) -{ - RTC_DCHECK(peer_connection_factory_); - RTC_DCHECK(!peer_connection_); - - webrtc::PeerConnectionInterface::RTCConfiguration config; - config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; - config.enable_dtls_srtp = dtls; - webrtc::PeerConnectionInterface::IceServer server; - server.uri = GetPeerConnectionString(); - config.servers.push_back(server); - - peer_connection_ = peer_connection_factory_->CreatePeerConnection( - config, nullptr, nullptr, this); - return peer_connection_ != nullptr; -} - -void Conductor::DeletePeerConnection() -{ - main_wnd_->StopLocalRenderer(); - main_wnd_->StopRemoteRenderer(); - peer_connection_ = nullptr; - peer_connection_factory_ = nullptr; - peer_id_ = -1; - loopback_ = false; -} - -void Conductor::EnsureStreamingUI() -{ - RTC_DCHECK(peer_connection_); - if (main_wnd_->IsWindow()) - { - if (main_wnd_->current_ui() != MainWindow::STREAMING) - main_wnd_->SwitchToStreamingUI(); - } -} - -// -// PeerConnectionObserver implementation. -// - -void Conductor::OnAddTrack( - rtc::scoped_refptr receiver, - const std::vector> & - streams) -{ - RTC_LOG(INFO) << __FUNCTION__ << " " << receiver->id(); - main_wnd_->QueueUIThreadCallback(NEW_TRACK_ADDED, - receiver->track().release()); -} - -void Conductor::OnRemoveTrack( - rtc::scoped_refptr receiver) -{ - RTC_LOG(INFO) << __FUNCTION__ << " " << receiver->id(); - main_wnd_->QueueUIThreadCallback(TRACK_REMOVED, receiver->track().release()); -} - -void Conductor::OnIceCandidate(const webrtc::IceCandidateInterface *candidate) -{ - RTC_LOG(INFO) << __FUNCTION__ << " " << candidate->sdp_mline_index(); - // For loopback test. To save some connecting delay. - if (loopback_) - { - if (!peer_connection_->AddIceCandidate(candidate)) - { - RTC_LOG(WARNING) << "Failed to apply the received candidate"; - } - return; - } - - Json::StyledWriter writer; - Json::Value jmessage; - - jmessage[kCandidateSdpMidName] = candidate->sdp_mid(); - jmessage[kCandidateSdpMlineIndexName] = candidate->sdp_mline_index(); - std::string sdp; - if (!candidate->ToString(&sdp)) - { - RTC_LOG(LS_ERROR) << "Failed to serialize candidate"; - return; - } - jmessage[kCandidateSdpName] = sdp; - SendMessage(writer.write(jmessage)); -} - -// -// PeerConnectionClientObserver implementation. -// - -void Conductor::OnSignedIn() -{ - RTC_LOG(INFO) << __FUNCTION__; - main_wnd_->SwitchToPeerList(client_->peers()); -} - -void Conductor::OnDisconnected() -{ - RTC_LOG(INFO) << __FUNCTION__; - - DeletePeerConnection(); - - if (main_wnd_->IsWindow()) - main_wnd_->SwitchToConnectUI(); -} - -void Conductor::OnPeerConnected(int id, const std::string &name) -{ - RTC_LOG(INFO) << __FUNCTION__; - // Refresh the list if we're showing it. - if (main_wnd_->current_ui() == MainWindow::LIST_PEERS) - main_wnd_->SwitchToPeerList(client_->peers()); -} - -void Conductor::OnPeerDisconnected(int id) -{ - RTC_LOG(INFO) << __FUNCTION__; - if (id == peer_id_) - { - RTC_LOG(INFO) << "Our peer disconnected"; - main_wnd_->QueueUIThreadCallback(PEER_CONNECTION_CLOSED, NULL); - } - else - { - // Refresh the list if we're showing it. - if (main_wnd_->current_ui() == MainWindow::LIST_PEERS) - main_wnd_->SwitchToPeerList(client_->peers()); - } -} - -void Conductor::OnMessageFromPeer(int peer_id, const std::string &message) -{ - RTC_DCHECK(peer_id_ == peer_id || peer_id_ == -1); - RTC_DCHECK(!message.empty()); - - if (!peer_connection_.get()) - { - RTC_DCHECK(peer_id_ == -1); - peer_id_ = peer_id; - - if (!InitializePeerConnection()) - { - RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance"; - client_->SignOut(); - return; - } - } - else if (peer_id != peer_id_) - { - RTC_DCHECK(peer_id_ != -1); - RTC_LOG(WARNING) - << "Received a message from unknown peer while already in a " - "conversation with a different peer."; - return; - } - - Json::Reader reader; - Json::Value jmessage; - if (!reader.parse(message, jmessage)) - { - RTC_LOG(WARNING) << "Received unknown message. " << message; - return; - } - std::string type_str; - std::string json_object; - - rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName, - &type_str); - if (!type_str.empty()) - { - if (type_str == "offer-loopback") - { - // This is a loopback call. - // Recreate the peerconnection with DTLS disabled. - if (!ReinitializePeerConnectionForLoopback()) - { - RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance"; - DeletePeerConnection(); - client_->SignOut(); - } - return; - } - absl::optional type_maybe = - webrtc::SdpTypeFromString(type_str); - if (!type_maybe) - { - RTC_LOG(LS_ERROR) << "Unknown SDP type: " << type_str; - return; - } - webrtc::SdpType type = *type_maybe; - std::string sdp; - if (!rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName, - &sdp)) - { - RTC_LOG(WARNING) << "Can't parse received session description message."; - return; - } - webrtc::SdpParseError error; - std::unique_ptr session_description = - webrtc::CreateSessionDescription(type, sdp, &error); - if (!session_description) - { - RTC_LOG(WARNING) << "Can't parse received session description message. " - "SdpParseError was: " - << error.description; - return; - } - RTC_LOG(INFO) << " Received session description :" << message; - peer_connection_->SetRemoteDescription( - DummySetSessionDescriptionObserver::Create(), - session_description.release()); - if (type == webrtc::SdpType::kOffer) - { - peer_connection_->CreateAnswer( - this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions()); - } - } - else - { - std::string sdp_mid; - int sdp_mlineindex = 0; - std::string sdp; - if (!rtc::GetStringFromJsonObject(jmessage, kCandidateSdpMidName, - &sdp_mid) || - !rtc::GetIntFromJsonObject(jmessage, kCandidateSdpMlineIndexName, - &sdp_mlineindex) || - !rtc::GetStringFromJsonObject(jmessage, kCandidateSdpName, &sdp)) - { - RTC_LOG(WARNING) << "Can't parse received message."; - return; - } - webrtc::SdpParseError error; - std::unique_ptr candidate( - webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp, &error)); - if (!candidate.get()) - { - RTC_LOG(WARNING) << "Can't parse received candidate message. " - "SdpParseError was: " - << error.description; - return; - } - if (!peer_connection_->AddIceCandidate(candidate.get())) - { - RTC_LOG(WARNING) << "Failed to apply the received candidate"; - return; - } - RTC_LOG(INFO) << " Received candidate :" << message; - } -} - -void Conductor::OnMessageSent(int err) -{ - // Process the next pending message if any. - main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, NULL); -} - -void Conductor::OnServerConnectionFailure() -{ - main_wnd_->MessageBox("Error", ("Failed to connect to " + server_).c_str(), - true); -} - -// -// MainWndCallback implementation. -// - -void Conductor::StartLogin(const std::string &server, int port) -{ - if (client_->is_connected()) - return; - server_ = server; - client_->Connect(server, port, GetPeerName()); -} - -void Conductor::DisconnectFromServer() -{ - if (client_->is_connected()) - client_->SignOut(); -} - -void Conductor::ConnectToPeer(int peer_id) -{ - RTC_DCHECK(peer_id_ == -1); - RTC_DCHECK(peer_id != -1); - - if (peer_connection_.get()) - { - main_wnd_->MessageBox( - "Error", "We only support connecting to one peer at a time", true); - return; - } - - if (InitializePeerConnection()) - { - peer_id_ = peer_id; - peer_connection_->CreateOffer( - this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions()); - } - else - { - main_wnd_->MessageBox("Error", "Failed to initialize PeerConnection", true); - } -} - -void Conductor::AddTracks() -{ - if (!peer_connection_->GetSenders().empty()) - { - return; // Already added tracks. - } - - rtc::scoped_refptr audio_track( - peer_connection_factory_->CreateAudioTrack( - kAudioLabel, peer_connection_factory_->CreateAudioSource( - cricket::AudioOptions()))); - auto result_or_error = peer_connection_->AddTrack(audio_track, {kStreamId}); - if (!result_or_error.ok()) - { - RTC_LOG(LS_ERROR) << "Failed to add audio track to PeerConnection: " - << result_or_error.error().message(); - } - - rtc::scoped_refptr video_device = - CapturerTrackSource::Create(); - if (video_device) - { - rtc::scoped_refptr video_track_( - peer_connection_factory_->CreateVideoTrack(kVideoLabel, video_device)); - main_wnd_->StartLocalRenderer(video_track_); - - result_or_error = peer_connection_->AddTrack(video_track_, {kStreamId}); - if (!result_or_error.ok()) - { - RTC_LOG(LS_ERROR) << "Failed to add video track to PeerConnection: " - << result_or_error.error().message(); - } - } - else - { - RTC_LOG(LS_ERROR) << "OpenVideoCaptureDevice failed"; - } - - main_wnd_->SwitchToStreamingUI(); -} - -void Conductor::DisconnectFromCurrentPeer() -{ - RTC_LOG(INFO) << __FUNCTION__; - if (peer_connection_.get()) - { - client_->SendHangUp(peer_id_); - DeletePeerConnection(); - } - - if (main_wnd_->IsWindow()) - main_wnd_->SwitchToPeerList(client_->peers()); -} - -void Conductor::UIThreadCallback(int msg_id, void *data) -{ - switch (msg_id) - { - case PEER_CONNECTION_CLOSED: - RTC_LOG(INFO) << "PEER_CONNECTION_CLOSED"; - DeletePeerConnection(); - - if (main_wnd_->IsWindow()) - { - if (client_->is_connected()) - { - main_wnd_->SwitchToPeerList(client_->peers()); - } - else - { - main_wnd_->SwitchToConnectUI(); - } - } - else - { - DisconnectFromServer(); - } - break; - - case SEND_MESSAGE_TO_PEER: - { - RTC_LOG(INFO) << "SEND_MESSAGE_TO_PEER"; - std::string *msg = reinterpret_cast(data); - if (msg) - { - // For convenience, we always run the message through the queue. - // This way we can be sure that messages are sent to the server - // in the same order they were signaled without much hassle. - pending_messages_.push_back(msg); - } - - if (!pending_messages_.empty() && !client_->IsSendingMessage()) - { - msg = pending_messages_.front(); - pending_messages_.pop_front(); - - if (!client_->SendToPeer(peer_id_, *msg) && peer_id_ != -1) - { - RTC_LOG(LS_ERROR) << "SendToPeer failed"; - DisconnectFromServer(); - } - delete msg; - } - - if (!peer_connection_.get()) - peer_id_ = -1; - - break; - } - - case NEW_TRACK_ADDED: - { - auto *track = reinterpret_cast(data); - if (track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) - { - auto *video_track = static_cast(track); - main_wnd_->StartRemoteRenderer(video_track); - } - track->Release(); - break; - } - - case TRACK_REMOVED: - { - // Remote peer stopped sending a track. - auto *track = reinterpret_cast(data); - track->Release(); - break; - } - - default: - RTC_NOTREACHED(); - break; - } -} - -void Conductor::OnSuccess(webrtc::SessionDescriptionInterface *desc) -{ - peer_connection_->SetLocalDescription( - DummySetSessionDescriptionObserver::Create(), desc); - - std::string sdp; - desc->ToString(&sdp); - - // For loopback test. To save some connecting delay. - if (loopback_) - { - // Replace message type from "offer" to "answer" - std::unique_ptr session_description = - webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, sdp); - peer_connection_->SetRemoteDescription( - DummySetSessionDescriptionObserver::Create(), - session_description.release()); - return; - } - - Json::StyledWriter writer; - Json::Value jmessage; - jmessage[kSessionDescriptionTypeName] = - webrtc::SdpTypeToString(desc->GetType()); - jmessage[kSessionDescriptionSdpName] = sdp; - SendMessage(writer.write(jmessage)); -} - -void Conductor::OnFailure(webrtc::RTCError error) -{ - RTC_LOG(LERROR) << ToString(error.type()) << ": " << error.message(); -} - -void Conductor::SendMessage(const std::string &json_object) -{ - std::string *msg = new std::string(json_object); - main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, msg); -} diff --git a/client/webrtc_demo/src/conductor.h b/client/webrtc_demo/src/conductor.h deleted file mode 100644 index fcd60af..0000000 --- a/client/webrtc_demo/src/conductor.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2012 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef EXAMPLES_PEERCONNECTION_CLIENT_CONDUCTOR_H_ -#define EXAMPLES_PEERCONNECTION_CLIENT_CONDUCTOR_H_ - -#include -#include -#include -#include -#include - -#include "api/media_stream_interface.h" -#include "api/peer_connection_interface.h" -#include "main_wnd.h" -#include "peer_connection_client.h" - -namespace webrtc -{ - class VideoCaptureModule; -} // namespace webrtc - -namespace cricket -{ - class VideoRenderer; -} // namespace cricket - -class Conductor : public webrtc::PeerConnectionObserver, - public webrtc::CreateSessionDescriptionObserver, - public PeerConnectionClientObserver, - public MainWndCallback -{ -public: - enum CallbackID - { - MEDIA_CHANNELS_INITIALIZED = 1, - PEER_CONNECTION_CLOSED, - SEND_MESSAGE_TO_PEER, - NEW_TRACK_ADDED, - TRACK_REMOVED, - }; - - Conductor(PeerConnectionClient *client, MainWindow *main_wnd); - - bool connection_active() const; - - void Close() override; - -protected: - ~Conductor(); - bool InitializePeerConnection(); - bool ReinitializePeerConnectionForLoopback(); - bool CreatePeerConnection(bool dtls); - void DeletePeerConnection(); - void EnsureStreamingUI(); - void AddTracks(); - - // - // PeerConnectionObserver implementation. - // - - void OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) override {} - void OnAddTrack( - rtc::scoped_refptr receiver, - const std::vector> & - streams) override; - void OnRemoveTrack( - rtc::scoped_refptr receiver) override; - void OnDataChannel( - rtc::scoped_refptr channel) override {} - void OnRenegotiationNeeded() override {} - void OnIceConnectionChange( - webrtc::PeerConnectionInterface::IceConnectionState new_state) override {} - void OnIceGatheringChange( - webrtc::PeerConnectionInterface::IceGatheringState new_state) override {} - void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) override; - void OnIceConnectionReceivingChange(bool receiving) override {} - - // - // PeerConnectionClientObserver implementation. - // - - void OnSignedIn() override; - - void OnDisconnected() override; - - void OnPeerConnected(int id, const std::string &name) override; - - void OnPeerDisconnected(int id) override; - - void OnMessageFromPeer(int peer_id, const std::string &message) override; - - void OnMessageSent(int err) override; - - void OnServerConnectionFailure() override; - - // - // MainWndCallback implementation. - // - - void StartLogin(const std::string &server, int port) override; - - void DisconnectFromServer() override; - - void ConnectToPeer(int peer_id) override; - - void DisconnectFromCurrentPeer() override; - - void UIThreadCallback(int msg_id, void *data) override; - - // CreateSessionDescriptionObserver implementation. - void OnSuccess(webrtc::SessionDescriptionInterface *desc) override; - void OnFailure(webrtc::RTCError error) override; - -protected: - // Send a message to the remote peer. - void SendMessage(const std::string &json_object); - - int peer_id_; - bool loopback_; - rtc::scoped_refptr peer_connection_; - rtc::scoped_refptr - peer_connection_factory_; - PeerConnectionClient *client_; - MainWindow *main_wnd_; - std::deque pending_messages_; - std::string server_; -}; - -#endif // EXAMPLES_PEERCONNECTION_CLIENT_CONDUCTOR_H_ diff --git a/client/webrtc_demo/src/cplaywidget.cpp b/client/webrtc_demo/src/cplaywidget.cpp index 0ccd3ae..1838a2e 100644 --- a/client/webrtc_demo/src/cplaywidget.cpp +++ b/client/webrtc_demo/src/cplaywidget.cpp @@ -6,7 +6,6 @@ #include "CPlayWidget.h" -// ???????????? #define UNIFORM_2D "uniform sampler2D" #define VERTEX_SHADER_IN "attribute" #define VERTEX_SHADER_OUT "varying" diff --git a/client/webrtc_demo/src/defaults.cc b/client/webrtc_demo/src/defaults.cc deleted file mode 100644 index da01c1b..0000000 --- a/client/webrtc_demo/src/defaults.cc +++ /dev/null @@ -1,74 +0,0 @@ -/* - * @Author: your name - * @Date: 2021-10-17 00:47:32 - * @LastEditTime: 2021-10-17 11:33:22 - * @LastEditors: your name - * @Description: In User Settings Edit - * @FilePath: \webrtcdemo\peerconnection\client\defaults.cc - */ -/* - * Copyright 2012 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "defaults.h" - -#include - -#ifdef WIN32 -#include -#else -#include -#endif - -#include "rtc_base/arraysize.h" - -const char kAudioLabel[] = "audio_label"; -const char kVideoLabel[] = "video_label"; -const char kStreamId[] = "stream_id"; -const uint16_t kDefaultServerPort = 8888; - -std::string GetEnvVarOrDefault(const char *env_var_name, - const char *default_value) -{ - std::string value; - const char *env_var = getenv(env_var_name); - if (env_var) - value = env_var; - - if (value.empty()) - value = default_value; - - return value; -} - -std::string GetPeerConnectionString() -{ - return GetEnvVarOrDefault("WEBRTC_CONNECT", "stun:stun.l.google.com:19302"); -} - -std::string GetDefaultServerName() -{ - return GetEnvVarOrDefault("WEBRTC_SERVER", "localhost"); -} - -std::string GetPeerName() -{ - char computer_name[256]; - std::string ret(GetEnvVarOrDefault("USERNAME", "user")); - ret += '@'; - if (gethostname(computer_name, arraysize(computer_name)) == 0) - { - ret += computer_name; - } - else - { - ret += "host"; - } - return ret; -} diff --git a/client/webrtc_demo/src/defaults.h b/client/webrtc_demo/src/defaults.h deleted file mode 100644 index 4e92756..0000000 --- a/client/webrtc_demo/src/defaults.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * @Author: your name - * @Date: 2021-10-17 00:47:32 - * @LastEditTime: 2021-10-17 11:44:57 - * @LastEditors: your name - * @Description: In User Settings Edit - * @FilePath: \peerconnection\client\defaults.h - */ -/* - * Copyright 2011 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef EXAMPLES_PEERCONNECTION_CLIENT_DEFAULTS_H_ -#define EXAMPLES_PEERCONNECTION_CLIENT_DEFAULTS_H_ - -#define WIN32 - -#include - -#include - -extern const char kAudioLabel[]; -extern const char kVideoLabel[]; -extern const char kStreamId[]; -extern const uint16_t kDefaultServerPort; - -std::string GetEnvVarOrDefault(const char *env_var_name, - const char *default_value); -std::string GetPeerConnectionString(); -std::string GetDefaultServerName(); -std::string GetPeerName(); - -#endif // EXAMPLES_PEERCONNECTION_CLIENT_DEFAULTS_H_ diff --git a/client/webrtc_demo/src/main.cpp b/client/webrtc_demo/src/main.cpp index c6213a4..4541156 100644 --- a/client/webrtc_demo/src/main.cpp +++ b/client/webrtc_demo/src/main.cpp @@ -12,15 +12,28 @@ #include "video_capturer_test.h" #include "api/peer_connection_interface.h" #include "api/create_peerconnection_factory.h" +#include "rtc_base/checks.h" +#include "rtc_base/ssl_adapter.h" +#include "rtc_base/win32_socket_init.h" +#include "rtc_base/win32_socket_server.h" #include -# pragma comment(lib, "secur32.lib") -# pragma comment(lib, "winmm.lib") -# pragma comment(lib, "dmoguids.lib") -# pragma comment(lib, "wmcodecdspuuid.lib") -# pragma comment(lib, "msdmo.lib") -# pragma comment(lib, "Strmiids.lib") -# pragma comment(lib, "User32.lib") +#pragma comment (lib,"advapi32.lib") + +extern"C" +BOOLEAN WINAPI SystemFunction036(PVOID, ULONG); + +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "winmm.lib") +#pragma comment(lib, "secur32.lib") +#pragma comment(lib, "iphlpapi.lib") +#pragma comment(lib, "crypt32.lib") +#pragma comment(lib, "dmoguids.lib") +#pragma comment(lib, "wmcodecdspuuid.lib") +#pragma comment(lib, "amstrmid.lib") +#pragma comment(lib, "msdmo.lib") +#pragma comment(lib, "d3d11.lib") +#pragma comment(lib, "dxgi.lib") void EnumCapture() { @@ -54,8 +67,6 @@ int main(int argc, char *argv[]) const size_t kHeight = 720; const size_t kFps = 30; - webrtc::PeerConnectionFactoryInterface::c - std::unique_ptr capturer; std::unique_ptr info( webrtc::VideoCaptureFactory::CreateDeviceInfo()); @@ -71,6 +82,13 @@ int main(int argc, char *argv[]) } } + + rtc::WinsockInitializer winsock_init; + rtc::Win32SocketServer w32_ss; + rtc::Win32Thread w32_thread(&w32_ss); + rtc::ThreadManager::Instance()->SetCurrentThread(&w32_thread); + rtc::InitializeSSL(); + setbuf(stdout, NULL); qRegisterMetaType>("rtc::scoped_refptr"); @@ -79,10 +97,11 @@ int main(int argc, char *argv[]) QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); QApplication a(argc, argv); MainWindow w; + // QObject::connect((VcmCapturerTest*)capturer.get(),SIGNAL(UpdateFrame(rtc::scoped_refptr&)),&w, // SLOT(OnUpdateFrame( rtc::scoped_refptr&)),Qt::ConnectionType::QueuedConnection); - QObject::connect((VcmCapturerTest*)capturer.get(),SIGNAL(UpdateFrame1(uint8_t*)),&w, - SLOT(OnUpdateFrame1( uint8_t *)),Qt::ConnectionType::QueuedConnection); +// QObject::connect((VcmCapturerTest*)capturer.get(),SIGNAL(UpdateFrame1(uint8_t*)),&w, +// SLOT(OnUpdateFrame1( uint8_t *)),Qt::ConnectionType::QueuedConnection); w.show(); return a.exec(); diff --git a/client/webrtc_demo/src/main_wnd.cc b/client/webrtc_demo/src/main_wnd.cc deleted file mode 100644 index 4b125eb..0000000 --- a/client/webrtc_demo/src/main_wnd.cc +++ /dev/null @@ -1,739 +0,0 @@ -/* - * Copyright 2012 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "main_wnd.h" - -#include - -#include "api/video/i420_buffer.h" -#include "defaults.h" -#include "rtc_base/arraysize.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" -#include "libyuv/convert_argb.h" - -ATOM MainWnd::wnd_class_ = 0; -const wchar_t MainWnd::kClassName[] = L"WebRTC_MainWnd"; - -namespace -{ - - const char kConnecting[] = "Connecting... "; - const char kNoVideoStreams[] = "(no video streams either way)"; - const char kNoIncomingStream[] = "(no incoming video)"; - - void CalculateWindowSizeForText(HWND wnd, - const wchar_t *text, - size_t *width, - size_t *height) - { - HDC dc = ::GetDC(wnd); - RECT text_rc = {0}; - ::DrawTextW(dc, text, -1, &text_rc, DT_CALCRECT | DT_SINGLELINE); - ::ReleaseDC(wnd, dc); - RECT client, window; - ::GetClientRect(wnd, &client); - ::GetWindowRect(wnd, &window); - - *width = text_rc.right - text_rc.left; - *width += (window.right - window.left) - (client.right - client.left); - *height = text_rc.bottom - text_rc.top; - *height += (window.bottom - window.top) - (client.bottom - client.top); - } - - HFONT GetDefaultFont() - { - static HFONT font = reinterpret_cast(GetStockObject(DEFAULT_GUI_FONT)); - return font; - } - - std::string GetWindowText(HWND wnd) - { - char text[MAX_PATH] = {0}; - ::GetWindowTextA(wnd, &text[0], ARRAYSIZE(text)); - return text; - } - - void AddListBoxItem(HWND listbox, const std::string &str, LPARAM item_data) - { - LRESULT index = ::SendMessageA(listbox, LB_ADDSTRING, 0, - reinterpret_cast(str.c_str())); - ::SendMessageA(listbox, LB_SETITEMDATA, index, item_data); - } - -} // namespace - -MainWnd::MainWnd(const char *server, - int port, - bool auto_connect, - bool auto_call) - : ui_(CONNECT_TO_SERVER), - wnd_(NULL), - edit1_(NULL), - edit2_(NULL), - label1_(NULL), - label2_(NULL), - button_(NULL), - listbox_(NULL), - destroyed_(false), - nested_msg_(NULL), - callback_(NULL), - server_(server), - auto_connect_(auto_connect), - auto_call_(auto_call) -{ - char buffer[10]; - snprintf(buffer, sizeof(buffer), "%i", port); - port_ = buffer; -} - -MainWnd::~MainWnd() -{ - RTC_DCHECK(!IsWindow()); -} - -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(GetDefaultFont()), - TRUE); - - CreateChildWindows(); - SwitchToConnectUI(); - - return wnd_ != NULL; -} - -bool MainWnd::Destroy() -{ - BOOL ret = FALSE; - if (IsWindow()) - { - ret = ::DestroyWindow(wnd_); - } - - return ret != FALSE; -} - -void MainWnd::RegisterObserver(MainWndCallback *callback) -{ - callback_ = callback; -} - -bool MainWnd::IsWindow() -{ - return wnd_ && ::IsWindow(wnd_) != FALSE; -} - -bool MainWnd::PreTranslateMessage(MSG *msg) -{ - bool ret = false; - if (msg->message == WM_CHAR) - { - if (msg->wParam == VK_TAB) - { - HandleTabbing(); - ret = true; - } - else if (msg->wParam == VK_RETURN) - { - OnDefaultAction(); - ret = true; - } - else if (msg->wParam == VK_ESCAPE) - { - if (callback_) - { - 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)); - ret = true; - } - return ret; -} - -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); -} - -void MainWnd::SwitchToPeerList(const Peers &peers) -{ - LayoutConnectUI(false); - - ::SendMessage(listbox_, LB_RESETCONTENT, 0, 0); - - AddListBoxItem(listbox_, "List of currently connected peers:", -1); - Peers::const_iterator i = peers.begin(); - for (; i != peers.end(); ++i) - AddListBoxItem(listbox_, i->second.c_str(), i->first); - - ui_ = LIST_PEERS; - LayoutPeerListUI(true); - ::SetFocus(listbox_); - - if (auto_call_ && peers.begin() != peers.end()) - { - // Get the number of items in the list - LRESULT count = ::SendMessage(listbox_, LB_GETCOUNT, 0, 0); - if (count != LB_ERR) - { - // Select the last item in the list - LRESULT selection = ::SendMessage(listbox_, LB_SETCURSEL, count - 1, 0); - if (selection != LB_ERR) - ::PostMessage(wnd_, WM_COMMAND, - MAKEWPARAM(GetDlgCtrlID(listbox_), LBN_DBLCLK), - reinterpret_cast(listbox_)); - } - } -} - -void MainWnd::SwitchToStreamingUI() -{ - LayoutConnectUI(false); - LayoutPeerListUI(false); - ui_ = STREAMING; -} - -void MainWnd::MessageBox(const char *caption, const char *text, bool is_error) -{ - DWORD flags = MB_OK; - if (is_error) - flags |= MB_ICONERROR; - - ::MessageBoxA(handle(), text, caption, flags); -} - -void MainWnd::StartLocalRenderer(webrtc::VideoTrackInterface *local_video) -{ - local_renderer_.reset(new VideoRenderer(handle(), 1, 1, local_video)); -} - -void MainWnd::StopLocalRenderer() -{ - local_renderer_.reset(); -} - -void MainWnd::StartRemoteRenderer(webrtc::VideoTrackInterface *remote_video) -{ - remote_renderer_.reset(new VideoRenderer(handle(), 1, 1, remote_video)); -} - -void MainWnd::StopRemoteRenderer() -{ - remote_renderer_.reset(); -} - -void MainWnd::QueueUIThreadCallback(int msg_id, void *data) -{ - ::PostThreadMessage(ui_thread_id_, UI_THREAD_CALLBACK, - static_cast(msg_id), - reinterpret_cast(data)); -} - -void MainWnd::OnPaint() -{ - PAINTSTRUCT ps; - ::BeginPaint(handle(), &ps); - - RECT rc; - ::GetClientRect(handle(), &rc); - - VideoRenderer *local_renderer = local_renderer_.get(); - VideoRenderer *remote_renderer = remote_renderer_.get(); - if (ui_ == STREAMING && remote_renderer && local_renderer) - { - AutoLock local_lock(local_renderer); - AutoLock remote_lock(remote_renderer); - - const BITMAPINFO &bmi = remote_renderer->bmi(); - int height = abs(bmi.bmiHeader.biHeight); - int width = bmi.bmiHeader.biWidth; - - const uint8_t *image = remote_renderer->image(); - if (image != NULL) - { - HDC dc_mem = ::CreateCompatibleDC(ps.hdc); - ::SetStretchBltMode(dc_mem, HALFTONE); - - // Set the map mode so that the ratio will be maintained for us. - HDC all_dc[] = {ps.hdc, dc_mem}; - for (size_t i = 0; i < arraysize(all_dc); ++i) - { - SetMapMode(all_dc[i], MM_ISOTROPIC); - SetWindowExtEx(all_dc[i], width, height, NULL); - SetViewportExtEx(all_dc[i], rc.right, rc.bottom, NULL); - } - - HBITMAP bmp_mem = ::CreateCompatibleBitmap(ps.hdc, rc.right, rc.bottom); - HGDIOBJ bmp_old = ::SelectObject(dc_mem, bmp_mem); - - POINT logical_area = {rc.right, rc.bottom}; - DPtoLP(ps.hdc, &logical_area, 1); - - HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0)); - RECT logical_rect = {0, 0, logical_area.x, logical_area.y}; - ::FillRect(dc_mem, &logical_rect, brush); - ::DeleteObject(brush); - - int x = (logical_area.x / 2) - (width / 2); - int y = (logical_area.y / 2) - (height / 2); - - StretchDIBits(dc_mem, x, y, width, height, 0, 0, width, height, image, - &bmi, DIB_RGB_COLORS, SRCCOPY); - - if ((rc.right - rc.left) > 200 && (rc.bottom - rc.top) > 200) - { - const BITMAPINFO &bmi = local_renderer->bmi(); - image = local_renderer->image(); - int thumb_width = bmi.bmiHeader.biWidth / 4; - int thumb_height = abs(bmi.bmiHeader.biHeight) / 4; - StretchDIBits(dc_mem, logical_area.x - thumb_width - 10, - logical_area.y - thumb_height - 10, thumb_width, - thumb_height, 0, 0, bmi.bmiHeader.biWidth, - -bmi.bmiHeader.biHeight, image, &bmi, DIB_RGB_COLORS, - SRCCOPY); - } - - BitBlt(ps.hdc, 0, 0, logical_area.x, logical_area.y, dc_mem, 0, 0, - SRCCOPY); - - // Cleanup. - ::SelectObject(dc_mem, bmp_old); - ::DeleteObject(bmp_mem); - ::DeleteDC(dc_mem); - } - else - { - // We're still waiting for the video stream to be initialized. - HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0)); - ::FillRect(ps.hdc, &rc, brush); - ::DeleteObject(brush); - - HGDIOBJ old_font = ::SelectObject(ps.hdc, GetDefaultFont()); - ::SetTextColor(ps.hdc, RGB(0xff, 0xff, 0xff)); - ::SetBkMode(ps.hdc, TRANSPARENT); - - std::string text(kConnecting); - if (!local_renderer->image()) - { - text += kNoVideoStreams; - } - else - { - text += kNoIncomingStream; - } - ::DrawTextA(ps.hdc, text.c_str(), -1, &rc, - DT_SINGLELINE | DT_CENTER | DT_VCENTER); - ::SelectObject(ps.hdc, old_font); - } - } - else - { - HBRUSH brush = ::CreateSolidBrush(::GetSysColor(COLOR_WINDOW)); - ::FillRect(ps.hdc, &rc, brush); - ::DeleteObject(brush); - } - - ::EndPaint(handle(), &ps); -} - -void MainWnd::OnDestroyed() -{ - PostQuitMessage(0); -} - -void MainWnd::OnDefaultAction() -{ - if (!callback_) - return; - if (ui_ == CONNECT_TO_SERVER) - { - std::string server(GetWindowText(edit1_)); - std::string port_str(GetWindowText(edit2_)); - int port = port_str.length() ? atoi(port_str.c_str()) : 0; - callback_->StartLogin(server, port); - } - else if (ui_ == LIST_PEERS) - { - LRESULT sel = ::SendMessage(listbox_, LB_GETCURSEL, 0, 0); - if (sel != LB_ERR) - { - LRESULT peer_id = ::SendMessage(listbox_, LB_GETITEMDATA, sel, 0); - if (peer_id != -1 && callback_) - { - callback_->ConnectToPeer(peer_id); - } - } - } - else - { - ::MessageBoxA(wnd_, "OK!", "Yeah", MB_OK); - } -} - -bool MainWnd::OnMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT *result) -{ - switch (msg) - { - case WM_ERASEBKGND: - *result = TRUE; - return true; - - case WM_PAINT: - OnPaint(); - return true; - - case WM_SETFOCUS: - if (ui_ == CONNECT_TO_SERVER) - { - SetFocus(edit1_); - } - else if (ui_ == LIST_PEERS) - { - SetFocus(listbox_); - } - return true; - - case WM_SIZE: - if (ui_ == CONNECT_TO_SERVER) - { - LayoutConnectUI(true); - } - else if (ui_ == LIST_PEERS) - { - LayoutPeerListUI(true); - } - break; - - case WM_CTLCOLORSTATIC: - *result = reinterpret_cast(GetSysColorBrush(COLOR_WINDOW)); - 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; - - case WM_CLOSE: - if (callback_) - callback_->Close(); - break; - } - return false; -} - -// static -LRESULT CALLBACK MainWnd::WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) -{ - MainWnd *me = - reinterpret_cast(::GetWindowLongPtr(hwnd, GWLP_USERDATA)); - if (!me && WM_CREATE == msg) - { - CREATESTRUCT *cs = reinterpret_cast(lp); - me = reinterpret_cast(cs->lpCreateParams); - me->wnd_ = hwnd; - ::SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(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; -} - -// static -bool MainWnd::RegisterWindowClass() -{ - if (wnd_class_) - return true; - - WNDCLASSEXW wcex = {sizeof(WNDCLASSEX)}; - wcex.style = CS_DBLCLKS; - wcex.hInstance = GetModuleHandle(NULL); - wcex.hbrBackground = reinterpret_cast(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::CreateChildWindow(HWND *wnd, - MainWnd::ChildWindowID id, - const wchar_t *class_name, - DWORD control_style, - DWORD ex_style) -{ - if (::IsWindow(*wnd)) - return; - - // Child windows are invisible at first, and shown after being resized. - DWORD style = WS_CHILD | control_style; - *wnd = ::CreateWindowExW(ex_style, class_name, L"", style, 100, 100, 100, 100, - wnd_, reinterpret_cast(id), - GetModuleHandle(NULL), NULL); - RTC_DCHECK(::IsWindow(*wnd) != FALSE); - ::SendMessage(*wnd, WM_SETFONT, reinterpret_cast(GetDefaultFont()), - TRUE); -} - -void MainWnd::CreateChildWindows() -{ - // Create the child windows in tab order. - CreateChildWindow(&label1_, LABEL1_ID, L"Static", ES_CENTER | ES_READONLY, 0); - CreateChildWindow(&edit1_, EDIT_ID, L"Edit", - ES_LEFT | ES_NOHIDESEL | WS_TABSTOP, WS_EX_CLIENTEDGE); - CreateChildWindow(&label2_, LABEL2_ID, L"Static", ES_CENTER | ES_READONLY, 0); - CreateChildWindow(&edit2_, EDIT_ID, L"Edit", - ES_LEFT | ES_NOHIDESEL | WS_TABSTOP, WS_EX_CLIENTEDGE); - CreateChildWindow(&button_, BUTTON_ID, L"Button", BS_CENTER | WS_TABSTOP, 0); - - CreateChildWindow(&listbox_, LISTBOX_ID, L"ListBox", - LBS_HASSTRINGS | LBS_NOTIFY, WS_EX_CLIENTEDGE); - - ::SetWindowTextA(edit1_, server_.c_str()); - ::SetWindowTextA(edit2_, port_.c_str()); -} - -void MainWnd::LayoutConnectUI(bool show) -{ - struct Windows - { - HWND wnd; - const wchar_t *text; - size_t width; - size_t height; - } windows[] = { - {label1_, L"Server"}, - {edit1_, L"XXXyyyYYYgggXXXyyyYYYggg"}, - {label2_, L":"}, - {edit2_, L"XyXyX"}, - {button_, L"Connect"}, - }; - - if (show) - { - const size_t kSeparator = 5; - size_t total_width = (ARRAYSIZE(windows) - 1) * kSeparator; - - for (size_t i = 0; i < ARRAYSIZE(windows); ++i) - { - CalculateWindowSizeForText(windows[i].wnd, windows[i].text, - &windows[i].width, &windows[i].height); - total_width += windows[i].width; - } - - RECT rc; - ::GetClientRect(wnd_, &rc); - size_t x = (rc.right / 2) - (total_width / 2); - size_t y = rc.bottom / 2; - for (size_t i = 0; i < ARRAYSIZE(windows); ++i) - { - size_t top = y - (windows[i].height / 2); - ::MoveWindow(windows[i].wnd, static_cast(x), static_cast(top), - static_cast(windows[i].width), - static_cast(windows[i].height), TRUE); - x += kSeparator + windows[i].width; - if (windows[i].text[0] != 'X') - ::SetWindowTextW(windows[i].wnd, windows[i].text); - ::ShowWindow(windows[i].wnd, SW_SHOWNA); - } - } - else - { - for (size_t i = 0; i < ARRAYSIZE(windows); ++i) - { - ::ShowWindow(windows[i].wnd, SW_HIDE); - } - } -} - -void MainWnd::LayoutPeerListUI(bool show) -{ - if (show) - { - RECT rc; - ::GetClientRect(wnd_, &rc); - ::MoveWindow(listbox_, 0, 0, rc.right, rc.bottom, TRUE); - ::ShowWindow(listbox_, SW_SHOWNA); - } - else - { - ::ShowWindow(listbox_, SW_HIDE); - InvalidateRect(wnd_, NULL, TRUE); - } -} - -void MainWnd::HandleTabbing() -{ - bool shift = ((::GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0); - UINT next_cmd = shift ? GW_HWNDPREV : GW_HWNDNEXT; - UINT loop_around_cmd = shift ? GW_HWNDLAST : GW_HWNDFIRST; - HWND focus = GetFocus(), next; - do - { - next = ::GetWindow(focus, next_cmd); - if (IsWindowVisible(next) && - (GetWindowLong(next, GWL_STYLE) & WS_TABSTOP)) - { - break; - } - - if (!next) - { - next = ::GetWindow(focus, loop_around_cmd); - if (IsWindowVisible(next) && - (GetWindowLong(next, GWL_STYLE) & WS_TABSTOP)) - { - break; - } - } - focus = next; - } while (true); - ::SetFocus(next); -} - -// -// MainWnd::VideoRenderer -// - -MainWnd::VideoRenderer::VideoRenderer( - HWND wnd, - int width, - int height, - webrtc::VideoTrackInterface *track_to_render) - : wnd_(wnd), rendered_track_(track_to_render) -{ - ::InitializeCriticalSection(&buffer_lock_); - ZeroMemory(&bmi_, sizeof(bmi_)); - bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi_.bmiHeader.biPlanes = 1; - bmi_.bmiHeader.biBitCount = 32; - bmi_.bmiHeader.biCompression = BI_RGB; - bmi_.bmiHeader.biWidth = width; - bmi_.bmiHeader.biHeight = -height; - bmi_.bmiHeader.biSizeImage = - width * height * (bmi_.bmiHeader.biBitCount >> 3); - rendered_track_->AddOrUpdateSink(this, rtc::VideoSinkWants()); -} - -MainWnd::VideoRenderer::~VideoRenderer() -{ - rendered_track_->RemoveSink(this); - ::DeleteCriticalSection(&buffer_lock_); -} - -void MainWnd::VideoRenderer::SetSize(int width, int height) -{ - AutoLock lock(this); - - if (width == bmi_.bmiHeader.biWidth && height == bmi_.bmiHeader.biHeight) - { - return; - } - - bmi_.bmiHeader.biWidth = width; - bmi_.bmiHeader.biHeight = -height; - bmi_.bmiHeader.biSizeImage = - width * height * (bmi_.bmiHeader.biBitCount >> 3); - image_.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]); -} - -void MainWnd::VideoRenderer::OnFrame(const webrtc::VideoFrame &video_frame) -{ - { - AutoLock lock(this); - - rtc::scoped_refptr buffer( - video_frame.video_frame_buffer()->ToI420()); - if (video_frame.rotation() != webrtc::kVideoRotation_0) - { - buffer = webrtc::I420Buffer::Rotate(*buffer, video_frame.rotation()); - } - - SetSize(buffer->width(), buffer->height()); - - RTC_DCHECK(image_.get() != NULL); - libyuv::I420ToARGB(buffer->DataY(), buffer->StrideY(), buffer->DataU(), - buffer->StrideU(), buffer->DataV(), buffer->StrideV(), - image_.get(), - bmi_.bmiHeader.biWidth * bmi_.bmiHeader.biBitCount / 8, - buffer->width(), buffer->height()); - } - InvalidateRect(wnd_, NULL, TRUE); -} diff --git a/client/webrtc_demo/src/main_wnd.h b/client/webrtc_demo/src/main_wnd.h deleted file mode 100644 index f3abe7e..0000000 --- a/client/webrtc_demo/src/main_wnd.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2012 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef EXAMPLES_PEERCONNECTION_CLIENT_MAIN_WND_H_ -#define EXAMPLES_PEERCONNECTION_CLIENT_MAIN_WND_H_ - -#include -#include -#include - -#include "api/media_stream_interface.h" -#include "api/video/video_frame.h" -#include "peer_connection_client.h" -#include "media/base/media_channel.h" -#include "media/base/video_common.h" -#if defined(WEBRTC_WIN) -#include "rtc_base/win32.h" -#endif // WEBRTC_WIN - -class MainWndCallback -{ -public: - virtual void StartLogin(const std::string &server, int port) = 0; - virtual void DisconnectFromServer() = 0; - virtual void ConnectToPeer(int peer_id) = 0; - virtual void DisconnectFromCurrentPeer() = 0; - virtual void UIThreadCallback(int msg_id, void *data) = 0; - virtual void Close() = 0; - -protected: - virtual ~MainWndCallback() {} -}; - -// Pure virtual interface for the main window. -class MainWindow -{ -public: - virtual ~MainWindow() {} - - enum UI - { - CONNECT_TO_SERVER, - LIST_PEERS, - STREAMING, - }; - - virtual void RegisterObserver(MainWndCallback *callback) = 0; - - virtual bool IsWindow() = 0; - virtual void MessageBox(const char *caption, - const char *text, - bool is_error) = 0; - - virtual UI current_ui() = 0; - - virtual void SwitchToConnectUI() = 0; - virtual void SwitchToPeerList(const Peers &peers) = 0; - virtual void SwitchToStreamingUI() = 0; - - virtual void StartLocalRenderer(webrtc::VideoTrackInterface *local_video) = 0; - virtual void StopLocalRenderer() = 0; - virtual void StartRemoteRenderer( - webrtc::VideoTrackInterface *remote_video) = 0; - virtual void StopRemoteRenderer() = 0; - - virtual void QueueUIThreadCallback(int msg_id, void *data) = 0; -}; - -#ifdef WIN32 - -class MainWnd : public MainWindow -{ -public: - static const wchar_t kClassName[]; - - enum WindowMessages - { - UI_THREAD_CALLBACK = WM_APP + 1, - }; - - MainWnd(const char *server, int port, bool auto_connect, bool auto_call); - ~MainWnd(); - - bool Create(); - bool Destroy(); - bool PreTranslateMessage(MSG *msg); - - virtual void RegisterObserver(MainWndCallback *callback); - virtual bool IsWindow(); - virtual void SwitchToConnectUI(); - virtual void SwitchToPeerList(const Peers &peers); - virtual void SwitchToStreamingUI(); - virtual void MessageBox(const char *caption, const char *text, bool is_error); - virtual UI current_ui() { return ui_; } - - virtual void StartLocalRenderer(webrtc::VideoTrackInterface *local_video); - virtual void StopLocalRenderer(); - virtual void StartRemoteRenderer(webrtc::VideoTrackInterface *remote_video); - virtual void StopRemoteRenderer(); - - virtual void QueueUIThreadCallback(int msg_id, void *data); - - HWND handle() const { return wnd_; } - - class VideoRenderer : public rtc::VideoSinkInterface - { - public: - VideoRenderer(HWND wnd, - int width, - int height, - webrtc::VideoTrackInterface *track_to_render); - virtual ~VideoRenderer(); - - void Lock() { ::EnterCriticalSection(&buffer_lock_); } - - void Unlock() { ::LeaveCriticalSection(&buffer_lock_); } - - // VideoSinkInterface implementation - void OnFrame(const webrtc::VideoFrame &frame) override; - - const BITMAPINFO &bmi() const { return bmi_; } - const uint8_t *image() const { return image_.get(); } - - protected: - void SetSize(int width, int height); - - enum - { - SET_SIZE, - RENDER_FRAME, - }; - - HWND wnd_; - BITMAPINFO bmi_; - std::unique_ptr image_; - CRITICAL_SECTION buffer_lock_; - rtc::scoped_refptr rendered_track_; - }; - - // A little helper class to make sure we always to proper locking and - // unlocking when working with VideoRenderer buffers. - template - class AutoLock - { - public: - explicit AutoLock(T *obj) : obj_(obj) { obj_->Lock(); } - ~AutoLock() { obj_->Unlock(); } - - protected: - T *obj_; - }; - -protected: - enum ChildWindowID - { - EDIT_ID = 1, - BUTTON_ID, - LABEL1_ID, - LABEL2_ID, - LISTBOX_ID, - }; - - void OnPaint(); - void OnDestroyed(); - - void OnDefaultAction(); - - bool OnMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT *result); - - static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); - static bool RegisterWindowClass(); - - void CreateChildWindow(HWND *wnd, - ChildWindowID id, - const wchar_t *class_name, - DWORD control_style, - DWORD ex_style); - void CreateChildWindows(); - - void LayoutConnectUI(bool show); - void LayoutPeerListUI(bool show); - - void HandleTabbing(); - -private: - std::unique_ptr local_renderer_; - std::unique_ptr remote_renderer_; - UI ui_; - HWND wnd_; - DWORD ui_thread_id_; - HWND edit1_; - HWND edit2_; - HWND label1_; - HWND label2_; - HWND button_; - HWND listbox_; - bool destroyed_; - void *nested_msg_; - MainWndCallback *callback_; - static ATOM wnd_class_; - std::string server_; - std::string port_; - bool auto_connect_; - bool auto_call_; -}; -#endif // WIN32 - -#endif // EXAMPLES_PEERCONNECTION_CLIENT_MAIN_WND_H_ diff --git a/client/webrtc_demo/src/mainwindow.cpp b/client/webrtc_demo/src/mainwindow.cpp index 7af6579..a425a46 100644 --- a/client/webrtc_demo/src/mainwindow.cpp +++ b/client/webrtc_demo/src/mainwindow.cpp @@ -1,13 +1,19 @@ #include "mainwindow.h" #include "ui_mainwindow.h" +#include +#include +#include "MyCapturer.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) - , ui(new Ui::MainWindow) + , ui(new Ui::MainWindow), + mHandler(new rtc::RefCountedObject()) { ui->setupUi(this); ui->openGLWidget->SetImgSize(640,480); - ui->openGLWidget->show(); + ui->openGLWidget->show(); + + mHandler->InitWebrtc(); } MainWindow::~MainWindow() @@ -27,3 +33,130 @@ void MainWindow::OnUpdateFrame1(uint8_t *dat) ui->openGLWidget->OnCameraData(dat); } + +int WebrtcHanlder::InitWebrtc() +{ + m_peer_connection_factory_ = webrtc::CreatePeerConnectionFactory( + nullptr /* network_thread */, nullptr /* worker_thread */, + nullptr /* signaling_thread */, nullptr /* default_adm */, + webrtc::CreateBuiltinAudioEncoderFactory(), + webrtc::CreateBuiltinAudioDecoderFactory(), + webrtc::CreateBuiltinVideoEncoderFactory(), + webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */, + nullptr /* audio_processing */); + + if (!m_peer_connection_factory_) { + auto x = new QMessageBox(nullptr); + x->setText("创建peerconnection factory失败"); + x->show(); + exit(0); + } + + webrtc::PeerConnectionInterface::RTCConfiguration config; + config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; + config.enable_dtls_srtp = true; + webrtc::PeerConnectionInterface::IceServer server; + server.uri = "stun:stun.l.google.com:19302"; // stunæœåŠ¡å™¨ + config.servers.push_back(server); + + m_peer_connection_ = m_peer_connection_factory_->CreatePeerConnection( + config, nullptr, nullptr, this); + + if (!m_peer_connection_) { + auto x = new QMessageBox(nullptr); + x->setText("创建peerconnection失败"); + x->show(); + exit(0); + } +} + + +const char kAudioLabel[] = "audio_label"; +const char kVideoLabel[] = "video_label"; +const char kStreamId[] = "stream_id"; + +int WebrtcHanlder::AddTrack() +{ + if (!m_peer_connection_->GetSenders().empty()) { + return -1; // Already added tracks. + } + // add audio tracks + rtc::scoped_refptr audio_track( + m_peer_connection_factory_->CreateAudioTrack( + kAudioLabel, m_peer_connection_factory_->CreateAudioSource( + cricket::AudioOptions()))); + + auto result_or_error = m_peer_connection_->AddTrack(audio_track, {kStreamId}); + if (!result_or_error.ok()) { + RTC_LOG(LS_ERROR) << "Failed to add audio track to PeerConnection: " + << result_or_error.error().message(); + } + //rtc::scoped_refptr video_device = + // CapturerTrackSource::Create(); + rtc::scoped_refptr video_device = new rtc::RefCountedObject(); + if (video_device) { + video_device->startCapturer(); + rtc::scoped_refptr video_track_( + m_peer_connection_factory_->CreateVideoTrack(kVideoLabel, video_device)); + + result_or_error = m_peer_connection_->AddTrack(video_track_, { kStreamId }); + if (!result_or_error.ok()) { + RTC_LOG(LS_ERROR) << "Failed to add video track to PeerConnection: " + << result_or_error.error().message(); + } + } else { + RTC_LOG(LS_ERROR) << "OpenVideoCaptureDevice failed"; + } +} + +WebrtcHanlder::~WebrtcHanlder() +{ + +} + +void WebrtcHanlder::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) { + +} + +void WebrtcHanlder::OnAddTrack(rtc::scoped_refptr receiver, const std::vector > &streams) +{ + +} + +void WebrtcHanlder::OnRemoveTrack(rtc::scoped_refptr receiver) +{ + +} + +void WebrtcHanlder::OnDataChannel(rtc::scoped_refptr channel) { + +} + +void WebrtcHanlder::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) { + +} + +void WebrtcHanlder::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) { + +} + +void WebrtcHanlder::OnIceCandidate(const webrtc::IceCandidateInterface *candidate) +{ + +} + +void WebrtcHanlder::OnIceConnectionReceivingChange(bool receiving) { + +} + +void WebrtcHanlder::OnSuccess(webrtc::SessionDescriptionInterface *desc) +{ + qDebug()<type().c_str(); +} + +void WebrtcHanlder::OnFailure(webrtc::RTCError error) +{ + qDebug()< #include "api/video/i420_buffer.h" @@ -8,18 +32,61 @@ QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE -class MainWindow : public QMainWindow + +class WebrtcHanlder :public webrtc::PeerConnectionObserver, + public webrtc::CreateSessionDescriptionObserver{ +public: + int InitWebrtc(); + int AddTrack(); +protected: + ~WebrtcHanlder(); + // + // PeerConnectionClientObserver implementation. + // + void OnSignalingChange( + webrtc::PeerConnectionInterface::SignalingState new_state) override; + void OnAddTrack(rtc::scoped_refptr receiver, + const std::vector>& + streams) override; + void OnRemoveTrack( + rtc::scoped_refptr receiver) override; + void OnDataChannel( + rtc::scoped_refptr channel) override; + void OnRenegotiationNeeded() override {} + void OnIceConnectionChange( + webrtc::PeerConnectionInterface::IceConnectionState new_state) override; + void OnIceGatheringChange( + webrtc::PeerConnectionInterface::IceGatheringState new_state) override; + void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override; + void OnIceConnectionReceivingChange(bool receiving) override; + + // CreateSessionDescriptionObserver + void OnSuccess(webrtc::SessionDescriptionInterface* desc) override; + void OnFailure(webrtc::RTCError error) override; + +private: + rtc::scoped_refptr m_peer_connection_; + rtc::scoped_refptr + m_peer_connection_factory_; + + +}; + +class MainWindow :public QMainWindow { Q_OBJECT - public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); +protected: + public slots: void OnUpdateFrame( rtc::scoped_refptr& buffer); void OnUpdateFrame1( uint8_t *); private: Ui::MainWindow *ui; + rtc::scoped_refptr mHandler; + }; #endif // MAINWINDOW_H diff --git a/client/webrtc_demo/src/peer_connection_client.cc b/client/webrtc_demo/src/peer_connection_client.cc deleted file mode 100644 index d35e0c9..0000000 --- a/client/webrtc_demo/src/peer_connection_client.cc +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright 2012 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "peer_connection_client.h" - -#include "defaults.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" -#include "rtc_base/net_helpers.h" - -#ifdef WIN32 -#include "rtc_base/win32_socket_server.h" -#endif - -namespace -{ - - // This is our magical hangup signal. - const char kByeMessage[] = "BYE"; - // Delay between server connection retries, in milliseconds - const int kReconnectDelay = 2000; - - rtc::AsyncSocket *CreateClientSocket(int family) - { -#ifdef WIN32 - rtc::Win32Socket *sock = new rtc::Win32Socket(); - sock->CreateT(family, SOCK_STREAM); - return sock; -#elif defined(WEBRTC_POSIX) - rtc::Thread *thread = rtc::Thread::Current(); - RTC_DCHECK(thread != NULL); - return thread->socketserver()->CreateAsyncSocket(family, SOCK_STREAM); -#else -#error Platform not supported. -#endif - } - -} // namespace - -PeerConnectionClient::PeerConnectionClient() - : callback_(NULL), resolver_(NULL), state_(NOT_CONNECTED), my_id_(-1) {} - -PeerConnectionClient::~PeerConnectionClient() -{ - rtc::Thread::Current()->Clear(this); -} - -void PeerConnectionClient::InitSocketSignals() -{ - RTC_DCHECK(control_socket_.get() != NULL); - RTC_DCHECK(hanging_get_.get() != NULL); - 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); -} - -int PeerConnectionClient::id() const -{ - return my_id_; -} - -bool PeerConnectionClient::is_connected() const -{ - return my_id_ != -1; -} - -const Peers &PeerConnectionClient::peers() const -{ - return peers_; -} - -void PeerConnectionClient::RegisterObserver( - PeerConnectionClientObserver *callback) -{ - RTC_DCHECK(!callback_); - callback_ = callback; -} - -void PeerConnectionClient::Connect(const std::string &server, - int port, - const std::string &client_name) -{ - RTC_DCHECK(!server.empty()); - RTC_DCHECK(!client_name.empty()); - - if (state_ != NOT_CONNECTED) - { - RTC_LOG(WARNING) - << "The client must not be connected before you can call Connect()"; - callback_->OnServerConnectionFailure(); - return; - } - - if (server.empty() || client_name.empty()) - { - callback_->OnServerConnectionFailure(); - return; - } - - if (port <= 0) - port = kDefaultServerPort; - - server_address_.SetIP(server); - server_address_.SetPort(port); - client_name_ = client_name; - - if (server_address_.IsUnresolvedIP()) - { - state_ = RESOLVING; - resolver_ = new rtc::AsyncResolver(); - resolver_->SignalDone.connect(this, &PeerConnectionClient::OnResolveResult); - resolver_->Start(server_address_); - } - else - { - DoConnect(); - } -} - -void PeerConnectionClient::OnResolveResult( - rtc::AsyncResolverInterface *resolver) -{ - if (resolver_->GetError() != 0) - { - callback_->OnServerConnectionFailure(); - resolver_->Destroy(false); - resolver_ = NULL; - state_ = NOT_CONNECTED; - } - else - { - server_address_ = resolver_->address(); - DoConnect(); - } -} - -void PeerConnectionClient::DoConnect() -{ - control_socket_.reset(CreateClientSocket(server_address_.ipaddr().family())); - hanging_get_.reset(CreateClientSocket(server_address_.ipaddr().family())); - InitSocketSignals(); - char buffer[1024]; - snprintf(buffer, sizeof(buffer), "GET /sign_in?%s HTTP/1.0\r\n\r\n", - client_name_.c_str()); - onconnect_data_ = buffer; - - bool ret = ConnectControlSocket(); - if (ret) - state_ = SIGNING_IN; - if (!ret) - { - callback_->OnServerConnectionFailure(); - } -} - -bool PeerConnectionClient::SendToPeer(int peer_id, const std::string &message) -{ - if (state_ != CONNECTED) - return false; - - RTC_DCHECK(is_connected()); - RTC_DCHECK(control_socket_->GetState() == rtc::Socket::CS_CLOSED); - if (!is_connected() || peer_id == -1) - return false; - - char headers[1024]; - snprintf(headers, sizeof(headers), - "POST /message?peer_id=%i&to=%i HTTP/1.0\r\n" - "Content-Length: %zu\r\n" - "Content-Type: text/plain\r\n" - "\r\n", - my_id_, peer_id, message.length()); - onconnect_data_ = headers; - onconnect_data_ += message; - return ConnectControlSocket(); -} - -bool PeerConnectionClient::SendHangUp(int peer_id) -{ - return SendToPeer(peer_id, kByeMessage); -} - -bool PeerConnectionClient::IsSendingMessage() -{ - return state_ == CONNECTED && - control_socket_->GetState() != rtc::Socket::CS_CLOSED; -} - -bool PeerConnectionClient::SignOut() -{ - if (state_ == NOT_CONNECTED || state_ == SIGNING_OUT) - return true; - - if (hanging_get_->GetState() != rtc::Socket::CS_CLOSED) - hanging_get_->Close(); - - if (control_socket_->GetState() == rtc::Socket::CS_CLOSED) - { - state_ = SIGNING_OUT; - - if (my_id_ != -1) - { - char buffer[1024]; - snprintf(buffer, sizeof(buffer), - "GET /sign_out?peer_id=%i HTTP/1.0\r\n\r\n", my_id_); - onconnect_data_ = buffer; - return ConnectControlSocket(); - } - else - { - // Can occur if the app is closed before we finish connecting. - return true; - } - } - else - { - state_ = SIGNING_OUT_WAITING; - } - - return true; -} - -void PeerConnectionClient::Close() -{ - control_socket_->Close(); - hanging_get_->Close(); - onconnect_data_.clear(); - peers_.clear(); - if (resolver_ != NULL) - { - resolver_->Destroy(false); - resolver_ = NULL; - } - my_id_ = -1; - state_ = NOT_CONNECTED; -} - -bool PeerConnectionClient::ConnectControlSocket() -{ - RTC_DCHECK(control_socket_->GetState() == rtc::Socket::CS_CLOSED); - int err = control_socket_->Connect(server_address_); - if (err == SOCKET_ERROR) - { - Close(); - return false; - } - return true; -} - -void PeerConnectionClient::OnConnect(rtc::AsyncSocket *socket) -{ - RTC_DCHECK(!onconnect_data_.empty()); - size_t sent = socket->Send(onconnect_data_.c_str(), onconnect_data_.length()); - RTC_DCHECK(sent == onconnect_data_.length()); - onconnect_data_.clear(); -} - -void PeerConnectionClient::OnHangingGetConnect(rtc::AsyncSocket *socket) -{ - char buffer[1024]; - snprintf(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); - RTC_DCHECK(sent == len); -} - -void PeerConnectionClient::OnMessageFromPeer(int peer_id, - const std::string &message) -{ - if (message.length() == (sizeof(kByeMessage) - 1) && - message.compare(kByeMessage) == 0) - { - callback_->OnPeerDisconnected(peer_id); - } - else - { - callback_->OnMessageFromPeer(peer_id, message); - } -} - -bool PeerConnectionClient::GetHeaderValue(const std::string &data, - size_t eoh, - const char *header_pattern, - size_t *value) -{ - RTC_DCHECK(value != NULL); - size_t found = data.find(header_pattern); - if (found != std::string::npos && found < eoh) - { - *value = atoi(&data[found + strlen(header_pattern)]); - return true; - } - return false; -} - -bool PeerConnectionClient::GetHeaderValue(const std::string &data, - size_t eoh, - const char *header_pattern, - std::string *value) -{ - RTC_DCHECK(value != NULL); - size_t found = data.find(header_pattern); - if (found != std::string::npos && found < eoh) - { - size_t begin = found + strlen(header_pattern); - size_t end = data.find("\r\n", begin); - if (end == std::string::npos) - end = eoh; - value->assign(data.substr(begin, end - begin)); - return true; - } - return false; -} - -bool PeerConnectionClient::ReadIntoBuffer(rtc::AsyncSocket *socket, - std::string *data, - size_t *content_length) -{ - char buffer[0xffff]; - do - { - int bytes = socket->Recv(buffer, sizeof(buffer), nullptr); - if (bytes <= 0) - break; - data->append(buffer, bytes); - } while (true); - - bool ret = false; - size_t i = data->find("\r\n\r\n"); - if (i != std::string::npos) - { - RTC_LOG(INFO) << "Headers received"; - if (GetHeaderValue(*data, i, "\r\nContent-Length: ", content_length)) - { - size_t total_response_size = (i + 4) + *content_length; - if (data->length() >= total_response_size) - { - ret = true; - std::string should_close; - const char kConnection[] = "\r\nConnection: "; - if (GetHeaderValue(*data, i, kConnection, &should_close) && - should_close.compare("close") == 0) - { - socket->Close(); - // Since we closed the socket, there was no notification delivered - // to us. Compensate by letting ourselves know. - OnClose(socket, 0); - } - } - else - { - // We haven't received everything. Just continue to accept data. - } - } - else - { - RTC_LOG(LS_ERROR) << "No content length field specified by the server."; - } - } - return ret; -} - -void PeerConnectionClient::OnRead(rtc::AsyncSocket *socket) -{ - size_t content_length = 0; - if (ReadIntoBuffer(socket, &control_data_, &content_length)) - { - size_t peer_id = 0, eoh = 0; - bool ok = - ParseServerResponse(control_data_, content_length, &peer_id, &eoh); - if (ok) - { - if (my_id_ == -1) - { - // First response. Let's store our server assigned ID. - RTC_DCHECK(state_ == SIGNING_IN); - my_id_ = static_cast(peer_id); - RTC_DCHECK(my_id_ != -1); - - // The body of the response will be a list of already connected peers. - if (content_length) - { - size_t pos = eoh + 4; - while (pos < control_data_.size()) - { - size_t eol = control_data_.find('\n', pos); - if (eol == std::string::npos) - break; - int id = 0; - std::string name; - bool connected; - if (ParseEntry(control_data_.substr(pos, eol - pos), &name, &id, - &connected) && - id != my_id_) - { - peers_[id] = name; - callback_->OnPeerConnected(id, name); - } - pos = eol + 1; - } - } - RTC_DCHECK(is_connected()); - callback_->OnSignedIn(); - } - else if (state_ == SIGNING_OUT) - { - Close(); - callback_->OnDisconnected(); - } - else if (state_ == SIGNING_OUT_WAITING) - { - SignOut(); - } - } - - control_data_.clear(); - - if (state_ == SIGNING_IN) - { - RTC_DCHECK(hanging_get_->GetState() == rtc::Socket::CS_CLOSED); - state_ = CONNECTED; - hanging_get_->Connect(server_address_); - } - } -} - -void PeerConnectionClient::OnHangingGetRead(rtc::AsyncSocket *socket) -{ - RTC_LOG(INFO) << __FUNCTION__; - size_t content_length = 0; - if (ReadIntoBuffer(socket, ¬ification_data_, &content_length)) - { - size_t peer_id = 0, eoh = 0; - bool ok = - ParseServerResponse(notification_data_, content_length, &peer_id, &eoh); - - if (ok) - { - // Store the position where the body begins. - size_t pos = eoh + 4; - - if (my_id_ == static_cast(peer_id)) - { - // A notification about a new member or a member that just - // disconnected. - int id = 0; - std::string name; - bool connected = false; - if (ParseEntry(notification_data_.substr(pos), &name, &id, - &connected)) - { - if (connected) - { - peers_[id] = name; - callback_->OnPeerConnected(id, name); - } - else - { - peers_.erase(id); - callback_->OnPeerDisconnected(id); - } - } - } - else - { - OnMessageFromPeer(static_cast(peer_id), - notification_data_.substr(pos)); - } - } - - notification_data_.clear(); - } - - if (hanging_get_->GetState() == rtc::Socket::CS_CLOSED && - state_ == CONNECTED) - { - hanging_get_->Connect(server_address_); - } -} - -bool PeerConnectionClient::ParseEntry(const std::string &entry, - std::string *name, - int *id, - bool *connected) -{ - RTC_DCHECK(name != NULL); - RTC_DCHECK(id != NULL); - RTC_DCHECK(connected != NULL); - RTC_DCHECK(!entry.empty()); - - *connected = false; - size_t separator = entry.find(','); - if (separator != std::string::npos) - { - *id = atoi(&entry[separator + 1]); - name->assign(entry.substr(0, separator)); - separator = entry.find(',', separator + 1); - if (separator != std::string::npos) - { - *connected = atoi(&entry[separator + 1]) ? true : false; - } - } - return !name->empty(); -} - -int PeerConnectionClient::GetResponseStatus(const std::string &response) -{ - int status = -1; - size_t pos = response.find(' '); - if (pos != std::string::npos) - status = atoi(&response[pos + 1]); - return status; -} - -bool PeerConnectionClient::ParseServerResponse(const std::string &response, - size_t content_length, - size_t *peer_id, - size_t *eoh) -{ - int status = GetResponseStatus(response.c_str()); - if (status != 200) - { - RTC_LOG(LS_ERROR) << "Received error from server"; - Close(); - callback_->OnDisconnected(); - return false; - } - - *eoh = response.find("\r\n\r\n"); - RTC_DCHECK(*eoh != std::string::npos); - if (*eoh == std::string::npos) - return false; - - *peer_id = -1; - - // See comment in peer_channel.cc for why we use the Pragma header. - GetHeaderValue(response, *eoh, "\r\nPragma: ", peer_id); - - return true; -} - -void PeerConnectionClient::OnClose(rtc::AsyncSocket *socket, int err) -{ - RTC_LOG(INFO) << __FUNCTION__; - - socket->Close(); - -#ifdef WIN32 - if (err != WSAECONNREFUSED) - { -#else - if (err != ECONNREFUSED) - { -#endif - if (socket == hanging_get_.get()) - { - if (state_ == CONNECTED) - { - hanging_get_->Close(); - hanging_get_->Connect(server_address_); - } - } - else - { - callback_->OnMessageSent(err); - } - } - else - { - if (socket == control_socket_.get()) - { - RTC_LOG(WARNING) << "Connection refused; retrying in 2 seconds"; - rtc::Thread::Current()->PostDelayed(RTC_FROM_HERE, kReconnectDelay, this, - 0); - } - else - { - Close(); - callback_->OnDisconnected(); - } - } -} - -void PeerConnectionClient::OnMessage(rtc::Message *msg) -{ - // ignore msg; there is currently only one supported message ("retry") - DoConnect(); -} diff --git a/client/webrtc_demo/src/peer_connection_client.h b/client/webrtc_demo/src/peer_connection_client.h deleted file mode 100644 index d7ae913..0000000 --- a/client/webrtc_demo/src/peer_connection_client.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2011 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef EXAMPLES_PEERCONNECTION_CLIENT_PEER_CONNECTION_CLIENT_H_ -#define EXAMPLES_PEERCONNECTION_CLIENT_PEER_CONNECTION_CLIENT_H_ - -#include -#include -#include - -#include "rtc_base/net_helpers.h" -#include "rtc_base/physical_socket_server.h" -#include "rtc_base/third_party/sigslot/sigslot.h" - -typedef std::map Peers; - -struct PeerConnectionClientObserver { - virtual void OnSignedIn() = 0; // Called when we're logged on. - virtual void OnDisconnected() = 0; - virtual void OnPeerConnected(int id, const std::string& name) = 0; - virtual void OnPeerDisconnected(int peer_id) = 0; - virtual void OnMessageFromPeer(int peer_id, const std::string& message) = 0; - virtual void OnMessageSent(int err) = 0; - virtual void OnServerConnectionFailure() = 0; - - protected: - virtual ~PeerConnectionClientObserver() {} -}; - -class PeerConnectionClient : public sigslot::has_slots<>, - public rtc::MessageHandler { - public: - enum State { - NOT_CONNECTED, - RESOLVING, - SIGNING_IN, - CONNECTED, - SIGNING_OUT_WAITING, - SIGNING_OUT, - }; - - PeerConnectionClient(); - ~PeerConnectionClient(); - - int id() const; - bool is_connected() const; - const Peers& peers() const; - - void RegisterObserver(PeerConnectionClientObserver* callback); - - void Connect(const std::string& server, - int port, - const std::string& client_name); - - bool SendToPeer(int peer_id, const std::string& message); - bool SendHangUp(int peer_id); - bool IsSendingMessage(); - - bool SignOut(); - - // implements the MessageHandler interface - void OnMessage(rtc::Message* msg); - - protected: - void DoConnect(); - void Close(); - void InitSocketSignals(); - bool ConnectControlSocket(); - void OnConnect(rtc::AsyncSocket* socket); - void OnHangingGetConnect(rtc::AsyncSocket* socket); - void OnMessageFromPeer(int peer_id, const std::string& message); - - // Quick and dirty support for parsing HTTP header values. - bool GetHeaderValue(const std::string& data, - size_t eoh, - const char* header_pattern, - size_t* value); - - bool GetHeaderValue(const std::string& data, - size_t eoh, - const char* header_pattern, - std::string* value); - - // Returns true if the whole response has been read. - bool ReadIntoBuffer(rtc::AsyncSocket* socket, - std::string* data, - size_t* content_length); - - void OnRead(rtc::AsyncSocket* socket); - - void OnHangingGetRead(rtc::AsyncSocket* socket); - - // Parses a single line entry in the form ",," - bool ParseEntry(const std::string& entry, - std::string* name, - int* id, - bool* connected); - - int GetResponseStatus(const std::string& response); - - bool ParseServerResponse(const std::string& response, - size_t content_length, - size_t* peer_id, - size_t* eoh); - - void OnClose(rtc::AsyncSocket* socket, int err); - - void OnResolveResult(rtc::AsyncResolverInterface* resolver); - - PeerConnectionClientObserver* callback_; - rtc::SocketAddress server_address_; - rtc::AsyncResolver* resolver_; - std::unique_ptr control_socket_; - std::unique_ptr hanging_get_; - std::string onconnect_data_; - std::string control_data_; - std::string notification_data_; - std::string client_name_; - Peers peers_; - State state_; - int my_id_; -}; - -#endif // EXAMPLES_PEERCONNECTION_CLIENT_PEER_CONNECTION_CLIENT_H_ diff --git a/client/webrtc_demo/src/video_capture.cpp b/client/webrtc_demo/src/video_capture.cpp index adc106b..4c45f52 100644 --- a/client/webrtc_demo/src/video_capture.cpp +++ b/client/webrtc_demo/src/video_capture.cpp @@ -13,9 +13,9 @@ VcmCapturerTest::~VcmCapturerTest() { bool VcmCapturerTest::Init(size_t width, size_t height, size_t target_fps, - size_t capture_device_index) { + size_t capture_device_index) +{ std::unique_ptr device_info(webrtc::VideoCaptureFactory::CreateDeviceInfo()); - char device_name[256]; char unique_name[256]; @@ -50,15 +50,17 @@ bool VcmCapturerTest::Init(size_t width, VcmCapturerTest* VcmCapturerTest::Create(size_t width, size_t height, size_t target_fps, - size_t capture_device_index) { - std::unique_ptr vcm_capturer(new VcmCapturerTest()); - if (!vcm_capturer->Init(width, height, target_fps, capture_device_index)) { - RTC_LOG(LS_WARNING) << "Failed to create VcmCapturer(w = " << width - << ", h = " << height << ", fps = " << target_fps - << ")"; - return nullptr; - } - return vcm_capturer.release(); + size_t capture_device_index) +{ + std::unique_ptr vcm_capturer(new VcmCapturerTest()); + if (!vcm_capturer->Init(width, height, target_fps, capture_device_index)) + { + RTC_LOG(LS_WARNING) << "Failed to create VcmCapturer(w = " << width + << ", h = " << height << ", fps = " << target_fps + << ")"; + return nullptr; + } + return vcm_capturer.release(); } void VcmCapturerTest::Destroy() { @@ -89,7 +91,7 @@ void VcmCapturerTest::OnFrame(const webrtc::VideoFrame& frame) { memcpy(dat + m_height*m_width + m_height*m_width/4, frame.video_frame_buffer()->ToI420()->DataV(),m_height*m_width/4); - emit(this->UpdateFrame1(dat)); + this->UpdateFrame1(dat); VideoCapturerTest::OnFrame(frame); cnt++; diff --git a/client/webrtc_demo/webrtc_demo.pro b/client/webrtc_demo/webrtc_demo.pro index 70953ae..50ed135 100644 --- a/client/webrtc_demo/webrtc_demo.pro +++ b/client/webrtc_demo/webrtc_demo.pro @@ -1,4 +1,6 @@ -QT += core gui +QT += core gui websockets + + greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -8,8 +10,7 @@ CONFIG += c++11 # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS NOMINMAX WEBRTC_WIN - +DEFINES += QT_DEPRECATED_WARNINGS NOMINMAX WEBRTC_WIN NOMINMAX WIN32_LEAN_AND_MEAN WEBRTC_WIN _CRT_SECURE_NO_WARNINGS WIN32 QT_NO_EMIT # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. @@ -20,23 +21,17 @@ INCLUDEPATH += third/include/ LIBS += -L$$PWD/third/lib libwebrtc.lib ole32.lib oleaut32.lib strmiids.lib SOURCES += \ - src/conductor.cc \ + src/MyCapturer.cpp \ src/cplaywidget.cpp \ - src/defaults.cc \ src/main.cpp \ - src/main_wnd.cc \ src/mainwindow.cpp \ - src/peer_connection_client.cc \ src/video_capture.cpp \ src/video_capturer_test.cpp HEADERS += \ - src/conductor.h \ + src/MyCapturer.h \ src/cplaywidget.h \ - src/defaults.h \ - src/main_wnd.h \ src/mainwindow.h \ - src/peer_connection_client.h \ src/video_capture.h \ src/video_capturer_test.h @@ -47,3 +42,11 @@ FORMS += \ qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target + + +win32:QMAKE_CXXFLAGS_WARN_ON += -wd4819 +win32:QMAKE_CXXFLAGS += /FS +#win32:QMAKE_CXXFLAGS += /utf-8 +#é¿å…VC编译器关于fopen等应使用fopen_s的安全警告 +win32:DEFINES += _CRT_SECURE_NO_WARNINGS + diff --git a/client/webrtc_demo/webrtc_demo.pro.user b/client/webrtc_demo/webrtc_demo.pro.user index 5bd2fab..33ddd4d 100644 --- a/client/webrtc_demo/webrtc_demo.pro.user +++ b/client/webrtc_demo/webrtc_demo.pro.user @@ -1,10 +1,10 @@ - + EnvironmentId - {978c9f3e-040c-4248-8a94-d8dbc0368d0d} + {76c403c8-c45c-47e2-adcf-7c2390aa8798} ProjectExplorer.Project.ActiveTarget @@ -71,7 +71,7 @@ 0 0 - D:/project/qt/build-webrtc_demo-Desktop_Qt_5_14_0_MSVC2017_64bit-Debug + D:/project/multimedia/client/build-webrtc_demo-Desktop_Qt_5_14_0_MSVC2017_64bit-Debug true @@ -119,7 +119,7 @@ 2 - D:/project/qt/build-webrtc_demo-Desktop_Qt_5_14_0_MSVC2017_64bit-Release + D:/project/multimedia/client/build-webrtc_demo-Desktop_Qt_5_14_0_MSVC2017_64bit-Release true @@ -167,7 +167,7 @@ 0 - D:/project/qt/build-webrtc_demo-Desktop_Qt_5_14_0_MSVC2017_64bit-Profile + D:/project/multimedia/client/build-webrtc_demo-Desktop_Qt_5_14_0_MSVC2017_64bit-Profile true @@ -287,8 +287,8 @@ 2 - Qt4ProjectManager.Qt4RunConfiguration:D:/project/qt/webrtc_demo/webrtc_demo.pro - D:/project/qt/webrtc_demo/webrtc_demo.pro + Qt4ProjectManager.Qt4RunConfiguration:D:/project/multimedia/client/webrtc_demo/webrtc_demo.pro + D:/project/multimedia/client/webrtc_demo/webrtc_demo.pro false @@ -299,7 +299,7 @@ false true - D:/project/qt/build-webrtc_demo-Desktop_Qt_5_14_0_MSVC2017_64bit-Debug + D:/project/multimedia/client/build-webrtc_demo-Desktop_Qt_5_14_0_MSVC2017_64bit-Debug 1