├── .github ├── ISSUE_TEMPLATE │ ├── feature-request.md │ └── report-an-issue.md ├── actions │ ├── download_cppsdk │ │ ├── bash │ │ │ ├── action.yml │ │ │ └── download_cppsdk.sh │ │ └── powershell │ │ │ ├── action.yml │ │ │ └── download_cppsdk.ps1 │ ├── notarise │ │ └── mac │ │ │ └── action.yml │ ├── sign │ │ ├── mac │ │ │ └── action.yml │ │ ├── sign.py │ │ └── win │ │ │ └── action.yml │ └── upload_assets │ │ ├── upload_release_asset.ps1 │ │ └── upload_release_asset.sh └── workflows │ ├── build.yml │ └── deploy-to-github-pages.yml ├── .gitignore ├── DolbyIO ├── .clang-format ├── Config │ ├── FilterPlugin.ini │ ├── FilterPluginAndroid.ini │ ├── FilterPluginLinux.ini │ ├── FilterPluginMac.ini │ └── FilterPluginWin64.ini ├── Content │ ├── BP_DolbyIOGameInstanceSample.uasset │ ├── BP_DolbyIOScreensharePlane.uasset │ ├── BP_DolbyIOScreensharePreviewPlane.uasset │ ├── BP_DolbyIOSingleVideoPlane.uasset │ ├── BP_DolbyIOStarter.uasset │ ├── BP_DolbyIOVideoPlaneSpawner.uasset │ ├── BP_DolbyIOVideoPreviewPlane.uasset │ ├── M_DolbyIOVideo.uasset │ ├── VideoSamples │ │ ├── BP_DolbyIOGenericVideoPlane.uasset │ │ ├── BP_DolbyIOScreensharePlane.uasset │ │ ├── BP_DolbyIOScreensharePreviewPlane.uasset │ │ ├── BP_DolbyIOSingleVideoPlane.uasset │ │ ├── BP_DolbyIOVideoPlaneSpawner.uasset │ │ ├── BP_DolbyIOVideoPreviewPlane.uasset │ │ └── M_DolbyIOVideo.uasset │ ├── W_DolbyIOSampleMenu.uasset │ └── WidgetSamples │ │ ├── W_DolbyIOSampleAudioControls.uasset │ │ ├── W_DolbyIOSampleButton.uasset │ │ ├── W_DolbyIOSampleCombobox.uasset │ │ ├── W_DolbyIOSampleConferenceControls.uasset │ │ ├── W_DolbyIOSampleDeviceControls.uasset │ │ ├── W_DolbyIOSampleMenu.uasset │ │ └── W_DolbyIOSampleScreenshareControls.uasset ├── DolbyIO.uplugin ├── Resources │ └── Icon128.png └── Source │ ├── DolbyIO.Build.cs │ ├── DolbyIO_UPL.xml │ ├── Private │ ├── DolbyIOModule.cpp │ ├── Subsystem │ │ ├── DolbyIOAudio.cpp │ │ ├── DolbyIOConference.cpp │ │ ├── DolbyIODevices.cpp │ │ ├── DolbyIODevices.h │ │ ├── DolbyIOInitialization.cpp │ │ ├── DolbyIOScreenshare.cpp │ │ ├── DolbyIOTransforms.cpp │ │ ├── DolbyIOVideo.cpp │ │ └── DolbyIOVideoTracks.cpp │ ├── Utils │ │ ├── DolbyIOAuthentication.cpp │ │ ├── DolbyIOBroadcastEvent.h │ │ ├── DolbyIOConversions.cpp │ │ ├── DolbyIOConversions.h │ │ ├── DolbyIOCppSdk.h │ │ ├── DolbyIOErrorHandler.cpp │ │ ├── DolbyIOErrorHandler.h │ │ └── DolbyIOLogging.h │ └── Video │ │ ├── DolbyIOVideoFrameHandler.h │ │ ├── DolbyIOVideoProcessingFrameHandler.h │ │ ├── DolbyIOVideoSink.cpp │ │ ├── DolbyIOVideoSink.h │ │ ├── DolbyIOVideoTexture.cpp │ │ └── DolbyIOVideoTexture.h │ └── Public │ ├── DolbyIO.h │ ├── DolbyIOAuthentication.h │ ├── DolbyIOBlueprints.h │ ├── DolbyIOCppSdkFwd.h │ └── DolbyIOTypes.h ├── LICENSE ├── README.md ├── docs ├── .gitignore ├── babel.config.js ├── docs │ ├── Intro.md │ ├── blueprints │ │ ├── _category_.json │ │ ├── events.md │ │ ├── functions.md │ │ ├── img │ │ │ ├── docsVersionDropdown.png │ │ │ └── localeDropdown.png │ │ └── types.mdx │ └── tutorial │ │ ├── _category_.json │ │ ├── android.md │ │ ├── camera-preview.md │ │ ├── common-setup.md │ │ ├── cpp.md │ │ ├── device-management.md │ │ ├── first-conference.md │ │ ├── game-instance.md │ │ ├── installation.md │ │ ├── multiple-games.md │ │ ├── obtain-permissions.md │ │ ├── remote-screenshare.md │ │ ├── remote-video.md │ │ └── screenshare-preview.md ├── docusaurus.config.js ├── package-lock.json ├── package.json ├── sidebars.js ├── src │ ├── components │ │ ├── HomepageFeatures │ │ │ ├── index.tsx │ │ │ └── styles.module.css │ │ └── VoiceFontsTable.js │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.module.css │ │ └── index.tsx ├── static │ ├── .nojekyll │ └── img │ │ ├── camera-preview-combobox.png │ │ ├── camera-preview-eg.png │ │ ├── camera-preview-selection.png │ │ ├── common-setup-connect.png │ │ ├── device-management-comboboxes.png │ │ ├── device-management-follow.png │ │ ├── device-management-selection.png │ │ ├── favicon.ico │ │ ├── first-conf-demo.png │ │ ├── first-conf-get-token-from-url.png │ │ ├── first-conf-get-token-using-key-secret.png │ │ ├── first-conf-observer-component.png │ │ ├── first-conf-set-token.png │ │ ├── game-instance-eg.png │ │ ├── game-instance-level-eg.png │ │ ├── game-instance-wrong.png │ │ ├── game-instance-wrong2.png │ │ ├── generated │ │ ├── DolbyIOBlueprintFunctionLibrary │ │ │ └── img │ │ │ │ ├── nd_img_BindMaterial.png │ │ │ │ ├── nd_img_BroadcastMessage.png │ │ │ │ ├── nd_img_ChangeScreenshareParameters.png │ │ │ │ ├── nd_img_GetParticipants.png │ │ │ │ ├── nd_img_GetTexture.png │ │ │ │ ├── nd_img_MuteInput.png │ │ │ │ ├── nd_img_MuteOutput.png │ │ │ │ ├── nd_img_MuteParticipant.png │ │ │ │ ├── nd_img_SendMessage.png │ │ │ │ ├── nd_img_SetAudioCaptureMode.png │ │ │ │ ├── nd_img_SetAudioInputDevice.png │ │ │ │ ├── nd_img_SetAudioOutputDevice.png │ │ │ │ ├── nd_img_SetLocalPlayerLocation.png │ │ │ │ ├── nd_img_SetLocalPlayerRotation.png │ │ │ │ ├── nd_img_SetLogSettings.png │ │ │ │ ├── nd_img_SetRemotePlayerLocation.png │ │ │ │ ├── nd_img_SetSpatialEnvironmentScale.png │ │ │ │ ├── nd_img_UnbindMaterial.png │ │ │ │ ├── nd_img_UnmuteInput.png │ │ │ │ ├── nd_img_UnmuteOutput.png │ │ │ │ ├── nd_img_UnmuteParticipant.png │ │ │ │ └── nd_img_UpdateUserMetadata.png │ │ ├── DolbyIOConnect │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIODemoConference │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIODisableVideo │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIODisconnect │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOEnableVideo │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOGetAudioInputDevices │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOGetAudioOutputDevices │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOGetCurrentAudioInputDevice │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOGetCurrentAudioOutputDevice │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOGetCurrentScreenshareSource │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOGetCurrentVideoDevice │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOGetScreenshareSources │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOGetTokenFromURL │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOGetVideoDevices │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOSetToken │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOStartScreenshare │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── DolbyIOStopScreenshare │ │ │ └── img │ │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ └── GetDolbyIOToken │ │ │ └── img │ │ │ └── nd_img_UK2Node_AsyncAction.png │ │ ├── logo-white.svg │ │ ├── logo.svg │ │ ├── multiple-games.png │ │ ├── participant-status-changes.png │ │ ├── remote-screenshare-eg.png │ │ ├── remote-video-eg.png │ │ ├── screenshare-preview-combobox.png │ │ ├── screenshare-preview-eg.png │ │ ├── screenshare-preview-result.png │ │ ├── screenshare-preview-start.png │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ ├── undraw_docusaurus_tree.svg │ │ ├── video-plane-cs.png │ │ └── video-plane-result.png └── tsconfig.json └── scripts └── android.sh /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: GaryMakinDolby 7 | --- 8 | 9 | **Describe the feature request** 10 | 11 | [Please describe what you expect from this feature.] 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/report-an-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Use this template to report an issue. 4 | title: '' 5 | labels: bug 6 | assignees: GaryMakinDolby 7 | --- 8 | 9 | **Describe the bug** 10 | 11 | [A clear and concise description of what the bug is.] 12 | 13 | **Expected Behavior** 14 | 15 | [Describe the expected behavior of the feature.] 16 | 17 | **Minimalistic code (recommended)** 18 | 19 | [Please provide a link to a repository showing specifically the issue. It should only have the minimal footprint of your own implementation - something which does not requires any NDA.] 20 | 21 | **Specifications** 22 | 23 | - OS: [e.g. Windows, macOS, ...] 24 | - Version: 25 | - _for each libraries : name -> version_ 26 | - [e.g. comms-sdk-unreal 1.0.0] 27 | - [...] 28 | -------------------------------------------------------------------------------- /.github/actions/download_cppsdk/bash/action.yml: -------------------------------------------------------------------------------- 1 | name: 'CppSDKReleaseAssetDownloader' 2 | description: 'Download specific C++ SDK release asset.' 3 | inputs: 4 | url: 5 | description: 'C++ SDK release URL.' 6 | required: true 7 | tag: 8 | description: 'Release tag of C++ SDK release.' 9 | required: true 10 | asset_suffix: 11 | description: 'The suffix of the C++ SDK asset defining the platform.' 12 | required: true 13 | runs: 14 | using: 'composite' 15 | steps: 16 | - name: Download C++ MacOS 17 | run: | 18 | export INPUT_URL=${{ inputs.url }} 19 | export INPUT_TAG=${{ inputs.tag }} 20 | export INPUT_ASSET_NAME=cppsdk-${{ inputs.tag }}-${{ inputs.asset_suffix }} 21 | ./.github/actions/download_cppsdk/bash/download_cppsdk.sh 22 | shell: bash 23 | -------------------------------------------------------------------------------- /.github/actions/download_cppsdk/bash/download_cppsdk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | curl -L ${INPUT_URL}/${INPUT_TAG}/${INPUT_ASSET_NAME} > ${GITHUB_WORKSPACE}/${INPUT_ASSET_NAME} \ 5 | && unzip -q ${GITHUB_WORKSPACE}/${INPUT_ASSET_NAME} -d ${GITHUB_WORKSPACE}/${PLUGIN_SOURCE_DIR} \ 6 | && rm ${GITHUB_WORKSPACE}/${INPUT_ASSET_NAME} 7 | -------------------------------------------------------------------------------- /.github/actions/download_cppsdk/powershell/action.yml: -------------------------------------------------------------------------------- 1 | name: 'CppSDKReleaseAssetDownloader' 2 | description: 'Download specific C++ SDK release asset.' 3 | inputs: 4 | url: 5 | description: 'C++ SDK release URL.' 6 | required: true 7 | tag: 8 | description: 'Release tag of C++ SDK release.' 9 | required: true 10 | asset_suffix: 11 | description: 'The suffix of the C++ SDK asset defining the platform.' 12 | required: true 13 | runs: 14 | using: 'composite' 15 | steps: 16 | - name: Download C++ Windows 17 | run: | 18 | $Env:INPUT_URL = "${{ inputs.url }}" 19 | $Env:INPUT_TAG = "${{ inputs.tag }}" 20 | $Env:INPUT_ASSET_NAME = "cppsdk-${{ inputs.tag }}-${{ inputs.asset_suffix }}" 21 | ./.github/actions/download_cppsdk/powershell/download_cppsdk.ps1 22 | shell: powershell 23 | -------------------------------------------------------------------------------- /.github/actions/download_cppsdk/powershell/download_cppsdk.ps1: -------------------------------------------------------------------------------- 1 | Write-Output "Download asset" 2 | curl -Uri ${Env:INPUT_URL}/${Env:INPUT_TAG}/${Env:INPUT_ASSET_NAME} -UseBasicParsing -Out ${Env:GITHUB_WORKSPACE}/${Env:INPUT_ASSET_NAME} 3 | Expand-Archive ${Env:GITHUB_WORKSPACE}/${Env:INPUT_ASSET_NAME} -DestinationPath ${Env:GITHUB_WORKSPACE}/${Env:PLUGIN_SOURCE_DIR} 4 | rm ${Env:GITHUB_WORKSPACE}/${Env:INPUT_ASSET_NAME} 5 | -------------------------------------------------------------------------------- /.github/actions/notarise/mac/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Notarise' 2 | description: 'Notarise Unreal Plugin ' 3 | inputs: 4 | catalog_path: 5 | description: 'Path to zip which going to be notarise' 6 | required: true 7 | file: 8 | description: 'Name of zip file which going to be notarise' 9 | required: true 10 | runs: 11 | using: 'composite' 12 | steps: 13 | - name: Notarise Unreal Plugin 14 | run: | 15 | export KEYCHAIN_PATH="/Users/dolbyio/Library/Keychains/dolbyio.keychain-db" 16 | security default-keychain -s ${KEYCHAIN_PATH} 17 | export INPUT_NOTARISATION_FILE=${{ inputs.file }} 18 | echo "entering ${{ inputs.catalog_path }}" 19 | cd ${{ inputs.catalog_path }} 20 | security unlock-keychain -p ${DOLBYIO_KEYCHAIN_PASSWORD} ${KEYCHAIN_PATH} 21 | echo "submitting ${INPUT_NOTARISATION_FILE}" 22 | if ! $(security show-keychain-info ${KEYCHAIN_PATH} 2> /dev/null); then 23 | security unlock-keychain -p ${DOLBYIO_KEYCHAIN_PASSWORD} ${KEYCHAIN_PATH}; 24 | fi 25 | xcrun notarytool submit ${INPUT_NOTARISATION_FILE} --keychain-profile unreal-sdk-notarization-profile --keychain ${KEYCHAIN_PATH} --wait > ${{ github.workspace }}/notarylog.json 26 | export NOTARIZATION_ID=$(awk '$1=="id:"{print $2}' ${{ github.workspace }}/notarylog.json | head -n 1) 27 | xcrun notarytool log ${NOTARIZATION_ID} --keychain-profile unreal-sdk-notarization-profile ${{ github.workspace }}/notarylog.json 28 | export notarization_status=$(cat ${{ github.workspace }}/notarylog.json | jq ".issues") 29 | if [[ ${notarization_status} == "null" ]]; then echo "Success"; else exit 1; fi 30 | shell: bash 31 | -------------------------------------------------------------------------------- /.github/actions/sign/mac/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Sign' 2 | description: 'Sign Unreal Plugin libs' 3 | inputs: 4 | path: 5 | description: 'Path to dir with objects which going to be sign' 6 | required: true 7 | platform: 8 | description: 'Define build platform [macos|windows]' 9 | required: true 10 | runs: 11 | using: 'composite' 12 | steps: 13 | - name: Sign Unreal Plugin 14 | run: | 15 | export INPUT_SIGN_PATH=${{ inputs.path }} 16 | export INPUT_PLATFORM=${{ inputs.platform }} 17 | security unlock-keychain -p ${DOLBYIO_KEYCHAIN_PASSWORD} ~/Library/Keychains/dolbyio.keychain-db 18 | python3 ./.github/actions/sign/sign.py 19 | shell: bash 20 | -------------------------------------------------------------------------------- /.github/actions/sign/sign.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import base64 4 | 5 | 6 | class Sign(): 7 | def __init__(self, root_app): 8 | self.timestamp_servers = ['http://timestamp.comodoca.com/authenticode', 9 | 'http://timestamp.verisign.com/scripts/timestamp.dll', 10 | 'http://timestamp.globalsign.com/scripts/timstamp.dll', 11 | 'http://timestamp.globalsign.com/tsa/r6advanced1', 12 | 'http://www.startssl.com/timestamp'] 13 | self.root_app = root_app 14 | self.file_ext_win = ['.dll', '.exe'] 15 | self.dirs_win = [] 16 | self.file_ext_darwin = ['.dylib'] 17 | self.dir_darwin = ".app" 18 | 19 | def _sign_target(self, target, sign_cmd): 20 | 21 | print(f"Sign {target}") 22 | ret = os.system(f"{sign_cmd} \"{target}\"") 23 | 24 | return ret 25 | 26 | def _verify_target(self, target, verify_cmd): 27 | print(f"Verify {target}") 28 | ret = os.system(f"{verify_cmd} \"{target}\"") 29 | 30 | return ret 31 | 32 | def sign_macos(self): 33 | 34 | # Sign libs 35 | targets = list() 36 | 37 | # Define codesign cmd 38 | codesign_verify_cmd = "codesign --verify --deep --verbose=4" 39 | codesign_cmd = "codesign --force --strict --timestamp --sign 'Developer ID Application: VOXEET INC. (B55NRA8BRW)'" 40 | 41 | # collect targets 42 | for root, dirs, files in os.walk(self.root_app): 43 | for file_ in files: 44 | if os.path.splitext(file_)[-1] in self.file_ext_darwin: 45 | targets += [os.path.join(root, file_)] 46 | 47 | targets_sorted = sorted(targets, key=lambda x: x.count(os.sep), reverse=True) 48 | 49 | for target in targets: 50 | ret_s = self._sign_target(target, codesign_cmd) 51 | 52 | if ret_s != 0: 53 | print(f"ERROR: {codesign_cmd} returned {ret_s} during signing {target}.") 54 | 55 | ret_v = self._verify_target(target, codesign_verify_cmd) 56 | 57 | if ret_v !=0: 58 | raise IOError(f"ERROR: {codesign_verify_cmd} returned {ret_v} during verification of {target}") 59 | 60 | print(f"{len(targets)} target(s) signed") 61 | 62 | def sign_windows(self): 63 | targets = list() 64 | passwd = os.environ["WINDOWS_CERTIFICATE_PASSWORD"] 65 | 66 | # signtool from Windows Kits 10 was added manually to env path on the Windows machine 67 | 68 | # collect targets 69 | for root, dirs, files in os.walk(self.root_app): 70 | for file_ in files: 71 | if os.path.splitext(file_)[-1] in self.file_ext_win: 72 | abs_file_path = os.path.join(root, file_) 73 | targets += [abs_file_path] 74 | 75 | # sign targets 76 | for target in targets: 77 | 78 | # Sign target with corresponding timestamp server 79 | for timestamp_server in self.timestamp_servers: 80 | print(f"Attempt for timestamp server: {timestamp_server}") 81 | signtool_cmd = f"signtool sign /fd SHA256 /f C:\Cert\Dolby.pfx /p {passwd} /t {timestamp_server}" 82 | ret_s = self._sign_target(target, signtool_cmd) 83 | 84 | if ret_s != 0: 85 | print(f"ERROR: {signtool_cmd} returned {ret_s} during signing {target}. Checking another timestamp server.") 86 | else: 87 | print(f"Signed: {target}") 88 | break 89 | 90 | # Verify target 91 | signtool_verify_cmd = 'signtool verify /pa' 92 | ret_v = self._verify_target(target, signtool_verify_cmd) 93 | 94 | if ret_v != 0: 95 | raise IOError(f"ERROR: {signtool_verify_cmd} returned {ret_v} during verification of {target}.") 96 | 97 | print(f"{len(targets)} target(s) signed") 98 | 99 | 100 | if __name__ == '__main__': 101 | getattr(Sign(os.environ["INPUT_SIGN_PATH"]), 102 | 'sign_{}'.format(os.environ["INPUT_PLATFORM"]) 103 | )() 104 | -------------------------------------------------------------------------------- /.github/actions/sign/win/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Sign' 2 | description: 'Sign Unreal Plugin libs' 3 | inputs: 4 | path: 5 | description: 'Path to dir with objects which going to be sign' 6 | required: true 7 | platform: 8 | description: 'Define build platform [macos|windows]' 9 | required: true 10 | runs: 11 | using: 'composite' 12 | steps: 13 | - name: Sign Unreal Plugin 14 | run: | 15 | $env:INPUT_SIGN_PATH = "${{ inputs.path }}" 16 | $env:INPUT_PLATFORM = "${{ inputs.platform }}" 17 | $env:WINDOWS_CERTIFICATE_PASSWORD = "$env:WINDOWS_CERTIFICATE_PASSWORD" 18 | python ./.github/actions/sign/sign.py 19 | shell: powershell 20 | -------------------------------------------------------------------------------- /.github/actions/upload_assets/upload_release_asset.ps1: -------------------------------------------------------------------------------- 1 | param([string]$File = "file.zip") 2 | $id_of_release=( C:\ProgramData\chocolatey\bin\curl.exe -s -L ` 3 | -H "Accept: application/vnd.github+json" ` 4 | -H "Authorization: Bearer ${env:GH_TOKEN}" ` 5 | -H "X-GitHub-Api-Version: 2022-11-28" ` 6 | https://api.github.com/repos/DolbyIO/comms-sdk-unreal/releases/tags/${env:GITHUB_REF_NAME} | C:\ProgramData\chocolatey\bin\jq.exe ".id") 7 | 8 | echo "upload file $File for tag: ${env:GITHUB_REF_NAME} for ID: ${id_of_release}" 9 | 10 | C:\ProgramData\chocolatey\bin\curl.exe -L -X POST ` 11 | -H "Accept: application/vnd.github+json" ` 12 | -H "Authorization: token ${Env:GH_TOKEN}" ` 13 | -H "X-GitHub-Api-Version: 2022-11-28" ` 14 | -H "Content-Type: application/octet-stream" ` 15 | --data-binary "@$File" https://uploads.github.com/repos/DolbyIO/comms-sdk-unreal/releases/${id_of_release}/assets?name=$File -------------------------------------------------------------------------------- /.github/actions/upload_assets/upload_release_asset.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ID_OF_RELEASE=$(curl --fail -s -L \ 3 | -H "Accept: application/vnd.github+json" \ 4 | -H "Authorization: Bearer ${GH_TOKEN}"\ 5 | -H "X-GitHub-Api-Version: 2022-11-28" \ 6 | https://api.github.com/repos/DolbyIO/comms-sdk-unreal/releases/tags/${GITHUB_REF_NAME} | jq ".id") 7 | 8 | echo "upload file $1 for tag: ${GITHUB_REF_NAME} for ID: ${ID_OF_RELEASE}" 9 | curl -L \ 10 | -X POST \ 11 | -H "Accept: application/vnd.github+json" \ 12 | -H "Authorization: token ${GH_TOKEN}"\ 13 | -H "X-GitHub-Api-Version: 2022-11-28" \ 14 | -H "Content-Type: application/octet-stream" \ 15 | https://uploads.github.com/repos/DolbyIO/comms-sdk-unreal/releases/${ID_OF_RELEASE}/assets?name=${1}\ 16 | --data-binary "@${1}" -------------------------------------------------------------------------------- /.github/workflows/deploy-to-github-pages.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | # Allow one concurrent deployment 9 | concurrency: 10 | group: deploy-to-github-pages 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | deploy: 15 | # Grant GITHUB_TOKEN the permissions required to make a Pages deployment 16 | permissions: 17 | contents: read 18 | pages: write # to deploy to Pages 19 | id-token: write # to verify the deployment originates from an appropriate source 20 | 21 | # Deploy to the github-pages environment 22 | environment: 23 | name: github-pages 24 | url: ${{ steps.deployment.outputs.page_url }} 25 | 26 | runs-on: ubuntu-latest 27 | steps: 28 | - name: Checkout 🛎️ 29 | uses: actions/checkout@v3 30 | with: 31 | persist-credentials: false 32 | 33 | - name: Install and Build 🔧 34 | run: | 35 | cd docs 36 | npm install 37 | npm run build 38 | 39 | - name: Setup GitHub Pages 🛠 40 | uses: actions/configure-pages@v2 41 | 42 | - name: Upload artifact ⬆️ 43 | uses: actions/upload-pages-artifact@v1 44 | with: 45 | path: docs/build 46 | 47 | - name: Deploy to GitHub Pages 🚀 48 | id: deployment 49 | uses: actions/deploy-pages@v1 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store* 2 | .vs/ 3 | Binaries/ 4 | Intermediate/ 5 | *sdk-release* 6 | -------------------------------------------------------------------------------- /DolbyIO/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Microsoft 2 | AccessModifierOffset: -4 3 | AlignEscapedNewlines: Left 4 | AllowShortFunctionsOnASingleLine: Empty 5 | BraceWrapping: 6 | BeforeLambdaBody: true 7 | FixNamespaceComments: false 8 | IndentCaseLabels: true 9 | NamespaceIndentation: All 10 | PointerAlignment: Left 11 | UseTab: ForIndentation 12 | -------------------------------------------------------------------------------- /DolbyIO/Config/FilterPlugin.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and 3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. 4 | ; 5 | ; Examples: 6 | ; /README.txt 7 | ; /Extras/... 8 | ; /Binaries/ThirdParty/*.dll 9 | ; MacOS 10 | /sdk-release/include/... 11 | /sdk-release/lib/libcac_dvdnr.dylib 12 | /sdk-release/lib/libdlb_vidseg_c_api.dylib 13 | /sdk-release/lib/libdolbyio_comms_media.dylib 14 | /sdk-release/lib/libdolbyio_comms_sdk.dylib 15 | /sdk-release/lib/libdvclient.dylib 16 | /sdk-release/lib/libdvdnr.dylib 17 | /sdk-release/lib/libopencv_core.4.5.dylib 18 | /sdk-release/lib/libopencv_imgcodecs.4.5.dylib 19 | /sdk-release/lib/libopencv_imgproc.4.5.dylib 20 | /sdk-release/lib/libvideo_processor.dylib 21 | /sdk-release/lib/model.dnr 22 | /sdk-release/lib/video_processor.model 23 | ; Linux 24 | /sdk-release-ubuntu-20.04-clang10-libc++10/include/... 25 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libavcodec.so.59 26 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libavformat.so.59 27 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libavutil.so.57 28 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libdvdnr.so 29 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libdolbyio_comms_media.so 30 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libdolbyio_comms_sdk.so 31 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libdvclient.so 32 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/model.dnr 33 | ; Windows 34 | /sdk-release/include/... 35 | /sdk-release/bin/*.dll 36 | /sdk-release/bin/model.dnr 37 | /sdk-release/bin/video_processor.model 38 | /sdk-release/lib/dolbyio_comms_media.lib 39 | /sdk-release/lib/dolbyio_comms_sdk.lib 40 | /sdk-release/lib/video_processor.lib 41 | ; Android 42 | /sdk-release-android/... 43 | -------------------------------------------------------------------------------- /DolbyIO/Config/FilterPluginAndroid.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | /sdk-release-android/... 3 | -------------------------------------------------------------------------------- /DolbyIO/Config/FilterPluginLinux.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and 3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. 4 | ; 5 | ; Examples: 6 | ; /README.txt 7 | ; /Extras/... 8 | ; /Binaries/ThirdParty/*.dll 9 | /sdk-release-ubuntu-20.04-clang10-libc++10/include/... 10 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libavcodec.so.59 11 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libavformat.so.59 12 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libavutil.so.57 13 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libdvdnr.so 14 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libdolbyio_comms_media.so 15 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libdolbyio_comms_sdk.so 16 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/libdvclient.so 17 | /sdk-release-ubuntu-20.04-clang10-libc++10/lib/model.dnr 18 | -------------------------------------------------------------------------------- /DolbyIO/Config/FilterPluginMac.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and 3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. 4 | ; 5 | ; Examples: 6 | ; /README.txt 7 | ; /Extras/... 8 | ; /Binaries/ThirdParty/*.dll 9 | /sdk-release/include/... 10 | /sdk-release/lib/libcac_dvdnr.dylib 11 | /sdk-release/lib/libdlb_vidseg_c_api.dylib 12 | /sdk-release/lib/libdolbyio_comms_media.dylib 13 | /sdk-release/lib/libdolbyio_comms_sdk.dylib 14 | /sdk-release/lib/libdvclient.dylib 15 | /sdk-release/lib/libdvdnr.dylib 16 | /sdk-release/lib/libopencv_core.4.5.dylib 17 | /sdk-release/lib/libopencv_imgcodecs.4.5.dylib 18 | /sdk-release/lib/libopencv_imgproc.4.5.dylib 19 | /sdk-release/lib/libvideo_processor.dylib 20 | /sdk-release/lib/model.dnr 21 | /sdk-release/lib/video_processor.model 22 | -------------------------------------------------------------------------------- /DolbyIO/Config/FilterPluginWin64.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and 3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively. 4 | ; 5 | ; Examples: 6 | ; /README.txt 7 | ; /Extras/... 8 | ; /Binaries/ThirdParty/*.dll 9 | /sdk-release/include/... 10 | /sdk-release/bin/*.dll 11 | /sdk-release/bin/model.dnr 12 | /sdk-release/bin/video_processor.model 13 | /sdk-release/lib/dolbyio_comms_media.lib 14 | /sdk-release/lib/dolbyio_comms_sdk.lib 15 | /sdk-release/lib/video_processor.lib 16 | -------------------------------------------------------------------------------- /DolbyIO/Content/BP_DolbyIOGameInstanceSample.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/BP_DolbyIOGameInstanceSample.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/BP_DolbyIOScreensharePlane.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/BP_DolbyIOScreensharePlane.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/BP_DolbyIOScreensharePreviewPlane.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/BP_DolbyIOScreensharePreviewPlane.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/BP_DolbyIOSingleVideoPlane.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/BP_DolbyIOSingleVideoPlane.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/BP_DolbyIOStarter.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/BP_DolbyIOStarter.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/BP_DolbyIOVideoPlaneSpawner.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/BP_DolbyIOVideoPlaneSpawner.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/BP_DolbyIOVideoPreviewPlane.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/BP_DolbyIOVideoPreviewPlane.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/M_DolbyIOVideo.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/M_DolbyIOVideo.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/VideoSamples/BP_DolbyIOGenericVideoPlane.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/VideoSamples/BP_DolbyIOGenericVideoPlane.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/VideoSamples/BP_DolbyIOScreensharePlane.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/VideoSamples/BP_DolbyIOScreensharePlane.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/VideoSamples/BP_DolbyIOScreensharePreviewPlane.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/VideoSamples/BP_DolbyIOScreensharePreviewPlane.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/VideoSamples/BP_DolbyIOSingleVideoPlane.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/VideoSamples/BP_DolbyIOSingleVideoPlane.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/VideoSamples/BP_DolbyIOVideoPlaneSpawner.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/VideoSamples/BP_DolbyIOVideoPlaneSpawner.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/VideoSamples/BP_DolbyIOVideoPreviewPlane.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/VideoSamples/BP_DolbyIOVideoPreviewPlane.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/VideoSamples/M_DolbyIOVideo.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/VideoSamples/M_DolbyIOVideo.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/W_DolbyIOSampleMenu.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/W_DolbyIOSampleMenu.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/WidgetSamples/W_DolbyIOSampleAudioControls.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/WidgetSamples/W_DolbyIOSampleAudioControls.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/WidgetSamples/W_DolbyIOSampleButton.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/WidgetSamples/W_DolbyIOSampleButton.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/WidgetSamples/W_DolbyIOSampleCombobox.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/WidgetSamples/W_DolbyIOSampleCombobox.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/WidgetSamples/W_DolbyIOSampleConferenceControls.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/WidgetSamples/W_DolbyIOSampleConferenceControls.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/WidgetSamples/W_DolbyIOSampleDeviceControls.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/WidgetSamples/W_DolbyIOSampleDeviceControls.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/WidgetSamples/W_DolbyIOSampleMenu.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/WidgetSamples/W_DolbyIOSampleMenu.uasset -------------------------------------------------------------------------------- /DolbyIO/Content/WidgetSamples/W_DolbyIOSampleScreenshareControls.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Content/WidgetSamples/W_DolbyIOSampleScreenshareControls.uasset -------------------------------------------------------------------------------- /DolbyIO/DolbyIO.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.2.4", 5 | "FriendlyName": "Dolby.io Virtual Worlds", 6 | "Description": "Plugin integrating Dolby.io Communications.", 7 | "Category": "Communications", 8 | "CreatedBy": "Dolby Laboratories", 9 | "CreatedByURL": "https://dolby.io", 10 | "DocsURL": "https://api-references.dolby.io/comms-sdk-unreal/docs/intro", 11 | "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/fa7c269078dc456e886c44db5d372372", 12 | "SupportURL": "https://github.com/DolbyIO/comms-sdk-unreal/issues", 13 | "EnabledByDefault": true, 14 | "CanContainContent": true, 15 | "IsBetaVersion": false, 16 | "Installed": false, 17 | "Modules": [ 18 | { 19 | "Name": "DolbyIO", 20 | "Type": "Runtime", 21 | "LoadingPhase": "PreDefault", 22 | "WhitelistPlatforms": [ "Android", "Linux", "Mac", "Win64" ] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /DolbyIO/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/DolbyIO/Resources/Icon128.png -------------------------------------------------------------------------------- /DolbyIO/Source/DolbyIO.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | using System.IO; 4 | using UnrealBuildTool; 5 | 6 | public class DolbyIO : ModuleRules 7 | { 8 | public DolbyIO(ReadOnlyTargetRules Target) : base(Target) 9 | { 10 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 11 | 12 | CppStandard = CppStandardVersion.Cpp17; 13 | bEnableExceptions = true; 14 | 15 | PublicDependencyModuleNames.AddRange( 16 | new string[] { "Core", "CoreUObject", "Engine", "HTTP", "Json", "Projects", "RenderCore", "RHI" }); 17 | 18 | string ReleaseDir = "sdk-release"; 19 | if (Target.Platform == UnrealTargetPlatform.Linux) 20 | { 21 | ReleaseDir += "-ubuntu-20.04-clang10-libc++10"; 22 | } 23 | else if (Target.Platform == UnrealTargetPlatform.Android) 24 | { 25 | ReleaseDir += "-android"; 26 | } 27 | string SdkDir = Path.Combine("$(PluginDir)", ReleaseDir); 28 | PublicIncludePaths.Add(Path.Combine(SdkDir, "include")); 29 | string LibDir = Path.Combine(SdkDir, "lib"); 30 | 31 | if (Target.Platform == UnrealTargetPlatform.Win64) 32 | { 33 | PublicAdditionalLibraries.AddRange(new string[] { 34 | Path.Combine(LibDir, "dolbyio_comms_media.lib"), 35 | Path.Combine(LibDir, "dolbyio_comms_sdk.lib"), 36 | Path.Combine(LibDir, "video_processor.lib") 37 | }); 38 | 39 | string[] Dlls = new string[] { "avutil-57.dll", 40 | "avcodec-59.dll", 41 | "avformat-59.dll", 42 | "dvclient.dll", 43 | "dolbyio_comms_media.dll", 44 | "dolbyio_comms_sdk.dll", 45 | "opencv_core451.dll", 46 | "opencv_imgproc451.dll", 47 | "opencv_imgcodecs451.dll", 48 | "dvdnr.dll", 49 | "dlb_vidseg_c_api.dll", 50 | "video_processor.dll" }; 51 | PublicDelayLoadDLLs.AddRange(Dlls); 52 | 53 | string BinDir = Path.Combine(SdkDir, "bin"); 54 | foreach (string Dll in Dlls) 55 | { 56 | RuntimeDependencies.Add(Path.Combine(BinDir, Dll)); 57 | } 58 | RuntimeDependencies.Add(Path.Combine(BinDir, "model.dnr")); 59 | RuntimeDependencies.Add(Path.Combine(BinDir, "video_processor.model")); 60 | } 61 | else if (Target.Platform == UnrealTargetPlatform.Mac) 62 | { 63 | string[] Libs = new string[] { Path.Combine(LibDir, "libdolbyio_comms_media.dylib"), 64 | Path.Combine(LibDir, "libdolbyio_comms_sdk.dylib"), 65 | Path.Combine(LibDir, "libvideo_processor.dylib") }; 66 | PublicAdditionalLibraries.AddRange(Libs); 67 | PublicDelayLoadDLLs.AddRange(Libs); 68 | 69 | foreach (string Lib in Libs) 70 | { 71 | RuntimeDependencies.Add(Lib); 72 | } 73 | RuntimeDependencies.Add(Path.Combine(LibDir, "libdvclient.dylib")); 74 | RuntimeDependencies.Add(Path.Combine(LibDir, "libopencv_core.4.5.dylib")); 75 | RuntimeDependencies.Add(Path.Combine(LibDir, "libopencv_imgcodecs.4.5.dylib")); 76 | RuntimeDependencies.Add(Path.Combine(LibDir, "libopencv_imgproc.4.5.dylib")); 77 | RuntimeDependencies.Add(Path.Combine(LibDir, "libdvdnr.dylib")); 78 | RuntimeDependencies.Add(Path.Combine(LibDir, "libdlb_vidseg_c_api.dylib")); 79 | RuntimeDependencies.Add(Path.Combine(LibDir, "model.dnr")); 80 | RuntimeDependencies.Add(Path.Combine(LibDir, "video_processor.model")); 81 | } 82 | else if (Target.Platform == UnrealTargetPlatform.Linux) 83 | { 84 | string[] Libs = new string[] { Path.Combine(LibDir, "libavutil.so.57"), 85 | Path.Combine(LibDir, "libavcodec.so.59"), 86 | Path.Combine(LibDir, "libavformat.so.59"), 87 | Path.Combine(LibDir, "libdvclient.so"), 88 | Path.Combine(LibDir, "libdolbyio_comms_media.so"), 89 | Path.Combine(LibDir, "libdolbyio_comms_sdk.so") }; 90 | PublicAdditionalLibraries.AddRange(new string[] { 91 | Path.Combine(LibDir, "libdolbyio_comms_media.so"), 92 | Path.Combine(LibDir, "libdolbyio_comms_sdk.so"), 93 | }); 94 | PublicDelayLoadDLLs.AddRange(Libs); 95 | 96 | foreach (string Lib in Libs) 97 | { 98 | RuntimeDependencies.Add(Lib); 99 | } 100 | RuntimeDependencies.Add(Path.Combine(LibDir, "libdvdnr.so")); 101 | RuntimeDependencies.Add(Path.Combine(LibDir, "model.dnr")); 102 | } 103 | else if (Target.Platform == UnrealTargetPlatform.Android) 104 | { 105 | LibDir = Path.Combine(SdkDir, "libs", "android.arm64-v8a"); 106 | string[] Libs = new string[] { Path.Combine(LibDir, "libdolbyio_comms_media.so"), 107 | Path.Combine(LibDir, "libdolbyio_comms_sdk.so") }; 108 | PublicAdditionalLibraries.AddRange(Libs); 109 | 110 | AdditionalPropertiesForReceipt.Add( 111 | "AndroidPlugin", 112 | Path.Combine(Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath), "DolbyIO_UPL.xml")); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /DolbyIO/Source/DolbyIO_UPL.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | allprojects { 10 | repositories { 11 | flatDir { 12 | 13 | 14 | 15 | }}} 16 | 17 | 18 | 19 | 20 | dependencies { 21 | implementation name: 'comms-sdk-android-cppsdk-noprefab-2.7.0', ext: 'aar' 22 | implementation name: 'comms-sdk-android-cppsdk-shared-2.7.0', ext: 'aar' 23 | implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.7.20' 24 | } 25 | android { 26 | packagingOptions { 27 | pickFirst 'assets/model.dnr' 28 | } 29 | } 30 | 31 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/DolbyIOModule.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "Utils/DolbyIOCppSdk.h" 4 | #include "Utils/DolbyIOLogging.h" 5 | 6 | #include "HAL/PlatformProcess.h" 7 | #include "Interfaces/IPluginManager.h" 8 | #include "Misc/Paths.h" 9 | #include "Modules/ModuleManager.h" 10 | 11 | class FDolbyIOModule final : public IModuleInterface 12 | { 13 | using FDllHandle = void*; 14 | 15 | public: 16 | void StartupModule() override 17 | { 18 | FString BaseDir = 19 | FPaths::Combine(*IPluginManager::Get().FindPlugin("DolbyIO")->GetBaseDir(), TEXT("sdk-release")); 20 | #if PLATFORM_WINDOWS 21 | using namespace dolbyio::comms; 22 | app_allocator Allocator{ 23 | ::operator new, 24 | [](std::size_t Count, std::size_t Al) { return ::operator new(Count, static_cast(Al)); }, 25 | ::operator delete, 26 | [](void* Ptr, std::size_t Al) { ::operator delete(Ptr, static_cast(Al)); }}; 27 | // Add this here as I am not sure how Windows paths are interpreted (do I need the backslash) 28 | BaseDir = FPaths::Combine(BaseDir, TEXT("bin")); 29 | LoadDll(BaseDir, "avutil-57.dll"); 30 | LoadDll(BaseDir, "avcodec-59.dll"); 31 | LoadDll(BaseDir, "avformat-59.dll"); 32 | LoadDll(BaseDir, "dvclient.dll"); 33 | LoadDll(BaseDir, "dolbyio_comms_media.dll"); 34 | LoadDll(BaseDir, "dolbyio_comms_sdk.dll"); 35 | sdk::set_app_allocator(Allocator); 36 | LoadDll(BaseDir, "opencv_core451.dll"); 37 | LoadDll(BaseDir, "opencv_imgproc451.dll"); 38 | LoadDll(BaseDir, "opencv_imgcodecs451.dll"); 39 | LoadDll(BaseDir, "dvdnr.dll"); 40 | LoadDll(BaseDir, "dlb_vidseg_c_api.dll"); 41 | LoadDll(BaseDir, "video_processor.dll"); 42 | dolbyio::comms::plugin::video_processor::set_app_allocator(Allocator); 43 | #elif PLATFORM_MAC 44 | LoadDll(BaseDir, "lib/libdvclient.dylib"); 45 | LoadDll(BaseDir, "lib/libdolbyio_comms_media.dylib"); 46 | LoadDll(BaseDir, "lib/libdolbyio_comms_sdk.dylib"); 47 | LoadDll(BaseDir, "lib/libopencv_core.4.5.dylib"); 48 | LoadDll(BaseDir, "lib/libopencv_imgproc.4.5.dylib"); 49 | LoadDll(BaseDir, "lib/libopencv_imgcodecs.4.5.dylib"); 50 | LoadDll(BaseDir, "lib/libdlb_vidseg_c_api.dylib"); 51 | LoadDll(BaseDir, "lib/libdvdnr.dylib"); 52 | LoadDll(BaseDir, "lib/libvideo_processor.dylib"); 53 | #elif PLATFORM_LINUX 54 | BaseDir += "-ubuntu-20.04-clang10-libc++10"; 55 | LoadDll(BaseDir, "lib/libavutil.so.57"); 56 | LoadDll(BaseDir, "lib/libavcodec.so.59"); 57 | LoadDll(BaseDir, "lib/libavformat.so.59"); 58 | LoadDll(BaseDir, "lib/libdvclient.so"); 59 | LoadDll(BaseDir, "lib/libdolbyio_comms_media.so"); 60 | LoadDll(BaseDir, "lib/libdolbyio_comms_sdk.so"); 61 | #endif 62 | } 63 | 64 | void ShutdownModule() override 65 | { 66 | while (Dlls.Num()) 67 | { 68 | const FDll Dll = Dlls.Pop(); 69 | FPlatformProcess::FreeDllHandle(Dll.Handle); 70 | DLB_UE_LOG("Unloaded %s", *Dll.Name); 71 | } 72 | } 73 | 74 | private: 75 | void LoadDll(const FString& BaseDir, const FString& Dll) 76 | { 77 | const FString DllPath = FPaths::Combine(*BaseDir, *Dll); 78 | if (FDllHandle Handle = FPlatformProcess::GetDllHandle(*DllPath)) 79 | { 80 | DLB_UE_LOG("Loaded %s", *Dll); 81 | Dlls.Emplace(FDll{Handle, Dll}); 82 | } 83 | else 84 | { 85 | DLB_UE_LOG_BASE(Fatal, "Failed to load %s", *DllPath); 86 | } 87 | } 88 | 89 | struct FDll 90 | { 91 | FDllHandle Handle; 92 | FString Name; 93 | }; 94 | 95 | TArray Dlls; 96 | }; 97 | 98 | IMPLEMENT_MODULE(FDolbyIOModule, DolbyIO) 99 | DEFINE_LOG_CATEGORY(LogDolbyIO); 100 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Subsystem/DolbyIOAudio.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIO.h" 4 | 5 | #include "Utils/DolbyIOBroadcastEvent.h" 6 | #include "Utils/DolbyIOConversions.h" 7 | #include "Utils/DolbyIOErrorHandler.h" 8 | #include "Utils/DolbyIOLogging.h" 9 | 10 | using namespace dolbyio::comms; 11 | using namespace DolbyIO; 12 | 13 | void UDolbyIOSubsystem::SetSpatialEnvironment() 14 | { 15 | if (!IsConnectedAsActive() || !IsSpatialAudio()) 16 | { 17 | return; 18 | } 19 | 20 | // The SDK spatial settings expect meters as the default unit of length. 21 | // Unreal uses centimeters for scale, so the plugin's scale of "1" is a scale of "100" for the SDK. 22 | const float SdkScale = SpatialEnvironmentScale * ScaleCenti; 23 | const spatial_scale Scale{SdkScale, SdkScale, SdkScale}; 24 | const spatial_position Forward{1, 0, 0}; 25 | const spatial_position Up{0, 0, 1}; 26 | const spatial_position Right{0, 1, 0}; 27 | Sdk->conference() 28 | .set_spatial_environment(Scale, Forward, Up, Right) 29 | .on_error(DLB_ERROR_HANDLER(OnSetSpatialEnvironmentScaleError)); 30 | } 31 | 32 | void UDolbyIOSubsystem::SetSpatialEnvironmentScale(float Scale) 33 | { 34 | DLB_UE_LOG("Setting spatial environment scale: %f", Scale); 35 | SpatialEnvironmentScale = Scale; 36 | SetSpatialEnvironment(); 37 | } 38 | 39 | void UDolbyIOSubsystem::MuteInput() 40 | { 41 | DLB_UE_LOG("Muting input"); 42 | bIsInputMuted = true; 43 | ToggleInputMute(); 44 | } 45 | 46 | void UDolbyIOSubsystem::UnmuteInput() 47 | { 48 | DLB_UE_LOG("Unmuting input"); 49 | bIsInputMuted = false; 50 | ToggleInputMute(); 51 | } 52 | 53 | void UDolbyIOSubsystem::MuteOutput() 54 | { 55 | DLB_UE_LOG("Muting output"); 56 | bIsOutputMuted = true; 57 | ToggleOutputMute(); 58 | } 59 | 60 | void UDolbyIOSubsystem::UnmuteOutput() 61 | { 62 | DLB_UE_LOG("Unmuting output"); 63 | bIsOutputMuted = false; 64 | ToggleOutputMute(); 65 | } 66 | 67 | void UDolbyIOSubsystem::ToggleInputMute() 68 | { 69 | if (IsConnectedAsActive()) 70 | { 71 | Sdk->conference() 72 | .mute(bIsInputMuted) 73 | .on_error(DLB_ERROR_HANDLER(bIsInputMuted ? OnMuteInputError : OnUnmuteInputError)); 74 | } 75 | } 76 | 77 | void UDolbyIOSubsystem::ToggleOutputMute() 78 | { 79 | if (IsConnected() && ConnectionMode != EDolbyIOConnectionMode::ListenerRTS) 80 | { 81 | Sdk->conference() 82 | .mute_output(bIsOutputMuted) 83 | .on_error(DLB_ERROR_HANDLER(bIsOutputMuted ? OnMuteOutputError : OnUnmuteOutputError)); 84 | } 85 | } 86 | 87 | void UDolbyIOSubsystem::MuteParticipant(const FString& ParticipantID) 88 | { 89 | if (!IsConnected() || ParticipantID == LocalParticipantID) 90 | { 91 | return; 92 | } 93 | 94 | DLB_UE_LOG("Muting participant ID %s", *ParticipantID); 95 | Sdk->audio().remote().stop(ToStdString(ParticipantID)).on_error(DLB_ERROR_HANDLER(OnMuteParticipantError)); 96 | } 97 | 98 | void UDolbyIOSubsystem::UnmuteParticipant(const FString& ParticipantID) 99 | { 100 | if (!IsConnected() || ParticipantID == LocalParticipantID) 101 | { 102 | return; 103 | } 104 | 105 | DLB_UE_LOG("Unmuting participant ID %s", *ParticipantID); 106 | Sdk->audio().remote().start(ToStdString(ParticipantID)).on_error(DLB_ERROR_HANDLER(OnUnmuteParticipantError)); 107 | } 108 | 109 | bool UDolbyIOSubsystem::IsSpatialAudio() const 110 | { 111 | return SpatialAudioStyle != EDolbyIOSpatialAudioStyle::Disabled; 112 | } 113 | 114 | void UDolbyIOSubsystem::SetAudioCaptureMode(EDolbyIONoiseReduction NoiseReduction, EDolbyIOVoiceFont VoiceFont) 115 | { 116 | if (!Sdk) 117 | { 118 | DLB_WARNING(OnSetAudioCaptureModeError, "Cannot set audio capture mode - not initialized"); 119 | return; 120 | } 121 | 122 | DLB_UE_LOG("Setting audio capture mode to %s %s", *UEnum::GetValueAsString(NoiseReduction), 123 | *UEnum::GetValueAsString(VoiceFont)); 124 | Sdk->audio() 125 | .local() 126 | .set_capture_mode(ToSdkAudioCaptureMode(NoiseReduction, VoiceFont)) 127 | .on_error(DLB_ERROR_HANDLER(OnSetAudioCaptureModeError)); 128 | } 129 | 130 | void UDolbyIOSubsystem::Handle(const active_speaker_changed& Event) 131 | { 132 | TArray ActiveSpeakers; 133 | for (const std::string& Speaker : Event.active_speakers) 134 | { 135 | ActiveSpeakers.Add(ToFString(Speaker)); 136 | } 137 | BroadcastEvent(OnActiveSpeakersChanged, ActiveSpeakers); 138 | } 139 | 140 | void UDolbyIOSubsystem::Handle(const audio_levels& Event) 141 | { 142 | TArray ActiveSpeakers; 143 | TArray AudioLevels; 144 | for (const audio_level& Level : Event.levels) 145 | { 146 | ActiveSpeakers.Add(ToFString(Level.participant_id)); 147 | AudioLevels.Add(Level.level); 148 | } 149 | BroadcastEvent(OnAudioLevelsChanged, ActiveSpeakers, AudioLevels); 150 | } 151 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Subsystem/DolbyIODevices.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIODevices.h" 4 | 5 | #include "DolbyIO.h" 6 | #include "Utils/DolbyIOBroadcastEvent.h" 7 | #include "Utils/DolbyIOConversions.h" 8 | #include "Utils/DolbyIOErrorHandler.h" 9 | #include "Utils/DolbyIOLogging.h" 10 | 11 | using namespace dolbyio::comms; 12 | using namespace DolbyIO; 13 | 14 | #define DLB_DEVICES(OnError) \ 15 | if (!Devices) \ 16 | { \ 17 | DLB_WARNING(OnError, #OnError " - not initialized"); \ 18 | return; \ 19 | } \ 20 | Devices 21 | 22 | void UDolbyIOSubsystem::GetAudioInputDevices() 23 | { 24 | DLB_DEVICES(OnGetAudioInputDevicesError)->GetAudioInputDevices(); 25 | } 26 | void UDolbyIOSubsystem::GetAudioOutputDevices() 27 | { 28 | DLB_DEVICES(OnGetAudioOutputDevicesError)->GetAudioOutputDevices(); 29 | } 30 | void UDolbyIOSubsystem::GetCurrentAudioInputDevice() 31 | { 32 | DLB_DEVICES(OnGetCurrentAudioInputDeviceError)->GetCurrentAudioInputDevice(); 33 | } 34 | void UDolbyIOSubsystem::GetCurrentAudioOutputDevice() 35 | { 36 | DLB_DEVICES(OnGetCurrentAudioOutputDeviceError)->GetCurrentAudioOutputDevice(); 37 | } 38 | void UDolbyIOSubsystem::SetAudioInputDevice(const FString& NativeID) 39 | { 40 | DLB_DEVICES(OnSetAudioInputDeviceError)->SetAudioInputDevice(NativeID); 41 | } 42 | void UDolbyIOSubsystem::SetAudioOutputDevice(const FString& NativeID) 43 | { 44 | DLB_DEVICES(OnSetAudioOutputDeviceError)->SetAudioOutputDevice(NativeID); 45 | } 46 | void UDolbyIOSubsystem::GetVideoDevices() 47 | { 48 | DLB_DEVICES(OnGetVideoDevicesError)->GetVideoDevices(); 49 | } 50 | void UDolbyIOSubsystem::GetCurrentVideoDevice() 51 | { 52 | DLB_DEVICES(OnGetCurrentVideoDeviceError)->GetCurrentVideoDevice(); 53 | } 54 | 55 | namespace DolbyIO 56 | { 57 | constexpr bool bIsDeviceNone = true; 58 | 59 | FDevices::FDevices(UDolbyIOSubsystem& Subsystem, FDeviceManagement& DeviceManagement) 60 | : Subsystem(Subsystem), DeviceManagement(DeviceManagement) 61 | { 62 | } 63 | 64 | void FDevices::GetAudioInputDevices() 65 | { 66 | DLB_UE_LOG("Getting audio input devices"); 67 | DeviceManagement.get_audio_devices() 68 | .then( 69 | [this](const std::vector& DvcDevices) 70 | { 71 | TArray Devices; 72 | for (const audio_device& Device : DvcDevices) 73 | { 74 | if (Device.direction() & audio_device::direction::input) 75 | { 76 | DLB_UE_LOG("Got audio input device: %s", *ToString(Device)); 77 | Devices.Add(ToFDolbyIOAudioDevice(Device)); 78 | } 79 | } 80 | BroadcastEvent(Subsystem.OnAudioInputDevicesReceived, Devices); 81 | }) 82 | .on_error(DLB_ERROR_HANDLER(Subsystem.OnGetAudioInputDevicesError)); 83 | } 84 | 85 | void FDevices::GetAudioOutputDevices() 86 | { 87 | DLB_UE_LOG("Getting audio output devices"); 88 | DeviceManagement.get_audio_devices() 89 | .then( 90 | [this](const std::vector& DvcDevices) 91 | { 92 | TArray Devices; 93 | for (const audio_device& Device : DvcDevices) 94 | { 95 | if (Device.direction() & audio_device::direction::output) 96 | { 97 | DLB_UE_LOG("Got audio output device: %s", *ToString(Device)); 98 | Devices.Add(ToFDolbyIOAudioDevice(Device)); 99 | } 100 | } 101 | BroadcastEvent(Subsystem.OnAudioOutputDevicesReceived, Devices); 102 | }) 103 | .on_error(DLB_ERROR_HANDLER(Subsystem.OnGetAudioOutputDevicesError)); 104 | } 105 | 106 | void FDevices::GetCurrentAudioInputDevice() 107 | { 108 | DLB_UE_LOG("Getting current audio input device"); 109 | DeviceManagement.get_current_audio_input_device() 110 | .then( 111 | [this](std::optional Device) 112 | { 113 | if (!Device) 114 | { 115 | DLB_UE_LOG("Got current audio input device - none"); 116 | BroadcastEvent(Subsystem.OnCurrentAudioInputDeviceReceived, bIsDeviceNone, 117 | FDolbyIOAudioDevice{}); 118 | return; 119 | } 120 | DLB_UE_LOG("Got current audio input device - %s", *ToString(*Device)); 121 | BroadcastEvent(Subsystem.OnCurrentAudioInputDeviceReceived, !bIsDeviceNone, 122 | ToFDolbyIOAudioDevice(*Device)); 123 | }) 124 | .on_error(DLB_ERROR_HANDLER(Subsystem.OnGetCurrentAudioInputDeviceError)); 125 | } 126 | 127 | void FDevices::GetCurrentAudioOutputDevice() 128 | { 129 | DLB_UE_LOG("Getting current audio output device"); 130 | DeviceManagement.get_current_audio_output_device() 131 | .then( 132 | [this](std::optional Device) 133 | { 134 | if (!Device) 135 | { 136 | DLB_UE_LOG("Got current audio output device - none"); 137 | BroadcastEvent(Subsystem.OnCurrentAudioOutputDeviceReceived, bIsDeviceNone, 138 | FDolbyIOAudioDevice{}); 139 | return; 140 | } 141 | DLB_UE_LOG("Got current audio output device - %s", *ToString(*Device)); 142 | BroadcastEvent(Subsystem.OnCurrentAudioOutputDeviceReceived, !bIsDeviceNone, 143 | ToFDolbyIOAudioDevice(*Device)); 144 | }) 145 | .on_error(DLB_ERROR_HANDLER(Subsystem.OnGetCurrentAudioOutputDeviceError)); 146 | } 147 | 148 | void FDevices::SetAudioInputDevice(const FString& NativeID) 149 | { 150 | DLB_UE_LOG("Setting audio input device with native ID %s", *NativeID); 151 | DeviceManagement.get_audio_devices() 152 | .then( 153 | [this, SdkNativeID = ToSdkNativeDeviceID(NativeID)](const std::vector& DvcDevices) 154 | { 155 | for (const audio_device& Device : DvcDevices) 156 | if (Device.direction() & audio_device::direction::input && Device.native_id() == SdkNativeID) 157 | { 158 | DLB_UE_LOG("Setting audio input device to %s", *ToString(Device)); 159 | DeviceManagement.set_preferred_input_audio_device(Device).on_error( 160 | DLB_ERROR_HANDLER(Subsystem.OnSetAudioInputDeviceError)); 161 | return; 162 | } 163 | }) 164 | .on_error(DLB_ERROR_HANDLER(Subsystem.OnSetAudioInputDeviceError)); 165 | } 166 | 167 | void FDevices::SetAudioOutputDevice(const FString& NativeID) 168 | { 169 | DLB_UE_LOG("Setting audio output device with native ID %s", *NativeID); 170 | DeviceManagement.get_audio_devices() 171 | .then( 172 | [this, SdkNativeID = ToSdkNativeDeviceID(NativeID)](const std::vector& DvcDevices) 173 | { 174 | for (const audio_device& Device : DvcDevices) 175 | if (Device.direction() & audio_device::direction::output && Device.native_id() == SdkNativeID) 176 | { 177 | DLB_UE_LOG("Setting audio output device to %s", *ToString(Device)); 178 | DeviceManagement.set_preferred_output_audio_device(Device).on_error( 179 | DLB_ERROR_HANDLER(Subsystem.OnSetAudioOutputDeviceError)); 180 | return; 181 | } 182 | }) 183 | .on_error(DLB_ERROR_HANDLER(Subsystem.OnSetAudioOutputDeviceError)); 184 | } 185 | 186 | void FDevices::GetVideoDevices() 187 | { 188 | DLB_UE_LOG("Getting video devices"); 189 | DeviceManagement.get_video_devices() 190 | .then( 191 | [this](const std::vector& DvcDevices) 192 | { 193 | TArray Devices; 194 | Devices.Reserve(DvcDevices.size()); 195 | for (const camera_device& Device : DvcDevices) 196 | { 197 | DLB_UE_LOG("Got video device - display_name: %s unique_id: %s", *ToFString(Device.display_name), 198 | *ToFString(Device.unique_id)); 199 | Devices.Add(ToFDolbyIOVideoDevice(Device)); 200 | } 201 | BroadcastEvent(Subsystem.OnVideoDevicesReceived, Devices); 202 | }) 203 | .on_error(DLB_ERROR_HANDLER(Subsystem.OnGetVideoDevicesError)); 204 | } 205 | 206 | void FDevices::GetCurrentVideoDevice() 207 | { 208 | DLB_UE_LOG("Getting current video device"); 209 | DeviceManagement.get_current_video_device() 210 | .then( 211 | [this](std::optional Device) 212 | { 213 | if (!Device) 214 | { 215 | DLB_UE_LOG("Got current video device - none"); 216 | BroadcastEvent(Subsystem.OnCurrentVideoDeviceReceived, bIsDeviceNone, FDolbyIOVideoDevice{}); 217 | return; 218 | } 219 | DLB_UE_LOG("Got current video device - %s", *ToString(*Device)); 220 | BroadcastEvent(Subsystem.OnCurrentVideoDeviceReceived, !bIsDeviceNone, 221 | ToFDolbyIOVideoDevice(*Device)); 222 | }) 223 | .on_error(DLB_ERROR_HANDLER(Subsystem.OnGetCurrentVideoDeviceError)); 224 | } 225 | } 226 | 227 | void UDolbyIOSubsystem::Handle(const audio_device_changed& Event) 228 | { 229 | using namespace DolbyIO; 230 | 231 | if (!Event.device) 232 | { 233 | DLB_UE_LOG("Audio device changed for direction: %s to no device", *ToString(Event.utilized_direction)); 234 | if (Event.utilized_direction == audio_device::direction::input) 235 | BroadcastEvent(OnCurrentAudioInputDeviceChanged, bIsDeviceNone, FDolbyIOAudioDevice{}); 236 | else 237 | BroadcastEvent(OnCurrentAudioOutputDeviceChanged, bIsDeviceNone, FDolbyIOAudioDevice{}); 238 | return; 239 | } 240 | Sdk->device_management() 241 | .get_audio_devices() 242 | .then( 243 | [this, Event](const std::vector& DvcDevices) 244 | { 245 | for (const audio_device& Device : DvcDevices) 246 | if (*Event.device == Device.get_identity()) 247 | { 248 | DLB_UE_LOG("Audio device changed for direction: %s to device - %s", 249 | *ToString(Event.utilized_direction), *ToString(Device)); 250 | if (Event.utilized_direction == audio_device::direction::input) 251 | BroadcastEvent(OnCurrentAudioInputDeviceChanged, !bIsDeviceNone, 252 | ToFDolbyIOAudioDevice(Device)); 253 | else 254 | BroadcastEvent(OnCurrentAudioOutputDeviceChanged, !bIsDeviceNone, 255 | ToFDolbyIOAudioDevice(Device)); 256 | return; 257 | } 258 | }) 259 | .on_error(DLB_ERROR_HANDLER_NO_DELEGATE); 260 | } 261 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Subsystem/DolbyIODevices.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "Utils/DolbyIOCppSdk.h" 6 | 7 | #include "Containers/UnrealString.h" 8 | #include "DolbyIOTypes.h" 9 | #include "Misc/Optional.h" 10 | 11 | class UDolbyIOSubsystem; 12 | 13 | namespace DolbyIO 14 | { 15 | class FDevices 16 | { 17 | using FDeviceManagement = dolbyio::comms::services::device_management; 18 | 19 | public: 20 | FDevices(UDolbyIOSubsystem& Subsystem, FDeviceManagement& DeviceManagement); 21 | 22 | void GetAudioInputDevices(); 23 | void GetAudioOutputDevices(); 24 | void GetCurrentAudioInputDevice(); 25 | void GetCurrentAudioOutputDevice(); 26 | void SetAudioInputDevice(const FString& NativeID); 27 | void SetAudioOutputDevice(const FString& NativeID); 28 | void GetVideoDevices(); 29 | void GetCurrentVideoDevice(); 30 | 31 | UDolbyIOSubsystem& GetSubsystem() 32 | { 33 | return Subsystem; 34 | } 35 | 36 | private: 37 | UDolbyIOSubsystem& Subsystem; 38 | FDeviceManagement& DeviceManagement; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Subsystem/DolbyIOInitialization.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIO.h" 4 | 5 | #include "DolbyIODevices.h" 6 | #include "Utils/DolbyIOBroadcastEvent.h" 7 | #include "Utils/DolbyIOConversions.h" 8 | #include "Utils/DolbyIOErrorHandler.h" 9 | #include "Utils/DolbyIOLogging.h" 10 | #include "Video/DolbyIOVideoFrameHandler.h" 11 | #include "Video/DolbyIOVideoSink.h" 12 | 13 | #include "Engine/GameInstance.h" 14 | #include "Engine/World.h" 15 | #include "Interfaces/IPluginManager.h" 16 | #include "Misc/EngineVersion.h" 17 | #include "Misc/Paths.h" 18 | #include "TimerManager.h" 19 | 20 | using namespace dolbyio::comms; 21 | using namespace dolbyio::comms::plugin; 22 | using namespace DolbyIO; 23 | 24 | void UDolbyIOSubsystem::Initialize(FSubsystemCollectionBase& Collection) 25 | { 26 | Super::Initialize(Collection); 27 | 28 | ConferenceStatus = conference_status::destroyed; 29 | 30 | { 31 | FScopeLock Lock{&VideoSinksLock}; 32 | VideoSinks.Emplace(LocalCameraTrackID, std::make_shared(LocalCameraTrackID)); 33 | VideoSinks.Emplace(LocalScreenshareTrackID, std::make_shared(LocalScreenshareTrackID)); 34 | LocalCameraFrameHandler = std::make_shared(VideoSinks[LocalCameraTrackID]); 35 | LocalScreenshareFrameHandler = std::make_shared(VideoSinks[LocalScreenshareTrackID]); 36 | } 37 | 38 | FTimerManager& TimerManager = GetGameInstance()->GetTimerManager(); 39 | TimerManager.SetTimer(LocationTimerHandle, this, &UDolbyIOSubsystem::SetLocationUsingFirstPlayer, 0.1, true); 40 | TimerManager.SetTimer(RotationTimerHandle, this, &UDolbyIOSubsystem::SetRotationUsingFirstPlayer, 0.01, true); 41 | 42 | BroadcastEvent(OnTokenNeeded); 43 | } 44 | 45 | void UDolbyIOSubsystem::Deinitialize() 46 | { 47 | DLB_UE_LOG("Deinitializing"); 48 | 49 | FScopeLock Lock{&VideoSinksLock}; 50 | for (auto& Sink : VideoSinks) 51 | { 52 | Sink.Value->Disable(); // ignore new frames now on 53 | } 54 | 55 | Super::Deinitialize(); 56 | } 57 | 58 | namespace 59 | { 60 | class FSdkLogCallback : public logger_sink_callback 61 | { 62 | public: 63 | void log(log_level Level, std::string_view Message) const override 64 | { 65 | #define DLB_UE_LOG_SDK_BASE(Verbosity) \ 66 | DLB_UE_LOG_BASE(Verbosity, "%s", *ToFText(std::string{Message}).ToString()); \ 67 | return; 68 | switch (Level) 69 | { 70 | case log_level::ERROR: 71 | DLB_UE_LOG_SDK_BASE(Error); 72 | case log_level::WARNING: 73 | DLB_UE_LOG_SDK_BASE(Warning); 74 | default: 75 | DLB_UE_LOG_SDK_BASE(Log); 76 | } 77 | } 78 | }; 79 | } 80 | 81 | void UDolbyIOSubsystem::SetLogSettings(EDolbyIOLogLevel SdkLogLevel, EDolbyIOLogLevel MediaLogLevel, 82 | EDolbyIOLogLevel DvcLogLevel, bool bLogToConsole, bool bLogToFile) 83 | { 84 | sdk::log_settings LogSettings; 85 | LogSettings.sdk_log_level = ToSdkLogLevel(SdkLogLevel); 86 | LogSettings.media_log_level = ToSdkLogLevel(MediaLogLevel); 87 | LogSettings.dvc_log_level = ToSdkLogLevel(DvcLogLevel); 88 | LogSettings.suppress_stdout_logs = true; 89 | 90 | if (bLogToConsole) 91 | { 92 | LogSettings.log_callback = std::make_shared(); 93 | } 94 | if (bLogToFile) 95 | { 96 | const FString& LogDir = FPaths::ProjectLogDir(); 97 | DLB_UE_LOG("Logs will be saved in directory %s", *LogDir); 98 | LogSettings.log_directory = ToStdString(LogDir); 99 | } 100 | 101 | try 102 | { 103 | sdk::set_log_settings(LogSettings); 104 | } 105 | catch (...) 106 | { 107 | DLB_ERROR_HANDLER(OnSetLogSettingsError).HandleError(); 108 | } 109 | } 110 | 111 | void UDolbyIOSubsystem::SetToken(const FString& Token) 112 | { 113 | if (!Sdk) 114 | { 115 | DLB_UE_LOG("Initializing with token: %s", *Token); 116 | AsyncTask(ENamedThreads::AnyThread, [this, Token] { Initialize(Token); }); 117 | } 118 | else if (RefreshTokenCb) 119 | { 120 | DLB_UE_LOG("Refreshing token: %s", *Token); 121 | try 122 | { 123 | (*RefreshTokenCb)(ToStdString(Token)); 124 | } 125 | catch (...) 126 | { 127 | DLB_ERROR_HANDLER(OnSetTokenError).HandleError(); 128 | } 129 | RefreshTokenCb.Reset(); // RefreshToken callback can only be called once 130 | } 131 | } 132 | 133 | void UDolbyIOSubsystem::Initialize(const FString& Token) 134 | { 135 | try 136 | { 137 | Sdk = TSharedPtr(sdk::create(ToStdString(Token), 138 | [this](std::unique_ptr&& RefreshCb) 139 | { 140 | DLB_UE_LOG("Refresh token requested"); 141 | RefreshTokenCb = TSharedPtr(RefreshCb.release()); 142 | BroadcastEvent(OnTokenNeeded); 143 | }) 144 | .release()); 145 | } 146 | catch (...) 147 | { 148 | DLB_ERROR_HANDLER(OnSetTokenError).HandleError(); 149 | return; 150 | } 151 | 152 | Devices = MakeShared(*this, Sdk->device_management()); 153 | 154 | #define DLB_REGISTER_HANDLER(Service, Event) \ 155 | [this](event_handler_id) { return Sdk->Service().add_event_handler([this](const Event& Event) { Handle(Event); }); } 156 | 157 | const FString ComponentName = "unreal-sdk"; 158 | const FString ComponentVersion = *IPluginManager::Get().FindPlugin("DolbyIO")->GetDescriptor().VersionName + 159 | FString{"_UE"} + FEngineVersion::Current().ToString(EVersionComponent::Minor); 160 | DLB_UE_LOG("Registering component %s %s", *ComponentName, *ComponentVersion); 161 | Sdk->register_component_version(ToStdString(ComponentName), ToStdString(ComponentVersion)) 162 | .then( 163 | [this](sdk::component_data) 164 | { 165 | return Sdk->conference().add_event_handler([this](const conference_status_updated& Event) 166 | { UpdateStatus(Event.status); }); 167 | }) 168 | .then(DLB_REGISTER_HANDLER(conference, active_speaker_changed)) 169 | .then(DLB_REGISTER_HANDLER(device_management, audio_device_changed)) 170 | .then(DLB_REGISTER_HANDLER(conference, audio_levels)) 171 | .then(DLB_REGISTER_HANDLER(conference, conference_message_received)) 172 | .then(DLB_REGISTER_HANDLER(conference, local_participant_updated)) 173 | .then(DLB_REGISTER_HANDLER(conference, remote_participant_added)) 174 | .then(DLB_REGISTER_HANDLER(conference, remote_participant_updated)) 175 | .then(DLB_REGISTER_HANDLER(conference, remote_video_track_added)) 176 | .then(DLB_REGISTER_HANDLER(conference, remote_video_track_removed)) 177 | .then(DLB_REGISTER_HANDLER(device_management, screen_share_error)) 178 | .then([this](event_handler_id) 179 | #if PLATFORM_WINDOWS 180 | { return Sdk->device_management().set_default_audio_device_policy(default_audio_device_policy::output); }) 181 | .then([this] 182 | #endif 183 | #if PLATFORM_WINDOWS | PLATFORM_MAC 184 | // keep this comment here to avoid wrong clang-formatting 185 | { return video_processor::create(*Sdk); }) 186 | .then([this](std::shared_ptr VideoProcessorPtr) 187 | { VideoProcessor = std::move(VideoProcessorPtr); }) 188 | .then( 189 | [this] 190 | #endif 191 | { 192 | utils::vfs_event::add_event_handler(*Sdk, [this](const utils::vfs_event& Event) { Handle(Event); }); 193 | 194 | DLB_UE_LOG("Initialized"); 195 | BroadcastEvent(OnInitialized); 196 | }) 197 | .on_error(DLB_ERROR_HANDLER(OnSetTokenError)); 198 | } 199 | 200 | void UDolbyIOObserver::InitializeComponent() 201 | { 202 | if (UWorld* World = GetWorld()) 203 | { 204 | if (UGameInstance* GameInstance = World->GetGameInstance()) 205 | { 206 | if (UDolbyIOSubsystem* DolbyIOSubsystem = GameInstance->GetSubsystem()) 207 | { 208 | #define DLB_BIND(Event) DolbyIOSubsystem->Event.AddDynamic(this, &UDolbyIOObserver::Fwd##Event); 209 | DLB_BIND(OnTokenNeeded); 210 | 211 | DLB_BIND(OnInitialized); 212 | DLB_BIND(OnSetTokenError); 213 | 214 | DLB_BIND(OnConnected); 215 | DLB_BIND(OnConnectError); 216 | DLB_BIND(OnDemoConferenceError); 217 | 218 | DLB_BIND(OnDisconnected); 219 | DLB_BIND(OnDisconnectError); 220 | 221 | DLB_BIND(OnSetSpatialEnvironmentScaleError); 222 | 223 | DLB_BIND(OnMuteInputError); 224 | 225 | DLB_BIND(OnUnmuteInputError); 226 | 227 | DLB_BIND(OnMuteOutputError); 228 | 229 | DLB_BIND(OnUnmuteOutputError); 230 | 231 | DLB_BIND(OnMuteParticipantError); 232 | 233 | DLB_BIND(OnUnmuteParticipantError); 234 | 235 | DLB_BIND(OnParticipantAdded); 236 | DLB_BIND(OnParticipantUpdated); 237 | DLB_BIND(OnRemoteParticipantConnected); 238 | DLB_BIND(OnRemoteParticipantDisconnected); 239 | 240 | DLB_BIND(OnLocalParticipantUpdated); 241 | 242 | DLB_BIND(OnVideoTrackAdded); 243 | 244 | DLB_BIND(OnVideoTrackRemoved); 245 | 246 | DLB_BIND(OnVideoTrackEnabled); 247 | 248 | DLB_BIND(OnVideoTrackDisabled); 249 | 250 | DLB_BIND(OnVideoEnabled); 251 | DLB_BIND(OnEnableVideoError); 252 | 253 | DLB_BIND(OnVideoDisabled); 254 | DLB_BIND(OnDisableVideoError); 255 | 256 | DLB_BIND(OnScreenshareSourcesReceived); 257 | DLB_BIND(OnGetScreenshareSourcesError); 258 | 259 | DLB_BIND(OnScreenshareStarted); 260 | DLB_BIND(OnStartScreenshareError); 261 | 262 | DLB_BIND(OnScreenshareStopped); 263 | DLB_BIND(OnStopScreenshareError); 264 | 265 | DLB_BIND(OnChangeScreenshareParametersError); 266 | 267 | DLB_BIND(OnCurrentScreenshareSourceReceived); 268 | DLB_BIND(OnGetCurrentScreenshareSourceError); 269 | 270 | DLB_BIND(OnActiveSpeakersChanged); 271 | 272 | DLB_BIND(OnAudioLevelsChanged); 273 | 274 | DLB_BIND(OnSetLocalPlayerLocationError); 275 | 276 | DLB_BIND(OnSetLocalPlayerRotationError); 277 | 278 | DLB_BIND(OnSetRemotePlayerLocationError); 279 | 280 | DLB_BIND(OnSetLogSettingsError); 281 | 282 | DLB_BIND(OnAudioInputDevicesReceived); 283 | DLB_BIND(OnGetAudioInputDevicesError); 284 | 285 | DLB_BIND(OnAudioOutputDevicesReceived); 286 | DLB_BIND(OnGetAudioOutputDevicesError); 287 | 288 | DLB_BIND(OnCurrentAudioInputDeviceReceived); 289 | DLB_BIND(OnGetCurrentAudioInputDeviceError); 290 | 291 | DLB_BIND(OnCurrentAudioOutputDeviceReceived); 292 | DLB_BIND(OnGetCurrentAudioOutputDeviceError); 293 | 294 | DLB_BIND(OnVideoDevicesReceived); 295 | DLB_BIND(OnGetVideoDevicesError); 296 | 297 | DLB_BIND(OnCurrentVideoDeviceReceived); 298 | DLB_BIND(OnGetCurrentVideoDeviceError); 299 | 300 | DLB_BIND(OnCurrentAudioInputDeviceChanged); 301 | DLB_BIND(OnSetAudioInputDeviceError); 302 | 303 | DLB_BIND(OnCurrentAudioOutputDeviceChanged); 304 | DLB_BIND(OnSetAudioOutputDeviceError); 305 | 306 | DLB_BIND(OnUpdateUserMetadataError); 307 | 308 | DLB_BIND(OnSetAudioCaptureModeError); 309 | 310 | DLB_BIND(OnSendMessageError); 311 | 312 | DLB_BIND(OnMessageReceived); 313 | 314 | FwdOnTokenNeeded(); 315 | } 316 | } 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Subsystem/DolbyIOScreenshare.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIO.h" 4 | 5 | #include "Utils/DolbyIOBroadcastEvent.h" 6 | #include "Utils/DolbyIOConversions.h" 7 | #include "Utils/DolbyIOErrorHandler.h" 8 | #include "Utils/DolbyIOLogging.h" 9 | #include "Video/DolbyIOVideoFrameHandler.h" 10 | 11 | using namespace dolbyio::comms; 12 | using namespace DolbyIO; 13 | 14 | void UDolbyIOSubsystem::GetScreenshareSources() 15 | { 16 | if (!Sdk) 17 | { 18 | DLB_WARNING(OnGetScreenshareSourcesError, "Cannot get screenshare sources - not initialized"); 19 | return; 20 | } 21 | 22 | DLB_UE_LOG("Getting screenshare sources"); 23 | Sdk->device_management() 24 | .get_screen_share_sources() 25 | .then( 26 | [this](const std::vector& Sources) 27 | { 28 | TArray Ret; 29 | for (const screen_share_source& Source : Sources) 30 | { 31 | Ret.Add(ToFDolbyIOScreenshareSource(Source)); 32 | } 33 | BroadcastEvent(OnScreenshareSourcesReceived, Ret); 34 | }) 35 | .on_error(DLB_ERROR_HANDLER(OnGetScreenshareSourcesError)); 36 | } 37 | 38 | void UDolbyIOSubsystem::StartScreenshare(const FDolbyIOScreenshareSource& Source, 39 | EDolbyIOScreenshareEncoderHint EncoderHint, 40 | EDolbyIOScreenshareMaxResolution MaxResolution, 41 | EDolbyIOScreenshareDownscaleQuality DownscaleQuality) 42 | { 43 | if (!IsConnectedAsActive()) 44 | { 45 | DLB_WARNING(OnStartScreenshareError, "Cannot start screenshare - not connected as active user"); 46 | return; 47 | } 48 | 49 | const screen_share_source SdkSource = ToSdkScreenshareSource(Source); 50 | DLB_UE_LOG("Starting screenshare using source: %s %s %s %s", *ToString(SdkSource), 51 | *UEnum::GetValueAsString(EncoderHint), *UEnum::GetValueAsString(MaxResolution), 52 | *UEnum::GetValueAsString(DownscaleQuality)); 53 | Sdk->conference() 54 | .start_screen_share(SdkSource, LocalScreenshareFrameHandler, 55 | ToSdkContentInfo(EncoderHint, MaxResolution, DownscaleQuality)) 56 | .then([this] { BroadcastEvent(OnScreenshareStarted, LocalScreenshareTrackID); }) 57 | .on_error(DLB_ERROR_HANDLER(OnStartScreenshareError)); 58 | } 59 | 60 | void UDolbyIOSubsystem::StopScreenshare() 61 | { 62 | if (!Sdk) 63 | { 64 | return; 65 | } 66 | 67 | DLB_UE_LOG("Stopping screenshare"); 68 | Sdk->conference() 69 | .stop_screen_share() 70 | .then([this] { BroadcastEvent(OnScreenshareStopped, LocalScreenshareTrackID); }) 71 | .on_error(DLB_ERROR_HANDLER(OnStopScreenshareError)); 72 | } 73 | 74 | void UDolbyIOSubsystem::ChangeScreenshareParameters(EDolbyIOScreenshareEncoderHint EncoderHint, 75 | EDolbyIOScreenshareMaxResolution MaxResolution, 76 | EDolbyIOScreenshareDownscaleQuality DownscaleQuality) 77 | { 78 | if (!IsConnectedAsActive()) 79 | { 80 | return; 81 | } 82 | 83 | DLB_UE_LOG("Changing screenshare parameters to %s %s %s", *UEnum::GetValueAsString(EncoderHint), 84 | *UEnum::GetValueAsString(MaxResolution), *UEnum::GetValueAsString(DownscaleQuality)); 85 | Sdk->conference() 86 | .screen_share_content_info(ToSdkContentInfo(EncoderHint, MaxResolution, DownscaleQuality)) 87 | .on_error(DLB_ERROR_HANDLER(OnChangeScreenshareParametersError)); 88 | } 89 | 90 | void UDolbyIOSubsystem::GetCurrentScreenshareSource() 91 | { 92 | constexpr static bool bIsSourceNone = true; 93 | 94 | if (!Sdk) 95 | { 96 | DLB_WARNING(OnGetCurrentScreenshareSourceError, "Cannot get current screenshare source - not initialized"); 97 | return; 98 | } 99 | 100 | DLB_UE_LOG("Getting current screenshare source"); 101 | Sdk->device_management() 102 | .get_current_screen_share_source() 103 | .then( 104 | [this](std::optional Source) 105 | { 106 | if (!Source) 107 | { 108 | DLB_UE_LOG("Got current screenshare source - none"); 109 | BroadcastEvent(OnCurrentScreenshareSourceReceived, bIsSourceNone, FDolbyIOScreenshareSource{}); 110 | return; 111 | } 112 | DLB_UE_LOG("Got current screenshare source - %s", *ToString(*Source)); 113 | BroadcastEvent(OnCurrentScreenshareSourceReceived, !bIsSourceNone, 114 | ToFDolbyIOScreenshareSource(*Source)); 115 | }) 116 | .on_error(DLB_ERROR_HANDLER(OnGetScreenshareSourcesError)); 117 | } 118 | 119 | void UDolbyIOSubsystem::Handle(const screen_share_error& Event) 120 | { 121 | DLB_UE_LOG_BASE(Warning, "Received screen_share_error event source=%s type=%s description=%s force_stopped=%d", 122 | *ToString(Event.source), *ToString(Event.type), *ToFString(Event.description), Event.force_stopped); 123 | if (Event.force_stopped) 124 | { 125 | StopScreenshare(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Subsystem/DolbyIOTransforms.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIO.h" 4 | 5 | #include "Utils/DolbyIOConversions.h" 6 | #include "Utils/DolbyIOErrorHandler.h" 7 | #include "Utils/DolbyIOLogging.h" 8 | 9 | #include "Engine/GameInstance.h" 10 | #include "Engine/World.h" 11 | #include "GameFramework/Pawn.h" 12 | #include "GameFramework/PlayerController.h" 13 | #include "TimerManager.h" 14 | 15 | using namespace DolbyIO; 16 | 17 | void UDolbyIOSubsystem::SetLocalPlayerLocation(const FVector& Location) 18 | { 19 | if (LocationTimerHandle.IsValid()) 20 | { 21 | DLB_UE_LOG("Disabling automatic location setting"); 22 | GetGameInstance()->GetTimerManager().ClearTimer(LocationTimerHandle); 23 | } 24 | SetLocalPlayerLocationImpl(Location); 25 | } 26 | 27 | void UDolbyIOSubsystem::SetLocalPlayerLocationImpl(const FVector& Location) 28 | { 29 | if (!IsConnectedAsActive() || !IsSpatialAudio()) 30 | { 31 | return; 32 | } 33 | 34 | Sdk->conference() 35 | .set_spatial_position(ToStdString(LocalParticipantID), {Location.X, Location.Y, Location.Z}) 36 | .on_error(DLB_ERROR_HANDLER(OnSetLocalPlayerLocationError)); 37 | } 38 | 39 | void UDolbyIOSubsystem::SetLocalPlayerRotation(const FRotator& Rotation) 40 | { 41 | if (RotationTimerHandle.IsValid()) 42 | { 43 | DLB_UE_LOG("Disabling automatic rotation setting"); 44 | GetGameInstance()->GetTimerManager().ClearTimer(RotationTimerHandle); 45 | } 46 | SetLocalPlayerRotationImpl(Rotation); 47 | } 48 | 49 | void UDolbyIOSubsystem::SetLocalPlayerRotationImpl(const FRotator& Rotation) 50 | { 51 | if (!IsConnectedAsActive() || !IsSpatialAudio()) 52 | { 53 | return; 54 | } 55 | 56 | // The SDK expects the direction values to mean rotations around the {x,y,z} axes as specified by the 57 | // environment. In Unreal, rotation around x is roll (because x is forward), y is pitch and z is yaw. 58 | Sdk->conference() 59 | .set_spatial_direction({Rotation.Roll, Rotation.Pitch, Rotation.Yaw}) 60 | .on_error(DLB_ERROR_HANDLER(OnSetLocalPlayerRotationError)); 61 | } 62 | 63 | void UDolbyIOSubsystem::SetRemotePlayerLocation(const FString& ParticipantID, const FVector& Location) 64 | { 65 | if (!IsConnectedAsActive() || SpatialAudioStyle != EDolbyIOSpatialAudioStyle::Individual || 66 | ParticipantID == LocalParticipantID) 67 | { 68 | return; 69 | } 70 | 71 | Sdk->conference() 72 | .set_spatial_position(ToStdString(ParticipantID), {Location.X, Location.Y, Location.Z}) 73 | .on_error(DLB_ERROR_HANDLER(OnSetRemotePlayerLocationError)); 74 | } 75 | 76 | namespace 77 | { 78 | APawn* GetFirstPlayerPawn(UGameInstance* GameInstance) 79 | { 80 | if (UWorld* World = GameInstance->GetWorld()) 81 | { 82 | if (APlayerController* FirstPlayerController = World->GetFirstPlayerController()) 83 | { 84 | return FirstPlayerController->GetPawn(); 85 | } 86 | } 87 | return nullptr; 88 | } 89 | } 90 | 91 | void UDolbyIOSubsystem::SetLocationUsingFirstPlayer() 92 | { 93 | if (APawn* Pawn = GetFirstPlayerPawn(GetGameInstance())) 94 | { 95 | SetLocalPlayerLocationImpl(Pawn->GetActorLocation()); 96 | } 97 | } 98 | 99 | void UDolbyIOSubsystem::SetRotationUsingFirstPlayer() 100 | { 101 | if (APawn* Pawn = GetFirstPlayerPawn(GetGameInstance())) 102 | { 103 | SetLocalPlayerRotationImpl(Pawn->GetActorRotation()); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Subsystem/DolbyIOVideo.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIO.h" 4 | 5 | #include "DolbyIODevices.h" 6 | #include "Utils/DolbyIOBroadcastEvent.h" 7 | #include "Utils/DolbyIOConversions.h" 8 | #include "Utils/DolbyIOErrorHandler.h" 9 | #include "Utils/DolbyIOLogging.h" 10 | #include "Video/DolbyIOVideoFrameHandler.h" 11 | #include "Video/DolbyIOVideoProcessingFrameHandler.h" 12 | 13 | using namespace dolbyio::comms; 14 | using namespace DolbyIO; 15 | 16 | void UDolbyIOSubsystem::EnableVideo(const FDolbyIOVideoDevice& VideoDevice, bool bBlurBackground) 17 | { 18 | if (!Sdk) 19 | { 20 | DLB_WARNING(OnEnableVideoError, "Cannot enable video - not initialized"); 21 | return; 22 | } 23 | 24 | DLB_UE_LOG("Enabling video"); 25 | 26 | std::shared_ptr VideoFrameHandler = LocalCameraFrameHandler; 27 | if (bBlurBackground) 28 | { 29 | #if PLATFORM_WINDOWS | PLATFORM_MAC 30 | DLB_UE_LOG("Blurring background"); 31 | VideoFrameHandler = 32 | std::make_shared(VideoProcessor, LocalCameraFrameHandler->sink()); 33 | #else 34 | DLB_WARNING(OnEnableVideoError, "Cannot blur background on this platform"); 35 | #endif 36 | } 37 | 38 | Sdk->video() 39 | .local() 40 | .start(ToSdkVideoDevice(VideoDevice), VideoFrameHandler) 41 | .then( 42 | [this, VideoDevice] 43 | { 44 | bIsVideoEnabled = true; 45 | BroadcastEvent(OnVideoEnabled, LocalCameraTrackID); 46 | }) 47 | .on_error(DLB_ERROR_HANDLER(OnEnableVideoError)); 48 | } 49 | 50 | void UDolbyIOSubsystem::DisableVideo() 51 | { 52 | if (!Sdk) 53 | { 54 | return; 55 | } 56 | 57 | DLB_UE_LOG("Disabling video"); 58 | Sdk->video() 59 | .local() 60 | .stop() 61 | .then( 62 | [this] 63 | { 64 | bIsVideoEnabled = false; 65 | BroadcastEvent(OnVideoDisabled, LocalCameraTrackID); 66 | }) 67 | .on_error(DLB_ERROR_HANDLER(OnDisableVideoError)); 68 | } 69 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Subsystem/DolbyIOVideoTracks.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIO.h" 4 | 5 | #include "Utils/DolbyIOBroadcastEvent.h" 6 | #include "Utils/DolbyIOConversions.h" 7 | #include "Utils/DolbyIOErrorHandler.h" 8 | #include "Utils/DolbyIOLogging.h" 9 | #include "Video/DolbyIOVideoSink.h" 10 | 11 | using namespace dolbyio::comms; 12 | using namespace DolbyIO; 13 | 14 | void UDolbyIOSubsystem::BindMaterial(UMaterialInstanceDynamic* Material, const FString& VideoTrackID) 15 | { 16 | FScopeLock Lock{&VideoSinksLock}; 17 | for (auto& Sink : VideoSinks) 18 | { 19 | if (Sink.Key != VideoTrackID) 20 | { 21 | Sink.Value->UnbindMaterial(Material); 22 | } 23 | } 24 | 25 | if (const std::shared_ptr* Sink = VideoSinks.Find(VideoTrackID)) 26 | { 27 | (*Sink)->BindMaterial(Material); 28 | } 29 | } 30 | 31 | void UDolbyIOSubsystem::UnbindMaterial(UMaterialInstanceDynamic* Material, const FString& VideoTrackID) 32 | { 33 | FScopeLock Lock{&VideoSinksLock}; 34 | if (const std::shared_ptr* Sink = VideoSinks.Find(VideoTrackID)) 35 | { 36 | (*Sink)->UnbindMaterial(Material); 37 | } 38 | } 39 | 40 | UTexture2D* UDolbyIOSubsystem::GetTexture(const FString& VideoTrackID) 41 | { 42 | FScopeLock Lock{&VideoSinksLock}; 43 | if (const std::shared_ptr* Sink = VideoSinks.Find(VideoTrackID)) 44 | { 45 | return (*Sink)->GetTexture(); 46 | } 47 | return nullptr; 48 | } 49 | 50 | void UDolbyIOSubsystem::BroadcastVideoTrackAdded(const FDolbyIOVideoTrack& VideoTrack) 51 | { 52 | DLB_UE_LOG("Video track added: TrackID=%s ParticipantID=%s", *VideoTrack.TrackID, *VideoTrack.ParticipantID); 53 | WarnIfVideoTrackSuspicious(VideoTrack.TrackID); 54 | BroadcastEvent(OnVideoTrackAdded, VideoTrack); 55 | } 56 | 57 | void UDolbyIOSubsystem::WarnIfVideoTrackSuspicious(const FString& VideoTrackID) 58 | { 59 | if (VideoTrackID == "{-}") 60 | { 61 | DLB_UE_LOG_BASE(Warning, "Suspicious video track ID added, things may not work as expected"); 62 | } 63 | } 64 | 65 | void UDolbyIOSubsystem::BroadcastVideoTrackEnabled(const FDolbyIOVideoTrack& VideoTrack) 66 | { 67 | DLB_UE_LOG("Video track enabled: TrackID=%s ParticipantID=%s", *VideoTrack.TrackID, *VideoTrack.ParticipantID); 68 | BroadcastEvent(OnVideoTrackEnabled, VideoTrack); 69 | } 70 | 71 | void UDolbyIOSubsystem::ProcessBufferedVideoTracks(const FString& ParticipantID) 72 | { 73 | if (TArray* AddedTracks = BufferedAddedVideoTracks.Find(ParticipantID)) 74 | { 75 | FScopeLock Lock{&VideoSinksLock}; 76 | for (const FDolbyIOVideoTrack& AddedTrack : *AddedTracks) 77 | { 78 | if (std::shared_ptr* Sink = VideoSinks.Find(AddedTrack.TrackID)) 79 | { 80 | (*Sink)->OnTextureCreated( 81 | [=] 82 | { 83 | BroadcastVideoTrackAdded(AddedTrack); 84 | 85 | if (TArray* EnabledTracks = BufferedEnabledVideoTracks.Find(ParticipantID)) 86 | { 87 | TArray& EnabledTracksRef = *EnabledTracks; 88 | for (int i = 0; i < EnabledTracksRef.Num(); ++i) 89 | { 90 | if (EnabledTracksRef[i].TrackID == AddedTrack.TrackID) 91 | { 92 | BroadcastVideoTrackEnabled(EnabledTracksRef[i]); 93 | EnabledTracksRef.RemoveAt(i); 94 | if (!EnabledTracksRef.Num()) 95 | { 96 | BufferedEnabledVideoTracks.Remove(ParticipantID); 97 | } 98 | return; 99 | } 100 | } 101 | } 102 | }); 103 | } 104 | } 105 | BufferedAddedVideoTracks.Remove(ParticipantID); 106 | } 107 | } 108 | 109 | void UDolbyIOSubsystem::Handle(const remote_video_track_added& Event) 110 | { 111 | const FDolbyIOVideoTrack VideoTrack = ToFDolbyIOVideoTrack(Event.track); 112 | 113 | FScopeLock Lock1{&VideoSinksLock}; 114 | VideoSinks.Emplace(VideoTrack.TrackID, std::make_shared(VideoTrack.TrackID)); 115 | Sdk->video() 116 | .remote() 117 | .set_video_sink(Event.track, VideoSinks[VideoTrack.TrackID]) 118 | .on_error(DLB_ERROR_HANDLER_NO_DELEGATE); 119 | 120 | FScopeLock Lock2{&RemoteParticipantsLock}; 121 | if (RemoteParticipants.Contains(VideoTrack.ParticipantID)) 122 | { 123 | VideoSinks[VideoTrack.TrackID]->OnTextureCreated([this, VideoTrack] { BroadcastVideoTrackAdded(VideoTrack); }); 124 | } 125 | else 126 | { 127 | DLB_UE_LOG("Buffering video track added: TrackID=%s ParticipantID=%s", *VideoTrack.TrackID, 128 | *VideoTrack.ParticipantID); 129 | BufferedAddedVideoTracks.FindOrAdd(VideoTrack.ParticipantID).Add(VideoTrack); 130 | } 131 | } 132 | 133 | void UDolbyIOSubsystem::Handle(const remote_video_track_removed& Event) 134 | { 135 | const FDolbyIOVideoTrack VideoTrack = ToFDolbyIOVideoTrack(Event.track); 136 | DLB_UE_LOG("Video track removed: TrackID=%s ParticipantID=%s", *VideoTrack.TrackID, *VideoTrack.ParticipantID); 137 | WarnIfVideoTrackSuspicious(VideoTrack.TrackID); 138 | 139 | FScopeLock Lock{&VideoSinksLock}; 140 | if (std::shared_ptr* Sink = VideoSinks.Find(VideoTrack.TrackID)) 141 | { 142 | (*Sink)->UnbindAllMaterials(); 143 | VideoSinks.Remove(VideoTrack.TrackID); 144 | } 145 | else 146 | { 147 | DLB_UE_LOG_BASE(Warning, "Non-existent video track removed"); 148 | } 149 | 150 | BroadcastEvent(OnVideoTrackRemoved, VideoTrack); 151 | } 152 | 153 | void UDolbyIOSubsystem::Handle(const utils::vfs_event& Event) 154 | { 155 | for (const auto& TrackMapItem : Event.new_enabled) 156 | { 157 | const FDolbyIOVideoTrack VideoTrack = ToFDolbyIOVideoTrack(TrackMapItem); 158 | 159 | if (GetTexture(VideoTrack.TrackID)) 160 | { 161 | BroadcastVideoTrackEnabled(VideoTrack); 162 | } 163 | else 164 | { 165 | DLB_UE_LOG("Buffering video track enabled: TrackID=%s ParticipantID=%s", *VideoTrack.TrackID, 166 | *VideoTrack.ParticipantID); 167 | BufferedEnabledVideoTracks.FindOrAdd(VideoTrack.ParticipantID).Add(VideoTrack); 168 | } 169 | } 170 | for (const auto& TrackMapItem : Event.new_disabled) 171 | { 172 | const FDolbyIOVideoTrack VideoTrack = ToFDolbyIOVideoTrack(TrackMapItem); 173 | DLB_UE_LOG("Video track ID %s for participant ID %s disabled", *VideoTrack.TrackID, *VideoTrack.ParticipantID); 174 | BroadcastEvent(OnVideoTrackDisabled, VideoTrack); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Utils/DolbyIOAuthentication.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIOAuthentication.h" 4 | 5 | #include "Utils/DolbyIOLogging.h" 6 | 7 | #include "HttpModule.h" 8 | #include "Interfaces/IHttpResponse.h" 9 | #include "Misc/Base64.h" 10 | #include "Serialization/JsonSerializer.h" 11 | 12 | namespace 13 | { 14 | bool TryBroadcastToken(const FHttpResponsePtr& Response, const FGetDolbyIOTokenOutputPin& Delegate) 15 | { 16 | TSharedPtr ResponseObj; 17 | FJsonSerializer::Deserialize(TJsonReaderFactory<>::Create(Response->GetContentAsString()), ResponseObj); 18 | FString Token; 19 | if (!ResponseObj->TryGetStringField("access_token", Token)) 20 | { 21 | return false; 22 | } 23 | Delegate.Broadcast(Token, ""); 24 | return true; 25 | } 26 | 27 | void BroadcastError(const FGetDolbyIOTokenOutputPin& Delegate, const FString& ErrorMsg) 28 | { 29 | DLB_UE_LOG_BASE(Error, "%s", *ErrorMsg); 30 | Delegate.Broadcast("", ErrorMsg); 31 | } 32 | } 33 | 34 | void UDolbyIOGetTokenFromURL::Activate() 35 | { 36 | if (URL.IsEmpty()) 37 | { 38 | return BroadcastError(OnError, "URL must not be empty"); 39 | } 40 | 41 | FHttpRequestRef Request = FHttpModule::Get().CreateRequest(); 42 | Request->SetURL(URL); 43 | Request->SetVerb("GET"); 44 | Request->AppendToHeader("Content-Type", "application/x-www-form-urlencoded"); 45 | Request->OnProcessRequestComplete().BindUObject(this, &UDolbyIOGetTokenFromURL::OnTokenObtainedImpl); 46 | Request->ProcessRequest(); 47 | } 48 | 49 | void UDolbyIOGetTokenFromURL::OnTokenObtainedImpl(FHttpRequestPtr, FHttpResponsePtr Response, 50 | bool bConnectedSuccessfully) 51 | { 52 | if (!bConnectedSuccessfully) 53 | { 54 | return BroadcastError(OnError, "Could not connect to given URL"); 55 | } 56 | if (!TryBroadcastToken(Response, OnTokenObtained)) 57 | { 58 | BroadcastError(OnError, "Could not get access token - no token in response from URL"); 59 | } 60 | } 61 | 62 | UDolbyIOGetTokenFromURL* UDolbyIOGetTokenFromURL::DolbyIOGetTokenFromURL(const FString& URL) 63 | { 64 | UDolbyIOGetTokenFromURL* Self = NewObject(); 65 | Self->URL = URL; 66 | return Self; 67 | } 68 | 69 | void UGetDolbyIOToken::Activate() 70 | { 71 | if (AppKey.IsEmpty() || AppSecret.IsEmpty()) 72 | { 73 | return BroadcastError(OnError, "App key and secret must not be empty"); 74 | } 75 | if (TokenExpirationTimeInSeconds <= 0) 76 | { 77 | return BroadcastError(OnError, "Token expiration time must be greater than zero"); 78 | } 79 | 80 | FHttpRequestRef Request = FHttpModule::Get().CreateRequest(); 81 | Request->SetURL("https://session.voxeet.com/v1/oauth2/token"); 82 | Request->SetVerb("POST"); 83 | Request->AppendToHeader("Authorization", "Basic " + FBase64::Encode(AppKey + ":" + AppSecret)); 84 | Request->AppendToHeader("Content-Type", "application/x-www-form-urlencoded"); 85 | Request->SetContentAsString("grant_type=client_credentials&expires_in=" + 86 | FString::FromInt(TokenExpirationTimeInSeconds)); 87 | Request->OnProcessRequestComplete().BindUObject(this, &UGetDolbyIOToken::OnTokenObtained); 88 | Request->ProcessRequest(); 89 | } 90 | 91 | void UGetDolbyIOToken::OnTokenObtained(FHttpRequestPtr, FHttpResponsePtr Response, bool bConnectedSuccessfully) 92 | { 93 | if (!bConnectedSuccessfully) 94 | { 95 | return BroadcastError(OnError, "Could not connect to backend serving access tokens"); 96 | } 97 | if (!TryBroadcastToken(Response, TokenObtained)) 98 | { 99 | BroadcastError(OnError, "Could not get access token - verify app key and secret and validity"); 100 | } 101 | } 102 | 103 | UGetDolbyIOToken* UGetDolbyIOToken::GetDolbyIOToken(const FString& AppKey, const FString& AppSecret, 104 | int TokenExpirationTimeInSeconds) 105 | { 106 | UGetDolbyIOToken* Self = NewObject(); 107 | Self->AppKey = AppKey; 108 | Self->AppSecret = AppSecret; 109 | Self->TokenExpirationTimeInSeconds = TokenExpirationTimeInSeconds; 110 | return Self; 111 | } 112 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Utils/DolbyIOBroadcastEvent.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "Async/Async.h" 6 | 7 | namespace DolbyIO 8 | { 9 | template void BroadcastEvent(TDelegate& Event, TArgs&&... Args) 10 | { 11 | AsyncTask(ENamedThreads::GameThread, [=] { Event.Broadcast(Args...); }); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Utils/DolbyIOConversions.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "DolbyIOTypes.h" 6 | #include "Utils/DolbyIOCppSdk.h" 7 | 8 | namespace DolbyIO 9 | { 10 | constexpr int ScaleCenti = 100; 11 | 12 | std::string ToStdString(const FString& String); 13 | FString ToFString(const std::string& String); 14 | FText ToFText(const std::string& String); 15 | 16 | FString ToString(dolbyio::comms::conference_status Status); 17 | FString ToString(dolbyio::comms::participant_status Status); 18 | FString ToString(const dolbyio::comms::audio_device& Device); 19 | FString ToString(enum dolbyio::comms::audio_device::direction Direction); 20 | FString ToString(const dolbyio::comms::camera_device& Device); 21 | FString ToString(const dolbyio::comms::screen_share_source& Source); 22 | FString ToString(dolbyio::comms::screen_share_error::error_type err_type); 23 | 24 | EDolbyIOParticipantStatus ToEDolbyIOParticipantStatus(std::optional Status); 25 | FDolbyIOParticipantInfo ToFDolbyIOParticipantInfo(const dolbyio::comms::participant_info& Info); 26 | FDolbyIOVideoTrack ToFDolbyIOVideoTrack(const dolbyio::comms::video_track& Track); 27 | FDolbyIOVideoTrack ToFDolbyIOVideoTrack( 28 | const dolbyio::comms::utils::participant_track_map::value_type& TrackMapItem); 29 | 30 | dolbyio::comms::spatial_audio_style ToSdkSpatialAudioStyle(EDolbyIOSpatialAudioStyle SpatialAudioStyle); 31 | dolbyio::comms::screen_share_content_info ToSdkContentInfo(EDolbyIOScreenshareEncoderHint EncoderHint, 32 | EDolbyIOScreenshareMaxResolution MaxResolution, 33 | EDolbyIOScreenshareDownscaleQuality DownscaleQuality); 34 | dolbyio::comms::noise_reduction ToSdkNoiseReduction(EDolbyIONoiseReduction NoiseReduction); 35 | dolbyio::comms::voice_font ToSdkVoiceFont(EDolbyIOVoiceFont VoiceFont); 36 | dolbyio::comms::audio_capture_mode::standard ToSdkAudioCaptureMode(EDolbyIONoiseReduction NoiseReduction, 37 | EDolbyIOVoiceFont VoiceFont); 38 | dolbyio::comms::log_level ToSdkLogLevel(EDolbyIOLogLevel Level); 39 | dolbyio::comms::camera_device ToSdkVideoDevice(const FDolbyIOVideoDevice& VideoDevice); 40 | dolbyio::comms::video_codec ToSdkVideoCodec(EDolbyIOVideoCodec Codec); 41 | 42 | using FSdkNativeDeviceID = 43 | #if PLATFORM_WINDOWS 44 | std::string; 45 | #else 46 | unsigned; 47 | #endif 48 | FSdkNativeDeviceID ToSdkNativeDeviceID(const FString& ID); 49 | FString ToUnrealDeviceID(const FSdkNativeDeviceID& ID); 50 | 51 | FDolbyIOAudioDevice ToFDolbyIOAudioDevice(const dolbyio::comms::audio_device& Device); 52 | FDolbyIOVideoDevice ToFDolbyIOVideoDevice(const dolbyio::comms::camera_device& Device); 53 | 54 | FDolbyIOScreenshareSource ToFDolbyIOScreenshareSource(const dolbyio::comms::screen_share_source& Source); 55 | dolbyio::comms::screen_share_source ToSdkScreenshareSource(const FDolbyIOScreenshareSource& Source); 56 | } 57 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Utils/DolbyIOCppSdk.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "HAL/Platform.h" 6 | 7 | #if PLATFORM_MAC 8 | #define DOLBYIO_COMMS_SUPPRESS_APPLE_NO_RTTI_WARNING 9 | #define __NUMBERFORMATTING__ // redefinition of 'FVector' 10 | #endif 11 | 12 | #include 13 | #include 14 | 15 | #if PLATFORM_WINDOWS | PLATFORM_MAC 16 | #include 17 | #endif 18 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Utils/DolbyIOErrorHandler.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "Utils/DolbyIOErrorHandler.h" 4 | 5 | #include "DolbyIO.h" 6 | #include "Utils/DolbyIOBroadcastEvent.h" 7 | #include "Utils/DolbyIOConversions.h" 8 | #include "Utils/DolbyIOLogging.h" 9 | 10 | #include "Misc/Paths.h" 11 | 12 | namespace DolbyIO 13 | { 14 | using namespace dolbyio::comms; 15 | 16 | FErrorHandler::FErrorHandler(const FString& File, int Line, UDolbyIOSubsystem& DolbyIOSubsystem) 17 | : File(FPaths::GetCleanFilename(File)), Line(Line), DolbyIOSubsystem(DolbyIOSubsystem) 18 | { 19 | } 20 | 21 | FErrorHandler::FErrorHandler(const FString& File, int Line, UDolbyIOSubsystem& DolbyIOSubsystem, 22 | const FDolbyIOOnErrorDelegate& OnError) 23 | : File(FPaths::GetCleanFilename(File)), Line(Line), DolbyIOSubsystem(DolbyIOSubsystem), OnError(&OnError) 24 | { 25 | } 26 | 27 | void FErrorHandler::operator()(std::exception_ptr&& ExcPtr) const 28 | { 29 | #if PLATFORM_ANDROID 30 | HandleErrorOnGameThread(MoveTemp(ExcPtr)); 31 | #else 32 | HandleError([ExcP = MoveTemp(ExcPtr)] { std::rethrow_exception(ExcP); }); 33 | #endif 34 | } 35 | 36 | void FErrorHandler::HandleError() const 37 | { 38 | HandleError([] { throw; }); 39 | } 40 | 41 | #define DLB_CATCH(Exception) \ 42 | catch (const dolbyio::comms::Exception& Ex) \ 43 | { \ 44 | LogException("dolbyio::comms::" #Exception, Ex.what()); \ 45 | } 46 | void FErrorHandler::HandleError(TFunction Callee) const 47 | try 48 | { 49 | Callee(); 50 | } 51 | DLB_CATCH(async_operation_canceled) // : exception 52 | DLB_CATCH(certificate_exception) // : exception 53 | DLB_CATCH(conference_state_exception) // : conference_exception 54 | DLB_CATCH(dvc_error_exception) // : media_engine_exception 55 | DLB_CATCH(create_answer_exception) // : media_engine_exception 56 | DLB_CATCH(create_peer_connection_exception) // : media_engine_exception 57 | DLB_CATCH(ice_candidate_exception) // : media_engine_exception 58 | DLB_CATCH(media_stream_exception) // : media_engine_exception 59 | DLB_CATCH(peer_connection_disconnected_exception) // : media_engine_exception 60 | DLB_CATCH(peer_connection_failed_exception) // : media_engine_exception 61 | DLB_CATCH(sdp_exception) // : media_engine_exception 62 | DLB_CATCH(media_engine_exception) // : conference_exception 63 | DLB_CATCH(conference_exception) // : exception 64 | DLB_CATCH(http_exception) // : io_exception 65 | DLB_CATCH(invalid_token_exception) // : restapi_exception 66 | DLB_CATCH(restapi_exception) // : io_exception 67 | DLB_CATCH(security_check_exception) // : io_exception 68 | DLB_CATCH(signaling_channel_exception) // : io_exception 69 | DLB_CATCH(io_exception) // : exception 70 | DLB_CATCH(json_exception) // : exception 71 | DLB_CATCH(jwt_exception) // : exception 72 | DLB_CATCH(dvc_exception) // : media_exception 73 | DLB_CATCH(media_exception) // : exception 74 | DLB_CATCH(session_exception) // : exception 75 | DLB_CATCH(spatial_placement_exception) // : exception 76 | DLB_CATCH(exception) 77 | catch (const std::exception& Ex) 78 | { 79 | LogException("std::exception", Ex.what()); 80 | } 81 | catch (...) 82 | { 83 | LogException("unknown exception", ""); 84 | } 85 | 86 | void FErrorHandler::HandleErrorOnGameThread(std::exception_ptr&& ExcPtr) const 87 | { 88 | AsyncTask(ENamedThreads::GameThread, 89 | [ExcP = MoveTemp(ExcPtr), CopySelf = *this] 90 | { 91 | try 92 | { 93 | std::rethrow_exception(ExcP); 94 | } 95 | catch (...) 96 | { 97 | CopySelf.HandleError(); 98 | } 99 | }); 100 | } 101 | 102 | void FErrorHandler::LogException(const FString& Type, const FString& What) const 103 | { 104 | const FString ErrorMsg = Type + ": " + What; 105 | DLB_UE_LOG_BASE(Error, "Caught %s (conference status: %s, %s:%d)", *ErrorMsg, 106 | *ToString(DolbyIOSubsystem.ConferenceStatus), *File, Line); 107 | if (OnError) 108 | { 109 | BroadcastEvent(*OnError, ErrorMsg); 110 | } 111 | } 112 | 113 | void FErrorHandler::Warn(const FDolbyIOOnErrorDelegate& OnError, const FString& Msg) 114 | { 115 | DLB_UE_LOG_BASE(Warning, "%s", *Msg); 116 | BroadcastEvent(OnError, Msg); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Utils/DolbyIOErrorHandler.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "Containers/UnrealString.h" 6 | 7 | class UDolbyIOSubsystem; 8 | class FDolbyIOOnErrorDelegate; 9 | 10 | namespace DolbyIO 11 | { 12 | class FErrorHandler final 13 | { 14 | public: 15 | #define DLB_ERROR_HANDLER(OnError) FErrorHandler(__FILE__, __LINE__, GetSubsystem(), OnError) 16 | #define DLB_ERROR_HANDLER_NO_DELEGATE FErrorHandler(__FILE__, __LINE__, GetSubsystem()) 17 | 18 | #define DLB_WARNING(OnError, Msg) FErrorHandler::Warn(OnError, Msg) 19 | 20 | FErrorHandler(const FString& File, int Line, UDolbyIOSubsystem& DolbyIOSubsystem); 21 | FErrorHandler(const FString& File, int Line, UDolbyIOSubsystem& DolbyIOSubsystem, 22 | const FDolbyIOOnErrorDelegate& OnError); 23 | 24 | void operator()(std::exception_ptr&& ExcPtr) const; 25 | void HandleError() const; 26 | 27 | static void Warn(const FDolbyIOOnErrorDelegate& OnError, const FString& Msg); 28 | 29 | private: 30 | void HandleError(TFunction Callee) const; 31 | void HandleErrorOnGameThread(std::exception_ptr&& ExcPtr) const; 32 | void LogException(const FString& Type, const FString& What) const; 33 | 34 | const FString File; 35 | const int Line; 36 | const UDolbyIOSubsystem& DolbyIOSubsystem; 37 | const FDolbyIOOnErrorDelegate* const OnError{}; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Utils/DolbyIOLogging.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "Logging/LogMacros.h" 6 | 7 | DECLARE_LOG_CATEGORY_EXTERN(LogDolbyIO, Log, All); 8 | 9 | #define DLB_UE_LOG_BASE(Verbosity, Format, ...) UE_LOG(LogDolbyIO, Verbosity, TEXT(Format), ##__VA_ARGS__) 10 | #define DLB_UE_LOG(Format, ...) DLB_UE_LOG_BASE(Log, Format, ##__VA_ARGS__) 11 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Video/DolbyIOVideoFrameHandler.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "Utils/DolbyIOCppSdk.h" 6 | 7 | namespace DolbyIO 8 | { 9 | class FVideoFrameHandler final : public dolbyio::comms::video_frame_handler 10 | { 11 | public: 12 | FVideoFrameHandler(std::shared_ptr Sink) : Sink(std::move(Sink)) {} 13 | 14 | std::shared_ptr sink() override 15 | { 16 | return Sink; 17 | } 18 | std::shared_ptr source() override 19 | { 20 | return nullptr; 21 | } 22 | 23 | private: 24 | std::shared_ptr Sink; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Video/DolbyIOVideoProcessingFrameHandler.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "Utils/DolbyIOCppSdk.h" 6 | 7 | namespace DolbyIO 8 | { 9 | class FVideoProcessingFrameHandler final : public dolbyio::comms::video_frame_handler, 10 | public dolbyio::comms::video_source, 11 | public dolbyio::comms::video_sink, 12 | public std::enable_shared_from_this 13 | { 14 | public: 15 | FVideoProcessingFrameHandler(std::shared_ptr VideoFrameHandler, 16 | std::shared_ptr PreviewSink) 17 | : VideoFrameHandler(std::move(VideoFrameHandler)), PreviewSink(std::move(PreviewSink)) 18 | { 19 | } 20 | 21 | private: 22 | std::shared_ptr sink() override 23 | { 24 | return VideoFrameHandler->sink(); 25 | } 26 | std::shared_ptr source() override 27 | { 28 | return shared_from_this(); 29 | } 30 | 31 | void set_sink(const std::shared_ptr& Sink, 32 | const dolbyio::comms::video_source::config& Config) override 33 | { 34 | SdkSink = Sink; 35 | VideoFrameHandler->source()->set_sink(shared_from_this(), Config); 36 | } 37 | 38 | void handle_frame(const dolbyio::comms::video_frame& VideoFrame) override 39 | { 40 | if (SdkSink) 41 | { 42 | SdkSink->handle_frame(VideoFrame); 43 | PreviewSink->handle_frame(VideoFrame); 44 | } 45 | } 46 | 47 | std::shared_ptr VideoFrameHandler; 48 | std::shared_ptr PreviewSink; 49 | std::shared_ptr SdkSink; 50 | }; 51 | 52 | }; 53 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Video/DolbyIOVideoSink.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIOVideoSink.h" 4 | 5 | #include "DolbyIOVideoTexture.h" 6 | #include "Utils/DolbyIOLogging.h" 7 | 8 | #include 9 | 10 | #include "Async/Async.h" 11 | #include "Engine/Texture2D.h" 12 | #include "Materials/MaterialInstanceDynamic.h" 13 | 14 | namespace DolbyIO 15 | { 16 | using namespace dolbyio::comms; 17 | 18 | namespace 19 | { 20 | constexpr auto TexParamName = "DolbyIO Frame"; 21 | 22 | void UnbindMaterialImpl(UMaterialInstanceDynamic& Material) 23 | { 24 | Material.SetTextureParameterValue(TexParamName, FVideoTexture::GetEmptyTexture()); 25 | } 26 | } 27 | 28 | FVideoSink::FVideoSink(const FString& VideoTrackID) : VideoTrackID(VideoTrackID) {} 29 | 30 | void FVideoSink::OnTextureCreated(FOnTextureCreated OnTextureCreated) 31 | { 32 | if (Texture) 33 | { 34 | return OnTextureCreated(); 35 | } 36 | OnTexCreated = MoveTemp(OnTextureCreated); 37 | } 38 | 39 | UTexture2D* FVideoSink::GetTexture() 40 | { 41 | return Texture ? Texture->GetTexture() : nullptr; 42 | } 43 | 44 | void FVideoSink::BindMaterial(UMaterialInstanceDynamic* Material) 45 | { 46 | if (IsValid(Material)) 47 | { 48 | DLB_UE_LOG("Binding material %u to video track ID %s", Material->GetUniqueID(), *VideoTrackID); 49 | Materials.Add(Material); 50 | if (Texture) 51 | { 52 | Material->SetTextureParameterValue(TexParamName, GetTexture()); 53 | } 54 | } 55 | } 56 | 57 | void FVideoSink::UnbindMaterial(UMaterialInstanceDynamic* Material) 58 | { 59 | if (Materials.Remove(Material) && IsValid(Material)) 60 | { 61 | DLB_UE_LOG("Unbinding material %u from video track ID %s", Material->GetUniqueID(), *VideoTrackID); 62 | UnbindMaterialImpl(*Material); 63 | } 64 | } 65 | 66 | void FVideoSink::UnbindAllMaterials() 67 | { 68 | AsyncTask(ENamedThreads::GameThread, 69 | [MaterialsArray = Materials.Array()] 70 | { 71 | for (UMaterialInstanceDynamic* Material : MaterialsArray) 72 | { 73 | if (IsValid(Material)) 74 | { 75 | UnbindMaterialImpl(*Material); 76 | } 77 | } 78 | }); 79 | } 80 | 81 | void FVideoSink::Disable() 82 | { 83 | bIsEnabled = false; 84 | } 85 | 86 | void FVideoSink::handle_frame(const video_frame& VideoFrame) 87 | { 88 | if (!bIsEnabled) 89 | { 90 | return; 91 | } 92 | 93 | !Texture ? CreateTexture(VideoFrame.width(), VideoFrame.height()) 94 | : ResizeTexture(VideoFrame.width(), VideoFrame.height()); 95 | Convert(VideoFrame); 96 | AsyncTask(ENamedThreads::GameThread, [Tex = this->Texture] { Tex->Render(); }); 97 | } 98 | 99 | void FVideoSink::CreateTexture(int Width, int Height) 100 | { 101 | FEvent* TexCreated = FGenericPlatformProcess::GetSynchEventFromPool(); 102 | AsyncTask(ENamedThreads::GameThread, 103 | [=] 104 | { 105 | Texture = MakeShared(Width, Height); 106 | TexCreated->Trigger(); 107 | 108 | for (UMaterialInstanceDynamic* Material : Materials) 109 | { 110 | if (IsValid(Material)) 111 | { 112 | Material->SetTextureParameterValue(TexParamName, GetTexture()); 113 | } 114 | } 115 | }); 116 | TexCreated->Wait(); 117 | FGenericPlatformProcess::ReturnSynchEventToPool(TexCreated); 118 | OnTexCreated(); 119 | DLB_UE_LOG("Created texture %u for video track ID %s %dx%d", GetTexture()->GetUniqueID(), *VideoTrackID, Width, 120 | Height); 121 | } 122 | 123 | void FVideoSink::ResizeTexture(int Width, int Height) 124 | { 125 | if (Texture->Resize(Width, Height)) 126 | { 127 | AsyncTask(ENamedThreads::GameThread, 128 | [=, Tex = this->Texture] 129 | { 130 | DLB_UE_LOG("Resizing texture %u: old %dx%d new %dx%d", Tex->GetTexture()->GetUniqueID(), 131 | Tex->GetTexture()->GetSizeX(), Tex->GetTexture()->GetSizeY(), Width, Height); 132 | }); 133 | } 134 | } 135 | 136 | void FVideoSink::Convert(const video_frame& VideoFrame) 137 | { 138 | std::shared_ptr VideoFrameBuffer = VideoFrame.video_frame_buffer(); 139 | 140 | if (!VideoFrameBuffer) 141 | { 142 | return; 143 | } 144 | 145 | #if !PLATFORM_MAC 146 | if (VideoFrameBuffer->type() == video_frame_buffer::type::native) 147 | { 148 | if (std::shared_ptr BufferI420 = VideoFrameBuffer->to_i420()) 149 | { 150 | VideoFrameBuffer = std::move(BufferI420); 151 | } 152 | } 153 | #endif 154 | 155 | const int Width = VideoFrame.width(); 156 | const int Height = VideoFrame.height(); 157 | const int DestStride = Width * FVideoTexture::Stride; 158 | 159 | FScopeLock Lock{Texture->GetBufferLock()}; 160 | 161 | enum video_frame_buffer::type VideoFrameBufferType = VideoFrameBuffer->type(); 162 | 163 | if (VideoFrameBufferType == video_frame_buffer::type::argb) 164 | { 165 | if (const video_frame_buffer_argb_interface* FrameARGB = VideoFrameBuffer->get_argb()) 166 | { 167 | video_utils::format_converter::argb_copy(FrameARGB->data(), FrameARGB->stride(), Texture->GetBuffer(), 168 | DestStride, Width, Height); 169 | } 170 | } 171 | else if (VideoFrameBufferType == video_frame_buffer::type::i420) 172 | { 173 | if (const video_frame_buffer_i420_interface* FrameI420 = VideoFrameBuffer->get_i420()) 174 | { 175 | video_utils::format_converter::i420_to_argb( 176 | FrameI420->data_y(), FrameI420->stride_y(), FrameI420->data_u(), FrameI420->stride_u(), 177 | FrameI420->data_v(), FrameI420->stride_v(), Texture->GetBuffer(), DestStride, Width, Height); 178 | } 179 | } 180 | else if (VideoFrameBufferType == video_frame_buffer::type::nv12) 181 | { 182 | if (const video_frame_buffer_nv12_interface* FrameNV12 = VideoFrameBuffer->get_nv12()) 183 | { 184 | video_utils::format_converter::nv12_to_argb(FrameNV12->data_y(), FrameNV12->stride_y(), 185 | FrameNV12->data_uv(), FrameNV12->stride_uv(), 186 | Texture->GetBuffer(), DestStride, Width, Height); 187 | } 188 | } 189 | #if PLATFORM_MAC 190 | else if (VideoFrameBufferType == video_frame_buffer::type::native) 191 | { 192 | class FLockedCVPixelBuffer 193 | { 194 | public: 195 | FLockedCVPixelBuffer(CVPixelBufferRef PixelBuffer) : PixelBuffer(PixelBuffer) 196 | { 197 | CVPixelBufferLockBaseAddress(PixelBuffer, kCVPixelBufferLock_ReadOnly); 198 | } 199 | ~FLockedCVPixelBuffer() 200 | { 201 | CVPixelBufferUnlockBaseAddress(PixelBuffer, kCVPixelBufferLock_ReadOnly); 202 | } 203 | 204 | operator CVPixelBufferRef() const 205 | { 206 | return PixelBuffer; 207 | } 208 | 209 | private: 210 | CVPixelBufferRef PixelBuffer; 211 | }; 212 | 213 | if (const video_frame_buffer_native_interface* FrameNative = VideoFrameBuffer->get_native()) 214 | { 215 | FLockedCVPixelBuffer PixelBuffer{FrameNative->cv_pixel_buffer_ref()}; 216 | video_utils::format_converter::nv12_to_argb( 217 | static_cast(CVPixelBufferGetBaseAddressOfPlane(PixelBuffer, 0)), 218 | CVPixelBufferGetBytesPerRowOfPlane(PixelBuffer, 0), 219 | static_cast(CVPixelBufferGetBaseAddressOfPlane(PixelBuffer, 1)), 220 | CVPixelBufferGetBytesPerRowOfPlane(PixelBuffer, 1), Texture->GetBuffer(), DestStride, Width, 221 | Height); 222 | } 223 | } 224 | #endif 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Video/DolbyIOVideoSink.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "Utils/DolbyIOCppSdk.h" 6 | 7 | #include "Templates/SharedPointer.h" 8 | 9 | class UMaterialInstanceDynamic; 10 | class UTexture2D; 11 | 12 | namespace DolbyIO 13 | { 14 | class FVideoSink final : public dolbyio::comms::video_sink 15 | { 16 | using FOnTextureCreated = TFunction; 17 | 18 | public: 19 | FVideoSink(const FString& VideoTrackID); 20 | 21 | void OnTextureCreated(FOnTextureCreated OnTextureCreated); 22 | 23 | UTexture2D* GetTexture(); 24 | void BindMaterial(UMaterialInstanceDynamic* Material); 25 | void UnbindMaterial(UMaterialInstanceDynamic* Material); 26 | void UnbindAllMaterials(); 27 | void Disable(); 28 | 29 | private: 30 | void handle_frame(const dolbyio::comms::video_frame&) override; 31 | 32 | void CreateTexture(int Width, int Height); 33 | void ResizeTexture(int Width, int Height); 34 | void Convert(const dolbyio::comms::video_frame& VideoFrame); 35 | 36 | TSharedPtr Texture; 37 | TSet Materials; 38 | const FString VideoTrackID; 39 | FOnTextureCreated OnTexCreated = [] {}; 40 | bool bIsEnabled = true; 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Video/DolbyIOVideoTexture.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #include "DolbyIOVideoTexture.h" 4 | 5 | #include "Engine/Texture2D.h" 6 | #include "RenderingThread.h" 7 | #include "Runtime/Launch/Resources/Version.h" 8 | #include "TextureResource.h" 9 | 10 | namespace DolbyIO 11 | { 12 | FVideoTexture::FVideoTexture(int Width, int Height) : Texture(UTexture2D::CreateTransient(Width, Height)) 13 | { 14 | Texture->AddToRoot(); 15 | Texture->UpdateResource(); 16 | Resize(Width, Height); 17 | } 18 | 19 | FVideoTexture::~FVideoTexture() 20 | { 21 | Texture->RemoveFromRoot(); 22 | } 23 | 24 | UTexture2D* FVideoTexture::GetTexture() 25 | { 26 | return Texture; 27 | } 28 | 29 | bool FVideoTexture::Resize(int InWidth, int InHeight) 30 | { 31 | FScopeLock Lock{&BufferLock}; 32 | 33 | if (Width == InWidth && Height == InHeight) 34 | { 35 | return false; 36 | } 37 | 38 | Width = InWidth; 39 | Height = InHeight; 40 | Buffer.Reserve(Width * Height * Stride); 41 | return true; 42 | } 43 | 44 | FCriticalSection* FVideoTexture::GetBufferLock() 45 | { 46 | return &BufferLock; 47 | } 48 | 49 | uint8* FVideoTexture::GetBuffer() 50 | { 51 | return Buffer.GetData(); 52 | } 53 | 54 | namespace 55 | { 56 | #if ENGINE_MAJOR_VERSION == 5 57 | #define PLATFORM_DATA GetPlatformData() 58 | #else 59 | #define PLATFORM_DATA PlatformData 60 | #endif 61 | 62 | class FLockedTexture 63 | { 64 | public: 65 | FLockedTexture(UTexture2D& Tex) 66 | : Tex(Tex), PlatformData(*Tex.PLATFORM_DATA), Mip(PlatformData.Mips[0]), 67 | Buffer(Mip.BulkData.Lock(LOCK_READ_WRITE)) 68 | { 69 | } 70 | 71 | ~FLockedTexture() 72 | { 73 | Mip.BulkData.Unlock(); 74 | Tex.UpdateResource(); 75 | FlushRenderingCommands(); 76 | } 77 | 78 | void Resize(int Width, int Height) 79 | { 80 | Mip.SizeX = PlatformData.SizeX = Width; 81 | Mip.SizeY = PlatformData.SizeY = Height; 82 | Buffer = Mip.BulkData.Realloc(Width * Height * FVideoTexture::Stride); 83 | Clear(); 84 | } 85 | 86 | void Clear() 87 | { 88 | FMemory::Memzero(Buffer, Mip.BulkData.GetBulkDataSize()); 89 | } 90 | 91 | private: 92 | UTexture2D& Tex; 93 | FTexturePlatformData& PlatformData; 94 | FTexture2DMipMap& Mip; 95 | void* Buffer; 96 | }; 97 | } 98 | 99 | void FVideoTexture::Render() 100 | { 101 | if (Texture->GetSizeX() != Width || Texture->GetSizeY() != Height) 102 | { 103 | FLockedTexture Tex{*Texture}; 104 | Tex.Resize(Width, Height); 105 | } 106 | 107 | ENQUEUE_RENDER_COMMAND(DolbyIOUpdateTexture) 108 | ( 109 | [SharedThis = AsShared()](FRHICommandListImmediate& RHICmdList) 110 | { 111 | FScopeLock Lock{SharedThis->GetBufferLock()}; 112 | auto FRHITexture2D_Ptr = SharedThis->Texture->GetResource()->GetTexture2DRHI(); 113 | uint32 SizeX = FRHITexture2D_Ptr->GetSizeX(), SizeY = FRHITexture2D_Ptr->GetSizeY(); 114 | RHIUpdateTexture2D(FRHITexture2D_Ptr, 0, 115 | FUpdateTextureRegion2D{0, 0, 0, 0, SizeX, SizeY}, 116 | SizeX * Stride, SharedThis->GetBuffer()); 117 | }); 118 | } 119 | 120 | namespace 121 | { 122 | UTexture2D* CreateEmptyTexture() 123 | { 124 | UTexture2D* Ret = UTexture2D::CreateTransient(1, 1); 125 | Ret->AddToRoot(); 126 | FLockedTexture Tex{*Ret}; 127 | Tex.Clear(); 128 | return Ret; 129 | } 130 | } 131 | 132 | UTexture2D* FVideoTexture::GetEmptyTexture() 133 | { 134 | static UTexture2D* Ret = CreateEmptyTexture(); 135 | return Ret; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /DolbyIO/Source/Private/Video/DolbyIOVideoTexture.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "HAL/CriticalSection.h" 6 | #include "Templates/SharedPointer.h" 7 | 8 | class UTexture2D; 9 | 10 | namespace DolbyIO 11 | { 12 | class FVideoTexture final : public TSharedFromThis 13 | { 14 | public: 15 | FVideoTexture(int Width, int Height); 16 | ~FVideoTexture(); 17 | 18 | UTexture2D* GetTexture(); 19 | 20 | bool Resize(int Width, int Height); 21 | FCriticalSection* GetBufferLock(); 22 | uint8* GetBuffer(); 23 | void Render(); 24 | 25 | static UTexture2D* GetEmptyTexture(); 26 | 27 | static constexpr int Stride = 4; 28 | 29 | private: 30 | UTexture2D* const Texture; 31 | TArray Buffer; 32 | FCriticalSection BufferLock; 33 | int Width; 34 | int Height; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /DolbyIO/Source/Public/DolbyIOAuthentication.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | #include "Kismet/BlueprintAsyncActionBase.h" 6 | 7 | #include "Interfaces/IHttpRequest.h" 8 | 9 | #include "DolbyIOAuthentication.generated.h" 10 | 11 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FGetDolbyIOTokenOutputPin, const FString&, Token, const FString&, 12 | ErrorMsg); 13 | 14 | UCLASS() 15 | class DOLBYIO_API UDolbyIOGetTokenFromURL : public UBlueprintAsyncActionBase 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | /** Gets a Dolby.io client access token from a URL. 21 | * 22 | * For convenience during early development and prototyping, this function is provided to acquire an client access 23 | * token directly from the game. 24 | * 25 | * Using this function effectively distributes the permanent app credential with your Unreal application, which is 26 | * not safe for production deployment. Follow our security best practices 27 | * (https://docs.dolby.io/communications-apis/docs/guides-client-authentication) to set up a server through which 28 | * you can acquire a temporary client access token. 29 | * 30 | * @param URL - The URL to use to obtain the token. 31 | */ 32 | UFUNCTION(BlueprintCallable, Category = "Dolby.io Comms", 33 | Meta = (BlueprintInternalUseOnly = "true", DisplayName = "Dolby.io Get Token From URL")) 34 | static UDolbyIOGetTokenFromURL* DolbyIOGetTokenFromURL(const FString& URL); 35 | 36 | UPROPERTY(BlueprintAssignable) 37 | FGetDolbyIOTokenOutputPin OnTokenObtained; 38 | 39 | UPROPERTY(BlueprintAssignable) 40 | FGetDolbyIOTokenOutputPin OnError; 41 | 42 | private: 43 | void Activate() override; 44 | 45 | void OnTokenObtainedImpl(FHttpRequestPtr, FHttpResponsePtr, bool bConnectedSuccessfully); 46 | 47 | FString URL; 48 | }; 49 | 50 | UCLASS() 51 | class DOLBYIO_API UGetDolbyIOToken : public UBlueprintAsyncActionBase 52 | { 53 | GENERATED_BODY() 54 | 55 | public: 56 | /** Gets a Dolby.io client access token using an app key and secret combination. 57 | * 58 | * For convenience during early development and prototyping, this function is provided to acquire an client access 59 | * token directly from the game. 60 | * 61 | * Using this function effectively distributes the permanent app credential with your Unreal application, which is 62 | * not safe for production deployment. Follow our security best practices 63 | * (https://docs.dolby.io/communications-apis/docs/guides-client-authentication) to set up a server through which 64 | * you can acquire a temporary client access token. 65 | * 66 | * @param AppKey - The app key. 67 | * @param AppSecret - The app secret. 68 | * @param TokenExpirationTimeInSeconds - The token's expiration time (in seconds). 69 | */ 70 | UFUNCTION(BlueprintCallable, Category = "Dolby.io Comms", 71 | Meta = (BlueprintInternalUseOnly = "true", DisplayName = "Dolby.io Get Token Using App Key And Secret")) 72 | static UGetDolbyIOToken* GetDolbyIOToken(const FString& AppKey, const FString& AppSecret, 73 | int TokenExpirationTimeInSeconds = 3600); 74 | 75 | UPROPERTY(BlueprintAssignable) 76 | FGetDolbyIOTokenOutputPin TokenObtained; 77 | 78 | UPROPERTY(BlueprintAssignable) 79 | FGetDolbyIOTokenOutputPin OnError; 80 | 81 | private: 82 | void Activate() override; 83 | 84 | void OnTokenObtained(FHttpRequestPtr, FHttpResponsePtr, bool bConnectedSuccessfully); 85 | 86 | FString AppKey; 87 | FString AppSecret; 88 | int TokenExpirationTimeInSeconds; 89 | }; 90 | -------------------------------------------------------------------------------- /DolbyIO/Source/Public/DolbyIOCppSdkFwd.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Dolby Laboratories 2 | 3 | #pragma once 4 | 5 | namespace dolbyio::comms 6 | { 7 | enum class conference_status; 8 | class refresh_token; 9 | class sdk; 10 | 11 | namespace plugin 12 | { 13 | class video_processor; 14 | } 15 | 16 | struct active_speaker_changed; 17 | struct audio_device_changed; 18 | struct audio_levels; 19 | struct conference_message_received; 20 | struct local_participant_updated; 21 | struct remote_participant_added; 22 | struct remote_participant_updated; 23 | struct remote_video_track_added; 24 | struct remote_video_track_removed; 25 | struct screen_share_error; 26 | 27 | namespace utils 28 | { 29 | struct vfs_event; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Dolby Laboratories 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :warning: This repository is no longer maintained :warning: 2 | 3 | [![Build Unreal Plugin](https://github.com/DolbyIO/comms-sdk-unreal/actions/workflows/build.yml/badge.svg)](https://github.com/DolbyIO/comms-sdk-unreal/actions/workflows/build.yml) 4 | [![Documentation](https://github.com/DolbyIO/comms-sdk-unreal/actions/workflows/deploy-to-github-pages.yml/badge.svg)](https://github.com/DolbyIO/comms-sdk-unreal/actions/workflows/deploy-to-github-pages.yml) 5 | [![License](https://img.shields.io/github/license/DolbyIO/comms-sdk-unreal)](LICENSE) 6 | 7 | # Dolby.io Virtual Worlds plugin for Unreal Engine 8 | 9 | With the Dolby.io Virtual Worlds plugin for Unreal Engine, you can easily integrate [Dolby.io](https://dolby.io) Spatial Audio, powered by Dolby Atmos technology into your virtual world applications. 10 | 11 | You can find the plugin documentation [here](https://api-references.dolby.io/comms-sdk-unreal/). 12 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docs/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/docs/Intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | title: Intro 4 | --- 5 | 6 | # Dolby.io Virtual Worlds plugin for Unreal Engine 7 | 8 | With the Dolby.io Virtual Worlds plugin for Unreal Engine, you can easily integrate [Dolby.io](https://dolby.io) Spatial Audio, powered by Dolby Atmos technology into your virtual world applications. 9 | 10 | ## Supported platforms 11 | 12 | The plugin is compatible with the following operating systems: 13 | - Windows 10 or later 14 | - macOS 10.14 or later if you use UE4 15 | - macOS 12.5 or later if you use UE5 16 | - Ubuntu 20.04 or later 17 | - Android 8 or later if you use UE5.3 or later (experimental, arm64-v8a devices only) 18 | 19 | ## Prerequisites 20 | 21 | Before you start, make sure that you have: 22 | - Unreal Engine 4.27 or later installed on your computer. For more details, see the [Unreal Engine download](https://www.unrealengine.com/en-US/download) page and the [4.27](https://docs.unrealengine.com/4.27/en-US/Basics/InstallingUnrealEngine/) or [5.2](https://docs.unrealengine.com/5.2/en-US/installing-unreal-engine/) installation manuals. 23 | - A [Dolby.io](https://dolby.io) account. If you do not have an account, [sign up](https://dolby.io/signup) for free. 24 | - A client access token or an app key and an app secret copied from the Communications & Media [Dolby.io Dashboard](https://dashboard.dolby.io/). 25 | -------------------------------------------------------------------------------- /docs/docs/blueprints/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Blueprint nodes", 3 | "position": 3, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Dolby.io Communications API Virtual Worlds Plugin for Unreal Engine - Blueprint nodes" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/docs/blueprints/img/docsVersionDropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/docs/blueprints/img/docsVersionDropdown.png -------------------------------------------------------------------------------- /docs/docs/blueprints/img/localeDropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/docs/blueprints/img/localeDropdown.png -------------------------------------------------------------------------------- /docs/docs/blueprints/types.mdx: -------------------------------------------------------------------------------- 1 | import VoiceFontsTable from '@site/src/components/VoiceFontsTable'; 2 | 3 | # Types 4 | 5 | ## Dolby.io Audio Device 6 | 7 | The platform-agnostic description of an audio device. 8 | 9 | | Struct member | Type | Description | 10 | |---|:---|:---| 11 | | **Name** | [text](https://docs.unrealengine.com/5.2/en-US/ftext-in-unreal-engine/) | The name of the device. | 12 | | **Native ID** | string | The native ID of the device. | 13 | 14 | --- 15 | 16 | ## Dolby.io Connection Mode 17 | 18 | Defines whether to connect as an active user or a listener. 19 | 20 | | Enum value | Description | 21 | |---|:---| 22 | | **Active** | Join a conference as an active user. | 23 | | **Listener Regular** | Receive multiple video streams from senders. | 24 | | **Listener RTS** | Receive a realtime mixed stream. | 25 | 26 | --- 27 | 28 | ## Dolby.io Log Level 29 | 30 | The level of logs of the Dolby.io C++ SDK. 31 | 32 | | Enum value | Description | 33 | |---|:---| 34 | | **Off** | Turns off logging. | 35 | | **Error** | The error level logging generates logs when an error occurs and the SDK cannot properly function. | 36 | | **Warning** | The warning level logging generates logs when the SDK detects an unexpected problem but is still able to work as usual. | 37 | | **Info** | The info level logging generates an informative number of logs. | 38 | | **Debug** | The debug level logging generates a high number of logs to provide diagnostic information in a detailed manner. | 39 | | **Verbose** | The verbose level logging generates the highest number of logs, including even the HTTP requests. | 40 | 41 | --- 42 | 43 | ## Dolby.io Noise Reduction 44 | 45 | The audio noise reduction level. 46 | 47 | | Enum value | Description | 48 | |---|:---| 49 | | **High** | Removes all background sounds to improve voice quality. Use this mode if you want to send only voice to a conference. | 50 | | **Low** | Removes stationary background sounds, such as the sound of a computer fan, air conditioning, or microphone hum, from audio transmitted to a conference. In this mode, non-stationary sounds are transmitted to give participants full context of other participants' environments and create a more realistic audio experience. | 51 | 52 | --- 53 | 54 | ## Dolby.io Participant Info 55 | 56 | Contains the current status of a conference participant and information whether the participant's audio is enabled. 57 | 58 | | Struct member | Type | Description | 59 | |---|:---|:---| 60 | | **User ID** | string | The unique identifier of the participant. | 61 | | **Name** | string | The participant's name. | 62 | | **External ID** | string | The external unique identifier that the customer's application can add to the participant while opening a session. If a participant uses the same external ID in conferences, the participant's ID also remains the same across all sessions. | 63 | | **Avatar URL** | string | The URL of the participant's avatar. | 64 | | **Is Listener** | bool | Indicates whether the participants is a listener. True means this is a participant who can receive audio and video streams, but cannot send any stream to a conference. False means this is a participant who can send and receive an audio and video stream during a conference. | 65 | | **Is Sending Audio** | bool | A boolean that informs whether the participant is sending audio into conference. | 66 | | **Is Audible Locally** | bool | Indicates whether a remote participant is audible locally. This will always be false for the local participant. | 67 | | **Status** | [Dolby.io Participant Status](#dolbyio-participant-status) | The conference status of the remote participant. | 68 | 69 | --- 70 | 71 | ## Dolby.io Participant Status 72 | 73 | | Enum value | Description | 74 | |---|:---| 75 | | **Reserved** | A participant is invited to a conference. | 76 | | **Connecting** | A participant received the conference invitation and is connecting to a conference. | 77 | | **On Air** | A participant successfully connected to a conference. | 78 | | **Decline** | An invited participant declined the conference invitation. Currently, the Web SDK does not offer the decline method, although participants who use Web SDK can receive the Decline status from other application users who use the Android or iOS SDK. The Web SDK does not receive the notification if the invited participant uses the decline method after joining a conference. | 79 | | **Left** | A participant left the conference. | 80 | | **Inactive** | A participant did not enable audio, video, or screen-share and, therefore, is not connected to any stream. | 81 | | **Warning** | A participant experiences a peer connection problem, which may result in the Error or Connected status. | 82 | | **Error** | A peer connection failed, and the participant cannot connect to a conference. | 83 | | **Kicked** | A participant was kicked from the conference. | 84 | | **Unknown** | | 85 | 86 | --- 87 | 88 | ## Dolby.io Screenshare Downscale Quality 89 | 90 | The quality for the downscaling algorithm to be used. The higher the quality, the clearer the picture will be, but the higher the CPU usage will be. 91 | 92 | | Enum value | Description | 93 | |---|:---| 94 | | **Low** | Use the quicker algorithm, fast and lowest CPU used but low quality. | 95 | | **Medium** | Use the linear filter algorithm used mainly for horizontal scaling. | 96 | | **High** | Use the bilinear filter algorithm, faster than highest, but quality not as good. If downscaling fluid screen content from 4K to 1080p this option should be used. | 97 | | **Highest** | Use the box filter algorithm, uses the most CPU and is the slowest but produces the best quality. If downscaling detailed screen content from 4K to 2K this option should be used. | 98 | 99 | --- 100 | 101 | ## Dolby.io Screenshare Encoder Hint 102 | 103 | The encoder hint provides a hint to the plugin as to what type of content is being captured by the screen share. This can be used to help when making decisions for choosing encoder settings based on what aspects of the content are important. For instance, if network conditions worsen is it more important to keep a higher resolution of screen share or frame rate to keep the motion more fluid. 104 | 105 | | Enum value | Description | 106 | |---|:---| 107 | | **Unspecified** | The content hint is not specified, encoder will choose settings based on the fact track is screen share only. | 108 | | **Detailed** | Content is detailed, encoder should keep resolution high if it can. | 109 | | **Text** | Content is text, encoder should keep resolution high if it can. | 110 | | **Fluid** | Content is fluid, full of motion, encoder should keep frame rate higher. | 111 | 112 | --- 113 | 114 | ## Dolby.io Screenshare Max Resolution 115 | 116 | The max resolution for the capture screen content to be shared as. If the actual captured resolution is higher than the set max resolution the plugin will downscale to the max resolution. The plugin captures screen content based on the chosen display's resolution. The max resolution will also be downscaled if the captured resolution is higher, otherwise this has no effect. Therefore the screen content will never be shared at a resolution higher than the one set here, but if the captured display has lower resolution the content will not be upscaled. 117 | 118 | | Enum value | Description | 119 | |---|:---| 120 | | **Downscale To 1080p** | Downscale the height to 1080p, the width will be chosen to respect the actual aspect ratio of the raw captured frame. Downscaling will only happen if the captured resolution is higher. | 121 | | **Downscale To 1440p** | Downscale the height to 1440p, the width will be chosen to respect the actual aspect ratio of the raw captured frame. Downscaling will only happen if the captured resolution is higher. | 122 | | **Actual Captured** | No downscaling, send the content to the encoder in the actual captured resolution. | 123 | 124 | --- 125 | 126 | ## Dolby.io Screenshare Source 127 | 128 | The platform agnostic description of source for screen sharing. 129 | 130 | | Struct member | Type | Description | 131 | |---|:---|:---| 132 | | **ID** | int64 | Unique id of the screen in question. | 133 | | **Is Screen** | bool | Indicates whether this is an entire screen (true) or an application window (false). | 134 | | **Title** | [text](https://docs.unrealengine.com/5.2/en-US/ftext-in-unreal-engine/) | Title of the screen. | 135 | 136 | --- 137 | 138 | ## Dolby.io Spatial Audio Style 139 | 140 | The possible spatial audio styles of the conference. 141 | 142 | | Enum value | Description | 143 | |---|:---| 144 | | **Disabled** | Spatial audio is disabled. | 145 | | **Individual** | The individual option sets the spatial location that is based on the spatial scene, local participant's position, and remote participants' positions. This allows a client to control the position using the local, self-contained logic. However, the client has to communicate a large set of requests constantly to the server, which increases network traffic, log subsystem pressure, and complexity of the client-side application. | 146 | | **Shared** | Spatial audio for shared scenes, The shared option sets the spatial location that is based on the spatial scene and the local participant's position, while the relative positions among participants are calculated by the Dolby.io server. This way, the spatial scene is shared by all participants, so that each client can set its own position and participate in the shared scene. This approach simplifies communication between the client and the server and decreases network traffic. | 147 | 148 | --- 149 | 150 | ## Dolby.io Video Codec 151 | 152 | The preferred video codec. 153 | 154 | | Enum value | Description | 155 | |---|:---| 156 | | **H264** | The H.264 codec. | 157 | | **VP8** | The VP8 codec. | 158 | | **None** | No codec used (meaning an audio-only conference). | 159 | 160 | --- 161 | 162 | ## Dolby.io Video Device 163 | 164 | The platform agnostic description of a video device. 165 | 166 | | Struct member | Type | Description | 167 | |---|:---|:---| 168 | | **Name** | [text](https://docs.unrealengine.com/5.2/en-US/ftext-in-unreal-engine/) | The name of the device. | 169 | | **Unique ID** | string | The unique ID of the device. | 170 | 171 | --- 172 | 173 | ## Dolby.io Video Forwarding Strategy 174 | 175 | Defines how the plugin should select conference participants whose videos will be transmitted to the local participant. 176 | 177 | | Enum value | Description | 178 | |---|:---| 179 | | **Last Speaker** | Selects participants based on their audio volume. | 180 | | **Closest User** | Selects participants based on the distance from the local participant. This strategy is available only for participants who enabled spatial audio. | 181 | 182 | --- 183 | 184 | ## Dolby.io Video Track 185 | 186 | Contains data about a Dolby.io video track. 187 | 188 | | Struct member | Type | Description | 189 | |---|:---|:---| 190 | | **Track ID** | string | The unique ID of the video track. | 191 | | **Participant ID** | string | The participant from whom the track is coming. | 192 | | **Is Screenshare** | bool | Indicates whether this is a screenshare video track (true) or a camera video track (false). | 193 | 194 | --- 195 | 196 | ## Dolby.io Voice Font 197 | 198 | The preferred voice modification effect that you can use to change the local participant's voice in real time. 199 | 200 | 201 | -------------------------------------------------------------------------------- /docs/docs/tutorial/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Tutorials", 3 | "position": 2, 4 | "link": { 5 | "type": "generated-index", 6 | "description": "Dolby.io Communications API Virtual Worlds Plugin for Unreal Engine - Tutorials" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/docs/tutorial/android.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 13 3 | sidebar_label: Targetting Android 4 | title: Targetting Android 5 | --- 6 | 7 | This tutorial explains how to set up the plugin to target Android devices. 8 | 9 | ## Prerequisites 10 | 11 | Please follow the [official Android setup guide](https://docs.unrealengine.com/5.3/en-US/how-to-set-up-android-sdk-and-ndk-for-your-unreal-engine-development-environment/) for the Unreal Engine and make sure you can package and launch an Android game on a phone without using the plugin first. 12 | 13 | ## Setup 14 | 1. Follow the [installation](installation) instructions for your development platform. 15 | 2. Make sure that the Unreal Editor is closed. 16 | 3. Download a plugin [release](https://github.com/DolbyIO/comms-sdk-unreal/releases) for Android and unpack the plugin to the `Plugins` folder. The release version should match your development platform release. Say yes to any overwrite prompts. 17 | 4. Open your project in Unreal Editor. 18 | 5. Tick the `Project Settings -> Platforms -> Android -> Advanced Build -> Disable libc++_shared dependency validation in all dependencies` checkbox. 19 | 20 | ## UnrealBuildTool 21 | 22 | It is also to necessary to enable linking libc++ dynamically on Android. The steps below explain how to do so on Unreal Engine 5.3 and Windows. 23 | 24 | 1. Open your project in Visual Studio. 25 | 2. Open `Programs/UnrealBuildTool/Platform/Android/AndroidToolChain.cs`. 26 | 3. Find the line `Result += " -static-libstdc++";` and comment it out or simply delete it. 27 | -------------------------------------------------------------------------------- /docs/docs/tutorial/camera-preview.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | sidebar_label: Camera Preview 4 | title: Camera Preview 5 | --- 6 | 7 | This tutorial explains how to render a preview of your camera feed. 8 | 9 | ## Prerequisites 10 | 11 | Before you start, [set up](common-setup) your project. 12 | 13 | ## Set up camera preview 14 | 15 | 1. Find `BP_DolbyIOVideoPreviewPlane` in the `VideoSamples` folder of the plugin's content in `Content Browser` and drag it onto the scene. 16 | 17 | > **_NOTE:_** If you do not see this item, go to the `Content Browser` settings and tick `Show Plugin Content`. 18 | 19 | 2. Rescale the plane to the desired aspect ratio, for example, [6.4, 3.6, 1.0], and rotate it by [90, 0, 90] to make it face the player start, as in the following example: 20 | 21 | ![](../../static/img/video-plane-result.png) 22 | 23 | 3. Open the sample menu by pressing "M". 24 | 25 | 4. Open the "Video devices" combo box and select a device to enable video streaming from that device or select "--- None ---" to disable video streaming. You should see your camera feed on the plane when you select a valid device and the plane should disappear when you select none. 26 | 27 | ## How it works 28 | 29 | `W_DolbyIOSampleDeviceControls` is a sample widget whose "Video devices" combo box is filled using [`Get Video Devices`](../blueprints/functions#dolbyio-get-video-devices) (and an additional "None" device). We also save the devices in a variable and use [`Get Current Video Device`](../blueprints/functions#dolbyio-get-current-video-device) to select the device that is currently in use. 30 | 31 | ![](../../static/img/camera-preview-combobox.png) 32 | 33 | When you select a device from the combo box, we get a corresponding device from the variable and use [`Enable Video`](../blueprints/functions#dolbyio-enable-video) to start streaming or [`Disable Video`](../blueprints/functions#dolbyio-disable-video) if the device is "None". 34 | 35 | ![](../../static/img/camera-preview-selection.png) 36 | 37 | `BP_DolbyIOVideoPreviewPlane` is a sample Blueprint with a simple `Event Graph`, which handles [`On Video Enabled`](../blueprints/events#on-video-enabled) and [`On Video Disabled`](../blueprints/events#on-video-disabled). 38 | 39 | ![](../../static/img/camera-preview-eg.png) 40 | 41 | It also contains a generic `Construction Script` to set up the plane's material: 42 | 43 | ![](../../static/img/video-plane-cs.png) 44 | -------------------------------------------------------------------------------- /docs/docs/tutorial/common-setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | sidebar_label: Common Tutorial Setup 4 | title: Common Tutorial Setup 5 | --- 6 | 7 | This tutorial explains how to initialize the plugin and connect to a conference, which is a common prerequisite for other tutorials. 8 | 9 | ## Prerequisites 10 | 11 | The tutorials and samples are designed to work with the Unreal Engine 5 First Person game template. 12 | 13 | ## Getting started 14 | 15 | 1. Find `BP_DolbyIOStarter` in the plugin's content in `Content Browser` and drag it onto the scene. 16 | 17 | > **_NOTE:_** If you do not see this item, go to the `Content Browser` settings and tick `Show Plugin Content`. 18 | 19 | 2. Make sure the newly-placed actor is selected and enter your client access token or authentication URL or app key and secret combination in the `Details` panel. 20 | 21 | You can modify other parameters of this actor as you see fit, but using the demo conference does not make sense for some tutorials, because it is an audio-only conference. 22 | 23 | If you launch the game now, assuming the credentials are set up appropriately, you should connect to a conference. 24 | 25 | > **_NOTE:_** `BP_DolbyIOStarter` is a sample Blueprint which handles several "key pressed" events and as such is designed to work the template game only, because it will likely override key bindings in more advanced games. It is meant to be used as an example on how to get started, not for use in production. 26 | -------------------------------------------------------------------------------- /docs/docs/tutorial/cpp.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 10 3 | sidebar_label: Using the Plugin with C++ 4 | title: Using the Plugin with C++ 5 | --- 6 | 7 | After enabling the plugin, you need to use the `UDolbyIOSubsystem` class to be able to use the available features in C++. We will show an example using Unreal Engine 5's First Person C++ game template. For simplicity, we assume that the project is named "Foo". 8 | 9 | ## 1. Add DolbyIO module 10 | Open `Foo/Source/Foo/Foo.build.cs` and add `"DolbyIO"` in `PublicDependencyModuleNames`: 11 | ``` 12 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "DolbyIO", "Engine", "InputCore", "HeadMountedDisplay" }); 13 | ``` 14 | 15 | ## 2. Edit FooCharacter.h 16 | Open `Foo/Source/Foo/FooCharacter.h` and add these lines somewhere in the `AFooCharacter` class: 17 | ``` 18 | UFUNCTION() 19 | void OnDolbyIOInitialized(); 20 | 21 | class UDolbyIOSubsystem* DolbyIOSubsystem; 22 | ``` 23 | 24 | ## 3. Edit FooCharacter.cpp 25 | Open `Foo/Source/Foo/FooCharacter.cpp` and replace the `BeginPlay` function definition with: 26 | ``` 27 | #include "DolbyIO.h" 28 | 29 | void AFooCharacter::BeginPlay() 30 | { 31 | // Call the base class 32 | Super::BeginPlay(); 33 | 34 | if (UGameInstance* GameInstance = GetGameInstance()) 35 | { 36 | DolbyIOSubsystem = GameInstance->GetSubsystem(); 37 | if (DolbyIOSubsystem) 38 | { 39 | DolbyIOSubsystem->OnInitialized.AddDynamic(this, &AFooCharacter::OnDolbyIOInitialized); 40 | DolbyIOSubsystem->SetToken("paste token here"); 41 | } 42 | } 43 | } 44 | 45 | void AFooCharacter::OnDolbyIOInitialized() 46 | { 47 | if (DolbyIOSubsystem) 48 | { 49 | DolbyIOSubsystem->DemoConference(); 50 | } 51 | } 52 | ``` 53 | 54 | ## 4. Configure access credentials 55 | Provide your client access token in the `DolbyIOSubsystem->SetToken...` line. 56 | 57 | ## 5. Compile and run 58 | You should connect to the demo conference when the game starts. 59 | -------------------------------------------------------------------------------- /docs/docs/tutorial/device-management.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 8 3 | sidebar_label: Device Management 4 | title: Device Management 5 | --- 6 | 7 | This tutorial explains how to set up audio device management with a simple user interface. 8 | 9 | ## Prerequisites 10 | 11 | Before you start, follow the [common setup](common-setup) tutorial. 12 | 13 | ## Sample menu 14 | 15 | 1. Open the sample menu by pressing "M". 16 | 17 | 2. Open the "Audio input devices" combo box and select the desired device. The plugin should now use that device for audio input. 18 | 19 | 3. Open the "Audio output devices" combo box and select the desired device. The plugin should now use that device for audio output. 20 | 21 | ## How it works 22 | 23 | `W_DolbyIOSampleDeviceControls` is a sample widget whose "Audio input devices" and "Audio output devices" combo boxes are filled using [`Get Audio Input Devices`](../blueprints/functions#dolbyio-get-audio-input-devices) and [`Get Audio Output Devices`](../blueprints/functions#dolbyio-get-audio-output-devices). We also save the input and output devices in variables and use [`Get Current Audio Input Device`](../blueprints/functions#dolbyio-get-current-audio-input-device) and [`Get Current Audio Output Device`](../blueprints/functions#dolbyio-get-current-audio-output-device) to select the devices that are currently in use. 24 | 25 | ![](../../static/img/device-management-comboboxes.png) 26 | 27 | When you select a device from the combo box, we get a corresponding device from a variable and use [`Set Audio Input Device`](../blueprints/functions#dolbyio-set-audio-input-device) or [`Set Audio Output Device`](../blueprints/functions#dolbyio-set-audio-output-device). 28 | 29 | ![](../../static/img/device-management-selection.png) 30 | 31 | ## Using the same audio output device as Unreal Engine 5 32 | 33 | In Unreal Engine 5, you can ensure the plugin uses the same audio output device as the engine itself by handling the engine's `Audio Device Notification Subsystem`'s `Device Switched` event as shown below: 34 | 35 | ![](../../static/img/device-management-follow.png) 36 | -------------------------------------------------------------------------------- /docs/docs/tutorial/first-conference.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | sidebar_label: Getting Started - First Conference 4 | title: Getting Started - First Conference 5 | --- 6 | 7 | The following steps present how to create a sample game which uses the plugin and connects to a demo conference. It is based on the Unreal Engine 5 First Person game template. 8 | 9 | ## 1. Open Event Graph 10 | Open Unreal Editor and locate the `All/Content/FirstPerson/Blueprints` folder in the `Content Browser` window. Select the folder and open the `BP_FirstPersonCharacter` Blueprint. 11 | 12 | ## 2. Add `DolbyIOObserver` component 13 | Click the `+Add` button located in the `Components` window and select `Dolby.io Observer`. 14 | 15 | ![](../../static/img/first-conf-observer-component.png) 16 | 17 | ## 3. Configure access credentials 18 | Select the added component and check its details in the `Details` panel. Scroll down to the `Events` section to see the available events. Select the [`On Token Needed`](../blueprints/events#on-token-needed) event from the list by clicking the plus button next to it. After this step, an `On Token Needed (DolbyIOObserver)` node should appear in the Event Graph. 19 | 20 | ### Option A - Use client access token 21 | 1. Place a [`Dolby.io Set Token`](../blueprints/functions#dolbyio-set-token) node and connect it to the `On Token Needed (DolbyIOObserver)` node. 22 | 23 | ![](../../static/img/first-conf-set-token.png) 24 | 25 | 2. Paste your client access token copied from the Dolby.io dashboard to the [`Dolby.io Set Token`](../blueprints/functions#dolbyio-set-token) node. 26 | 27 | ### Option B - Use authentication URL 28 | 29 | 1. Place a [`Dolby.io Get Token From URL`](../blueprints/functions#dolbyio-get-token-from-url) node and connect it to the `On Token Needed (DolbyIOObserver)` node. 30 | 31 | 2. Place a [`Dolby.io Set Token`](../blueprints/functions#dolbyio-set-token) node and connect it to the [`Dolby.io Get Token From URL`](../blueprints/functions#dolbyio-get-token-from-url) node as shown below: 32 | 33 | ![](../../static/img/first-conf-get-token-from-url.png) 34 | 35 | 3. Provide your URL to the [`Dolby.io Get Token From URL`](../blueprints/functions#dolbyio-get-token-from-url) function. 36 | 37 | ### Option C - Use app key and secret 38 | 1. Place a [`Dolby.io Get Token Using App Key And Secret`](../blueprints/functions#dolbyio-get-token-using-app-key-and-secret) node and connect it to the `On Token Needed (DolbyIOObserver)` node. 39 | 40 | 2. Place a [`Dolby.io Set Token`](../blueprints/functions#dolbyio-set-token) node and connect it to the [`Dolby.io Get Token Using App Key And Secret`](../blueprints/functions#dolbyio-get-token-using-app-key-and-secret) node as shown below: 41 | 42 | ![](../../static/img/first-conf-get-token-using-key-secret.png) 43 | 44 | 3. Provide your app key and app secret to the [`Dolby.io Get Token Using App Key And Secret`](../blueprints/functions#dolbyio-get-token-using-app-key-and-secret) function. 45 | 46 | ## 4. Connect to demo conference 47 | Place a [`Dolby.io Demo Conference`](../blueprints/functions#dolbyio-demo-conference) node and connect it to the [`Dolby.io Set Token`](../blueprints/functions#dolbyio-set-token) node as shown below: 48 | 49 | ![](../../static/img/first-conf-demo.png) 50 | 51 | ## 5. Run the game 52 | You should now be able join a demo conference and hear audio from its participants. If you are not able to join the conference, check the `Output Log` for clues - in particular, check whether the credentials are set up appropriately. -------------------------------------------------------------------------------- /docs/docs/tutorial/game-instance.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 9 3 | sidebar_label: Game Instance Usage 4 | title: Game Instance Usage 5 | --- 6 | 7 | This tutorial explains how to use the plugin when working from within a game instance. 8 | 9 | ## Starting notes 10 | 11 | The plugin's core class is a game instance subsystem. This means that its state is persistent throughout the game. It also means that it is created after the game instance. Therefore, we cannot use it this way from a game instance Blueprint: 12 | 13 | ![](../../static/img/game-instance-wrong.png) 14 | 15 | This is because this sequence is equivalent to: 16 | 17 | ![](../../static/img/game-instance-wrong2.png) 18 | 19 | However, at the moment `Event Init` is called, the `Dolby.io Subsystem` does not yet exist, so nothing will happen. Nor is there any other event within the base game instance that can tell us that the subsystem does exist. We have therefore provided a sample showing how to overcome this issue. 20 | 21 | ## How the sample works 22 | 23 | Suppose you want to handle the [`On Participant Updated`](../blueprints/events#on-participant-updated) event from within the game instance. 24 | 25 | 1. Find `BP_DolbyIOGameInstanceSample` in the plugin's content in `Content Browser` and open its `Event Graph`. 26 | 27 | > **_NOTE:_** If you do not see this item, go to the `Content Browser` settings and tick `Show Plugin Content`. 28 | 29 | 2. Notice that we are creating an event to tell the game instance that the `Dolby.io Subsystem` is ready for use. From within this event handler, we can now assign event handlers to the plugin's events as shown below: 30 | 31 | ![](../../static/img/game-instance-eg.png) 32 | 33 | 3. Copy these nodes into your own game instance or change the project settings to use `BP_DolbyIOGameInstanceSample`. 34 | 35 | 4. Call `On DolbyIO Ready` from any Blueprint instantiated after the game is started. A good idea is to do this from the `BeginPlay` event of the starting level Blueprint: 36 | 37 | ![](../../static/img/game-instance-level-eg.png) 38 | 39 | The game instance should now be set up to handle the [`On Participant Updated`](../blueprints/events#on-participant-updated) event. You can use this method for other events as well by chaining `Bind Event` calls. In theory, it is possible to control the plugin entirely from a game instance, however doing so is less convenient than using the `Dolby.io Observer` actor component. 40 | -------------------------------------------------------------------------------- /docs/docs/tutorial/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | sidebar_label: Installation 4 | title: Installation 5 | --- 6 | 7 | Download and enable the plugin to be able to use it in the Unreal Editor. You can either use the binary or build the plugin from source. 8 | 9 | - On macOS, you need to additionally [obtain permissions](obtain-permissions) to use your microphone and camera. 10 | - On Ubuntu, you need to have libc++ installed: `sudo apt install libc++-dev`. 11 | - If you want to target Android, please see [this tutorial](android). 12 | 13 | ## Enable the plugin using the binary 14 | 1. Make sure that your project contains a `Plugins` folder in the root of your game folder. If you do not have this folder, create it. 15 | 2. Download the latest plugin [release](https://github.com/DolbyIO/comms-sdk-unreal/releases) for your platform and unpack the plugin to the `Plugins` folder. 16 | 3. Launch your project using the Unreal Editor and select `Edit > Plugins` from the menu to enable the plugin manually. This step requires restarting the editor. 17 | 18 | ## Build the plugin from source 19 | 1. Make sure that your project contains a `Plugins` folder in the root of your game folder. If you do not have this folder, create it. 20 | 2. Download the `DolbyIO` folder from [GitHub](https://github.com/DolbyIO/comms-sdk-unreal/tree/main/DolbyIO) and add it to the `Plugins` folder. 21 | 3. Download the latest Dolby.io Communications C++ SDK [release](https://github.com/DolbyIO/comms-sdk-cpp/releases) for your platform (use the "universal" package for macOS or the "clang10-libc++10" package for Ubuntu) and unzip it. The unpacked package should contain the `sdk-release` folder for Windows and macOS or the `sdk-release-ubuntu-20.04-clang10-libc++10` folder for Ubuntu. 22 | 4. Move the unzipped folder to the `{YourGameRoot}/Plugins/DolbyIO` folder. 23 | 5. Regenerate project files and make sure that the Unreal Editor is closed. 24 | 6. Build the project using the `Development Editor` configuration. 25 | -------------------------------------------------------------------------------- /docs/docs/tutorial/multiple-games.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 11 3 | sidebar_label: Launching multiple games 4 | title: Launching multiple games 5 | --- 6 | 7 | If multiple games call [Set Token](../blueprints/functions.md#dolbyio-set-token) at the same time, which is likely to happen when using "Number of Players" with a value of more than 1 in the editor, then it is likely that one of these calls will trigger an error. We recommend handling the error by retrying this function after a short delay. Usually, one tick is enough, but if you have time, we recommend setting a longer delay: 8 | 9 | ![](../../static/img/multiple-games.png) 10 | 11 | There is a known issue with the initialization and deinitialization of the plugin with the workaround above when playing games in the "Selected Viewport". The user can expect sporadic crashes to occur when launching or closing games. These issues do not occur when playing games as "Standalone Games". Therefore, we recommend using the latter option when setting "Number of Players" to more than 1. 12 | -------------------------------------------------------------------------------- /docs/docs/tutorial/obtain-permissions.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 12 3 | sidebar_label: macOS Permissions 4 | title: macOS Permissions 5 | --- 6 | 7 | ## Unreal Editor 8 | 9 | Using the plugin in the Unreal Editor requires the editor to obtain microphone and camera permissions, however: 10 | - On Unreal Engine 5.0 and earlier, the editor is not packaged correctly to ask for either permission. 11 | - On Unreal Engine 5.1, the editor is not packaged correctly to ask for the camera permission. 12 | - On Unreal Engine 5.2, the editor is packaged correctly to ask for both permissions. 13 | - On Unreal Engine 5.3, the editor is again not packaged correctly to ask for either permission. 14 | 15 | Therefore, you may need to forcefully provide these permissions to the editors and possibly the Epic Games Launcher. To do so, you can use the [tccutil](https://github.com/DocSystem/tccutil) permissions manager and the following commands: 16 | - Unreal Engine 4: `sudo python tccutil.py -e -id com.epicgames.UE4Editor --microphone --camera` 17 | - Unreal Engine 5: `sudo python tccutil.py -e -id com.epicgames.UnrealEditor --microphone --camera` 18 | - Epic Games Launcher: `sudo python tccutil.py -e -id com.epicgames.EpicGamesLauncher --microphone --camera` 19 | 20 | The mentioned permissions manager is not endorsed by Dolby in any way and may be dangerous as it needs root permissions to access sensitive system files and requires you to grant full disk access to the terminal. If you do not wish to use it, you need to find another way to provide the required permissions to the Unreal Editor. Otherwise, you need to package the game to use the plugin and cannot test it in the editor. 21 | 22 | ## Packaging games 23 | 24 | In order to package games using the plugin with the data required to request the necessary permissions, you need to add the following lines to your game's `Info.plist` file, or, if you want to automatically add these lines to all your packaged games, to the `{UnrealEngineRoot}/Engine/Source/Runtime/Launch/Resources/Mac/Info.plist` file: 25 | 26 | ``` 27 | NSMicrophoneUsageDescription 28 | Dolby.io Virtual Worlds 29 | NSCameraUsageDescription 30 | Dolby.io Virtual Worlds 31 | ``` 32 | 33 | We recommend the latter solution if it does not conflict with your setup because the `Info.plist` file is overwritten each time the game is packaged. Note that Unreal Engine 5.1 and later provide the `NSMicrophoneUsageDescription` entry, so you only need to add the `NSCameraUsageDescription`. 34 | -------------------------------------------------------------------------------- /docs/docs/tutorial/remote-screenshare.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | sidebar_label: Rendering Remote Screen Share 4 | title: Rendering Remote Screen Share 5 | --- 6 | 7 | This tutorial explains how to render screen share feeds coming from remote participants. 8 | 9 | ## Prerequisites 10 | 11 | Before you start, follow the [common setup](common-setup) tutorial. 12 | 13 | ## Set up a remote screen share preview 14 | 15 | 1. Find `BP_DolbyIOScreensharePlane` in the `VideoSamples` folder of the plugin's content in `Content Browser` and drag it onto the scene. 16 | 17 | > **_NOTE:_** If you do not see this item, go to the `Content Browser` settings and tick `Show Plugin Content`. 18 | 19 | 2. Rescale the plane to the desired aspect ratio, for example, [6.4, 3.6, 1.0], and rotate it by [90, 0, 90] to make it face the player start, as in the following example: 20 | 21 | ![](../../static/img/video-plane-result.png) 22 | 23 | If you launch the game now, assuming you successfully connect to a conference with screen share enabled, you should see the screen share feed on the plane. 24 | 25 | ## How it works 26 | 27 | `BP_DolbyIOScreensharePlane` is a sample Blueprint with a simple `Event Graph`, which handles [`On Video Track Added`](../blueprints/events#on-video-track-added) and [`On Video Track Removed`](../blueprints/events#on-video-track-removed). 28 | 29 | ![](../../static/img/remote-screenshare-eg.png) 30 | 31 | It also contains a generic `Construction Script` to set up the plane's material: 32 | 33 | ![](../../static/img/video-plane-cs.png) 34 | -------------------------------------------------------------------------------- /docs/docs/tutorial/remote-video.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | sidebar_label: Rendering Remote Video 4 | title: Rendering Remote Video 5 | --- 6 | 7 | This tutorial explains how to render camera video coming from other participants. 8 | 9 | ## Prerequisites 10 | 11 | Before you start, follow the [common setup](common-setup) tutorial. 12 | 13 | ## Set up remote video rendering 14 | 15 | 1. Find `BP_DolbyIOSingleVideoPlane` in the `VideoSamples` folder of the plugin's content in `Content Browser` and drag it onto the scene. 16 | 17 | > **_NOTE:_** If you do not see this item, go to the `Content Browser` settings and tick `Show Plugin Content`. 18 | 19 | 2. Rescale the plane to the desired aspect ratio, for example, [6.4, 3.6, 1.0], and rotate it by [90, 0, 90] to make it face the player start, as in the following example: 20 | 21 | ![](../../static/img/video-plane-result.png) 22 | 23 | If you launch the game now, assuming you successfully connect to a conference with at least one remote participant video enabled, you should see one video feed on the plane. 24 | 25 | > **_NOTE:_** This particular implementation allows only one remote video feed. For an example on how to render all video feeds, see [this](#multiple-videos) section. 26 | 27 | ## How it works 28 | 29 | `BP_DolbyIOSingleVideoPlane` is a sample Blueprint with a simple `Event Graph`, which handles [`On Video Track Added`](../blueprints/events#on-video-track-added) and [`On Video Track Removed`](../blueprints/events#on-video-track-removed). 30 | 31 | ![](../../static/img/remote-video-eg.png) 32 | 33 | It also contains a generic `Construction Script` to set up the plane's material: 34 | 35 | ![](../../static/img/video-plane-cs.png) 36 | 37 | ## Multiple videos 38 | 39 | 1. Find `BP_DolbyIOVideoPlaneSpawner` in the `VideoSamples` folder of the plugin's content in `Content Browser` and drag it onto the scene. 40 | 41 | > **_NOTE:_** This sample actor spawns a `BP_DolbyIOGenericVideoPlane` whenever a new video track is added and destroys the plane when its video track is removed. `BP_DolbyIOGenericVideoPlane` is just a plane that contains the same `Construction Script` as above. Its `Event Graph` does nothing by default but contains some nodes in order to be used as a copy-pastable template. 42 | 43 | 2. `BP_DolbyIOVideoPlaneSpawner` will spawn the first video plane at its location, so place the actor at a location where you want to see the first video. It will also spawn each new video plane a bit to the right (+Y axis) of the previous plane. Therefore, a good idea is to place it above the game template scene so that the planes do not end up hidden inside other meshes. 44 | 45 | If you launch the game now, assuming you successfully connect to a conference with more than one remote participant video enabled, you should see multiple video feeds on the spawned planes. 46 | 47 | ## How the spawner works 48 | 49 | `BP_DolbyIOVideoPlaneSpawner` is a sample actor which handles [`On Video Track Added`](../blueprints/events#on-video-track-added) and [`On Video Track Removed`](../blueprints/events#on-video-track-removed) in its `Event Graph`: 50 | 51 | - [`On Video Track Added`](../blueprints/events#on-video-track-added) is handled by spawning a new `BP_DolbyIOGenericVideoPlane`, binding the material of the new plane to the new track ID, and saving the plane in a map variable. 52 | 53 | - [`On Video Track Removed`](../blueprints/events#on-video-track-removed) is handled by destroying the plane which is bound to the track and removing it from the map variable. 54 | 55 | The implementation of these events is specific to this (rather artificial) use case, but it shows that it is possible to render many videos without much effort. 56 | 57 | For a more practical example, consider a case where you have avatars with video planes positioned above the avatars' heads. The planes should have their materials set up as shown in the `Construction Script` above. Assuming you already have a way of managing the avatar actors (their world transform, their lifetime, etc.) and each avatar corresponds to a participant ID, then all you need to do is bind the material from a selected avatar's video plane to the participant's video track. 58 | -------------------------------------------------------------------------------- /docs/docs/tutorial/screenshare-preview.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | sidebar_label: Screen Share Preview 4 | title: Screen Share Preview 5 | --- 6 | 7 | This tutorial explains how to render a preview of your screen share feed. 8 | 9 | ## Prerequisites 10 | 11 | Before you start, follow the [common setup](common-setup) tutorial. 12 | 13 | ## Set up a screen share preview 14 | 15 | 1. Find `BP_DolbyIOScreensharePreviewPlane` in the `VideoSamples` folder of the plugin's content in `Content Browser` and drag it onto the scene. 16 | 17 | > **_NOTE:_** If you do not see this item, go to the `Content Browser` settings and tick `Show Plugin Content`. 18 | 19 | 2. Rescale the plane to the desired aspect ratio, for example, [6.4, 3.6, 1.0], and rotate it by [90, 0, 90] to make it face the player start, as in the following example: 20 | 21 | ![](../../static/img/video-plane-result.png) 22 | 23 | 3. Open the sample menu by pressing "M". 24 | 25 | 4. Open the "Screenshare sources" combo box and select the desired source. Assuming there is no conflicting screen share going on, you should see your screen share feed on the plane after pressing the "Start screenshare" button and the plane should disappear when you press "Stop screenshare". 26 | 27 | ![](../../static/img/screenshare-preview-result.png) 28 | 29 | ## How it works 30 | 31 | `W_DolbyIOSampleScreenshareControls` is a sample widget whose "Screenshare sources" combo box is filled using [`Get Screenshare Sources`](../blueprints/functions#dolbyio-get-screenshare-sources). We also save the sources in a variable. 32 | 33 | ![](../../static/img/screenshare-preview-combobox.png) 34 | 35 | When you click "Start screenshare", we match the selected source from the combo box with the corresponding source from the variable, get other parameters from their combo boxes and [`Start Screenshare`](../blueprints/functions#dolbyio-start-screenshare). 36 | 37 | Additionally, whenever you change the screen share parameters using their combo boxes, we call [`Change Screenshare Parameters`](../blueprints/functions#dolbyio-change-screenshare-parameters). It is safe to call this function whenever a combo box selection changes even when screen share is not started, because it does nothing in that case. 38 | 39 | Finally, we simply [`Stop Screenshare`](../blueprints/functions#dolbyio-stop-screenshare) when the "Stop screenshare" button is clicked. 40 | 41 | ![](../../static/img/screenshare-preview-start.png) 42 | 43 | `BP_DolbyIOScreensharePreviewPlane` is a sample Blueprint with a simple `Event Graph`, which handles [`On Screenshare Started`](../blueprints/events#on-screenshare-started) and [`On Screenshare Stopped`](../blueprints/events#on-screenshare-stopped). 44 | 45 | ![](../../static/img/screenshare-preview-eg.png) 46 | 47 | It also contains a generic `Construction Script` to set up the plane's material: 48 | 49 | ![](../../static/img/video-plane-cs.png) -------------------------------------------------------------------------------- /docs/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Note: type annotations allow type checking and IDEs autocompletion 3 | 4 | const lightCodeTheme = require('prism-react-renderer/themes/github'); 5 | const darkCodeTheme = require('prism-react-renderer/themes/dracula'); 6 | 7 | /** @type {import('@docusaurus/types').Config} */ 8 | const config = { 9 | title: 'Dolby.io Communications API', 10 | tagline: 'Virtual Worlds Plugin for Unreal Engine', 11 | favicon: 'img/favicon.ico', 12 | 13 | // Set the production url of your site here 14 | url: 'https://api-references.dolby.io', 15 | // Set the // pathname under which your site is served 16 | // For GitHub pages deployment, it is often '//' 17 | baseUrl: '/comms-sdk-unreal/', 18 | 19 | // GitHub pages deployment config. 20 | // If you aren't using GitHub pages, you don't need these. 21 | //organizationName: 'DolbyIO', // Usually your GitHub org/user name. 22 | //projectName: 'comms-sdk-unreal', // Usually your repo name. 23 | //deploymentBranch: 'doc-github-page', 24 | trailingSlash: false, 25 | onBrokenLinks: 'throw', 26 | onBrokenMarkdownLinks: 'warn', 27 | 28 | // Even if you don't use internalization, you can use this field to set useful 29 | // metadata like html lang. For example, if your site is Chinese, you may want 30 | // to replace "en" with "zh-Hans". 31 | i18n: { 32 | defaultLocale: 'en', 33 | locales: ['en'], 34 | }, 35 | 36 | presets: [ 37 | [ 38 | 'classic', 39 | /** @type {import('@docusaurus/preset-classic').Options} */ 40 | ({ 41 | docs: { 42 | sidebarPath: require.resolve('./sidebars.js'), 43 | }, 44 | theme: { 45 | customCss: require.resolve('./src/css/custom.css'), 46 | }, 47 | }), 48 | ], 49 | ], 50 | 51 | themeConfig: 52 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ 53 | ({ 54 | // Replace with your project's social card 55 | navbar: { 56 | title: 'Virtual Worlds plugin for Unreal Engine', 57 | style: 'dark', 58 | logo: { 59 | alt: 'Dolby logo', 60 | src: 'img/logo-white.svg', 61 | className: 'logo', 62 | }, 63 | }, 64 | footer: { 65 | style: 'dark', 66 | /* 67 | links: [ 68 | { 69 | title: 'Docs', 70 | items: [ 71 | { 72 | label: 'Tutorial', 73 | to: '/docs/intro', 74 | }, 75 | ], 76 | }, 77 | ], 78 | */ 79 | copyright: `Copyright © ${new Date().getFullYear()} Dolby.io`, 80 | }, 81 | prism: { 82 | theme: lightCodeTheme, 83 | darkTheme: darkCodeTheme, 84 | }, 85 | }), 86 | }; 87 | 88 | module.exports = config; 89 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@docusaurus/core": "^2.3.1", 19 | "@docusaurus/preset-classic": "^2.3.1", 20 | "@mdx-js/react": "^1.6.22", 21 | "clsx": "^1.2.1", 22 | "prism-react-renderer": "^1.3.5", 23 | "react": "^17.0.2", 24 | "react-dom": "^17.0.2" 25 | }, 26 | "devDependencies": { 27 | "@docusaurus/module-type-aliases": "^2.3.1", 28 | "@tsconfig/docusaurus": "^1.0.6", 29 | "typescript": "^4.9.5" 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.5%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | }, 43 | "engines": { 44 | "node": ">=16.14" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /docs/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 18 | 19 | // But you can create a sidebar manually 20 | /* 21 | tutorialSidebar: [ 22 | 'intro', 23 | 'hello', 24 | { 25 | type: 'category', 26 | label: 'Tutorial', 27 | items: ['tutorial/create-a-document'], 28 | }, 29 | ], 30 | */ 31 | }; 32 | 33 | module.exports = sidebars; 34 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import styles from './styles.module.css'; 4 | 5 | type FeatureItem = { 6 | title: string; 7 | Svg: React.ComponentType>; 8 | description: JSX.Element; 9 | }; 10 | 11 | const FeatureList: FeatureItem[] = [ 12 | ]; 13 | 14 | function Feature({title, Svg, description}: FeatureItem) { 15 | return ( 16 |
17 |
18 | 19 |
20 |
21 |

