Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add: Latency measurements such as sender to receiver latency measurements using RTP header extensions abs-capture-time and video-timing #425

Merged
merged 30 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b9e12d2
Add sending abs-capture-time in JS streamer and a test
lukehb Dec 6, 2024
fc83cee
Add some comments
lukehb Dec 6, 2024
b950af3
Added extra commenting
lukehb Dec 10, 2024
47398a8
Added SDPUtils to /Common
lukehb Dec 10, 2024
4a3d131
Working state
lukehb Dec 20, 2024
cfcbdf9
Added test to check if abs-capture-time is in offer/answer when flag …
lukehb Jan 16, 2025
cf1cf95
Update JSStreamer dockerfile to build using local files. Speed up bui…
lukehb Jan 17, 2025
911ead6
Added SDP offer/remote description set event to PixelStreaming API
lukehb Jan 20, 2025
1f5b9f8
Connect new latency calculation API to stats panel
lukehb Jan 23, 2025
e15961a
Added latency info to tests, fixed linting
lukehb Jan 24, 2025
56ae963
Fix failing unit test
lukehb Jan 24, 2025
8ef4748
Fix linting
lukehb Jan 24, 2025
6e85d66
Attempt to fix test race condition through explicitly adding listener…
lukehb Jan 24, 2025
47f041c
Attempt to update playwright version used in minimal stream tester
lukehb Jan 24, 2025
514089c
Remove problematic test teardown when test was skipped
lukehb Jan 29, 2025
2c47b94
Add extra info step to streaming CI job to help diagnose CI failures
lukehb Jan 29, 2025
ee4edc2
Iterating on what to log
lukehb Jan 29, 2025
4f1ea36
Attempt to revert some load bearing changes and add logging to stream…
lukehb Jan 29, 2025
df82e74
Move to using latest minimal streamer release
lukehb Jan 29, 2025
c5c46e0
Disable header extension for Firefox as it causes it to not connect
lukehb Jan 29, 2025
4b4db38
Made code more exclusive of Firefox weirdness
lukehb Jan 29, 2025
1833e62
Linting fix
lukehb Jan 29, 2025
1e707f5
Merge branch 'master' into capture-time
lukehb Jan 30, 2025
989a62a
Fixing linting error
lukehb Jan 31, 2025
701c265
Tided up how latency stats are displayed in stats panel
lukehb Feb 7, 2025
e00a2e5
Apply suggestions from code review
lukehb Feb 7, 2025
0b48276
Merge branch 'master' into capture-time
lukehb Feb 9, 2025
3314c9c
Merge branch 'master' into capture-time
lukehb Feb 12, 2025
070bbf8
Fix failing CI for build:esm job
lukehb Feb 12, 2025
ee5d7bd
Made it clearer whether video timing or abs-capture-time is used
lukehb Feb 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/healthcheck-libraries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@ jobs:

- name: Clean build of frontend implementation
working-directory: Frontend/implementations/typescript
run: npm install && npm run build
run: npm install && npm run build

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this step to the CI, as this was actually broken and not being caught.

- name: Clean build of frontend implementation as ES6
working-directory: Frontend/implementations/typescript
run: npm install && npm run build:esm
13 changes: 9 additions & 4 deletions .github/workflows/healthcheck-streaming.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ jobs:
uses: robinraju/release-downloader@v1
with:
repository: 'EpicGamesExt/PixelStreamingInfrastructure'
tag: 'minimal-streamer'
fileName: 'Minimal-PixelStreamer-5.5.7z'
tag: 'minimal-streamer-5.5'
fileName: 'Minimal-PixelStreamer-5.5-Win64-Development.7z'
Copy link
Contributor Author

@lukehb lukehb Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upgraded to using our latest minimal streamer release, as the other one was a bit out of date now.


- name: Extract streamer
run: 7z x -oStreamer Minimal-PixelStreamer-5.5.7z
run: 7z x -oStreamer Minimal-PixelStreamer-5.5-Win64-Development.7z

- name: Build Common
working-directory: Common
Expand Down Expand Up @@ -109,7 +109,7 @@ jobs:

- name: Run Streamer
working-directory: Streamer
run: Start-Process ".\Minimal\Binaries\Win64\Minimal-Win64-Shipping-Cmd.exe" -ArgumentList "-warp","-dx12","-windowed","-res=1920","-resy=720","-PixelStreamingURL=ws://localhost:8888","-RenderOffScreen","-AllowSoftwaRerendering","-PixelStreamingEncoderCodec=vp8"
run: Start-Process ".\Minimal\Binaries\Win64\Minimal-Cmd.exe" -ArgumentList "-warp","-dx12","-windowed","-resx=1920","-resy=720","-PixelStreamingURL=ws://localhost:8888","-RenderOffScreen","-AllowSoftwareRendering","-PixelStreamingEncoderCodec=vp8", "-Log=Minimal.log"

- name: Prepare test
working-directory: Extras\MinimalStreamTester
Expand All @@ -121,9 +121,14 @@ jobs:
- name: Wait for signalling to come up
run: curl --retry 10 --retry-delay 20 --retry-connrefused http://localhost:999/api/status


- name: Wait for streamer to come up
run: curl --retry 10 --retry-delay 20 --retry-connrefused http://localhost:999/api/streamers/DefaultStreamer

- name: Output streamer logs
working-directory: Streamer
run: ls ".\Minimal\" && Test-Path ".\Minimal\Saved\Logs\Minimal.log" && cat ".\Minimal\Saved\Logs\Minimal.log"

