轉載-webrtc實現屏幕共享

Google Chrome項目中實現了WebRTC并提供了示例,WebRTC提供了視頻會議的核心技術文兑,包括音視頻的采集丰滑、編解碼顾犹、網絡傳輸、顯示等功能褒墨,并且還支持跨平臺:windows炫刷,linux,mac郁妈,android浑玛。Chrome是開源的,提供了視頻會議示例(基于攝像頭)噩咪,也有屏幕截圖組件(全屏顾彰、窗口),但是沒有屏幕分享的例子胃碾,搜了百度涨享、谷歌、github都沒有仆百。在Google論壇找到了關鍵的圖像轉視頻流后實現了此模塊厕隧。

在72版本測試通過,有同事在53版本也可以儒旬。

代碼如下:

MyCapturer.h

/**
* Windows屏幕錄像模塊
*/

#include <media/base/videocapturer.h>
#include <media/base/videocommon.h>
#include <modules/desktop_capture/desktop_capturer.h>
#include <modules/desktop_capture/desktop_frame.h>
#include <api/video/i420_buffer.h>
#include <api/scoped_refptr.h>
#include <rtc_base/messagehandler.h>
#include <rtc_base/thread.h>

class MyCapturer : public cricket::VideoCapturer,
                   public rtc::MessageHandler,
                   public webrtc::DesktopCapturer::Callback {
 public:
  MyCapturer();
  ~MyCapturer();

  void CaptureFrame();

  virtual cricket::CaptureState Start(
      const cricket::VideoFormat& capture_format);
  virtual void Stop();
  virtual bool IsRunning();
  virtual bool IsScreencast() const { return true; }
  virtual void OnCaptureResult(webrtc::DesktopCapturer::Result result,
                               std::unique_ptr<webrtc::DesktopFrame> frame);
  virtual void OnMessage(rtc::Message* msg);

 protected:
  virtual bool GetPreferredFourccs(std::vector<uint32_t>* fourccs);

 private:
  std::unique_ptr<webrtc::DesktopCapturer> capturer;
  rtc::scoped_refptr<webrtc::I420Buffer> i420_buffer_;
};

MyCapturer.cc

#include "MyCapturer.h"
#include <base/threading/thread.h>
#include <modules/desktop_capture/desktop_capture_options.h>
#include <third_party/libyuv/include/libyuv.h>

MyCapturer::MyCapturer() {
  std::vector<cricket::VideoFormat> formats;
  formats.push_back(cricket::VideoFormat(
      800, 600, cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
  SetSupportedFormats(formats);
}

MyCapturer ::~MyCapturer() {}

cricket::CaptureState MyCapturer::Start(
    const cricket::VideoFormat& capture_format) {
  cricket::VideoFormat supported;
  if (GetBestCaptureFormat(capture_format, &supported))
    SetCaptureFormat(&supported);
  SetCaptureState(cricket::CS_RUNNING);
  auto options = webrtc::DesktopCaptureOptions::CreateDefault();
  options.set_allow_directx_capturer(true);
  capturer = webrtc::DesktopCapturer::CreateScreenCapturer(options);
  capturer->Start(this);
  CaptureFrame();
  return cricket::CS_RUNNING;
}

void MyCapturer::Stop() {
  SetCaptureState(cricket::CS_STOPPED);
  SetCaptureFormat(NULL);
}

bool MyCapturer::IsRunning() {
  return capture_state() == cricket::CS_RUNNING;
}

bool MyCapturer::GetPreferredFourccs(std::vector<uint32_t>* fourccs) {
  fourccs->push_back(cricket::FOURCC_I420);
  fourccs->push_back(cricket::FOURCC_MJPG);
  return true;
}

void MyCapturer::OnCaptureResult(webrtc::DesktopCapturer::Result result,
                                 std::unique_ptr<webrtc::DesktopFrame> 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),
          width, height);
}

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);
}

將這個類加入peerconnection/client工程后栏账,在Conductor::AddTracks()中調用,將

std::unique_ptr<cricket::VideoCapturer> video_device = OpenVideoCaptureDevice();

修改為

std::unique_ptr<cricket::VideoCapturer> video_device = std::unique_ptr<cricket::VideoCapturer>(new MyCapturer());
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末栈源,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子竖般,更是在濱河造成了極大的恐慌甚垦,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異艰亮,居然都是意外死亡闭翩,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門迄埃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疗韵,“玉大人,你說我怎么就攤上這事侄非〗锻簦” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵逞怨,是天一觀的道長者疤。 經常有香客問我,道長叠赦,這世上最難降的妖魔是什么驹马? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮除秀,結果婚禮上糯累,老公的妹妹穿的比我還像新娘。我一直安慰自己册踩,他們只是感情好泳姐,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棍好,像睡著了一般仗岸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上借笙,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天扒怖,我揣著相機與錄音,去河邊找鬼业稼。 笑死盗痒,一個胖子當著我的面吹牛,可吹牛的內容都是我干的低散。 我是一名探鬼主播俯邓,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼熔号!你這毒婦竟也來了稽鞭?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤引镊,失蹤者是張志新(化名)和其女友劉穎朦蕴,沒想到半個月后篮条,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡吩抓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年涉茧,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疹娶。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡伴栓,死狀恐怖,靈堂內的尸體忽然破棺而出雨饺,到底是詐尸還是另有隱情钳垮,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布沛膳,位于F島的核電站扔枫,受9級特大地震影響,放射性物質發(fā)生泄漏锹安。R本人自食惡果不足惜短荐,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叹哭。 院中可真熱鬧忍宋,春花似錦、人聲如沸风罩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽超升。三九已至入宦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間室琢,已是汗流浹背乾闰。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盈滴,地道東北人涯肩。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像巢钓,于是被迫代替她去往敵國和親病苗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內容