Skip to content

Commit

Permalink
[Mac] feat: Support screen capture for macOS. (#24) (#36)
Browse files Browse the repository at this point in the history
* feat: Add screen capture support for macOS.

* chore: rename files.

* chore: update.

* chore: Implement DesktopSource, DesktopMediaList ojbc interface.

* chore: add license.

* fix: capture_state.

* update.

* update.

* Hide private delegate declaration.

* Re-generate thumbnail for all sources when call UpdateSourceList.

* fix: Fix window resize issue.

* update.

* update.

* fix for intel mac.

* cleanup.

* update.

* Add Window/Screen change listener.

* Add force reload for MediaListUpdate and capture cursor.

* fix: Fix the screen freeze caused by the desktop frame not setting the timestamp.

* update.

* fix issue for screen sharing.

* Fixed H264 profile-level-id limitation that could not encode desktop frames with resolutions higher than 720p.
  • Loading branch information
cloudwebrtc authored Aug 3, 2022
1 parent a828846 commit 9e144fa
Show file tree
Hide file tree
Showing 16 changed files with 1,193 additions and 4 deletions.
41 changes: 41 additions & 0 deletions sdk/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,43 @@ if (is_ios || is_mac) {
"../rtc_base/system:gcd_helpers",
]
}

rtc_library("desktopcapture_objc") {
visibility = [ "*" ]
sources = [
"objc/components/capturer/RTCDesktopCapturer+Private.h",
"objc/components/capturer/RTCDesktopCapturer.h",
"objc/components/capturer/RTCDesktopCapturer.mm",
"objc/components/capturer/RTCDesktopSource+Private.h",
"objc/components/capturer/RTCDesktopSource.h",
"objc/components/capturer/RTCDesktopSource.mm",
"objc/components/capturer/RTCDesktopMediaList+Private.h",
"objc/components/capturer/RTCDesktopMediaList.h",
"objc/components/capturer/RTCDesktopMediaList.mm",
"objc/native/src/objc_desktop_capture.h",
"objc/native/src/objc_desktop_capture.mm",
"objc/native/src/objc_desktop_media_list.h",
"objc/native/src/objc_desktop_media_list.mm",
]
frameworks = [
"AppKit.framework",
]

configs += [ "..:common_objc" ]

public_configs = [ ":common_config_objc" ]

deps = [
":base_objc",
":helpers_objc",
":videoframebuffer_objc",
"../rtc_base/system:gcd_helpers",
"../modules/desktop_capture",
]
if(is_mac) {
deps += [ "//third_party:jpeg", ]
}
}

