Windows编译运行webrtc全过程,并实现屏幕共享

  文章分为三部分,代码获取/编译/运行。

 

  第一步获取代码,打开cmd执行以下指令即可

set WORKSPACE=E:\webrtc
mkdir %WORKSPACE%
cd /d %WORKSPACE%
git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
set PATH=%WORKSPACE%\depot_tools;%PATH% mkdir webrtc-checkout && cd webrtc-checkout set DEPOT_TOOLS_WIN_TOOLCHAIN=0 fetch --nohooks webrtc gclient sync

  (下载代码需要用到外网的服务器,我是直接购买机房在外国的云服务器,安装Windows Server系统来编译。使用vpn等是不可行的,因为一般vpn服务器还在国内,受到监管,而购买外网服务器则没有这个问题,不会被拦截;你只是最后回传一个编译好的库文件而已,也就没什么大的问题,可以购买一个很低端的配置,就不贵。)

  代码下载完毕之后如下图所示

  

 

  第二部编译代码。需要visual studio并安装vc++,还要把windows sdk的debug开启。如下两图的步骤

  

  (如果使用vs2022编译,则需要安装20348版本的sdk,默认是没勾选的哦)

  为了实现屏幕共享,我们还需要改动示例代码

  

  1 /*
  2  *  Copyright 2012 The WebRTC Project Authors. All rights reserved.
  3  *
  4  *  Use of this source code is governed by a BSD-style license
  5  *  that can be found in the LICENSE file in the root of the source
  6  *  tree. An additional intellectual property rights grant can be found
  7  *  in the file PATENTS.  All contributing project authors may
  8  *  be found in the AUTHORS file in the root of the source tree.
  9  */
 10 
 11 #include "examples/peerconnection/client/conductor.h"
 12 
 13 #include <stddef.h>
 14 #include <stdint.h>
 15 
 16 #include <memory>
 17 #include <utility>
 18 #include <vector>
 19 #include <thread>
 20 
 21 #include "absl/memory/memory.h"
 22 #include "absl/types/optional.h"
 23 #include "api/audio/audio_mixer.h"
 24 #include "api/audio_codecs/audio_decoder_factory.h"
 25 #include "api/audio_codecs/audio_encoder_factory.h"
 26 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 27 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
 28 #include "api/audio_options.h"
 29 #include "api/create_peerconnection_factory.h"
 30 #include "api/rtp_sender_interface.h"
 31 #include "api/video_codecs/builtin_video_decoder_factory.h"
 32 #include "api/video_codecs/builtin_video_encoder_factory.h"
 33 #include "api/video_codecs/video_decoder_factory.h"
 34 #include "api/video_codecs/video_encoder_factory.h"
 35 #include "examples/peerconnection/client/defaults.h"
 36 #include "modules/audio_device/include/audio_device.h"
 37 #include "modules/audio_processing/include/audio_processing.h"
 38 #include "modules/video_capture/video_capture.h"
 39 #include "modules/video_capture/video_capture_factory.h"
 40 #include "p2p/base/port_allocator.h"
 41 #include "pc/video_track_source.h"
 42 #include "rtc_base/checks.h"
 43 #include "rtc_base/logging.h"
 44 #include "rtc_base/ref_counted_object.h"
 45 #include "rtc_base/rtc_certificate_generator.h"
 46 #include "rtc_base/strings/json.h"
 47 #include "test/vcm_capturer.h"
 48 #include "modules/desktop_capture/desktop_capturer.h"
 49 #include "modules/desktop_capture/desktop_frame.h"
 50 #include "modules/desktop_capture/desktop_capture_options.h"
 51 #include "media/base/adapted_video_track_source.h"
 52 #include "api/video/i420_buffer.h"
 53 #include "third_party/libyuv/include/libyuv.h"
 54 
 55 namespace {
 56 // Names used for a IceCandidate JSON object.
 57 const char kCandidateSdpMidName[] = "sdpMid";
 58 const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex";
 59 const char kCandidateSdpName[] = "candidate";
 60 
 61 // Names used for a SessionDescription JSON object.
 62 const char kSessionDescriptionTypeName[] = "type";
 63 const char kSessionDescriptionSdpName[] = "sdp";
 64 
 65 class DummySetSessionDescriptionObserver
 66     : public webrtc::SetSessionDescriptionObserver {
 67  public:
 68   static DummySetSessionDescriptionObserver* Create() {
 69     return new rtc::RefCountedObject<DummySetSessionDescriptionObserver>();
 70   }
 71   virtual void OnSuccess() { RTC_LOG(INFO) << __FUNCTION__; }
 72   virtual void OnFailure(webrtc::RTCError error) {
 73     RTC_LOG(INFO) << __FUNCTION__ << " " << ToString(error.type()) << ": "
 74                   << error.message();
 75   }
 76 };
 77 
 78 class CapturerTrackSource : public webrtc::VideoTrackSource {
 79  public:
 80   static rtc::scoped_refptr<CapturerTrackSource> Create() {
 81     const size_t kWidth = 640;
 82     const size_t kHeight = 480;
 83     const size_t kFps = 30;
 84     std::unique_ptr<webrtc::test::VcmCapturer> capturer;
 85     std::unique_ptr<webrtc::VideoCaptureModule::DeviceInfo> info(
 86         webrtc::VideoCaptureFactory::CreateDeviceInfo());
 87     if (!info) {
 88       return nullptr;
 89     }
 90     int num_devices = info->NumberOfDevices();
 91     for (int i = 0; i < num_devices; ++i) {
 92       capturer = absl::WrapUnique(
 93           webrtc::test::VcmCapturer::Create(kWidth, kHeight, kFps, i));
 94       if (capturer) {
 95         return new rtc::RefCountedObject<CapturerTrackSource>(
 96             std::move(capturer));
 97       }
 98     }
 99 
100     return nullptr;
101   }
102 
103  protected:
104   explicit CapturerTrackSource(
105       std::unique_ptr<webrtc::test::VcmCapturer> capturer)
106       : VideoTrackSource(/*remote=*/false), capturer_(std::move(capturer)) {}
107 
108  private:
109   rtc::VideoSourceInterface<webrtc::VideoFrame>* source() override {
110     return capturer_.get();
111   }
112   std::unique_ptr<webrtc::test::VcmCapturer> capturer_;
113 };
114 
115 class MyDesktopCapture : public rtc::AdaptedVideoTrackSource,
116                          public webrtc::DesktopCapturer::Callback {
117  public:
118   ~MyDesktopCapture() override {
119     StopCapture();
120     if (!dc_)
121       return;
122 
123     dc_.reset(nullptr);
124   }
125   //--RefCountedObject
126   void SetState(SourceState new_state);
127 
128   SourceState state() const override { return state_; }
129   bool remote() const override { return remote_; }
130 
131   bool is_screencast() const override { return false; }
132   absl::optional<bool> needs_denoising() const override {
133     return absl::nullopt;
134   }
135 
136   bool GetStats(Stats* stats) override { return false; }
137   //--RefCountedObject
138 
139   std::string GetWindowTitle() const { return window_title_; }
140 
141   void StartCapture() {
142     if (start_flag_) {
143       RTC_LOG(WARNING) << "Capture already been running...";
144       return;
145     }
146 
147     start_flag_ = true;
148 
149     // Start new thread to capture
150     capture_thread_.reset(new std::thread([this]() {
151       dc_->Start(this);
152 
153       while (start_flag_) {
154         dc_->CaptureFrame();
155         std::this_thread::sleep_for(std::chrono::milliseconds(1000 / fps_));
156       }
157     }));
158   }
159 
160   void StopCapture() {
161     start_flag_ = false;
162 
163     if (capture_thread_ && capture_thread_->joinable()) {
164       capture_thread_->join();
165     }
166   }
167 
168   static rtc::scoped_refptr<MyDesktopCapture> Create(
169       size_t target_fps,
170       size_t capture_screen_index) {
171     auto dc = webrtc::DesktopCapturer::CreateScreenCapturer(
172         webrtc::DesktopCaptureOptions::CreateDefault());
173 
174     if (!dc)
175       return nullptr;
176 
177     webrtc::DesktopCapturer::SourceList sources;
178     dc->GetSourceList(&sources);
179     if (capture_screen_index > sources.size()) {
180       RTC_LOG(LS_WARNING) << "The total sources of screen is " << sources.size()
181                           << ", but require source of index at "
182                           << capture_screen_index;
183       return nullptr;
184     }
185 
186     RTC_CHECK(dc->SelectSource(sources[capture_screen_index].id));
187     auto window_title = sources[capture_screen_index].title;
188     auto fps = target_fps;
189 
190     RTC_LOG(LS_INFO) << "Init DesktopCapture finish";
191     // Start new thread to capture
192     return new rtc::RefCountedObject<MyDesktopCapture>(std::move(dc), fps,
193                                                        std::move(window_title));
194   }
195 
196   void OnCaptureResult(
197       webrtc::DesktopCapturer::Result result,
198       std::unique_ptr<webrtc::DesktopFrame> desktopframe) override {
199     if (result != webrtc::DesktopCapturer::Result::SUCCESS)
200       return;
201     int width = desktopframe->size().width();
202     int height = desktopframe->size().height();
203     // int half_width = (width + 1) / 2;
204 
205     if (!i420_buffer_.get() ||
206         i420_buffer_->width() * i420_buffer_->height() < width * height) {
207       i420_buffer_ = webrtc::I420Buffer::Create(width, height);
208     }
209 
210     int stride = width;
211     uint8_t* yplane = i420_buffer_->MutableDataY();
212     uint8_t* uplane = i420_buffer_->MutableDataU();
213     uint8_t* vplane = i420_buffer_->MutableDataV();
214     libyuv::ConvertToI420(desktopframe->data(), 0, yplane, stride, uplane,
215                           (stride + 1) / 2, vplane, (stride + 1) / 2, 0, 0,
216                           width, height, width, height, libyuv::kRotate0,
217                           libyuv::FOURCC_ARGB);
218     webrtc::VideoFrame frame =
219         webrtc::VideoFrame(i420_buffer_, 0, 0, webrtc::kVideoRotation_0);
220     this->OnFrame(frame);
221   }
222 
223  protected:
224   explicit MyDesktopCapture(std::unique_ptr<webrtc::DesktopCapturer> dc,
225                             size_t fps,
226                             std::string window_title)
227       : dc_(std::move(dc)),
228         fps_(fps),
229         window_title_(std::move(window_title)),
230         start_flag_(false),
231         remote_(false) {}
232 
233  private:
234   std::unique_ptr<webrtc::DesktopCapturer> dc_;
235   size_t fps_;
236   std::string window_title_;
237   rtc::scoped_refptr<webrtc::I420Buffer> i420_buffer_;
238   std::unique_ptr<std::thread> capture_thread_;
239   std::atomic_bool start_flag_;
240   // RefCountedObject
241   SourceState state_;
242   const bool remote_;
243 };
244 
245 }  // namespace
246 
247 Conductor::Conductor(PeerConnectionClient* client, MainWindow* main_wnd)
248     : peer_id_(-1), loopback_(false), client_(client), main_wnd_(main_wnd) {
249   client_->RegisterObserver(this);
250   main_wnd->RegisterObserver(this);
251 }
252 
253 Conductor::~Conductor() {
254   RTC_DCHECK(!peer_connection_);
255 }
256 
257 bool Conductor::connection_active() const {
258   return peer_connection_ != nullptr;
259 }
260 
261 void Conductor::Close() {
262   client_->SignOut();
263   DeletePeerConnection();
264 }
265 
266 static std::unique_ptr<rtc::Thread> g_worker_thread;
267 static std::unique_ptr<rtc::Thread> g_signaling_thread;
268 bool Conductor::InitializePeerConnection() {
269   RTC_DCHECK(!peer_connection_factory_);
270   RTC_DCHECK(!peer_connection_);
271   g_worker_thread = rtc::Thread::Create();
272     g_worker_thread->Start();
273     g_signaling_thread = rtc::Thread::Create();
274     g_signaling_thread->Start();
275 
276   peer_connection_factory_ = webrtc::CreatePeerConnectionFactory(
277       nullptr /* network_thread */, g_worker_thread.get() /* worker_thread */,
278       g_signaling_thread.get() /* signaling_thread */, nullptr /* default_adm */,
279       webrtc::CreateBuiltinAudioEncoderFactory(),
280       webrtc::CreateBuiltinAudioDecoderFactory(),
281       webrtc::CreateBuiltinVideoEncoderFactory(),
282       webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
283       nullptr /* audio_processing */);
284 
285   if (!peer_connection_factory_) {
286     main_wnd_->MessageBox("Error", "Failed to initialize PeerConnectionFactory",
287                           true);
288     DeletePeerConnection();
289     return false;
290   }
291 
292   if (!CreatePeerConnection(/*dtls=*/true)) {
293     main_wnd_->MessageBox("Error", "CreatePeerConnection failed", true);
294     DeletePeerConnection();
295   }
296 
297   AddTracks();
298 
299   return peer_connection_ != nullptr;
300 }
301 
302 bool Conductor::ReinitializePeerConnectionForLoopback() {
303   loopback_ = true;
304   std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> senders =
305       peer_connection_->GetSenders();
306   peer_connection_ = nullptr;
307   if (CreatePeerConnection(/*dtls=*/false)) {
308     for (const auto& sender : senders) {
309       peer_connection_->AddTrack(sender->track(), sender->stream_ids());
310     }
311     peer_connection_->CreateOffer(
312         this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
313   }
314   return peer_connection_ != nullptr;
315 }
316 
317 bool Conductor::CreatePeerConnection(bool dtls) {
318   RTC_DCHECK(peer_connection_factory_);
319   RTC_DCHECK(!peer_connection_);
320 
321   webrtc::PeerConnectionInterface::RTCConfiguration config;
322   config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
323   config.enable_dtls_srtp = dtls;
324   webrtc::PeerConnectionInterface::IceServer server;
325   server.uri = GetPeerConnectionString();
326   config.servers.push_back(server);
327 
328   peer_connection_ = peer_connection_factory_->CreatePeerConnection(
329       config, nullptr, nullptr, this);
330   return peer_connection_ != nullptr;
331 }
332 
333 void Conductor::DeletePeerConnection() {
334   main_wnd_->StopLocalRenderer();
335   main_wnd_->StopRemoteRenderer();
336   peer_connection_ = nullptr;
337   peer_connection_factory_ = nullptr;
338   peer_id_ = -1;
339   loopback_ = false;
340 }
341 
342 void Conductor::EnsureStreamingUI() {
343   RTC_DCHECK(peer_connection_);
344   if (main_wnd_->IsWindow()) {
345     if (main_wnd_->current_ui() != MainWindow::STREAMING)
346       main_wnd_->SwitchToStreamingUI();
347   }
348 }
349 
350 //
351 // PeerConnectionObserver implementation.
352 //
353 
354 void Conductor::OnAddTrack(
355     rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
356     const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>&
357         streams) {
358   RTC_LOG(INFO) << __FUNCTION__ << " " << receiver->id();
359   main_wnd_->QueueUIThreadCallback(NEW_TRACK_ADDED,
360                                    receiver->track().release());
361 }
362 
363 void Conductor::OnRemoveTrack(
364     rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) {
365   RTC_LOG(INFO) << __FUNCTION__ << " " << receiver->id();
366   main_wnd_->QueueUIThreadCallback(TRACK_REMOVED, receiver->track().release());
367 }
368 
369 void Conductor::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
370   RTC_LOG(INFO) << __FUNCTION__ << " " << candidate->sdp_mline_index();
371   // For loopback test. To save some connecting delay.
372   if (loopback_) {
373     if (!peer_connection_->AddIceCandidate(candidate)) {
374       RTC_LOG(WARNING) << "Failed to apply the received candidate";
375     }
376     return;
377   }
378 
379   Json::StyledWriter writer;
380   Json::Value jmessage;
381 
382   jmessage[kCandidateSdpMidName] = candidate->sdp_mid();
383   jmessage[kCandidateSdpMlineIndexName] = candidate->sdp_mline_index();
384   std::string sdp;
385   if (!candidate->ToString(&sdp)) {
386     RTC_LOG(LS_ERROR) << "Failed to serialize candidate";
387     return;
388   }
389   jmessage[kCandidateSdpName] = sdp;
390   SendMessage(writer.write(jmessage));
391 }
392 
393 //
394 // PeerConnectionClientObserver implementation.
395 //
396 
397 void Conductor::OnSignedIn() {
398   RTC_LOG(INFO) << __FUNCTION__;
399   main_wnd_->SwitchToPeerList(client_->peers());
400 }
401 
402 void Conductor::OnDisconnected() {
403   RTC_LOG(INFO) << __FUNCTION__;
404 
405   DeletePeerConnection();
406 
407   if (main_wnd_->IsWindow())
408     main_wnd_->SwitchToConnectUI();
409 }
410 
411 void Conductor::OnPeerConnected(int id, const std::string& name) {
412   RTC_LOG(INFO) << __FUNCTION__;
413   // Refresh the list if we're showing it.
414   if (main_wnd_->current_ui() == MainWindow::LIST_PEERS)
415     main_wnd_->SwitchToPeerList(client_->peers());
416 }
417 
418 void Conductor::OnPeerDisconnected(int id) {
419   RTC_LOG(INFO) << __FUNCTION__;
420   if (id == peer_id_) {
421     RTC_LOG(INFO) << "Our peer disconnected";
422     main_wnd_->QueueUIThreadCallback(PEER_CONNECTION_CLOSED, NULL);
423   } else {
424     // Refresh the list if we're showing it.
425     if (main_wnd_->current_ui() == MainWindow::LIST_PEERS)
426       main_wnd_->SwitchToPeerList(client_->peers());
427   }
428 }
429 
430 void Conductor::OnMessageFromPeer(int peer_id, const std::string& message) {
431   RTC_DCHECK(peer_id_ == peer_id || peer_id_ == -1);
432   RTC_DCHECK(!message.empty());
433 
434   if (!peer_connection_.get()) {
435     RTC_DCHECK(peer_id_ == -1);
436     peer_id_ = peer_id;
437 
438     if (!InitializePeerConnection()) {
439       RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
440       client_->SignOut();
441       return;
442     }
443   } else if (peer_id != peer_id_) {
444     RTC_DCHECK(peer_id_ != -1);
445     RTC_LOG(WARNING)
446         << "Received a message from unknown peer while already in a "
447            "conversation with a different peer.";
448     return;
449   }
450 
451   Json::Reader reader;
452   Json::Value jmessage;
453   if (!reader.parse(message, jmessage)) {
454     RTC_LOG(WARNING) << "Received unknown message. " << message;
455     return;
456   }
457   std::string type_str;
458   std::string json_object;
459 
460   rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName,
461                                &type_str);
462   if (!type_str.empty()) {
463     if (type_str == "offer-loopback") {
464       // This is a loopback call.
465       // Recreate the peerconnection with DTLS disabled.
466       if (!ReinitializePeerConnectionForLoopback()) {
467         RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
468         DeletePeerConnection();
469         client_->SignOut();
470       }
471       return;
472     }
473     absl::optional<webrtc::SdpType> type_maybe =
474         webrtc::SdpTypeFromString(type_str);
475     if (!type_maybe) {
476       RTC_LOG(LS_ERROR) << "Unknown SDP type: " << type_str;
477       return;
478     }
479     webrtc::SdpType type = *type_maybe;
480     std::string sdp;
481     if (!rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName,
482                                       &sdp)) {
483       RTC_LOG(WARNING) << "Can't parse received session description message.";
484       return;
485     }
486     webrtc::SdpParseError error;
487     std::unique_ptr<webrtc::SessionDescriptionInterface> session_description =
488         webrtc::CreateSessionDescription(type, sdp, &error);
489     if (!session_description) {
490       RTC_LOG(WARNING) << "Can't parse received session description message. "
491                           "SdpParseError was: "
492                        << error.description;
493       return;
494     }
495     RTC_LOG(INFO) << " Received session description :" << message;
496     peer_connection_->SetRemoteDescription(
497         DummySetSessionDescriptionObserver::Create(),
498         session_description.release());
499     if (type == webrtc::SdpType::kOffer) {
500       peer_connection_->CreateAnswer(
501           this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
502     }
503   } else {
504     std::string sdp_mid;
505     int sdp_mlineindex = 0;
506     std::string sdp;
507     if (!rtc::GetStringFromJsonObject(jmessage, kCandidateSdpMidName,
508                                       &sdp_mid) ||
509         !rtc::GetIntFromJsonObject(jmessage, kCandidateSdpMlineIndexName,
510                                    &sdp_mlineindex) ||
511         !rtc::GetStringFromJsonObject(jmessage, kCandidateSdpName, &sdp)) {
512       RTC_LOG(WARNING) << "Can't parse received message.";
513       return;
514     }
515     webrtc::SdpParseError error;
516     std::unique_ptr<webrtc::IceCandidateInterface> candidate(
517         webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp, &error));
518     if (!candidate.get()) {
519       RTC_LOG(WARNING) << "Can't parse received candidate message. "
520                           "SdpParseError was: "
521                        << error.description;
522       return;
523     }
524     if (!peer_connection_->AddIceCandidate(candidate.get())) {
525       RTC_LOG(WARNING) << "Failed to apply the received candidate";
526       return;
527     }
528     RTC_LOG(INFO) << " Received candidate :" << message;
529   }
530 }
531 
532 void Conductor::OnMessageSent(int err) {
533   // Process the next pending message if any.
534   main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, NULL);
535 }
536 
537 void Conductor::OnServerConnectionFailure() {
538   main_wnd_->MessageBox("Error", ("Failed to connect to " + server_).c_str(),
539                         true);
540 }
541 
542 //
543 // MainWndCallback implementation.
544 //
545 
546 void Conductor::StartLogin(const std::string& server, int port) {
547   if (client_->is_connected())
548     return;
549   server_ = server;
550   client_->Connect(server, port, GetPeerName());
551 }
552 
553 void Conductor::DisconnectFromServer() {
554   if (client_->is_connected())
555     client_->SignOut();
556 }
557 
558 void Conductor::ConnectToPeer(int peer_id) {
559   RTC_DCHECK(peer_id_ == -1);
560   RTC_DCHECK(peer_id != -1);
561 
562   if (peer_connection_.get()) {
563     main_wnd_->MessageBox(
564         "Error", "We only support connecting to one peer at a time", true);
565     return;
566   }
567 
568   if (InitializePeerConnection()) {
569     peer_id_ = peer_id;
570     peer_connection_->CreateOffer(
571         this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
572   } else {
573     main_wnd_->MessageBox("Error", "Failed to initialize PeerConnection", true);
574   }
575 }
576 
577 void Conductor::AddTracks() {
578   if (!peer_connection_->GetSenders().empty()) {
579     return;  // Already added tracks.
580   }
581 
582   rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
583       peer_connection_factory_->CreateAudioTrack(
584           kAudioLabel, peer_connection_factory_->CreateAudioSource(
585                            cricket::AudioOptions())));
586   auto result_or_error = peer_connection_->AddTrack(audio_track, {kStreamId});
587   if (!result_or_error.ok()) {
588     RTC_LOG(LS_ERROR) << "Failed to add audio track to PeerConnection: "
589                       << result_or_error.error().message();
590   }
591 
592   rtc::scoped_refptr<MyDesktopCapture> video_device = MyDesktopCapture::Create(15,0);
593   //rtc::scoped_refptr<CapturerTrackSource> video_device = CapturerTrackSource::Create();
594 
595   if (video_device) {
596     rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track_(
597         peer_connection_factory_->CreateVideoTrack(kVideoLabel, video_device));
598     video_device->StartCapture();
599     main_wnd_->StartLocalRenderer(video_track_);
600 
601     result_or_error = peer_connection_->AddTrack(video_track_, {kStreamId});
602     if (!result_or_error.ok()) {
603       RTC_LOG(LS_ERROR) << "Failed to add video track to PeerConnection: "
604                         << result_or_error.error().message();
605     }
606   } else {
607     RTC_LOG(LS_ERROR) << "OpenVideoCaptureDevice failed";
608   }
609 
610   main_wnd_->SwitchToStreamingUI();
611 }
612 
613 void Conductor::DisconnectFromCurrentPeer() {
614   RTC_LOG(INFO) << __FUNCTION__;
615   if (peer_connection_.get()) {
616     client_->SendHangUp(peer_id_);
617     DeletePeerConnection();
618   }
619 
620   if (main_wnd_->IsWindow())
621     main_wnd_->SwitchToPeerList(client_->peers());
622 }
623 
624 void Conductor::UIThreadCallback(int msg_id, void* data) {
625   switch (msg_id) {
626     case PEER_CONNECTION_CLOSED:
627       RTC_LOG(INFO) << "PEER_CONNECTION_CLOSED";
628       DeletePeerConnection();
629 
630       if (main_wnd_->IsWindow()) {
631         if (client_->is_connected()) {
632           main_wnd_->SwitchToPeerList(client_->peers());
633         } else {
634           main_wnd_->SwitchToConnectUI();
635         }
636       } else {
637         DisconnectFromServer();
638       }
639       break;
640 
641     case SEND_MESSAGE_TO_PEER: {
642       RTC_LOG(INFO) << "SEND_MESSAGE_TO_PEER";
643       std::string* msg = reinterpret_cast<std::string*>(data);
644       if (msg) {
645         // For convenience, we always run the message through the queue.
646         // This way we can be sure that messages are sent to the server
647         // in the same order they were signaled without much hassle.
648         pending_messages_.push_back(msg);
649       }
650 
651       if (!pending_messages_.empty() && !client_->IsSendingMessage()) {
652         msg = pending_messages_.front();
653         pending_messages_.pop_front();
654 
655         if (!client_->SendToPeer(peer_id_, *msg) && peer_id_ != -1) {
656           RTC_LOG(LS_ERROR) << "SendToPeer failed";
657           DisconnectFromServer();
658         }
659         delete msg;
660       }
661 
662       if (!peer_connection_.get())
663         peer_id_ = -1;
664 
665       break;
666     }
667 
668     case NEW_TRACK_ADDED: {
669       auto* track = reinterpret_cast<webrtc::MediaStreamTrackInterface*>(data);
670       if (track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) {
671         auto* video_track = static_cast<webrtc::VideoTrackInterface*>(track);
672         main_wnd_->StartRemoteRenderer(video_track);
673       }
674       track->Release();
675       break;
676     }
677 
678     case TRACK_REMOVED: {
679       // Remote peer stopped sending a track.
680       auto* track = reinterpret_cast<webrtc::MediaStreamTrackInterface*>(data);
681       track->Release();
682       break;
683     }
684 
685     default:
686       RTC_NOTREACHED();
687       break;
688   }
689 }
690 
691 void Conductor::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
692   RTC_LOG(INFO) << __FUNCTION__;
693   peer_connection_->SetLocalDescription(
694       DummySetSessionDescriptionObserver::Create(), desc);
695 
696   std::string sdp;
697   desc->ToString(&sdp);
698 
699   // For loopback test. To save some connecting delay.
700   if (loopback_) {
701     // Replace message type from "offer" to "answer"
702     std::unique_ptr<webrtc::SessionDescriptionInterface> session_description =
703         webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, sdp);
704     peer_connection_->SetRemoteDescription(
705         DummySetSessionDescriptionObserver::Create(),
706         session_description.release());
707     return;
708   }
709 
710   Json::StyledWriter writer;
711   Json::Value jmessage;
712   jmessage[kSessionDescriptionTypeName] =
713       webrtc::SdpTypeToString(desc->GetType());
714   jmessage[kSessionDescriptionSdpName] = sdp;
715   SendMessage(writer.write(jmessage));
716 }
717 
718 void Conductor::OnFailure(webrtc::RTCError error) {
719   RTC_LOG(LERROR) << ToString(error.type()) << ": " << error.message();
720 }
721 
722 void Conductor::SendMessage(const std::string& json_object) {
723   std::string* msg = new std::string(json_object);
724   main_wnd_->QueueUIThreadCallback(SEND_MESSAGE_TO_PEER, msg);
725 }
conductor.cc

  改好之后就打开vc++的命令行窗口

  

  并执行以下代码进行编译

