Skip to content

feat: add desktop/screen capture. #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ rtc_shared_library("libwebrtc"){
"include/rtc_audio_track.h",
"include/rtc_audio_source.h",
"include/rtc_data_channel.h",
"include/rtc_desktop_device.h",
"include/rtc_ice_candidate.h",
"include/rtc_media_stream.h",
"include/rtc_media_track.h",
Expand Down Expand Up @@ -62,6 +63,10 @@ rtc_shared_library("libwebrtc"){
"src/rtc_audio_track_impl.cc",
"src/rtc_data_channel_impl.h",
"src/rtc_data_channel_impl.cc",
"src/rtc_desktop_device_impl.h",
"src/rtc_desktop_device_impl.cc",
"src/rtc_desktop_capturer.h",
"src/rtc_desktop_capturer.cc",
"src/rtc_ice_candidate_impl.h",
"src/rtc_ice_candidate_impl.cc",
"src/rtc_peerconnection_impl.h",
Expand Down Expand Up @@ -138,6 +143,7 @@ rtc_shared_library("libwebrtc"){
"../media:rtc_media",
"../media:rtc_media_base",
"../modules/audio_device:audio_device",
"../modules/desktop_capture",
"../modules/audio_processing:api",
"../modules/audio_processing:audio_processing",
"../modules/video_capture:video_capture_module",
Expand Down
21 changes: 21 additions & 0 deletions include/rtc_desktop_device.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef LIB_WEBRTC_RTC_DESKTOP_DEVICE_HXX
#define LIB_WEBRTC_RTC_DESKTOP_DEVICE_HXX

#include "rtc_types.h"
#include "rtc_video_device.h"


namespace libwebrtc {

class RTCDesktopDevice : public RefCountInterface {
public:
virtual scoped_refptr<RTCVideoCapturer> CreateScreenCapturer() = 0;
virtual scoped_refptr<RTCVideoCapturer> CreateWindowCapturer() = 0;

protected:
virtual ~RTCDesktopDevice() {}
};

} // namespace libwebrtc

#endif // LIB_WEBRTC_RTC_VIDEO_DEVICE_HXX
6 changes: 5 additions & 1 deletion include/rtc_peerconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class RTCPeerConnection : public RefCountInterface {

virtual scoped_refptr<RTCDataChannel> CreateDataChannel(
const string label,
const RTCDataChannelInit* dataChannelDict) = 0;
RTCDataChannelInit* dataChannelDict) = 0;

virtual void CreateOffer(OnSdpCreateSuccess success,
OnSdpCreateFailure failure,
Expand Down Expand Up @@ -206,6 +206,10 @@ class RTCPeerConnection : public RefCountInterface {
scoped_refptr<RTCMediaTrack> track,
const vector<string> streamIds) = 0;

virtual scoped_refptr<RTCRtpTransceiver> AddTransceiver(RTCMediaType media_type) = 0;

virtual scoped_refptr<RTCRtpTransceiver> AddTransceiver( RTCMediaType media_type, scoped_refptr<RTCRtpTransceiverInit> init) = 0;

virtual bool RemoveTrack(scoped_refptr<RTCRtpSender> render) = 0;

virtual vector<scoped_refptr<RTCRtpSender>> senders() = 0;
Expand Down
3 changes: 3 additions & 0 deletions include/rtc_peerconnection_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "rtc_audio_source.h"
#include "rtc_audio_track.h"
#include "rtc_desktop_device.h"
#include "rtc_media_stream.h"
#include "rtc_mediaconstraints.h"
#include "rtc_video_device.h"
Expand Down Expand Up @@ -32,6 +33,8 @@ class RTCPeerConnectionFactory : public RefCountInterface {

virtual scoped_refptr<RTCVideoDevice> GetVideoDevice() = 0;

virtual scoped_refptr<RTCDesktopDevice> GetDesktopDevice() = 0;

virtual scoped_refptr<RTCAudioSource> CreateAudioSource(
const string audio_source_label) = 0;

Expand Down
5 changes: 4 additions & 1 deletion include/rtc_video_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ class RTCVideoDevice : public RefCountInterface {
uint32_t productUniqueIdUTF8Length = 0) = 0;

virtual scoped_refptr<RTCVideoCapturer> Create(const char* name,
uint32_t index) = 0;
uint32_t index,
size_t width,
size_t height,
size_t target_fps) = 0;

protected:
virtual ~RTCVideoDevice() {}
Expand Down
64 changes: 64 additions & 0 deletions src/rtc_desktop_capturer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "rtc_desktop_capturer.h"

namespace libwebrtc {

enum { kCaptureDelay = 33, kCaptureMessageId = 1000 };

RTCDesktopCapturer::RTCDesktopCapturer(
std::unique_ptr<webrtc::DesktopCapturer> desktopcapturer)
: capturer(std::move(desktopcapturer)) {
}

RTCDesktopCapturer ::~RTCDesktopCapturer() {}

CaptureState RTCDesktopCapturer::Start(
const cricket::VideoFormat& capture_format) {
capture_state_ = CS_RUNNING;
capturer->Start(this);
CaptureFrame();
return CS_RUNNING;
}

void RTCDesktopCapturer::Stop() {
capture_state_ = CS_STOPPED;
}

bool RTCDesktopCapturer::IsRunning() {
return capture_state_ == CS_RUNNING;
}

void RTCDesktopCapturer::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_ || !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 RTCDesktopCapturer::OnMessage(rtc::Message* msg) {
if (msg->message_id == kCaptureMessageId) {
CaptureFrame();
}
}

void RTCDesktopCapturer::CaptureFrame() {
if (capture_state_ == CS_RUNNING) {
capturer->CaptureFrame();
rtc::Thread::Current()->PostDelayed(RTC_FROM_HERE, kCaptureDelay, this,
kCaptureMessageId);
}
}
} // namespace libwebrtc
52 changes: 52 additions & 0 deletions src/rtc_desktop_capturer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#ifndef LIB_WEBRTC_DESKTOP_CAPTURER_IMPL_HXX
#define LIB_WEBRTC_DESKTOP_CAPTURER_IMPL_HXX

#include "modules/desktop_capture/desktop_capture_options.h"
#include "modules/desktop_capture/desktop_capturer.h"
#include "modules/desktop_capture/desktop_frame.h"
#include "modules/video_capture/video_capture.h"
#include "modules/video_capture/video_capture_factory.h"

#include "api/scoped_refptr.h"
#include "api/video/i420_buffer.h"
#include "api/video/video_frame.h"
#include "api/video/video_source_interface.h"
#include "media/base/video_adapter.h"
#include "media/base/video_broadcaster.h"
#include "pc/video_track_source.h"
#include "rtc_base/thread.h"
#include "rtc_desktop_device.h"
#include "src/internal/vcm_capturer.h"
#include "src/internal/video_capturer.h"
#include "third_party/libyuv/include/libyuv.h"

// std::unique_ptr<cricket::VideoCapturer> video_device =
// std::unique_ptr<cricket::VideoCapturer>(new DesktopCapturerDeviceImpl());

namespace libwebrtc {

enum CaptureState { CS_RUNNING, CS_STOPPED };

class RTCDesktopCapturer : public webrtc::internal::VideoCapturer,
public rtc::MessageHandler,
public webrtc::DesktopCapturer::Callback {
public:
RTCDesktopCapturer(std::unique_ptr<webrtc::DesktopCapturer> desktopcapturer);
~RTCDesktopCapturer();
void CaptureFrame();
virtual CaptureState Start(
const cricket::VideoFormat& capture_format);
virtual void Stop();
virtual bool IsRunning();
virtual void OnCaptureResult(
webrtc::DesktopCapturer::Result result,
std::unique_ptr<webrtc::DesktopFrame> frame) override;
virtual void OnMessage(rtc::Message* msg) override;
private:
std::unique_ptr<webrtc::DesktopCapturer> capturer;
rtc::scoped_refptr<webrtc::I420Buffer> i420_buffer_;
CaptureState capture_state_ = CS_STOPPED;
};

} // namespace libwebrtc
#endif
38 changes: 38 additions & 0 deletions src/rtc_desktop_device_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "rtc_desktop_device_impl.h"
#include "rtc_video_device_impl.h"

#include "rtc_desktop_capturer.h"

namespace libwebrtc {

DesktopDeviceImpl::DesktopDeviceImpl() {}

webrtc::DesktopCaptureOptions DesktopDeviceImpl::CreateOptions() {
webrtc::DesktopCaptureOptions options =
webrtc::DesktopCaptureOptions::CreateDefault();
options.set_allow_directx_capturer(false);
return options;
}

scoped_refptr<RTCVideoCapturer> DesktopDeviceImpl::CreateScreenCapturer() {
webrtc::DesktopCaptureOptions options;
RTCDesktopCapturer* desktopCapturer = new RTCDesktopCapturer(
webrtc::DesktopCapturer::CreateScreenCapturer(options));
scoped_refptr<RTCVideoCapturerImpl> video_capturer =
scoped_refptr<RTCVideoCapturerImpl>(
new RefCountedObject<RTCVideoCapturerImpl>(
std::unique_ptr<RTCDesktopCapturer>(desktopCapturer)));
return video_capturer;
}

scoped_refptr<RTCVideoCapturer> DesktopDeviceImpl::CreateWindowCapturer() {
webrtc::DesktopCaptureOptions options;
RTCDesktopCapturer* desktopCapturer = new RTCDesktopCapturer(
webrtc::DesktopCapturer::CreateWindowCapturer(options));
scoped_refptr<RTCVideoCapturerImpl> video_capturer =
scoped_refptr<RTCVideoCapturerImpl>(
new RefCountedObject<RTCVideoCapturerImpl>(
std::unique_ptr<RTCDesktopCapturer>(desktopCapturer)));
return video_capturer;
}
} // namespace libwebrtc
26 changes: 26 additions & 0 deletions src/rtc_desktop_device_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef LIB_WEBRTC_DESKTOP_DEVICE_IMPL_HXX
#define LIB_WEBRTC_DESKTOP_DEVICE_IMPL_HXX

#include "modules/desktop_capture/desktop_capture_options.h"
#include "modules/desktop_capture/desktop_capturer.h"
#include "modules/desktop_capture/desktop_frame.h"
#include "rtc_desktop_capturer.h"
#include "rtc_desktop_device.h"

// std::unique_ptr<cricket::VideoCapturer> video_device =
// std::unique_ptr<cricket::VideoCapturer>(new DesktopCapturerDeviceImpl());
namespace libwebrtc {
class DesktopDeviceImpl : public RTCDesktopDevice {
public:
DesktopDeviceImpl();

scoped_refptr<RTCVideoCapturer> CreateScreenCapturer() override;

scoped_refptr<RTCVideoCapturer> CreateWindowCapturer() override;

webrtc::DesktopCaptureOptions CreateOptions();
};

} // namespace libwebrtc

#endif
20 changes: 16 additions & 4 deletions src/rtc_peerconnection_factory_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,15 @@ scoped_refptr<RTCAudioSource> RTCPeerConnectionFactoryImpl::CreateAudioSource(
return source;
}

scoped_refptr<RTCDesktopDevice>
RTCPeerConnectionFactoryImpl::GetDesktopDevice() {
if (!desktop_device_impl_) {
desktop_device_impl_ = scoped_refptr<DesktopDeviceImpl>(
new RefCountedObject<DesktopDeviceImpl>());
}
return desktop_device_impl_;
}

scoped_refptr<RTCVideoSource> RTCPeerConnectionFactoryImpl::CreateVideoSource(
scoped_refptr<RTCVideoCapturer> capturer,
const string video_source_label,
Expand All @@ -140,13 +149,15 @@ scoped_refptr<RTCVideoSource> RTCPeerConnectionFactoryImpl::CreateVideoSource(
scoped_refptr<RTCVideoSource> source =
signaling_thread_->Invoke<scoped_refptr<RTCVideoSource>>(
RTC_FROM_HERE, [this, capturer, video_source_label, constraints] {
return CreateVideoSource_s(capturer, to_std_string(video_source_label).c_str(),
constraints);
return CreateVideoSource_s(
capturer, to_std_string(video_source_label).c_str(),
constraints);
});
return source;
}

return CreateVideoSource_s(capturer, to_std_string(video_source_label).c_str(), constraints);
return CreateVideoSource_s(
capturer, to_std_string(video_source_label).c_str(), constraints);
}

scoped_refptr<RTCVideoSource> RTCPeerConnectionFactoryImpl::CreateVideoSource_s(
Expand All @@ -168,7 +179,8 @@ scoped_refptr<RTCVideoSource> RTCPeerConnectionFactoryImpl::CreateVideoSource_s(
scoped_refptr<RTCMediaStream> RTCPeerConnectionFactoryImpl::CreateStream(
const string stream_id) {
rtc::scoped_refptr<webrtc::MediaStreamInterface> rtc_stream =
rtc_peerconnection_factory_->CreateLocalMediaStream(to_std_string(stream_id));
rtc_peerconnection_factory_->CreateLocalMediaStream(
to_std_string(stream_id));

scoped_refptr<MediaStreamImpl> stream = scoped_refptr<MediaStreamImpl>(
new RefCountedObject<MediaStreamImpl>(rtc_stream));
Expand Down
4 changes: 4 additions & 0 deletions src/rtc_peerconnection_factory_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define LIB_WEBRTC_MEDIA_SESSION_FACTORY_IMPL_HXX

#include "rtc_audio_device_impl.h"
#include "rtc_desktop_device_impl.h"
#include "rtc_peerconnection.h"
#include "rtc_peerconnection_factory.h"
#include "rtc_video_device_impl.h"
Expand Down Expand Up @@ -44,6 +45,8 @@ class RTCPeerConnectionFactoryImpl : public RTCPeerConnectionFactory {
const string video_source_label,
scoped_refptr<RTCMediaConstraints> constraints) override;

virtual scoped_refptr<RTCDesktopDevice> GetDesktopDevice() override;

virtual scoped_refptr<RTCAudioTrack> CreateAudioTrack(
scoped_refptr<RTCAudioSource> source,
const string track_id) override;
Expand Down Expand Up @@ -79,6 +82,7 @@ class RTCPeerConnectionFactoryImpl : public RTCPeerConnectionFactory {
rtc::scoped_refptr<webrtc::AudioDeviceModule> audio_device_module_;
scoped_refptr<AudioDeviceImpl> audio_device_impl_;
scoped_refptr<RTCVideoDeviceImpl> video_device_impl_;
scoped_refptr<DesktopDeviceImpl> desktop_device_impl_;
std::list<scoped_refptr<RTCPeerConnection>> peerconnections_;
std::unique_ptr<webrtc::TaskQueueFactory> task_queue_factory_;
};
Expand Down
Loading