{title}

22 |

{description}

23 |
24 |
25 | ); 26 | } 27 | 28 | export default function HomepageFeatures(): JSX.Element { 29 | return ( 30 |
31 |
32 |
33 | {FeatureList.map((props, idx) => ( 34 | 35 | ))} 36 |
37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /docs/src/components/VoiceFontsTable.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class VoiceFontsTable extends React.Component { 4 | render() { 5 | return ( 6 | 7 | 8 | 9 | 12 | 15 | 18 | 19 | 20 | 23 | 28 | 33 | 34 | 35 | 38 | 43 | 48 | 49 | 50 | 53 | 58 | 63 | 64 | 65 | 68 | 73 | 78 | 79 | 80 | 83 | 88 | 93 | 94 | 95 | 98 | 103 | 108 | 109 | 110 | 113 | 118 | 123 | 124 | 125 | 128 | 133 | 138 | 139 | 140 | 143 | 148 | 153 | 154 | 155 | 158 | 163 | 168 | 169 | 170 | 173 | 178 | 183 | 184 | 185 | 188 | 193 | 198 | 199 | 200 | 203 | 208 | 213 | 214 | 215 |
10 | Enum value 11 | 13 | Example 1 14 | 16 | Example 2 17 |
21 | None 22 | 24 |
25 |
27 |
29 |
30 |
32 |
36 | Abyss 37 | 39 |
40 |
42 |
44 |
45 |
47 |
51 | AMRadio 52 | 54 |
55 |
57 |
59 |
60 |
62 |
66 | BrokenRobot 67 | 69 |
70 |
72 |
74 |
75 |
77 |
81 | DarkModulation 82 | 84 |
85 |
87 |
89 |
90 |
92 |
96 | Feminine 97 | 99 |
100 |
102 |
104 |
105 |
107 |
111 | Helium 112 | 114 |
115 |
117 |
119 |
120 |
122 |
126 | Interference 127 | 129 |
130 |
132 |
134 |
135 |
137 |
141 | Masculine 142 | 144 |
145 |
147 |
149 |
150 |
152 |
156 | NervousRobot 157 | 159 |
160 |
162 |
164 |
165 |
167 |
171 | StarshipCaptain 172 | 174 |
175 |
177 |
179 |
180 |
182 |
186 | Swarm 187 | 189 |
190 |
192 |
194 |
195 |
197 |
201 | Wobble 202 | 204 |
205 |
207 |
209 |
210 |
212 |
216 | ); 217 | } 218 | } 219 | 220 | export default VoiceFontsTable; 221 | 222 | -------------------------------------------------------------------------------- /docs/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #AA33FF; 10 | --ifm-color-primary-light: #EACCFF; 11 | --ifm-code-font-size: 95%; 12 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 13 | } 14 | 15 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 16 | [data-theme='dark'] { 17 | --ifm-color-primary: #9559ff; 18 | --ifm-color-primary-dark: #9559ff; 19 | --ifm-color-primary-darker: #1fa588; 20 | --ifm-color-primary-darkest: #AA33FF; 21 | --ifm-color-primary-light: #29d5b0; 22 | --ifm-color-primary-lighter: #32d8b4; 23 | --ifm-color-primary-lightest: #4fddbf; 24 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 25 | } 26 | 27 | .logo { 28 | height: 22px !important; 29 | transform: translateY(28%); 30 | } 31 | 32 | img[alt=gettoken], 33 | img[alt=settoken], 34 | img[alt=ontoken], 35 | img[alt=details] { 36 | width: 500px; 37 | } 38 | 39 | img[alt=components], 40 | img[alt=subsystem] { 41 | width: 350px; 42 | } 43 | 44 | table { 45 | width: 100%; 46 | display: table; 47 | } -------------------------------------------------------------------------------- /docs/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /docs/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import Link from '@docusaurus/Link'; 4 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 5 | import Layout from '@theme/Layout'; 6 | import HomepageFeatures from '@site/src/components/HomepageFeatures'; 7 | import { Redirect } from 'react-router-dom'; 8 | 9 | import styles from './index.module.css'; 10 | 11 | function HomepageHeader() { 12 | const {siteConfig} = useDocusaurusContext(); 13 | return ( 14 |
15 |
16 |

{siteConfig.title}

17 |

{siteConfig.tagline}

18 |
19 | 22 | Tutorial and References ⏱️ 23 | 24 |
25 |
26 |
27 | ); 28 | } 29 | 30 | /* 31 | export default function Home(): JSX.Element { 32 | const {siteConfig} = useDocusaurusContext(); 33 | return ( 34 | 37 | 38 |
39 | 40 |
41 |
42 | ); 43 | } 44 | */ 45 | 46 | export default function Home(): JSX.Element { 47 | const {siteConfig} = useDocusaurusContext(); 48 | return ; 49 | } 50 | -------------------------------------------------------------------------------- /docs/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/.nojekyll -------------------------------------------------------------------------------- /docs/static/img/camera-preview-combobox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/camera-preview-combobox.png -------------------------------------------------------------------------------- /docs/static/img/camera-preview-eg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/camera-preview-eg.png -------------------------------------------------------------------------------- /docs/static/img/camera-preview-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/camera-preview-selection.png -------------------------------------------------------------------------------- /docs/static/img/common-setup-connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/common-setup-connect.png -------------------------------------------------------------------------------- /docs/static/img/device-management-comboboxes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/device-management-comboboxes.png -------------------------------------------------------------------------------- /docs/static/img/device-management-follow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/device-management-follow.png -------------------------------------------------------------------------------- /docs/static/img/device-management-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/device-management-selection.png -------------------------------------------------------------------------------- /docs/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/favicon.ico -------------------------------------------------------------------------------- /docs/static/img/first-conf-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/first-conf-demo.png -------------------------------------------------------------------------------- /docs/static/img/first-conf-get-token-from-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/first-conf-get-token-from-url.png -------------------------------------------------------------------------------- /docs/static/img/first-conf-get-token-using-key-secret.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/first-conf-get-token-using-key-secret.png -------------------------------------------------------------------------------- /docs/static/img/first-conf-observer-component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/first-conf-observer-component.png -------------------------------------------------------------------------------- /docs/static/img/first-conf-set-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/first-conf-set-token.png -------------------------------------------------------------------------------- /docs/static/img/game-instance-eg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/game-instance-eg.png -------------------------------------------------------------------------------- /docs/static/img/game-instance-level-eg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/game-instance-level-eg.png -------------------------------------------------------------------------------- /docs/static/img/game-instance-wrong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/game-instance-wrong.png -------------------------------------------------------------------------------- /docs/static/img/game-instance-wrong2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/game-instance-wrong2.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_BindMaterial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_BindMaterial.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_BroadcastMessage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_BroadcastMessage.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_ChangeScreenshareParameters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_ChangeScreenshareParameters.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_GetParticipants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_GetParticipants.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_GetTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_GetTexture.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_MuteInput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_MuteInput.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_MuteOutput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_MuteOutput.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_MuteParticipant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_MuteParticipant.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SendMessage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SendMessage.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetAudioCaptureMode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetAudioCaptureMode.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetAudioInputDevice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetAudioInputDevice.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetAudioOutputDevice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetAudioOutputDevice.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetLocalPlayerLocation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetLocalPlayerLocation.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetLocalPlayerRotation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetLocalPlayerRotation.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetLogSettings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetLogSettings.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetRemotePlayerLocation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetRemotePlayerLocation.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetSpatialEnvironmentScale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_SetSpatialEnvironmentScale.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UnbindMaterial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UnbindMaterial.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UnmuteInput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UnmuteInput.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UnmuteOutput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UnmuteOutput.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UnmuteParticipant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UnmuteParticipant.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UpdateUserMetadata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOBlueprintFunctionLibrary/img/nd_img_UpdateUserMetadata.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOConnect/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOConnect/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIODemoConference/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIODemoConference/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIODisableVideo/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIODisableVideo/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIODisconnect/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIODisconnect/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOEnableVideo/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOEnableVideo/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOGetAudioInputDevices/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOGetAudioInputDevices/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOGetAudioOutputDevices/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOGetAudioOutputDevices/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOGetCurrentAudioInputDevice/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOGetCurrentAudioInputDevice/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOGetCurrentAudioOutputDevice/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOGetCurrentAudioOutputDevice/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOGetCurrentScreenshareSource/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOGetCurrentScreenshareSource/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOGetCurrentVideoDevice/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOGetCurrentVideoDevice/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOGetScreenshareSources/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOGetScreenshareSources/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOGetTokenFromURL/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOGetTokenFromURL/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOGetVideoDevices/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOGetVideoDevices/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOSetToken/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOSetToken/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOStartScreenshare/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOStartScreenshare/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/DolbyIOStopScreenshare/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/DolbyIOStopScreenshare/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/generated/GetDolbyIOToken/img/nd_img_UK2Node_AsyncAction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/generated/GetDolbyIOToken/img/nd_img_UK2Node_AsyncAction.png -------------------------------------------------------------------------------- /docs/static/img/logo-white.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/static/img/multiple-games.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/multiple-games.png -------------------------------------------------------------------------------- /docs/static/img/participant-status-changes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/participant-status-changes.png -------------------------------------------------------------------------------- /docs/static/img/remote-screenshare-eg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/remote-screenshare-eg.png -------------------------------------------------------------------------------- /docs/static/img/remote-video-eg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/remote-video-eg.png -------------------------------------------------------------------------------- /docs/static/img/screenshare-preview-combobox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/screenshare-preview-combobox.png -------------------------------------------------------------------------------- /docs/static/img/screenshare-preview-eg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/screenshare-preview-eg.png -------------------------------------------------------------------------------- /docs/static/img/screenshare-preview-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/screenshare-preview-result.png -------------------------------------------------------------------------------- /docs/static/img/screenshare-preview-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/screenshare-preview-start.png -------------------------------------------------------------------------------- /docs/static/img/video-plane-cs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/video-plane-cs.png -------------------------------------------------------------------------------- /docs/static/img/video-plane-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxeet/comms-sdk-unreal/ea5a9da5f3b21edf4da5df16b972c3d7629058f7/docs/static/img/video-plane-result.png -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@tsconfig/docusaurus/tsconfig.json", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /scripts/android.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | AAR_PATH=$1 3 | AAR_NO_PREFAB_PATH=$2 4 | AAR_SHARED_PATH=$3 5 | 6 | if [[ -z "$AAR_PATH" ]]; then # use Maven 7 | AAR_PATH=~/.m2/repository/io/dolby/comms-sdk-android-cppsdk/2.7.0/*.aar 8 | AAR_NO_PREFAB_PATH=~/.m2/repository/io/dolby/comms-sdk-android-cppsdk-noprefab/2.7.0/*.aar 9 | AAR_SHARED_PATH=~/.m2/repository/io/dolby/comms-sdk-android-cppsdk-shared/2.7.0/*.aar 10 | fi 11 | 12 | AAR_TMP=aar_tmp 13 | RELEASE_PATH="DolbyIO/sdk-release-android" 14 | 15 | # clean release 16 | rm -rf ${RELEASE_PATH} 17 | mkdir ${RELEASE_PATH} 18 | 19 | # get includes from main aar 20 | unzip ${AAR_PATH} -d ${AAR_TMP} 21 | cp -r ${AAR_TMP}/prefab/modules/sdk/include ${RELEASE_PATH} 22 | rm -rf ${AAR_TMP} 23 | 24 | # get libs from noprefab aar 25 | unzip ${AAR_NO_PREFAB_PATH} -d ${AAR_TMP} 26 | for ARCH in arm64-v8a 27 | do 28 | LIBS_PATH=${RELEASE_PATH}/libs/android.${ARCH} 29 | mkdir -p ${LIBS_PATH} 30 | for LIB in media sdk 31 | do 32 | cp ${AAR_TMP}/jni/${ARCH}/libdolbyio_comms_${LIB}.so ${LIBS_PATH} 33 | done 34 | done 35 | rm -rf ${AAR_TMP} 36 | 37 | # copy noprefab and shared aar 38 | cp ${AAR_NO_PREFAB_PATH} ${RELEASE_PATH} 39 | cp ${AAR_SHARED_PATH} ${RELEASE_PATH} 40 | --------------------------------------------------------------------------------