- name: Test if we can stream
working-directory: Extras\MinimalStreamTester
run: |
Expand Down
31 changes: 31 additions & 0 deletions Common/src/Util/SdpUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright Epic Games, Inc. All Rights Reserved.

export class SDPUtils {
static addVideoHeaderExtensionToSdp(sdp: string, uri: string): string {
// Find the highest used header extension id by sorting the extension ids used,
// eliminating duplicates and adding one.
// Todo: Update this when WebRTC in Chrome supports the header extension API.
const usedIds = sdp
.split('\n')
.filter((line) => line.startsWith('a=extmap:'))
.map((line) => parseInt(line.split(' ')[0].substring(9), 10))
.sort((a, b) => a - b)
.filter((item, index, array) => array.indexOf(item) === index);
const nextId = usedIds[usedIds.length - 1] + 1;
const extmapLine = 'a=extmap:' + nextId + ' ' + uri + '\r\n';

const sections = sdp.split('\nm=').map((part, index) => {
return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
});
const sessionPart = sections.shift();
// Only add extension to m=video media section
return (
sessionPart +
sections
.map((mediaSection) =>
mediaSection.startsWith('m=video') ? mediaSection + extmapLine : mediaSection
)
.join('')
);
}
}
1 change: 1 addition & 0 deletions Common/src/pixelstreamingcommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export { MessageRegistry } from './Messages/message_registry';
export * as Messages from './Messages/signalling_messages';
export * as MessageHelpers from './Messages/message_helpers';
export { KeepaliveMonitor } from './Protocol/KeepaliveMonitor';
export * from './Util/SdpUtils';
10 changes: 3 additions & 7 deletions Extras/FrontendTests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@
### Setup
```
npm install
npx playwright install --with-deps
```

The above command should install the required browsers but for some reason I find I have to install chrome manually using the following command.

```
npx playwright install chrome
npx playwright install-deps
npx playwright install firefox
npx playwright install chromium
```

### Prepare
Expand Down
5 changes: 3 additions & 2 deletions Extras/FrontendTests/dockerfiles/linux/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ WORKDIR /tester
COPY /Extras/FrontendTests .

RUN npm install
RUN npx playwright install --with-deps
RUN npx playwright install chrome
RUN npx playwright install firefox
RUN npx playwright install chromium
RUN npx playwright install-deps

VOLUME /tester/playwright-report

Expand Down
9 changes: 4 additions & 5 deletions Extras/FrontendTests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@
"description": "",
"main": "index.js",
"scripts": {
"test": "playwright test",
"build": "",
"clean": ""
"test": "npx playwright test",
"build": ""
},
"keywords": [],
"author": "Epic Games",
"license": "MIT",
"devDependencies": {
"@playwright/test": "^1.49.0",
"@playwright/test": "^1.49.1",
"@types/node": "^20.12.7",
"@types/uuid": "^9.0.8"
},
"dependencies": {
"@epicgames-ps/lib-pixelstreamingfrontend-ue5.5": "*",
"@epicgames-ps/js-streamer": "^0.0.4",
"@epicgames-ps/lib-pixelstreamingfrontend-ue5.5": "*",
"dotenv": "^16.4.5",
"node-fetch": "^2.7.0",
"uuid": "^9.0.0"
Expand Down
6 changes: 3 additions & 3 deletions Extras/FrontendTests/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export default defineConfig({
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : 5,
/* Opt out of parallel tests in general as multiple streamers mean they can connect to the wrong test */
workers: 1,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: [['html', { open: 'never' }]],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
Expand All @@ -31,7 +31,7 @@ export default defineConfig({
projects: [
{
name: 'chrome',
use: { ...devices['Desktop Chrome'], channel: 'chrome' },
use: { ...devices['Desktop Chrome'], channel: 'chromium' },
},
// {
// name: 'chromium',
Expand Down
21 changes: 12 additions & 9 deletions Extras/FrontendTests/tests/basic_stream.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { test } from './fixtures';
import { expect } from './matchers';
import * as helpers from './helpers';
import { StatsReceivedEvent } from '@epicgames-ps/lib-pixelstreamingfrontend-ue5.5';

// NOTE: add a new test to check qp values

Expand All @@ -10,20 +11,22 @@ test('Test default stream.', {
}, async ({ page, streamerId }) => {

await page.goto(`/?StreamerId=${streamerId}`);
await page.getByText('Click to start').click();

// let the stream run for a short duration
await helpers.waitForVideo(page);
await helpers.delay(1000);

// query the frontend for its calculated stats
const frame_count:number = await page.evaluate(()=> {
let videoStats = pixelStreaming._webRtcController.peerConnectionController.aggregatedStats.inboundVideoStats;
return videoStats.framesReceived;
await helpers.startAndWaitForVideo(page);

let frameCount: number = await page.evaluate(()=> {
return new Promise<number>((resolve) => {
window.pixelStreaming.addEventListener("statsReceived", (e: StatsReceivedEvent) => {
if(e.data.aggregatedStats && e.data.aggregatedStats.inboundVideoStats && e.data.aggregatedStats.inboundVideoStats.framesReceived) {
resolve(e.data.aggregatedStats.inboundVideoStats.framesReceived);
}
});
});
});

// pass the test if we recorded any frames
expect(frame_count).toBeGreaterThan(0);
expect(frameCount).toBeGreaterThan(0);
});


Expand Down
Loading
Loading