mirror of
https://github.com/video-dev/hls.js.git
synced 2026-06-16 13:34:44 +00:00
203 lines
5.4 KiB
TypeScript
203 lines
5.4 KiB
TypeScript
import Hls from '../../../src/hls';
|
|
import { hlsDefaultConfig } from '../../../src/config';
|
|
import AudioStreamController from '../../../src/controller/audio-stream-controller';
|
|
import { Events } from '../../../src/events';
|
|
import { FragmentTracker } from '../../../src/controller/fragment-tracker';
|
|
import KeyLoader from '../../../src/loader/key-loader';
|
|
import { LoadStats } from '../../../src/loader/load-stats';
|
|
import { AttrList } from '../../../src/utils/attr-list';
|
|
import {
|
|
MediaAttributes,
|
|
MediaPlaylist,
|
|
} from '../../../src/types/media-playlist';
|
|
import { Level } from '../../../src/types/level';
|
|
import type {
|
|
AudioTrackSwitchingData,
|
|
AudioTrackLoadedData,
|
|
TrackLoadedData,
|
|
} from '../../../src/types/events';
|
|
import type { LevelDetails } from '../../../src/loader/level-details';
|
|
import type { Fragment } from '../../../src/loader/fragment';
|
|
|
|
import chai from 'chai';
|
|
import sinonChai from 'sinon-chai';
|
|
import { State } from '../../../src/controller/base-stream-controller';
|
|
|
|
chai.use(sinonChai);
|
|
const expect = chai.expect;
|
|
|
|
type AudioStreamControllerTestable = Omit<
|
|
AudioStreamController,
|
|
'levels' | 'mainDetails' | 'onAudioTrackSwitching' | 'onAudioTrackLoaded'
|
|
> & {
|
|
levels: Level[] | null;
|
|
mainDetails: LevelDetails;
|
|
onAudioTrackSwitching: (
|
|
event: Events.AUDIO_TRACK_SWITCHING,
|
|
data: AudioTrackSwitchingData,
|
|
) => void;
|
|
onAudioTrackLoaded: (
|
|
event: Events.AUDIO_TRACK_LOADED,
|
|
data: TrackLoadedData,
|
|
) => void;
|
|
};
|
|
|
|
describe('AudioStreamController', function () {
|
|
const audioTracks: MediaPlaylist[] = [
|
|
{
|
|
attrs: new AttrList({}) as MediaAttributes,
|
|
autoselect: true,
|
|
bitrate: 0,
|
|
forced: false,
|
|
type: 'AUDIO',
|
|
url: 'data://',
|
|
groupId: '1',
|
|
id: 0,
|
|
default: true,
|
|
name: 'A',
|
|
},
|
|
{
|
|
attrs: new AttrList({}) as MediaAttributes,
|
|
autoselect: true,
|
|
bitrate: 0,
|
|
forced: false,
|
|
type: 'AUDIO',
|
|
url: 'data://',
|
|
groupId: '1',
|
|
id: 1,
|
|
default: false,
|
|
name: 'B',
|
|
},
|
|
{
|
|
attrs: new AttrList({}) as MediaAttributes,
|
|
autoselect: true,
|
|
bitrate: 0,
|
|
forced: false,
|
|
type: 'AUDIO',
|
|
url: 'data://',
|
|
groupId: '1',
|
|
id: 2,
|
|
default: false,
|
|
name: 'C',
|
|
},
|
|
{
|
|
attrs: new AttrList({}) as MediaAttributes,
|
|
autoselect: true,
|
|
bitrate: 0,
|
|
forced: false,
|
|
type: 'AUDIO',
|
|
url: 'data://',
|
|
groupId: '2',
|
|
id: 0,
|
|
default: true,
|
|
name: 'A',
|
|
},
|
|
{
|
|
attrs: new AttrList({}) as MediaAttributes,
|
|
autoselect: true,
|
|
bitrate: 0,
|
|
forced: false,
|
|
type: 'AUDIO',
|
|
url: 'data://',
|
|
groupId: '2',
|
|
id: 1,
|
|
default: false,
|
|
name: 'B',
|
|
},
|
|
{
|
|
attrs: new AttrList({}) as MediaAttributes,
|
|
autoselect: true,
|
|
bitrate: 0,
|
|
forced: false,
|
|
type: 'AUDIO',
|
|
url: 'data://',
|
|
groupId: '3',
|
|
id: 2,
|
|
default: false,
|
|
name: 'C',
|
|
},
|
|
];
|
|
const tracks: Level[] = audioTracks.map((parsedLevel) => {
|
|
const level = new Level(parsedLevel);
|
|
return level;
|
|
});
|
|
|
|
let hls: Hls;
|
|
let fragmentTracker: FragmentTracker;
|
|
let keyLoader: KeyLoader;
|
|
let audioStreamController: AudioStreamControllerTestable;
|
|
|
|
beforeEach(function () {
|
|
hls = new Hls();
|
|
fragmentTracker = new FragmentTracker(hls);
|
|
keyLoader = new KeyLoader(hlsDefaultConfig);
|
|
audioStreamController = new AudioStreamController(
|
|
hls,
|
|
fragmentTracker,
|
|
keyLoader,
|
|
) as unknown as AudioStreamControllerTestable;
|
|
});
|
|
|
|
afterEach(function () {
|
|
hls.destroy();
|
|
});
|
|
|
|
describe('onAudioTrackSwitching', function () {
|
|
it('reset the controller state to IDLE when WAITING_TRACK', function () {
|
|
audioStreamController.state = State.WAITING_TRACK;
|
|
audioStreamController.onAudioTrackSwitching(
|
|
Events.AUDIO_TRACK_SWITCHING,
|
|
audioTracks[0],
|
|
);
|
|
expect(audioStreamController.state).to.equal(State.IDLE);
|
|
expect(audioStreamController.hasInterval()).to.be.true;
|
|
});
|
|
|
|
it('leaved the controller in the STOPPED state', function () {
|
|
audioStreamController.state = State.STOPPED;
|
|
audioStreamController.onAudioTrackSwitching(
|
|
Events.AUDIO_TRACK_SWITCHING,
|
|
audioTracks[0],
|
|
);
|
|
expect(audioStreamController.state).to.equal(State.STOPPED);
|
|
expect(audioStreamController.hasInterval()).to.be.false;
|
|
});
|
|
});
|
|
|
|
describe('onAudioTrackLoaded', function () {
|
|
it('should update the level details from the event data', function () {
|
|
const trackLoadedData: AudioTrackLoadedData = {
|
|
id: 0,
|
|
groupId: 'audio',
|
|
stats: new LoadStats(),
|
|
deliveryDirectives: null,
|
|
networkDetails: {},
|
|
details: {
|
|
live: false,
|
|
get fragments() {
|
|
const frags: Fragment[] = [];
|
|
for (let i = 0; i < this.endSN; i++) {
|
|
frags.push({ sn: i, type: 'main' } as unknown as Fragment);
|
|
}
|
|
return frags;
|
|
},
|
|
targetduration: 100,
|
|
} as unknown as LevelDetails,
|
|
};
|
|
|
|
audioStreamController.levels = tracks;
|
|
audioStreamController.mainDetails = trackLoadedData.details;
|
|
audioStreamController.tick = () => {};
|
|
|
|
audioStreamController.onAudioTrackLoaded(
|
|
Events.AUDIO_TRACK_LOADED,
|
|
trackLoadedData,
|
|
);
|
|
|
|
expect(audioStreamController.levels[0].details).to.equal(
|
|
trackLoadedData.details,
|
|
);
|
|
});
|
|
});
|
|
});
|