Skip to content

Commit f447f68

Browse files
committed
[Mac] feat: Support screen capture for macOS. (#24) (#36)
* 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.
1 parent 8806408 commit f447f68

16 files changed

+1192
-4
lines changed

sdk/BUILD.gn

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,43 @@ if (is_ios || is_mac) {
704704
"../rtc_base/system:gcd_helpers",
705705
]
706706
}
707+
708+
rtc_library("desktopcapture_objc") {
709+
visibility = [ "*" ]
710+
sources = [
711+
"objc/components/capturer/RTCDesktopCapturer+Private.h",
712+
"objc/components/capturer/RTCDesktopCapturer.h",
713+
"objc/components/capturer/RTCDesktopCapturer.mm",
714+
"objc/components/capturer/RTCDesktopSource+Private.h",
715+
"objc/components/capturer/RTCDesktopSource.h",
716+
"objc/components/capturer/RTCDesktopSource.mm",
717+
"objc/components/capturer/RTCDesktopMediaList+Private.h",
718+
"objc/components/capturer/RTCDesktopMediaList.h",
719+
"objc/components/capturer/RTCDesktopMediaList.mm",
720+
"objc/native/src/objc_desktop_capture.h",
721+
"objc/native/src/objc_desktop_capture.mm",
722+
"objc/native/src/objc_desktop_media_list.h",
723+
"objc/native/src/objc_desktop_media_list.mm",
724+
]
725+
frameworks = [
726+
"AppKit.framework",
727+
]
728+
729+
configs += [ "..:common_objc" ]
730+
731+
public_configs = [ ":common_config_objc" ]
732+
733+
deps = [
734+
":base_objc",
735+
":helpers_objc",
736+
":videoframebuffer_objc",
737+
"../rtc_base/system:gcd_helpers",
738+
"../modules/desktop_capture",
739+
]
740+
if(is_mac) {
741+
deps += [ "//third_party:jpeg", ]
742+
}
743+
}
707744