rtc_library("videocodec_objc") {
visibility = [ "*" ]
Expand Down Expand Up @@ -1456,6 +1493,9 @@ if (is_ios || is_mac) {
"objc/base/RTCYUVPlanarBuffer.h",
"objc/components/capturer/RTCCameraVideoCapturer.h",
"objc/components/capturer/RTCFileVideoCapturer.h",
"objc/components/capturer/RTCDesktopCapturer.h",
"objc/components/capturer/RTCDesktopSource.h",
"objc/components/capturer/RTCDesktopMediaList.h",
"objc/components/renderer/metal/RTCMTLNSVideoView.h",
"objc/components/renderer/opengl/RTCNSGLVideoView.h",
"objc/components/renderer/opengl/RTCVideoViewShading.h",
Expand Down Expand Up @@ -1489,6 +1529,7 @@ if (is_ios || is_mac) {
":opengl_ui_objc",
":peerconnectionfactory_base_objc",
":videocapture_objc",
":desktopcapture_objc",
":videocodec_objc",
":videotoolbox_objc",
]
Expand Down
49 changes: 49 additions & 0 deletions sdk/objc/components/capturer/RTCDesktopCapturer+Private.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2022 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "RTCDesktopCapturer.h"

#include "sdk/objc/native/src/objc_desktop_capture.h"

NS_ASSUME_NONNULL_BEGIN

RTC_OBJC_EXPORT
@protocol RTC_OBJC_TYPE
(DesktopCapturerDelegate)<NSObject>
-(void)didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *) frame;
-(void)didSourceCaptureStart;
-(void)didSourceCapturePaused;
-(void)didSourceCaptureStop;
-(void)didSourceCaptureError;
@end

@interface RTCDesktopCapturer ()

@property(nonatomic, readonly)std::shared_ptr<webrtc::ObjCDesktopCapturer> nativeCapturer;

- (void)didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame;

-(void)didSourceCaptureStart;

-(void)didSourceCapturePaused;

-(void)didSourceCaptureStop;

-(void)didSourceCaptureError;

@end

NS_ASSUME_NONNULL_END
61 changes: 61 additions & 0 deletions sdk/objc/components/capturer/RTCDesktopCapturer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2022 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import <AVFoundation/AVFoundation.h>
#import <Foundation/Foundation.h>

#import "RTCMacros.h"
#import "RTCVideoCapturer.h"
#import "RTCDesktopSource.h"

NS_ASSUME_NONNULL_BEGIN

@class RTCDesktopCapturer;

RTC_OBJC_EXPORT
@protocol RTC_OBJC_TYPE
(RTCDesktopCapturerDelegate)<NSObject>
-(void)didSourceCaptureStart:(RTCDesktopCapturer *) capturer;

-(void)didSourceCapturePaused:(RTCDesktopCapturer *) capturer;

-(void)didSourceCaptureStop:(RTCDesktopCapturer *) capturer;

-(void)didSourceCaptureError:(RTCDesktopCapturer *) capturer;
@end

RTC_OBJC_EXPORT
// Screen capture that implements RTCVideoCapturer. Delivers frames to a
// RTCVideoCapturerDelegate (usually RTCVideoSource).
@interface RTC_OBJC_TYPE (RTCDesktopCapturer) : RTC_OBJC_TYPE(RTCVideoCapturer)

@property(nonatomic, readonly) RTCDesktopSource *source;

- (instancetype)initWithSource:(RTCDesktopSource*)source delegate:(__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)>)delegate captureDelegate:(__weak id<RTC_OBJC_TYPE(RTCVideoCapturerDelegate)>)captureDelegate;

- (instancetype)initWithDefaultScreen:(__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)>)delegate captureDelegate:(__weak id<RTC_OBJC_TYPE(RTCVideoCapturerDelegate)>)captureDelegate;

- (void)startCapture;

- (void)startCaptureWithFPS:(NSInteger)fps;

- (void)stopCapture;

- (void)stopCaptureWithCompletionHandler:(nullable void (^)(void))completionHandler;

@end

NS_ASSUME_NONNULL_END
104 changes: 104 additions & 0 deletions sdk/objc/components/capturer/RTCDesktopCapturer.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright 2022 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import <Foundation/Foundation.h>

#import "base/RTCLogging.h"
#import "base/RTCVideoFrameBuffer.h"

#import "components/video_frame_buffer/RTCCVPixelBuffer.h"

#import "RTCDesktopCapturer.h"
#import "RTCDesktopCapturer+Private.h"
#import "RTCDesktopSource+Private.h"

@implementation RTC_OBJC_TYPE (RTCDesktopCapturer) {
__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)> _delegate;
}

@synthesize nativeCapturer = _nativeCapturer;
@synthesize source = _source;

- (instancetype)initWithSource:(RTCDesktopSource*)source delegate:(__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)>)delegate captureDelegate:(__weak id<RTC_OBJC_TYPE(RTCVideoCapturerDelegate)>)captureDelegate {
if (self = [super initWithDelegate:captureDelegate]) {
webrtc::DesktopType captureType = webrtc::kScreen;
if(source.sourceType == RTCDesktopSourceTypeWindow) {
captureType = webrtc::kWindow;
}
_nativeCapturer = std::make_shared<webrtc::ObjCDesktopCapturer>(captureType, source.nativeMediaSource->id(), self);
_source = source;
_delegate = delegate;
}
return self;
}

