Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion src/core/main/worker/content_preparer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { MediaSource_ } from "../../../compat/browser_compatibility_types";
import features from "../../../features";
import log from "../../../log";
import type { IManifest, IManifestMetadata } from "../../../manifest";
import { createRepresentationFilterFromFnString } from "../../../manifest";
import type Manifest from "../../../manifest/classes";
import type { IMediaSourceInterface } from "../../../mse";
import MainMediaSourceInterface from "../../../mse/main_media_source_interface";
import WorkerMediaSourceInterface from "../../../mse/worker_media_source_interface";
Expand All @@ -13,6 +15,7 @@ import { WorkerMessageType } from "../../../multithread_types";
import type { IPlayerError } from "../../../public_types";
import assert from "../../../utils/assert";
import idGenerator from "../../../utils/id_generator";
import isNullOrUndefined from "../../../utils/is_null_or_undefined";
import objectAssign from "../../../utils/object_assign";
import type {
CancellationError,
Expand Down Expand Up @@ -278,7 +281,7 @@ export default class ContentPreparer {
) {
return;
}

updateCodecSupportInWorkerMode(manifest);
const sentManifest = manifest.getMetadataSnapshot();
manifest.addEventListener(
"manifestUpdate",
Expand Down Expand Up @@ -534,3 +537,34 @@ function createMediaSourceInterfaceAndSegmentSinksStore(

return [mediaSourceInterface, segmentSinksStore, textSender];
}

/**
* Set Representation.isCodecSupportedInWebWorker to true or false
* If the codec is supported in the current context.
* If MSE in worker is not available, the attribute is not set.
*/
function updateCodecSupportInWorkerMode(manifestToUpdate: Manifest) {
if (isNullOrUndefined(MediaSource_)) {
return;
}

const codecsMap = new Map<string, boolean>();
for (const period of manifestToUpdate.periods) {
const checkedAdaptations = [
...(period.adaptations.video ?? []),
...(period.adaptations.audio ?? []),
];
for (const adaptation of checkedAdaptations) {
for (const representation of adaptation.representations) {
const codec = `${representation.mimeType};codecs="${representation.codecs[0]}"`;
if (codecsMap.has(codec)) {
representation.isCodecSupportedInWebWorker = codecsMap.get(codec);
} else {
const supported = MediaSource_.isTypeSupported(codec);
representation.isCodecSupportedInWebWorker = supported;
codecsMap.set(codec, supported);
}
}
}
}
}
2 changes: 2 additions & 0 deletions src/main_thread/init/multi_thread_content_initializer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { IMediaElement } from "../../compat/browser_compatibility_types";
import hasMseInWorker from "../../compat/has_mse_in_worker";
import mayMediaElementFailOnUndecipherableData from "../../compat/may_media_element_fail_on_undecipherable_data";
import shouldReloadMediaSourceOnDecipherabilityUpdate from "../../compat/should_reload_media_source_on_decipherability_update";
import type { ISegmentSinkMetrics } from "../../core/segment_sinks/segment_sinks_store";
Expand Down Expand Up @@ -1412,6 +1413,7 @@
const updatedCodecs = updateManifestCodecSupport(
manifest,
this._currentContentInfo?.contentDecryptor ?? null,
this._settings.worker && hasMseInWorker,

Check failure on line 1416 in src/main_thread/init/multi_thread_content_initializer.ts

View workflow job for this annotation

GitHub Actions / typechecking_and_linting (22.x)

Unexpected object value in conditional. The condition is always true
);
if (updatedCodecs.length > 0) {
sendMessage(this._settings.worker, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ describe("init - utils - updateManifestCodecSupport", () => {
},
};
const contentDecryptor = new ContentDecryptor(video, [keySystem1]);
updateManifestCodecSupport(manifest, contentDecryptor);
updateManifestCodecSupport(manifest, contentDecryptor, true);
expect(representationAVC.isSupported).toBe(true);
expect(representationHEVC.isSupported).toBe(true);
expect(representationVP9.isSupported).toBe(false); // Not Supported by MSE
Expand Down Expand Up @@ -274,11 +274,53 @@ describe("init - utils - updateManifestCodecSupport", () => {
const contentDecryptor = new ContentDecryptor(video, [keySystem1]);
await sleep(100);
contentDecryptor.attach();
updateManifestCodecSupport(manifest, contentDecryptor);
updateManifestCodecSupport(manifest, contentDecryptor, true);
expect(encryptedRepresentationAVC.isSupported).toBe(true);
expect(encryptedRepresentationHEVC.isSupported).toBe(false); // Not supported by EME
expect(encryptedRepresentationVP9.isSupported).toBe(false); // Not supported by MSE
expect(encryptedRepresentationMP4A.isSupported).toBe(true);
expect(encryptedRepresentationEC3.isSupported).toBe(false); // Not supported by EME
});

it("should update to false if the codec is not usable with MSE in worker", () => {
const representationAVC: IRepresentationMetadata = {
bitrate: 1000,
id: "representation1",
uniqueId: "representation1",
codecs: ["avc1.4d401e"],
mimeType: "video/mp4",
isSupported: undefined,
isCodecSupportedInWebWorker: undefined,
};
const representationHEVC: IRepresentationMetadata = {
bitrate: 2000,
id: "representation2",
uniqueId: "representation2",
codecs: ["hvc1.2.4.L153.B0"],
mimeType: "video/mp4",
isSupported: undefined,
isCodecSupportedInWebWorker: false,
};

const representationMP4A: IRepresentationMetadata = {
bitrate: 1000,
id: "representation4",
uniqueId: "representation4",
codecs: ["mp4a.40.2"],
mimeType: "audio/mp4",
isSupported: undefined,
isCodecSupportedInWebWorker: true,
};
const manifest = generateFakeManifestWithRepresentations(
[representationAVC, representationHEVC],
[representationMP4A],
);

const video = document.createElement("video");
const contentDecryptor = new ContentDecryptor(video, []);
updateManifestCodecSupport(manifest, contentDecryptor, true);
expect(representationAVC.isSupported).toBe(true);
expect(representationHEVC.isSupported).toBe(false); // not supported with MSE in worker
expect(representationMP4A.isSupported).toBe(true);
});
});
9 changes: 9 additions & 0 deletions src/main_thread/init/utils/update_manifest_codec_support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export function getCodecsWithUnknownSupport(
export function updateManifestCodecSupport(
manifest: IManifestMetadata,
contentDecryptor: ContentDecryptor | null,
isPlayingWithMSEinWorker: boolean,
): ICodecSupportInfo[] {
const codecSupportMap: Map<
string,
Expand Down Expand Up @@ -131,6 +132,14 @@ export function updateManifestCodecSupport(
let hasSupportedCodec: boolean = false;
let hasCodecWithUndefinedSupport: boolean = false;
adaptation.representations.forEach((representation) => {
if (
representation.isCodecSupportedInWebWorker === false &&
isPlayingWithMSEinWorker
) {
representation.isSupported = false;
return;
}

if (representation.isSupported !== undefined) {
if (representation.isSupported) {
hasSupportedCodec = true;
Expand Down
3 changes: 3 additions & 0 deletions src/manifest/classes/representation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ class Representation implements IRepresentationMetadata {
* `Manifest` methods for this.
*/
public shouldBeAvoided: boolean;
/** If the codec is supported with MSE in worker */
public isCodecSupportedInWebWorker: boolean | undefined;

/**
* @param {Object} args
Expand Down Expand Up @@ -484,6 +486,7 @@ class Representation implements IRepresentationMetadata {
hdrInfo: this.hdrInfo,
contentProtections: this.contentProtections,
decipherable: this.decipherable,
isCodecSupportedInWebWorker: this.isCodecSupportedInWebWorker,
};
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/manifest/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,4 +488,6 @@ export interface IRepresentationMetadata {
decipherable?: boolean | undefined;
/** Encryption information for this Representation. */
contentProtections?: IContentProtections | undefined;
/** If the codec is supported with MSE in worker */
isCodecSupportedInWebWorker?: boolean | undefined;
}
Loading