屏幕共享

最近更新时间:2022-09-20 05:17:40

anyRTC 为您提供屏幕分享使用的接口方法,通过本文档您可以了解实现的具体调用流程。

功能简介

目前Windows SDK屏幕分享功能支持屏幕分享窗口分享两种类型,其中屏幕分享还支持指定区域进行分享,应用侧可根据业务场景设置分享内容并推流。

屏幕分享

anyRTC对屏幕分享相关接口进行梳理,目前在 Windows 平台上支持:

  • 通过 screenRect 共享指定屏幕,或指定屏幕的部分区域
  • 通过 windowId 共享指定窗口,或指定窗口的部分区域

Windows 系统的所有屏幕(display)都画在一整张 virtual screen 上。对用户来说,只有拿到该屏幕在整张 virtual screen 上的相对位置,才能获得该屏幕的画面。通过获取该画面的 screenRect,我们可以按如下步骤在 Windows 平台上实现屏幕共享:

  1. 获取想要共享窗口的 screenRect
bool result = true;
int index;
for (index = 0;; index++) {
    DISPLAY_DEVICE device;
    device.cb = sizeof(device);
    result = EnumDisplayDevices(NULL, index, &device, 0);
    if (!result) break;
       
    if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
        continue;
   }
    
    DEVMODE device_mode;
    device_mode.dmSize = sizeof(DEVMODE);
    device_mode.dmDriverExtra = 0;
    EnumDisplaySettingsEx(device.DeviceName, ENUM_CURRENT_SETTINGS, &device_mode, 0);
    printf("device name:%ls\n", device.DeviceName);
    printf("x: %d\n", device_mode.dmPosition.x);
    printf("y: %d\n", device_mode.dmPosition.y);
    printf("w: %d\n", device_mode.dmPelsWidth);
    printf("h: %d\n", device_mode.dmPelsHeight);
}

更多关于 screenRect 的详情,请参考 Microsoft EnumDisplayDevicesA 说明

  1. 通过 screenRect 共享屏幕

    // 指定共享的屏幕或窗口
    RECT rc;
    ar::rtc::Rectangle rcCap;
    ar::rtc::Rectangle screenRegion = { rc.left, rc.right, rc.right - rc.left, rc.bottom - rc.top };
    capParam.dimensions.width = rc.right - rc.left;
    capParam.dimensions.height = rc.bottom - rc.top;
    
    ::GetWindowRect(hWnd, &rc);
    ScreenCaptureParameters capParam;
    capParam.dimensions.width = rc.right - rc.left;
    capParam.dimensions.height = rc.bottom - rc.top;
    
    VideoContentHint contentHint;
    ar::rtc::Rect rt;
    
    // 开始共享屏幕
    ret = m_lpAREngine->startScreenCaptureByScreenRect(screenRegion, rcCap, capParam);
    
    // 更新屏幕共享编码参数
    m_lpAREngine->updateScreenCaptureParameters(capParam);
    
    // 更新屏幕共享区域
    m_lpAREngine->updateScreenCaptureRegion(screenRegion);
    
    // 设置屏幕共享内容类型
    m_lpAREngine->setScreenCaptureContentHint(contentHint);
    
    // 停止屏幕共享
    m_lpAREngine->stopScreenCapture();
    

窗口分享

Windows 系统为每个窗口分配一个 windowId,数据类型为 HWND。该 ID 对应唯一的 Windows 窗口。为了兼容 x86 和 x64 系统,使用 view_t 类型。

通过获取该 windowId,我们可以按如下步骤在 Windows 平台上实现窗口共享:

  1. 获取想要共享窗口的 Window ID
BOOL CALLBACK EnumProc(HWND hWnd, LPARAM IParam)
{
    // 仅获取可视窗口 ID,忽略弹出窗口及目录窗口
    LONG IStyle = ::GetWindowLong(hWnd, GWL_STYLE);
    if ((IStyle&WS_VISIBLE) != 0 && (IStyle&(WAS_POPUP | WA_SYSMENU)) != 0) {
        HWND window_id = hWnd;
   }
    return TRUE;
}
EnumWindows(&EnumProc, NULL);

更多关于 windowId 的详情,请参考 Microsoft EnumWindows 说明

  1. 通过 Window ID 共享窗口

    // 指定共享的屏幕或窗口
    RECT rc;
    ar::rtc::Rectangle rcCap;
    ar::rtc::Rectangle screenRegion = { rc.left, rc.right, rc.right - rc.left, rc.bottom - rc.top };
    capParam.dimensions.width = rc.right - rc.left;
    capParam.dimensions.height = rc.bottom - rc.top;
    
    ::GetWindowRect(hWnd, &rc);
    ScreenCaptureParameters capParam;
    capParam.dimensions.width = rc.right - rc.left;
    capParam.dimensions.height = rc.bottom - rc.top;
    
    VideoContentHint contentHint;
    ar::rtc::Rect rt;
    
    // 开始共享窗口
    ret = m_lpAREngine->startScreenCaptureByWindowId(hWnd, rcCap, capParam);
    
    // 更新屏幕共享编码参数
    m_lpAREngine->updateScreenCaptureParameters(capParam);
    
    // 更新屏幕共享区域
    m_lpAREngine->updateScreenCaptureRegion(screenRegion);
    
    // 设置屏幕共享内容类型
    m_lpAREngine->setScreenCaptureContentHint(contentHint);
    
    // 停止屏幕共享
    m_lpAREngine->stopScreenCapture();
    

API 参考

开发注意事项

  • 视频共享编码属性 ScreenCaptureParameters 类中各参数的设置可能会影响计费。如果你将 dimensions 参数设为默认值,则 anyRTC 使用 1920 x 1080 进行计费。
  • 屏幕共享的媒体流的用户 ID 默认为 "share666",单个频道中只能有一个共享通道。单个频道支持多个共享的话,需要设定屏幕共享的 ID,请在调用开始共享 API 前使用私有方法:
m_lpAREngine->setParameters("{\"Cmd\":\"SetScreenCastUId\", \"UId\": \"screen888\"}");
  • 在 Windows 平台上进行屏幕共享时,如果共享的是 QQ 聊天窗口会导致共享窗口黑屏。