feat: Add experimental rewrite of go2rtc live provider (MSE/WebRTC/MP4/MJPEG) (#2580)
- Closes #2556 - Closes #2450 **Key intended features:** - go2rtc compatible - 100% test coverage to significantly improve ability to test, maintain and work around browser weirdnesses (e.g. Safari). - Written from the ground up in the style of the rest of the project. **To use:** - Change `live_provider` from `go2rtc` to `go2rtc-experimental`.
This commit is contained in:
@@ -35,6 +35,22 @@ describe('ProviderErrorDetector', () => {
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should adopt the specific reason carried on the event', () => {
|
||||
const host = createHostInDocument();
|
||||
const detector = new ProviderErrorDetector(host, vi.fn());
|
||||
detector.subscribe();
|
||||
|
||||
host.dispatchEvent(
|
||||
new CustomEvent(LIVE_ERROR_EVENT, { bubbles: true, detail: 'unsupported' }),
|
||||
);
|
||||
|
||||
expect(detector.getVerdict()).toEqual({
|
||||
state: 'not_live',
|
||||
authority: 'hard',
|
||||
reason: 'unsupported',
|
||||
});
|
||||
});
|
||||
|
||||
it('should notify only on the transition to not live', () => {
|
||||
const host = createHostInDocument();
|
||||
const onChange = vi.fn();
|
||||
|
||||
@@ -89,7 +89,7 @@ describe('StreamLivenessController', () => {
|
||||
const { controller } = setup();
|
||||
|
||||
expect(controller.isLive()).toBe(true);
|
||||
expect(controller.getPlaceholder()).toBeNull();
|
||||
expect(controller.getFailure()).toBeNull();
|
||||
});
|
||||
|
||||
it('should aggregate a detector losing liveness only after host connect', () => {
|
||||
@@ -123,9 +123,13 @@ describe('StreamLivenessController', () => {
|
||||
|
||||
failViaProviderError();
|
||||
|
||||
// Provider-error is not-live but does not want a placeholder.
|
||||
// Provider-error is not-live but does not want a placeholder; its cause is
|
||||
// still available for a wrapper that fills the frame itself.
|
||||
expect(controller.isLive()).toBe(false);
|
||||
expect(controller.getPlaceholder()).toBeNull();
|
||||
expect(controller.getFailure()).toEqual({
|
||||
reason: 'playback_error',
|
||||
renderPlaceholder: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not fire the issue without a target', () => {
|
||||
@@ -154,7 +158,10 @@ describe('StreamLivenessController', () => {
|
||||
fireMediaPlayerLiveness(false);
|
||||
|
||||
expect(controller.isLive()).toBe(false);
|
||||
expect(controller.getPlaceholder()).toEqual({ reason: 'stalled' });
|
||||
expect(controller.getFailure()).toEqual({
|
||||
reason: 'stalled',
|
||||
renderPlaceholder: true,
|
||||
});
|
||||
expect(issueTriggers).toEqual([
|
||||
{ key: 'media_unavailable', targetID: 'camera.office', reason: 'stalled' },
|
||||
]);
|
||||
@@ -232,7 +239,10 @@ describe('StreamLivenessController', () => {
|
||||
controller.hostConnected();
|
||||
|
||||
expect(controller.isLive()).toBe(false);
|
||||
expect(controller.getPlaceholder()).toEqual({ reason: 'entity_unavailable' });
|
||||
expect(controller.getFailure()).toEqual({
|
||||
reason: 'entity_unavailable',
|
||||
renderPlaceholder: true,
|
||||
});
|
||||
expect(issueTriggers).toEqual([
|
||||
{
|
||||
key: 'media_unavailable',
|
||||
@@ -298,7 +308,7 @@ describe('StreamLivenessController', () => {
|
||||
|
||||
// Direct frame evidence outranks the entity proxy: no teardown, no issue.
|
||||
expect(controller.isLive()).toBe(true);
|
||||
expect(controller.getPlaceholder()).toBeNull();
|
||||
expect(controller.getFailure()).toBeNull();
|
||||
expect(issueTriggers).toEqual([]);
|
||||
|
||||
vi.useRealTimers();
|
||||
@@ -343,6 +353,9 @@ describe('StreamLivenessController', () => {
|
||||
// The always_error opt-in is authoritative: an unavailable entity overrides
|
||||
// even confirmed frames.
|
||||
expect(controller.isLive()).toBe(false);
|
||||
expect(controller.getPlaceholder()).toEqual({ reason: 'entity_unavailable' });
|
||||
expect(controller.getFailure()).toEqual({
|
||||
reason: 'entity_unavailable',
|
||||
renderPlaceholder: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user