This topic describes how to implement screen sharing on macOS.
Function Introduction
Screen sharing lets you share your screen content in real time with other users in a channel during a video call or live stream. This feature enables instant information sharing and visual communication.
Prerequisites
Before you implement screen sharing, ensure that the following prerequisites are met:
You have a valid Alibaba Cloud account and have created an ApsaraVideo Real-time Communication application. For more information, see Create an application. You can obtain the App ID and App Key from the console.
You have integrated the ApsaraVideo Real-time Communication (ARTC) SDK into your project and implemented basic real-time audio and video features. For more information about SDK integration, see SDK download and integration. For more information about audio and video implementation, see Implement audio and video calls.
Notes
In ARTC versions earlier than 7.6, you must join a channel before you start screen sharing. For more information about how to join a channel, see Implement audio and video calls.
In ARTC 7.6 and later, you can start screen sharing without joining a channel. We recommend that you set
AliEngineScreenShareConfig.isPushStreamto FALSE. After you join the channel, set the parameter to TRUE and call theupdateScreenShareConfigmethod to start stream ingest.
Implementation
1. Configure screen sharing encoding parameters
To customize the encoding properties of the screen sharing video stream, call the setScreenShareEncoderConfiguration method. You can configure parameters such as resolution, frame rate, bitrate, Group of Pictures (GOP), and video rotation.
You can call this method before or after you join a channel. To set the screen stream encoding properties only once per session, we recommend that you call this method before you join the channel.
You can call this method multiple times to update the configuration as needed.
The related configurations are as follows:
Parameter name | Description | Default value |
dimensions | The video resolution. | 0 × 0. This value indicates that the ingest resolution matches the captured screen resolution. The maximum value is 3840 × 2160. |
frameRate | The video frame rate. | The default value is 5. The maximum value is 30. |
bitrate | The video encoding bitrate. Unit: Kbps. Note The bitrate must be within a reasonable range based on the resolution and frame rate. If the specified value is outside the valid range, the SDK automatically adjusts it to a valid value. | 512 |
keyFrameInterval | The keyframe interval, also known as the Group of Pictures (GOP). Unit: milliseconds (ms). | The default value is 0. This value indicates that the SDK internally controls the keyframe interval. |
forceStrictKeyFrameInterval | Specifies whether to force the encoder to strictly follow the configured keyframe interval. | The default value is false.
|
rotationMode | The rotation of the video stream. | The default value is AliEngineRotationMode_0. Valid values are 0, 90, 180, and 270. |
Sample code:
/*
config is a user-defined configuration struct
*/
AliRtcScreenShareEncoderConfiguration * encoderConfig = [[AliRtcScreenShareEncoderConfiguration alloc] init];
encoderConfig.dimensions = CGSizeMake( width_, height_);
encoderConfig.frameRate = frameRate_; // 5/10/15...
encoderConfig.bitrate = bitrate_; // 1200...
encoderConfig.rotation = AliRtcRotationMode_0; // 0/90/180/270
encoderConfig.keyFrameInterval = keyFrameInterval_; // 1/2/3 seconds
if (keyFrameInterval_ > 0) {
encoderConfig.forceStrictKeyFrameInterval = TRUE;
}
encoderConfig.forceStrictKeyFrameInterval = forceStrictKeyFrameInterval_;
[self.mainEngine setScreenShareEncoderConfiguration: encoderConfig];2. Set up screen sharing preview
To preview the local screen sharing feed, call the setLocalViewConfig method to set the display view for the screen sharing stream (AliEngineVideoTrackScreen).
AliVideoCanvas *canvas = [[AliVideoCanvas alloc]init];
canvas.mirrorMode = _mirrorButton.state == NSControlStateValueOn ? AliRtcRenderMirrorModeAllEnabled:AliRtcRenderMirrorModeAllDisabled;
canvas.view = renderView;
int rv = [self.mainEngine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackScreen];3. (Remote) View screen sharing
To view the screen sharing feed of a remote user, you can call the setRemoteViewConfig method in the onRemoteTrackAvailableNotify callback to set the display view.
- (void)onRemoteTrackAvailableNotify:(NSString *)uid audioTrack:(AliRtcAudioTrack)audioTrack videoTrack:(AliRtcVideoTrack)videoTrack {
/* Handle UI components on the main thread */
dispatch_async(dispatch_get_main_queue(), ^{
AliVideoCanvas *canvas = [[AliVideoCanvas alloc]init];
if ( videoTrack == AliRtcVideoTrackScreen ) {
canvas.view = self._screenshareView;
int rv = [self.mainEngine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackScreen];
} else {
/* Find the view corresponding to this user */
canvas.view = self.findView(uid);
int rv = [self.mainEngine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackScreen];
}
});
}
4. Enumerate all shareable desktops
Call the getScreenShareSourceInfoWithType method to obtain a list of shareable windows and desktops.
A system prompt appears to request permission. If the user denies the permission, all subsequent sharing attempts fail.
_screenInfoArray = [self.engine getScreenShareSourceInfoWithType:AliRtcScreenShareDesktop];
/* Add to list */
if (_screenInfoArray) {
for (AliRtcScreenSourceInfo *info in _screenInfoArray) {
// Name + ID
NSString *showString = [NSString stringWithFormat:@"%@+%@",info.sourceName,info.sourceId];
[_screenListBox addItemWithObjectValue:showString];
}
}
5. Start screen sharing
Call the startScreenShareWithDesktopId method to start screen sharing.
Note You must configure config.isPushStream.
AliRtcScreenShareConfig *config = [[AliRtcScreenShareConfig alloc]init];
/* For region-based sharing */
if ( shareRegion ) {
config.isShareByRegion = TRUE ;
AliRtcScreenShareRegion *region = [[AliRtcScreenShareRegion alloc]init];
region.originX = regionRect.origin.x;
region.originY = regionRect.origin.y;
region.width = regionRect.size.width;
region.height = regionRect.size.height;
config.shareRegion = region;
} else {
config.isShareByRegion = FALSE;
}
/* Set to true to push stream immediately; otherwise, set to FALSE
and call updateScreenShareConfig later */
if ( pushStream ) {
config.isPushStream = TRUE ;
} else {
config.isPushStream = FALSE ;
}
/* Set desktop ID from _screenListBox */
int idValue = [[_screenInfoArray[_screenListBox.indexOfSelectedItem] sourceId] intValue] ;
int r = [self.engine startScreenShareWithDesktopId:idValue config:config];
NSLog(@"startScreenShareWithDesktopId:%d",r);
if ( r != 0 ) {
// Error handling
}
6. (Optional) Update configuration
To update the screen sharing configuration, call the updateScreenShareConfig method.
AliRtcScreenShareConfig *config = [[AliRtcScreenShareConfig alloc]init];
/* For region-based sharing */
if ( share_region ) {
config.isShareByRegion = TRUE ;
AliRtcScreenShareRegion *region = [[AliRtcScreenShareRegion alloc]init];
region.originX = regionRect.origin.x;
region.originY = regionRect.origin.y;
region.width = regionRect.size.width;
region.height = regionRect.size.height;
config.shareRegion = region;
} else {
config.isShareByRegion = FALSE;
}
/* Set to true to push stream immediately; otherwise, set to FALSE
and call updateScreenShareConfig later */
if ( pushStream ) {
config.isPushStream = TRUE ;
} else {
config.isPushStream = FALSE ;
}
[self.engine updateScreenShareConfig:mScreenConfig];7. Stop screen sharing
[self.engine stopScreenShare];Multi-window sharing
The logic for configuring preview views, previewing, and ingesting streams is the same as that for desktop sharing. The sample code is not repeated in this section.
1. Display all shareable windows
Based on your business requirements, you can call the startScreenShareWithWindowId method to share a specific window.
_windowInfoArray = [self.engine getScreenShareSourceInfoWithType:AliRtcScreenShareWindow];
/* Display in listBox */
if (_windowInfoArray) {
for (AliRtcScreenSourceInfo *info in _windowInfoArray) {
// Name + ID
NSString *showString = [NSString stringWithFormat:@"%@+%@",info.sourceName,info.sourceId];
[_windowsListBox addItemWithObjectValue:showString];
}
}
2. Share a specific window
AliRtcScreenShareConfig *config = [[AliRtcScreenShareConfig alloc]init];
/* For region-based sharing */
if ( shareRegion ) {
config.isShareByRegion = TRUE ;
AliRtcScreenShareRegion *region = [[AliRtcScreenShareRegion alloc]init];
region.originX = regionRect.origin.x;
region.originY = regionRect.origin.y;
region.width = regionRect.size.width;
region.height = regionRect.size.height;
config.shareRegion = region;
} else {
config.isShareByRegion = FALSE;
}
/* Set to true to push stream immediately; otherwise, set to FALSE.
Later, call updateScreenShareConfig to modify the push stream flag */
if ( pushStream ) {
config.isPushStream = TRUE ;
} else {
config.isPushStream = FALSE ;
}
/* Set window ID from _windowsListBox */
int idValue = [[_windowInfoArray[_windowsListBox.indexOfSelectedItem] sourceId] intValue] ;
int r = [self.engine startScreenShareWithWindowId:idValue config:config];
NSLog(@"startScreenShareWithWindowId:%d",r);
if ( r != 0 ) {
// Error handling
}
3. Stop sharing a window or desktop
Call the stopScreenShare method to stop sharing.
[self.mainEngine stopScreenShare];