Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 25 additions & 14 deletions js/publish/src/audio/encoder.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, expect, mock, spyOn, test } from "bun:test";
import { u53 } from "@moq/hang/catalog";
import * as Moq from "@moq/net";
import { Time } from "@moq/net";
import { Signal } from "@moq/signals";
Expand Down Expand Up @@ -320,24 +321,34 @@ test("passes an explicit Opus DTX request to the encoder", async () => {
// it, which the catalog advertises as `delay`.
test("a rendition trailing the broadcast's earliest advertises delay", async () => {
using _webcodecs = installFakeWebCodecs();
const baseline = new Baseline();
using env = await setup(baseline);
const { encoder, feed } = env;
// A process that has just started reports performance.now() under 100ms, so a capture "100ms ago"
// is negative and the frame encoder rejects it. A fixed origin keeps every stamp nonnegative.
const clock = spyOn(performance, "now").mockReturnValue(200);
try {
const baseline = new Baseline();
using env = await setup(baseline);
const { encoder, feed } = env;

expect(encoder.out.catalog.peek()?.delay).toBeUndefined();
expect(encoder.out.catalog.peek()?.delay).toBeUndefined();

// A sibling that flushes each frame the instant it is captured.
baseline.observe(0, performance.now() * 1000);
// A sibling that flushes each frame the instant it is captured.
baseline.observe(0, performance.now() * 1000);

// Captured 100ms ago, so this rendition flushes at least that late.
const start = performance.now() * 1000 - 100_000;
for (let index = 0; index < 4; index++) {
await feed.push({ timestamp: Time.Micro(start + index * 20_000), channels: [new Float32Array(960)] });
}
await feed.drain();
// Captured 100ms ago, so this rendition flushes at least that late.
const start = performance.now() * 1000 - 100_000;
for (let index = 0; index < 4; index++) {
await feed.push({ timestamp: Time.Micro(start + index * 20_000), channels: [new Float32Array(960)] });
}
await feed.drain();

expect(env.written.length).toBe(2);
expect(encoder.out.catalog.peek()?.delay).toBeGreaterThanOrEqual(100);
expect(env.written).toEqual([
[100_000, 1],
[120_000, 1],
]);
expect(encoder.out.catalog.peek()?.delay).toBe(u53(100));
} finally {
clock.mockRestore();
}
});

// Regression: codec settings that can't resolve left the encoder unsettled, so `<moq-publish>` never
Expand Down
1 change: 0 additions & 1 deletion quest/m1/test-flakes-2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ Public API: none. Wire: none.
- [Shaper virtual time](/quest/m1/test-flakes-2/shaper-virtual-time.md) - `moq-shaper` tests judge seeded decisions on paused time, not on wall-clock delivery under load
- [Scoped WARN capture](/quest/m1/test-flakes-2/warn-capture.md) - the drop-unfinished tests count only their own WARNs
- [moq-mux debounce clock](/quest/m1/test-flakes-2/mux-debounce-clock.md) - the TS export debounce test advances on the paused clock
- [js/publish audio clock](/quest/m1/test-flakes-2/publish-audio-clock.md) - the audio encoder delay test runs on mock time
- [WebSocket paused TLS dial](/quest/m1/test-flakes-2/websocket-paused-tls.md) - the fixed-address WebSocket tests stop pausing the clock over a real dial
- [Rejoin after idle](/quest/m1/test-flakes-2/rejoin-idle-race.md) - an IETF rejoin never gets the stale warm cache first, because the copy goes idle before the cancel

Expand Down
11 changes: 0 additions & 11 deletions quest/m1/test-flakes-2/publish-audio-clock.md

This file was deleted.

Loading