mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-17 16:26:39 +03:00
e8f24ece6f
Issue #2648
169 lines
5.8 KiB
JavaScript
169 lines
5.8 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
describe('Transmuxer', () => {
|
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
|
|
const videoSegmentUri = '/base/test/test/assets/video.ts';
|
|
const audioSegmentUri = '/base/test/test/assets/audio.ts';
|
|
const mp4MimeType = 'video/mp4; codecs="avc1.42E01E"';
|
|
const transportStreamVideoMimeType = 'video/mp2t; codecs="avc1.42E01E"';
|
|
const transportStreamAudioMimeType = 'video/mp2t; codecs="mp4a.40.2"';
|
|
|
|
/** @type {!ArrayBuffer} */
|
|
let videoSegment;
|
|
/** @type {!ArrayBuffer} */
|
|
let audioSegment;
|
|
/** @type {!ArrayBuffer} */
|
|
let emptySegment;
|
|
|
|
/** @type {!shaka.media.Transmuxer} */
|
|
let transmuxer;
|
|
|
|
|
|
beforeAll(async () => {
|
|
const responses = await Promise.all([
|
|
shaka.test.Util.fetch(videoSegmentUri),
|
|
shaka.test.Util.fetch(audioSegmentUri),
|
|
]);
|
|
videoSegment = responses[0];
|
|
audioSegment = responses[1];
|
|
emptySegment = new ArrayBuffer(0);
|
|
});
|
|
|
|
beforeEach(() => {
|
|
transmuxer = new shaka.media.Transmuxer();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await transmuxer.destroy();
|
|
});
|
|
|
|
describe('isSupported', () => {
|
|
const Transmuxer = shaka.media.Transmuxer;
|
|
|
|
it('returns whether the content type is supported', () => {
|
|
expect(Transmuxer.isSupported(
|
|
mp4MimeType, ContentType.VIDEO)).toBe(false);
|
|
expect(Transmuxer.isSupported(
|
|
transportStreamVideoMimeType, ContentType.VIDEO)).toBe(true);
|
|
});
|
|
|
|
// Issue #1991
|
|
it('handles upper-case MIME types', () => {
|
|
const mimeType = transportStreamVideoMimeType.replace('mp2t', 'MP2T');
|
|
expect(Transmuxer.isSupported(mimeType, ContentType.VIDEO)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('convertTsCodecs', () => {
|
|
const convertTsCodecs =
|
|
(type, codecs) => shaka.media.Transmuxer.convertTsCodecs(type, codecs);
|
|
|
|
it('returns converted codecs', () => {
|
|
const convertedVideoCodecs =
|
|
convertTsCodecs(ContentType.VIDEO, transportStreamVideoMimeType);
|
|
const convertedAudioCodecs =
|
|
convertTsCodecs(ContentType.AUDIO, transportStreamAudioMimeType);
|
|
const expectedVideoCodecs = 'video/mp4; codecs="avc1.42E01E"';
|
|
const expectedAudioCodecs = 'audio/mp4; codecs="mp4a.40.2"';
|
|
expect(convertedVideoCodecs).toBe(expectedVideoCodecs);
|
|
expect(convertedAudioCodecs).toBe(expectedAudioCodecs);
|
|
});
|
|
|
|
it('converts legacy avc1 codec strings', () => {
|
|
expect(
|
|
convertTsCodecs(
|
|
ContentType.VIDEO, 'video/mp2t; codecs="avc1.100.42"'))
|
|
.toBe('video/mp4; codecs="avc1.64002a"');
|
|
expect(
|
|
convertTsCodecs(ContentType.VIDEO, 'video/mp2t; codecs="avc1.77.80"'))
|
|
.toBe('video/mp4; codecs="avc1.4d0050"');
|
|
expect(
|
|
convertTsCodecs(ContentType.VIDEO, 'video/mp2t; codecs="avc1.66.1"'))
|
|
.toBe('video/mp4; codecs="avc1.420001"');
|
|
});
|
|
|
|
// Issue #1991
|
|
it('handles upper-case MIME types', () => {
|
|
expect(convertTsCodecs(
|
|
ContentType.VIDEO, 'video/MP2T; codecs="avc1.420001"'))
|
|
.toBe('video/mp4; codecs="avc1.420001"');
|
|
});
|
|
});
|
|
|
|
describe('transmuxing', () => {
|
|
it('transmux video from TS to MP4', async () => {
|
|
let sawMDAT = false;
|
|
|
|
const transmuxedData = await transmuxer.transmux(videoSegment);
|
|
expect(transmuxedData.data).toEqual(jasmine.any(Uint8Array));
|
|
expect(transmuxedData.data.length).toBeGreaterThan(0);
|
|
expect(transmuxedData.captions).toEqual(jasmine.any(Array));
|
|
new shaka.util.Mp4Parser()
|
|
.box('mdat', shaka.util.Mp4Parser.allData((data) => {
|
|
sawMDAT = true;
|
|
expect(data.byteLength).toBeGreaterThan(0);
|
|
}))
|
|
.parse(transmuxedData.data);
|
|
expect(sawMDAT).toBeTruthy();
|
|
});
|
|
|
|
it('transmux audio from TS to MP4', async () => {
|
|
let sawMDAT = false;
|
|
const transmuxedData = await transmuxer.transmux(audioSegment);
|
|
expect(transmuxedData.data).toEqual(jasmine.any(Uint8Array));
|
|
expect(transmuxedData.data.length).toBeGreaterThan(0);
|
|
expect(transmuxedData.captions).toEqual(jasmine.any(Array));
|
|
new shaka.util.Mp4Parser()
|
|
.box('mdat', shaka.util.Mp4Parser.allData((data) => {
|
|
sawMDAT = true;
|
|
expect(data.byteLength).toBeGreaterThan(0);
|
|
}))
|
|
.parse(transmuxedData.data);
|
|
expect(sawMDAT).toBeTruthy();
|
|
});
|
|
|
|
it('transmux empty video from TS to MP4', async () => {
|
|
let sawMDAT = false;
|
|
const transmuxedData = await transmuxer.transmux(emptySegment);
|
|
expect(transmuxedData.data).toEqual(jasmine.any(Uint8Array));
|
|
expect(transmuxedData.captions).toEqual([]);
|
|
new shaka.util.Mp4Parser()
|
|
.box('mdat', shaka.util.Mp4Parser.allData((data) => {
|
|
sawMDAT = true;
|
|
}))
|
|
.parse(transmuxedData.data);
|
|
expect(sawMDAT).toBeFalsy();
|
|
});
|
|
|
|
it('passes through true timestamps', async () => {
|
|
let parsed = false;
|
|
const expectedMp4Timestamp = 5166000; // in timescale units
|
|
let mp4Timestamp;
|
|
|
|
const transmuxedData = await transmuxer.transmux(videoSegment);
|
|
const Mp4Parser = shaka.util.Mp4Parser;
|
|
|
|
new Mp4Parser()
|
|
.box('moof', Mp4Parser.children)
|
|
.box('traf', Mp4Parser.children)
|
|
.fullBox('tfdt', (box) => {
|
|
goog.asserts.assert(
|
|
box.version == 0 || box.version == 1,
|
|
'TFDT version can only be 0 or 1');
|
|
const parsedTFDTBox = shaka.util.Mp4BoxParsers.parseTFDT(
|
|
box.reader, box.version);
|
|
mp4Timestamp = parsedTFDTBox.baseMediaDecodeTime;
|
|
parsed = true;
|
|
})
|
|
.parse(transmuxedData.data);
|
|
|
|
expect(parsed).toBe(true);
|
|
expect(mp4Timestamp).toBe(expectedMp4Timestamp);
|
|
});
|
|
});
|
|
});
|