Record coordinated reception results and prepare scoped web H264 option
This commit is contained in:
+34
-5
@@ -3,7 +3,12 @@ const fs = require('node:fs');
|
||||
const vm = require('node:vm');
|
||||
const assert = require('node:assert/strict');
|
||||
const listeners = {}, documentListeners = {}, elements = [];
|
||||
let clock = 0, interval, starts = 0, stops = 0, osd = 0, returned = 0, readyState = 0;
|
||||
let clock = 0, interval, starts = 0, stops = 0, osd = 0, returned = 0, readyState = 0, remote = false;
|
||||
let policy = { IsEnigmaChannel: true, PreferH264: true }, policyCalls = 0, policyError = false;
|
||||
const profile = { DirectPlayProfiles: [{ Type: 'Video', VideoCodec: 'av1,h264' }],
|
||||
TranscodingProfiles: [{ Type: 'Video', Context: 'Streaming', VideoCodec: 'av1,h264', AudioCodec: 'aac', Protocol: 'hls', MaxWidth: 1920 },
|
||||
{ Type: 'Video', Context: 'Streaming', VideoCodec: 'av1', AudioCodec: 'aac', Protocol: 'hls' },
|
||||
{ Type: 'Audio', AudioCodec: 'aac', Protocol: 'http' }], CodecProfiles: [{ Type: 'Video', Codec: 'h264', Conditions: [{ Property: 'Width', Value: '1920' }] }] };
|
||||
const pending = [];
|
||||
const location = { hash: '#/livetv', pathname: '/web/index.html', search: '', replace(value) { this.hash = value; } };
|
||||
const document = {
|
||||
@@ -14,7 +19,9 @@ const document = {
|
||||
addEventListener(name, callback) { documentListeners[name] = callback; }
|
||||
};
|
||||
const window = {
|
||||
ApiClient: { getCurrentUserId: () => 'user', serverId: () => 'server', getItem: async (user, id) => ({ Id: id, Type: 'TvChannel' }) },
|
||||
ApiClient: { getCurrentUserId: () => 'user', serverId: () => 'server', getItem: async (user, id) => ({ Id: id, Type: 'TvChannel' }),
|
||||
getUrl: (path, params) => path + '?' + new URLSearchParams(params),
|
||||
ajax: async () => { ++policyCalls; if (policyError) throw Error('offline'); return policy; } },
|
||||
addEventListener(name, callback) { listeners[name] = callback; }
|
||||
};
|
||||
const context = {
|
||||
@@ -25,7 +32,7 @@ const context = {
|
||||
clearInterval(callback) { if (interval === callback) interval = null; }
|
||||
};
|
||||
const manager = {
|
||||
getCurrentPlayer: () => ({ isLocalPlayer: true }),
|
||||
getCurrentPlayer: () => ({ isLocalPlayer: !remote }),
|
||||
play() { ++starts; return new Promise(resolve => pending.push(resolve)); },
|
||||
stop: async () => { ++stops; }
|
||||
};
|
||||
@@ -33,8 +40,30 @@ const flush = async () => { for (let i = 0; i < 8; i++) await Promise.resolve();
|
||||
(async () => {
|
||||
vm.runInNewContext(fs.readFileSync(__dirname + '/web/decoder-channel-playback.js', 'utf8'), context);
|
||||
const Plugin = await window.DecoderChannelPlayback();
|
||||
new Plugin({ playbackManager: manager, toast() {}, loading: { hide() {} }, events: { on() {} },
|
||||
appRouter: { showVideoOsd: async () => { ++osd; }, show: async () => { ++returned; location.hash = '#/livetv?tab=2'; } } });
|
||||
const appHost = { getDeviceProfile: async () => profile };
|
||||
const dependencies = { playbackManager: manager, appHost, toast() {}, loading: { hide() {} }, events: { on() {} },
|
||||
appRouter: { showVideoOsd: async () => { ++osd; }, show: async () => { ++returned; location.hash = '#/livetv?tab=2'; } } };
|
||||
new Plugin(dependencies);
|
||||
const channel = { Id: 'channel', Type: 'TvChannel', ServerId: 'server' };
|
||||
const before = JSON.stringify(profile);
|
||||
const changed = await appHost.getDeviceProfile(channel, {});
|
||||
assert.notEqual(changed, profile); assert.equal(JSON.stringify(profile), before, 'shared profile must not mutate');
|
||||
assert.equal(changed.TranscodingProfiles.length, 2); assert.equal(changed.TranscodingProfiles[0].VideoCodec, 'h264');
|
||||
assert.equal(changed.TranscodingProfiles[0].MaxWidth, 1920); assert.equal(changed.TranscodingProfiles[0].AudioCodec, 'aac');
|
||||
assert.equal(JSON.stringify(changed.DirectPlayProfiles), JSON.stringify(profile.DirectPlayProfiles));
|
||||
assert.equal(JSON.stringify(changed.CodecProfiles), JSON.stringify(profile.CodecProfiles));
|
||||
let count = policyCalls;
|
||||
assert.equal(await appHost.getDeviceProfile({ Type: 'Movie' }, {}), profile); assert.equal(policyCalls, count);
|
||||
assert.equal(await appHost.getDeviceProfile({ ...channel, ServerId: 'other' }, {}), profile); assert.equal(policyCalls, count);
|
||||
remote = true; assert.equal(await appHost.getDeviceProfile(channel, {}), profile); assert.equal(policyCalls, count); remote = false;
|
||||
window.NativeShell = {}; assert.equal(await appHost.getDeviceProfile(channel, {}), profile); assert.equal(policyCalls, count); delete window.NativeShell;
|
||||
policy = { IsEnigmaChannel: false, PreferH264: true }; assert.equal(await appHost.getDeviceProfile(channel, {}), profile);
|
||||
policy = { IsEnigmaChannel: true, PreferH264: false }; assert.equal(await appHost.getDeviceProfile(channel, {}), profile);
|
||||
policyError = true; assert.equal(await appHost.getDeviceProfile(channel, {}), profile); policyError = false;
|
||||
policy = { IsEnigmaChannel: true, PreferH264: true };
|
||||
count = policyCalls; await appHost.getDeviceProfile(channel, {}); assert.equal(policyCalls, count + 1, 'retry refreshes current policy');
|
||||
const wrapped = appHost.getDeviceProfile; new Plugin(dependencies); assert.equal(appHost.getDeviceProfile, wrapped, 'one profile wrapper per appHost');
|
||||
console.log('PASS scoped H264 policy, clone, audio/conditions/direct play preserved, movies/other sources/native/remote bypass, disabled/failing policy, retry and dedup');
|
||||
assert.equal(location.hash, '#/livetv?tab=2');
|
||||
location.hash = '#/livetv?tab=0'; listeners.hashchange();
|
||||
assert.equal(location.hash, '#/livetv?tab=0');
|
||||
|
||||
Reference in New Issue
Block a user