- (instancetype)initWithDefaultScreen:(__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)>)delegate captureDelegate:(__weak id<RTC_OBJC_TYPE(RTCVideoCapturerDelegate)>)captureDelegate {
if (self = [super initWithDelegate:captureDelegate]) {
_nativeCapturer = std::make_unique<webrtc::ObjCDesktopCapturer>(webrtc::kScreen, -1, self);
_source = nil;
_delegate = delegate;
}
return self;
}


-(void)dealloc {
_nativeCapturer->Stop();
_nativeCapturer = nullptr;
}

- (void)startCapture {
[self didSourceCaptureStart];
_nativeCapturer->Start(30);
}

- (void)startCaptureWithFPS:(NSInteger)fps {
_nativeCapturer->Start(fps);
}

- (void)didCaptureVideoFrame
: (RTC_OBJC_TYPE(RTCVideoFrame) *)frame {
[self.delegate capturer:self didCaptureVideoFrame:frame];
}

- (void)stopCapture {
_nativeCapturer->Stop();
}

- (void)stopCaptureWithCompletionHandler:(nullable void (^)(void))completionHandler {
[self stopCapture];
if(completionHandler != nil) {
completionHandler();
}
}

-(void)didSourceCaptureStart {
[_delegate didSourceCaptureStart:self];
}

-(void)didSourceCapturePaused {
[_delegate didSourceCapturePaused:self];
}

-(void)didSourceCaptureStop {
[_delegate didSourceCaptureStop:self];
}

-(void)didSourceCaptureError {
[_delegate didSourceCaptureError:self];
}

@end
40 changes: 40 additions & 0 deletions sdk/objc/components/capturer/RTCDesktopMediaList+Private.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2022 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "RTCDesktopMediaList.h"

namespace webrtc {
class ObjCDesktopMediaList;
class MediaSource;
}

NS_ASSUME_NONNULL_BEGIN

@interface RTCDesktopMediaList ()

@property(nonatomic, readonly)std::shared_ptr<webrtc::ObjCDesktopMediaList> nativeMediaList;

-(void)mediaSourceAdded:(webrtc::MediaSource *) source;

-(void)mediaSourceRemoved:(webrtc::MediaSource *) source;

-(void)mediaSourceNameChanged:(webrtc::MediaSource *) source;

-(void)mediaSourceThumbnailChanged:(webrtc::MediaSource *) source;

@end

NS_ASSUME_NONNULL_END
51 changes: 51 additions & 0 deletions sdk/objc/components/capturer/RTCDesktopMediaList.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2022 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import <AVFoundation/AVFoundation.h>
#import <Foundation/Foundation.h>

#import "RTCMacros.h"
#import "RTCDesktopSource.h"

NS_ASSUME_NONNULL_BEGIN

RTC_OBJC_EXPORT
@protocol RTC_OBJC_TYPE
(RTCDesktopMediaListDelegate)<NSObject>

- (void)didDesktopSourceAdded:(RTC_OBJC_TYPE(RTCDesktopSource) *) source;

- (void)didDesktopSourceRemoved:(RTC_OBJC_TYPE(RTCDesktopSource) *) source;

- (void)didDesktopSourceNameChanged:(RTC_OBJC_TYPE(RTCDesktopSource) *) source;

- (void)didDesktopSourceThumbnailChanged:(RTC_OBJC_TYPE(RTCDesktopSource) *) source;
@end

RTC_OBJC_EXPORT
@interface RTC_OBJC_TYPE (RTCDesktopMediaList) : NSObject

-(instancetype)initWithType:(RTCDesktopSourceType)type delegate:(__weak id<RTC_OBJC_TYPE(RTCDesktopMediaListDelegate)>)delegate;

@property(nonatomic, readonly) RTCDesktopSourceType sourceType;

- (int32_t)UpdateSourceList:(BOOL)forceReload updateAllThumbnails:(BOOL)updateThumbnail;

- (NSArray<RTC_OBJC_TYPE (RTCDesktopSource) *>*) getSources;

@end

NS_ASSUME_NONNULL_END
Loading

0 comments on commit 9e144fa

Please sign in to comment.