set WORKSPACE=E:\webrtc
set PATH=%WORKSPACE%\depot_tools;%PATH%
cd /d %WORKSPACE%\webrtc-checkout\src
set DEPOT_TOOLS_WIN_TOOLCHAIN=0 set GYP_MSVS_VERSION=2019 gn gen out\Default --args="is_debug=false" ninja -C out\Default

  (如果是编译32位版本,则需要加入target_cpu=\"x86\")

  编译完成的截图如下

  

   如果你编译过程中报错,可能是由于你的操作系统登录名为中文,则需要手动改一下配置文件(检查如下图所示部位是否为空,为空则自行手动加入)

  

 

  最后是测试,我们找一台服务器来运行peerconnection_server端

  

   然后找两台电脑运行peerconnection_client端

 

(上文中我使用了n台电脑来演示步骤,力争简洁和完整。所以有时候读者会发现图片的风格从win10/win11/win server切换了,那是因为我需要去外网下代码,编译/运行等)

 

有高手希望指点的话可以通过微信与我联系,我的id是wxid_8r2mjkbcu2an22

 

最后修改时间 2021-10-24 10:50:16

 

如果要寻找特定版本,可以从这个网址

 然后切换到特定版本

cd /d %WORKSPACE%\webrtc-checkout\src
git checkout branch-heads/5060
gclient sync -D -r branch-heads/5060
# cd ..
# gn gen...

 最后修改时间 2022-09-11 19:53:14

posted @ 2019-12-22 18:28  云中双月  阅读(7781)  评论(5编辑  收藏  举报