708745
rtc_library("videocodec_objc") {
709746
visibility = [ "*" ]
@@ -1512,6 +1549,9 @@ if (is_ios || is_mac) {
15121549
"objc/base/RTCYUVPlanarBuffer.h",
15131550
"objc/components/capturer/RTCCameraVideoCapturer.h",
15141551
"objc/components/capturer/RTCFileVideoCapturer.h",
1552+
"objc/components/capturer/RTCDesktopCapturer.h",
1553+
"objc/components/capturer/RTCDesktopSource.h",
1554+
"objc/components/capturer/RTCDesktopMediaList.h",
15151555
"objc/components/renderer/metal/RTCMTLNSVideoView.h",
15161556
"objc/components/renderer/opengl/RTCNSGLVideoView.h",
15171557
"objc/components/renderer/opengl/RTCVideoViewShading.h",
@@ -1545,6 +1585,7 @@ if (is_ios || is_mac) {
15451585
":opengl_ui_objc",
15461586
":peerconnectionfactory_base_objc",
15471587
":videocapture_objc",
1588+
":desktopcapture_objc",
15481589
":videocodec_objc",
15491590
":videotoolbox_objc",
15501591
]
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2022 LiveKit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "RTCDesktopCapturer.h"
18+
19+
#include "sdk/objc/native/src/objc_desktop_capture.h"
20+
21+
NS_ASSUME_NONNULL_BEGIN
22+
23+
RTC_OBJC_EXPORT
24+
@protocol RTC_OBJC_TYPE
25+
(DesktopCapturerDelegate)<NSObject>
26+
-(void)didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *) frame;
27+
-(void)didSourceCaptureStart;
28+
-(void)didSourceCapturePaused;
29+
-(void)didSourceCaptureStop;
30+
-(void)didSourceCaptureError;
31+
@end
32+
33+
@interface RTCDesktopCapturer ()
34+
35+
@property(nonatomic, readonly)std::shared_ptr<webrtc::ObjCDesktopCapturer> nativeCapturer;
36+
37+
- (void)didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame;
38+
39+
-(void)didSourceCaptureStart;
40+
41+
-(void)didSourceCapturePaused;
42+
43+
-(void)didSourceCaptureStop;
44+
45+
-(void)didSourceCaptureError;
46+
47+
@end
48+
49+
NS_ASSUME_NONNULL_END
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2022 LiveKit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <AVFoundation/AVFoundation.h>
18+
#import <Foundation/Foundation.h>
19+
20+
#import "RTCMacros.h"
21+
#import "RTCVideoCapturer.h"
22+
#import "RTCDesktopSource.h"
23+
24+
NS_ASSUME_NONNULL_BEGIN
25+
26+
@class RTCDesktopCapturer;
27+
28+
RTC_OBJC_EXPORT
29+
@protocol RTC_OBJC_TYPE
30+
(RTCDesktopCapturerDelegate)<NSObject>
31+
-(void)didSourceCaptureStart:(RTCDesktopCapturer *) capturer;
32+
33+
-(void)didSourceCapturePaused:(RTCDesktopCapturer *) capturer;
34+
35+
-(void)didSourceCaptureStop:(RTCDesktopCapturer *) capturer;
36+
37+
-(void)didSourceCaptureError:(RTCDesktopCapturer *) capturer;
38+
@end
39+
40+
RTC_OBJC_EXPORT
41+
// Screen capture that implements RTCVideoCapturer. Delivers frames to a
42+
// RTCVideoCapturerDelegate (usually RTCVideoSource).
43+
@interface RTC_OBJC_TYPE (RTCDesktopCapturer) : RTC_OBJC_TYPE(RTCVideoCapturer)
44+
45+
@property(nonatomic, readonly) RTCDesktopSource *source;
46+
47+
- (instancetype)initWithSource:(RTCDesktopSource*)source delegate:(__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)>)delegate captureDelegate:(__weak id<RTC_OBJC_TYPE(RTCVideoCapturerDelegate)>)captureDelegate;
48+
49+
- (instancetype)initWithDefaultScreen:(__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)>)delegate captureDelegate:(__weak id<RTC_OBJC_TYPE(RTCVideoCapturerDelegate)>)captureDelegate;
50+
51+
- (void)startCapture;
52+
53+
- (void)startCaptureWithFPS:(NSInteger)fps;
54+
55+
- (void)stopCapture;
56+
57+
- (void)stopCaptureWithCompletionHandler:(nullable void (^)(void))completionHandler;
58+
59+
@end
60+
61+
NS_ASSUME_NONNULL_END
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright 2022 LiveKit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <Foundation/Foundation.h>
18+
19+
#import "base/RTCLogging.h"
20+
#import "base/RTCVideoFrameBuffer.h"
21+
22+
#import "components/video_frame_buffer/RTCCVPixelBuffer.h"
23+
24+
#import "RTCDesktopCapturer.h"
25+
#import "RTCDesktopCapturer+Private.h"
26+
#import "RTCDesktopSource+Private.h"
27+
28+
@implementation RTC_OBJC_TYPE (RTCDesktopCapturer) {
29+
__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)> _delegate;
30+
}
31+
32+
@synthesize nativeCapturer = _nativeCapturer;
33+
@synthesize source = _source;
34+
35+
- (instancetype)initWithSource:(RTCDesktopSource*)source delegate:(__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)>)delegate captureDelegate:(__weak id<RTC_OBJC_TYPE(RTCVideoCapturerDelegate)>)captureDelegate {
36+
if (self = [super initWithDelegate:captureDelegate]) {
37+
webrtc::DesktopType captureType = webrtc::kScreen;
38+
if(source.sourceType == RTCDesktopSourceTypeWindow) {
39+
captureType = webrtc::kWindow;
40+
}
41+
_nativeCapturer = std::make_shared<webrtc::ObjCDesktopCapturer>(captureType, source.nativeMediaSource->id(), self);
42+
_source = source;
43+
_delegate = delegate;
44+
}
45+
return self;
46+
}
47+
48+
- (instancetype)initWithDefaultScreen:(__weak id<RTC_OBJC_TYPE(RTCDesktopCapturerDelegate)>)delegate captureDelegate:(__weak id<RTC_OBJC_TYPE(RTCVideoCapturerDelegate)>)captureDelegate {
49+
if (self = [super initWithDelegate:captureDelegate]) {
50+
_nativeCapturer = std::make_unique<webrtc::ObjCDesktopCapturer>(webrtc::kScreen, -1, self);
51+
_source = nil;
52+
_delegate = delegate;
53+
}
54+
return self;
55+
}
56+
57+
58+
-(void)dealloc {
59+
_nativeCapturer->Stop();
60+
_nativeCapturer = nullptr;
61+
}
62+
63+
- (void)startCapture {
64+
[self didSourceCaptureStart];
65+
_nativeCapturer->Start(30);
66+
}
67+
68+
- (void)startCaptureWithFPS:(NSInteger)fps {
69+
_nativeCapturer->Start(fps);
70+
}
71+
72+
- (void)didCaptureVideoFrame
73+
: (RTC_OBJC_TYPE(RTCVideoFrame) *)frame {
74+
[self.delegate capturer:self didCaptureVideoFrame:frame];
75+
}
76+
77+
- (void)stopCapture {
78+
_nativeCapturer->Stop();
79+
}
80+
81+
- (void)stopCaptureWithCompletionHandler:(nullable void (^)(void))completionHandler {
82+
[self stopCapture];
83+
if(completionHandler != nil) {
84+
completionHandler();
85+
}
86+
}
87+
88+
-(void)didSourceCaptureStart {
89+
[_delegate didSourceCaptureStart:self];
90+
}
91+
92+
-(void)didSourceCapturePaused {
93+
[_delegate didSourceCapturePaused:self];
94+
}
95+
96+
-(void)didSourceCaptureStop {
97+
[_delegate didSourceCaptureStop:self];
98+
}
99+
100+
-(void)didSourceCaptureError {
101+
[_delegate didSourceCaptureError:self];
102+
}
103+
104+
@end
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2022 LiveKit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "RTCDesktopMediaList.h"
18+
19+
namespace webrtc {
20+
class ObjCDesktopMediaList;
21+
class MediaSource;
22+
}
23+
24+
NS_ASSUME_NONNULL_BEGIN
25+
26+
@interface RTCDesktopMediaList ()
27+
28+
@property(nonatomic, readonly)std::shared_ptr<webrtc::ObjCDesktopMediaList> nativeMediaList;
29+
30+
-(void)mediaSourceAdded:(webrtc::MediaSource *) source;
31+
32+
-(void)mediaSourceRemoved:(webrtc::MediaSource *) source;
33+
34+
-(void)mediaSourceNameChanged:(webrtc::MediaSource *) source;
35+
36+
-(void)mediaSourceThumbnailChanged:(webrtc::MediaSource *) source;
37+
38+
@end
39+
40+
NS_ASSUME_NONNULL_END
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2022 LiveKit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <AVFoundation/AVFoundation.h>
18+
#import <Foundation/Foundation.h>
19+
20+
#import "RTCMacros.h"
21+
#import "RTCDesktopSource.h"
22+
23+
NS_ASSUME_NONNULL_BEGIN
24+
25+
RTC_OBJC_EXPORT
26+
@protocol RTC_OBJC_TYPE
27+
(RTCDesktopMediaListDelegate)<NSObject>
28+
29+
- (void)didDesktopSourceAdded:(RTC_OBJC_TYPE(RTCDesktopSource) *) source;
30+
31+
- (void)didDesktopSourceRemoved:(RTC_OBJC_TYPE(RTCDesktopSource) *) source;
32+
33+
- (void)didDesktopSourceNameChanged:(RTC_OBJC_TYPE(RTCDesktopSource) *) source;
34+
35+
- (void)didDesktopSourceThumbnailChanged:(RTC_OBJC_TYPE(RTCDesktopSource) *) source;
36+
@end
37+
38+
RTC_OBJC_EXPORT
39+
@interface RTC_OBJC_TYPE (RTCDesktopMediaList) : NSObject
40+
41+
-(instancetype)initWithType:(RTCDesktopSourceType)type delegate:(__weak id<RTC_OBJC_TYPE(RTCDesktopMediaListDelegate)>)delegate;
42+
43+
@property(nonatomic, readonly) RTCDesktopSourceType sourceType;
44+
45+
- (int32_t)UpdateSourceList:(BOOL)forceReload updateAllThumbnails:(BOOL)updateThumbnail;
46+
47+
- (NSArray<RTC_OBJC_TYPE (RTCDesktopSource) *>*) getSources;
48+
49+
@end
50+
51+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)