Fix tenc fallback for encrypted ISOBMFF files (#470)

* fix tenc fallback

* Add test case

---------

Co-authored-by: Vanilagy <[email protected]>
This commit is contained in:
jepcd
2026-08-24 14:12:04 +02:00
committed by GitHub
co-authored by Vanilagy
parent 394eede178
commit 0f9dc1f91b
3 changed files with 60 additions and 11 deletions
+27 -5
View File
@@ -3151,9 +3151,10 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
data = readBytes(slice, sampleInfo.sampleSize); data = readBytes(slice, sampleInfo.sampleSize);
if (this.internalTrack.encryptionAuxInfo) { if (this.internalTrack.encryptionInfo) {
assert(this.internalTrack.encryptionInfo); let sampleEncryption: SampleEncryptionInfo | null = null;
if (this.internalTrack.encryptionAuxInfo) {
const entries = await resolveEncryptionAuxInfo( const entries = await resolveEncryptionAuxInfo(
this.internalTrack.demuxer.reader, this.internalTrack.demuxer.reader,
this.internalTrack.encryptionInfo, this.internalTrack.encryptionInfo,
@@ -3161,7 +3162,13 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
); );
if (sampleIndex < entries.length) { if (sampleIndex < entries.length) {
data = await decryptSample(this.internalTrack, entries[sampleIndex]!, data, null); sampleEncryption = entries[sampleIndex]!;
}
}
sampleEncryption ??= getDefaultSampleEncryption(this.internalTrack.encryptionInfo);
if (sampleEncryption) {
data = await decryptSample(this.internalTrack, sampleEncryption, data, null);
} }
} }
} }
@@ -3207,8 +3214,12 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
data = readBytes(slice, fragmentSample.byteSize); data = readBytes(slice, fragmentSample.byteSize);
if (fragmentSample.encryption) { if (this.internalTrack.encryptionInfo) {
data = await decryptSample(this.internalTrack, fragmentSample.encryption, data, fragment); const sampleEncryption = fragmentSample.encryption
?? getDefaultSampleEncryption(this.internalTrack.encryptionInfo);
if (sampleEncryption) {
data = await decryptSample(this.internalTrack, sampleEncryption, data, fragment);
}
} }
} }
@@ -3779,6 +3790,17 @@ const resolveEncryptionAuxInfo = async (
return entries; return entries;
}; };
const getDefaultSampleEncryption = (encryptionInfo: TrackEncryptionInfo): SampleEncryptionInfo | null => {
if (!encryptionInfo.defaultConstantIv) {
return null;
}
return {
iv: encryptionInfo.defaultConstantIv,
subsamples: null,
};
};
const decryptSample = async ( const decryptSample = async (
track: InternalTrack, track: InternalTrack,
sampleEncryption: SampleEncryptionInfo, sampleEncryption: SampleEncryptionInfo,
+27
View File
@@ -0,0 +1,27 @@
import { expect, test } from 'vitest';
import { Input } from '../../src/input.js';
import { UrlSource } from '../../src/source.js';
import { ALL_FORMATS } from '../../src/input-format.js';
import { AudioSampleSink } from '../../src/media-sink.js';
import { assert } from '../../src/misc.js';
test('Encrypted MP4 without senc', async () => {
using input = new Input({
source: new UrlSource('/639955605-b752f7ad-7ce8-43c2-8ae9-88e74c6ae696.mp4'),
formats: ALL_FORMATS,
formatOptions: {
isobmff: {
resolveKeyId: () => 'aabbccddeeff00112233445566778899',
},
},
});
const audioTrack = await input.getPrimaryAudioTrack();
assert(audioTrack);
// Test that it can decode
const sink = new AudioSampleSink(audioTrack);
using firstSample = await sink.getSample(0);
assert(firstSample);
expect(firstSample.timestamp).toBe(0);
});
Binary file not shown.