本文将为您介绍Windows端如何实现屏幕共享。
功能介绍
屏幕共享功能允许用户在视频通话、直播过程中将自己的屏幕内容实时分享给频道内的其他用户,实现信息的即时共享与可视化交流。
前提条件
在实现屏幕共享前,请确保达成以下条件:
实现屏幕共享
ARTC 7.6 版本之前开启屏幕共享之前需要入会,入会流程请参考实现音视频通话;
7.6版本之后不需要入会就可以开启屏幕共享,建议先设置AliEngineScreenShareConfig.isPushStream为FALSE,待入会之后设置为TRUE,调用UpdateScreenShareConfig开启推流;
1. 配置屏幕共享编码参数
如果需要自定义屏幕共享视频流的编码属性,可以调用setScreenShareEncoderConfiguration
接口进行配置,包含分辨率、帧率、码率、GOP、视频旋转方向。
该接口在加入频道前后均可配置,如果每次入会只需要设置一次屏幕流视频编码属性,建议在入会前调用。
如果需要更新配置,可以多次调用该接口。
相关配置如下:
参数名 | 参数说明 | 默认值 |
dimensions | 视频分辨率。 | 0x0,表示推流分辨率跟随屏幕采集的分辨率。最大取值为3840x2160。 |
frameRate | 视频帧率。 | 默认帧率为 5,最大取值为 30。 |
bitrate | 视频编码码率(Kbps)。 说明 码率设置根据分辨率和帧率有对应的合理范围,该值设置在合理范围内有效,否则SDK会自动调节码率到有效值。 | 512 |
keyFrameInterval | 关键帧间隔,GOP。单位为毫秒(ms)。 | 默认值0,表示SDK内部控制关键帧间隔。 |
forceStrictKeyFrameInterval | 是否强制编码器严格按照设置的关键帧间隔产生关键帧。 | 默认值为 false。
|
rotationMode | 推流旋转。 | 默认值为 AliEngineRotationMode_0。可选择 0、90、180、270 四个角度。 |
/*
config 为客户定义的配置结构体
*/
AliEngineScreenShareEncoderConfiguration encoderConfig;
encoderConfig.dimensions = AliEngineVideoDimensions(config.dimensions.width, config.dimensions.height);
encoderConfig.frameRate = (AliEngineFrameRate)config.frameRate;
encoderConfig.bitrate = (int)config.bitrate;
encoderConfig.rotationMode = (AliEngineRotationMode)config.rotationMode;
encoderConfig.keyFrameInterval = (int)config.keyFrameInterval;
encoderConfig.forceStrictKeyFrameInterval = config.forceStrictKeyFrameInterval;
mpEngine->setScreenShareEncoderConfiguration(canvas, AliEngineVideoTrackScreen);
2. 设置屏幕共享画面预览
如果需要预览屏幕共享画面,请调用SetLocalViewConfig
为屏幕共享流(AliEngineVideoTrackScreen)配置显示视图。
AliEngineVideoCanvas canvas;
canvas.renderMode = AliEngineRenderModeFill;
/* 配置好显示的窗口句柄 */
canvas.displayView = (void*)hWnd;
canvas.scaleMode = AliEngineVideoScale_16_9;
mpEngine->SetLocalViewConfig(canvas, AliEngineVideoTrackScreen);
3. (远端)观看屏幕共享
如果需要观看远端用户的屏幕共享画面,可以在OnRemoteTrackAvailableNotify
回调中为屏幕共享画面SetRemoteViewConfig
设置显示视图。
void ARTCEventListernerImpl::OnRemoteTrackAvailableNotify(const char *uid,
AliEngineAudioTrack audioTrack,
AliEngineVideoTrack videoTrack) {
char logBuffer[MAX_LOG_STRING_SIZE];
snprintf(logBuffer, USE_LOG_STRING_SIZE, "user %s push video=%d audio=%d", uid, videoTrack, audioTrack);
SendMessageA(this->mLogHandle, LB_ADDSTRING, WPARAM(), (LPARAM)logBuffer);
mDlg->HandleTrackChangeEvent(uid, audioTrack, videoTrack);
}
void CARTCExampleDlg::HandleTrackChangeEvent(const char *uid,
AliEngineAudioTrack audioTrack,
AliEngineVideoTrack videoTrack) {
if ((videoTrack & AliEngineVideoTrackScreen) > 0) {
if ((videoTrack & AliEngineVideoTrackCamera) == 0) {
AliEngineVideoCanvas canvas;
canvas.displayView = nullptr;
mEngine->SetRemoteViewConfig(canvas, uid, AliEngineVideoTrackCamera);
}
{
AliEngineVideoCanvas canvas;
canvas.displayView = mRemoteView.GetSafeHwnd();
mEngine->SetRemoteViewConfig(canvas, uid, AliEngineVideoTrackScreen);
}
return;
}
if ( (videoTrack & AliEngineVideoTrackCamera) > 0) {
AliEngineVideoCanvas canvas;
canvas.displayView = mRemoteView.GetSafeHwnd();
mEngine->SetRemoteViewConfig(canvas, uid, AliEngineVideoTrackCamera );
}
}
4. 开启屏幕共享
调用 StartScreenShareByScreenRegion
开启屏幕共享。
需要配置 mScreenConfig.isPushStream
。
/*
* 共享屏幕局部
*/
RECT rc;
::GetWindowRect(::GetDesktopWindow(), &rc);
AliEngineScreenShareRegion screenRegion;
screenRegion.originX = (float)rc.left;
screenRegion.originY = (float)rc.top;
screenRegion.width = (float)(rc.right - rc.left);
screenRegion.height = (float)(rc.bottom - rc.top);
AliEngineScreenShareConfig mScreenConfig;
mScreenConfig.isShareByRegion = false;
mScreenConfig.shareRegion = screenRegion;
/*
如果不推流,只预览,可以设置为FALSE,
如果预览的同时推流,则设置为TRUE,可以跳过步骤5(更新配置)直接推流。
*/
mScreenConfig.isPushStream = FALSE ;
mpEngine->StartScreenShareByScreenRegion(screenRegion, mScreenConfig);
5. (可选)更新配置
如果需要更新屏幕共享的配置,可以调用UpdateScreenShareConfig
进行。
/* 设置为屏幕共享推流 */
mScreenConfig.isPushStream = TRUE ;
/* 如果想共享局部 */
mScreenConfig.isShareByRegion = true ;
screenRegion.originX = (float)rc.left;
screenRegion.originY = (float)rc.top;
screenRegion.width = (float)(rc.right - rc.left);
screenRegion.height = (float)(rc.bottom - rc.top);
mScreenConfig.isShareByRegion = true;
mScreenConfig.shareRegion = screenRegion;
mpEngine->UpdateScreenShareConfig(mScreenConfig);
6. 停止屏幕共享
mpEngine->StopScreenShare();
多窗口共享
配置预览窗口、预览和推流这些基本逻辑和上面的屏幕共享一致,这里就不单独列出代码;
1. 枚举所有可共享的窗口或桌面
调用GetScreenShareSourceInfo
获取可共享的窗口或桌面列表。
/*
1,根据需要设置枚举的类型
*/
mScreenShareType = AliEngineScreenShareDesktop ;
mScreenShareType = AliEngineScreenShareWindow ;
/*
2,下面代码是填充一个comboBox列表
*/
CComboBox *listBox = (CComboBox *)GetDlgItem(IDC_COMBO_SCREEN_SOURCE_LIST);
listBox->ResetContent();
AliEngineScreenSourceList* mCurrentSourceList = mEngine->GetScreenShareSourceInfo(mScreenShareType);
if (nullptr != mCurrentSourceList)
{
for (size_t i = 0; i < mCurrentSourceList->GetCount(); i++) {
AliEngineScreenSourcInfo info = mCurrentSourceList->GetSourceInfo(i);
/*
* 如果不希望共享APP自身的窗口,可以通过sourceIsSelf来区分
*/
if ( info.sourceIsSelf ) {
continue ;
}
CString s = AliStringToCString(info.sourceName);
listBox->AddString(s)
}
}
/*
3,选中项之后记录ID和Title
*/
int idx = listBox->GetCurSel();
if (mCurrentSourceList && idx < mCurrentSourceList->GetCount())
{
AliEngineScreenSourcInfo info = mCurrentSourceList->GetSourceInfo(idx);
mSourceId = info.sourceId;
mSourceTitle = info.sourceName;
}
2. 共享对应窗口或桌面
根据业务需求,选择调用StartScreenShareByWindowId
或者startScreenShareByDesktopId
来共享对应窗口或者桌面。
msSourceId是共享桌面的ID,可以通过上文的枚举接口获取;
screenShareSource是配置;
AliEngineScreenShareRegion shareRegion ;
shareRegion.originX = 0.f;
shareRegion.originY = 0.f;
shareRegion.width = 640.f;
shareRegion.height = 480.f;
screenShareSource.isShareByRegion = true ;
screenShareSource.shareRegion = shareRegion;
/*
* 如果想只预览不推流,请参考屏幕共享的介绍,设置isPushStream=FALSE
*/
/*
* 根据产品需求,调用对应的接口进行共享桌面或者窗口
* 共享桌面
*/
mpEngine->StartScreenShareByDesktopId(atol(msSourceId.c_str()), screenShareSource);
/*
* 或者共享窗口
*/
mpEngine->StartScreenShareByWindowId(atol(msSourceId.c_str()), screenShareSource);
/*
* 可以显示获取共享窗口的显示范围和标题
*/
AliEngineScreenShareRegion region;
mEngine->GetDesktopRegion(mSourceId, mSourceTitle, region);
CString resolutionMsg;
resolutionMsg.Format(_T("Resolution: %d x %d"), region.width, region.height);
((CStatic*)GetDlgItem(IDC_STATIC_SCREEN_SOURCE_RESOLUTION))->SetWindowTextW(resolutionMsg);
((CEdit*)GetDlgItem(IDC_EDIT_SHARE_REGION_X))->SetWindowTextW(std::to_wstring(mScreenShareSource.shareRegion.originX).c_str());
((CEdit*)GetDlgItem(IDC_EDIT_SHARE_REGION_Y))->SetWindowTextW(std::to_wstring(mScreenShareSource.shareRegion.originY).c_str());
((CEdit*)GetDlgItem(IDC_EDIT_SHARE_REGION_X2))->SetWindowTextW(std::to_wstring(mScreenShareSource.shareRegion.width).c_str());
((CEdit*)GetDlgItem(IDC_EDIT_SHARE_REGION_Y2))->SetWindowTextW(std::to_wstring(mScreenShareSource.shareRegion.height).c_str());
}
3. 停止共享对应窗口或者桌面
mpEngine->StopScreenShare();