From 926b4842ec207faa5c064ead32a8ea2afa7b8503 Mon Sep 17 00:00:00 2001 From: Paul Berberian Date: Thu, 31 Aug 2023 19:10:02 +0200 Subject: [PATCH] wip --- .../old_webkit_media_keys.ts | 7 +++--- src/compat/eme/eme-api-implementation.ts | 2 +- ...create_content_time_boundaries_observer.ts | 4 ++-- .../init/multi_thread_content_initializer.ts | 21 ++++++++++++++++-- .../utils/content_time_boundaries_observer.ts | 9 ++++---- .../audio_video/audio_video_segment_buffer.ts | 22 +++++++++---------- src/main/send_message.ts | 18 +++++++-------- src/transports/dash/manifest_parser.ts | 12 +++++----- src/worker/index.ts | 5 ++--- src/worker/send_message.ts | 3 ++- src/worker/worker_content_initializer.ts | 2 +- 11 files changed, 61 insertions(+), 44 deletions(-) diff --git a/src/compat/eme/custom_media_keys/old_webkit_media_keys.ts b/src/compat/eme/custom_media_keys/old_webkit_media_keys.ts index 6c7df1dee2a..3b42d069c60 100644 --- a/src/compat/eme/custom_media_keys/old_webkit_media_keys.ts +++ b/src/compat/eme/custom_media_keys/old_webkit_media_keys.ts @@ -43,10 +43,11 @@ export interface IOldWebkitHTMLMediaElement extends HTMLVideoElement { * @returns {Boolean} */ export function isOldWebkitMediaElement( - element : HTMLMediaElement|IOldWebkitHTMLMediaElement + element : unknown ) : element is IOldWebkitHTMLMediaElement { - return typeof (element as IOldWebkitHTMLMediaElement) - .webkitGenerateKeyRequest === "function"; + return typeof ( + element as IOldWebkitHTMLMediaElement + )?.webkitGenerateKeyRequest === "function"; } /** diff --git a/src/compat/eme/eme-api-implementation.ts b/src/compat/eme/eme-api-implementation.ts index 92a48bc28fb..a03c79ae0d9 100644 --- a/src/compat/eme/eme-api-implementation.ts +++ b/src/compat/eme/eme-api-implementation.ts @@ -158,7 +158,7 @@ function getEmeApiImplementation( implementation = "webkit"; } else { // This is for Chrome with unprefixed EME api - if (isOldWebkitMediaElement(HTMLVideoElement.prototype)) { + if (isOldWebkitMediaElement(globalScope.HTMLVideoElement?.prototype)) { onEncrypted = createCompatibleEventListener(["needkey"]); const callbacks = getOldKitWebKitMediaKeyCallbacks(); isTypeSupported = callbacks.isTypeSupported; diff --git a/src/core/init/create_content_time_boundaries_observer.ts b/src/core/init/create_content_time_boundaries_observer.ts index 62cdcc0271d..5b325962135 100644 --- a/src/core/init/create_content_time_boundaries_observer.ts +++ b/src/core/init/create_content_time_boundaries_observer.ts @@ -1,6 +1,6 @@ import log from "../../log"; import Manifest, { - IPeriodMetadata, + Period, } from "../../manifest"; import { IPlayerError } from "../../public_types"; import { @@ -14,7 +14,7 @@ import ContentTimeBoundariesObserver from "./utils/content_time_boundaries_obser export interface IContentTimeBoundariesObserverCallbacks { onWarning: (evt: IPlayerError) => void; - onPeriodChanged: (period: IPeriodMetadata) => void; + onPeriodChanged: (period: Period) => void; } /** diff --git a/src/core/init/multi_thread_content_initializer.ts b/src/core/init/multi_thread_content_initializer.ts index 2869c480aa2..eb8389d9360 100644 --- a/src/core/init/multi_thread_content_initializer.ts +++ b/src/core/init/multi_thread_content_initializer.ts @@ -227,8 +227,25 @@ export default class MultiThreadContentInitializer extends ContentInitializer { if (this._mainThreadMediaSource?.id !== msgData.mediaSourceId) { return; } - this._mainThreadMediaSource.addSourceBuffer(msgData.value.sourceBufferType, - msgData.value.codec); + const sbInterface = this._mainThreadMediaSource.addSourceBuffer( + msgData.value.sourceBufferType, + msgData.value.codec); + sbInterface.addEventListener("sourceBufferError", () => { + sendMessage(this._settings.worker, { + type: "source-buffer-error", + mediaSourceId: msgData.mediaSourceId, + sourceBufferType: msgData.value.sourceBufferType, + value: null, + }); + }, this._initCanceller.signal); + sbInterface.addEventListener("sourceBufferUpdateEnd", () => { + sendMessage(this._settings.worker, { + type: "source-buffer-success", + mediaSourceId: msgData.mediaSourceId, + sourceBufferType: msgData.value.sourceBufferType, + value: null, + }); + }, this._initCanceller.signal); } break; diff --git a/src/core/init/utils/content_time_boundaries_observer.ts b/src/core/init/utils/content_time_boundaries_observer.ts index d874e65c365..6bc28a4c88b 100644 --- a/src/core/init/utils/content_time_boundaries_observer.ts +++ b/src/core/init/utils/content_time_boundaries_observer.ts @@ -17,7 +17,6 @@ import { MediaError } from "../../../errors"; import Manifest, { Adaptation, - IPeriodMetadata, IRepresentationIndex, Period, } from "../../../manifest"; @@ -187,7 +186,7 @@ export default class ContentTimeBoundariesObserver */ public onRepresentationChange( bufferType : IBufferType, - period : IPeriodMetadata + period : Period ) : void { this._addActivelyLoadedPeriod(period, bufferType); } @@ -257,7 +256,7 @@ export default class ContentTimeBoundariesObserver } private _addActivelyLoadedPeriod( - period : IPeriodMetadata, + period : Period, bufferType : IBufferType ) : void { const streamInfo = this._lazilyCreateActiveStreamInfo(bufferType); @@ -382,7 +381,7 @@ export interface IContentTimeBoundariesObserverEvent { /** Triggered when a minor error is encountered. */ warning : IPlayerError; /** Triggered when a new `Period` is currently playing. */ - periodChange : IPeriodMetadata; + periodChange : Period; /** * Triggered when the duration of the currently-playing content became known * or changed. @@ -637,7 +636,7 @@ interface IActiveStreamsInfo { * The first chronological Period in that list is the active one for * the current type. */ - activePeriods : SortedList; + activePeriods : SortedList; /** * If `true` the last segment for the last currently known Period has been * pushed for the current Adaptation and Representation choice. diff --git a/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts b/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts index a4415c71cc4..9f269f377af 100644 --- a/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +++ b/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import config from "../../../../config"; import log from "../../../../log"; import { getLoggableSegmentId } from "../../../../manifest"; import assertUnreachable from "../../../../utils/assert_unreachable"; @@ -180,19 +179,10 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer { const onError = this._onPendingTaskError.bind(this); const reCheck = this._flush.bind(this); - // Some browsers (happened with firefox 66) sometimes "forget" to send us - // `update` or `updateend` events. - // In that case, we're completely unable to continue the queue here and - // stay locked in a waiting state. - // This interval is here to check at regular intervals if the underlying - // SourceBuffer is currently updating. - const { SOURCE_BUFFER_FLUSHING_INTERVAL } = config.getCurrent(); - const intervalId = setInterval(reCheck, SOURCE_BUFFER_FLUSHING_INTERVAL); this._sourceBuffer.addEventListener("sourceBufferError", onError); this._sourceBuffer.addEventListener("sourceBufferUpdateEnd", reCheck); this._canceller.signal.register(() => { - clearInterval(intervalId); this._sourceBuffer.removeEventListener("sourceBufferError", onError); this._sourceBuffer.removeEventListener("sourceBufferUpdateEnd", reCheck); }); @@ -525,10 +515,20 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer { !this._isLastInitSegment(data.initSegmentUniqueId)) { // Push initialization segment before the media segment - const segmentData = this._initSegmentsMap.get(data.initSegmentUniqueId); + let segmentData = this._initSegmentsMap.get(data.initSegmentUniqueId); if (segmentData === undefined) { throw new Error("Invalid initialization segment uniqueId"); } + // XXX TODO + // Initialization segments have to be cloned for now + const dst = new ArrayBuffer(segmentData.byteLength); + const tmpU8 = new Uint8Array(dst); + tmpU8.set( + segmentData instanceof ArrayBuffer ? + new Uint8Array(segmentData) : + new Uint8Array(segmentData.buffer) + ); + segmentData = tmpU8; dataToPush.push(segmentData); this._lastInitSegmentUniqueId = data.initSegmentUniqueId; } diff --git a/src/main/send_message.ts b/src/main/send_message.ts index 3fb44937aa3..0332883f41b 100644 --- a/src/main/send_message.ts +++ b/src/main/send_message.ts @@ -167,9 +167,7 @@ export interface ISourceBufferOperationSuccessMainMessage { * `CreateSourceBufferWorkerMessage`. */ sourceBufferType: SourceBufferType; - value: { - buffered: Float64Array; - }; + value: null; } export interface ISourceBufferErrorMainMessage { @@ -181,12 +179,14 @@ export interface ISourceBufferErrorMainMessage { mediaSourceId: string; /** Identify the SourceBuffer in question. */ sourceBufferType: SourceBufferType; - value: { - /** The error's message. */ - message: string; - /** If `true` the error is due to the fact that the buffer is full. */ - isBufferFull: boolean; - }; + value: null; + // XXX TODO +// { +// /** The error's message. */ +// message: string; +// /** If `true` the error is due to the fact that the buffer is full. */ +// isBufferFull: boolean; +// } } /** diff --git a/src/transports/dash/manifest_parser.ts b/src/transports/dash/manifest_parser.ts index 2af75a92c89..8bed12d2c27 100644 --- a/src/transports/dash/manifest_parser.ts +++ b/src/transports/dash/manifest_parser.ts @@ -150,12 +150,12 @@ export default function generateManifestParser( return Promise.reject(cancelSignal.cancellationError); } const warnings : IPlayerError[] = []; - // options.representationFilter = (rep, ctxt) => { - // if (ctxt.trackType === "video") { - // return (rep.bitrate ?? 2100000) <= 2100000; - // } - // return true; - // }; + options.representationFilter = (rep, ctxt) => { + if (ctxt.trackType === "video") { + return (rep.bitrate ?? 2100000) <= 2100000; + } + return true; + }; const manifest = new Manifest(parserResponse.value.parsed, options, warnings); return { manifest, url, warnings }; } diff --git a/src/worker/index.ts b/src/worker/index.ts index c0fddf7107a..9204c471c23 100644 --- a/src/worker/index.ts +++ b/src/worker/index.ts @@ -19,7 +19,6 @@ import { } from "../main"; import Manifest, { Adaptation, - IPeriodMetadata, Period, Representation, } from "../manifest"; @@ -206,11 +205,11 @@ function startCurrentContent(val : IStartContentMessageValue) { sendMessage({ type: "warning", contentId, value: formatErrorForSender(err) }), - onPeriodChanged: (period: IPeriodMetadata) => { + onPeriodChanged: (period: Period) => { sendMessage({ type: "activePeriodChanged", contentId, - value: { period }, + value: { period: period.getMetadataSnapshot() }, }); }, }, diff --git a/src/worker/send_message.ts b/src/worker/send_message.ts index a9b10155870..32853a87003 100644 --- a/src/worker/send_message.ts +++ b/src/worker/send_message.ts @@ -22,7 +22,8 @@ export default function sendMessage( } else { // TypeScript made a mistake here, and 2busy2fix /* eslint-disable-next-line */ - (postMessage as any)(msg, transferables); + // XXX TODO add transferables urgently + (postMessage as any)(msg); } } diff --git a/src/worker/worker_content_initializer.ts b/src/worker/worker_content_initializer.ts index 65672d96b1e..ee0dfd6514e 100644 --- a/src/worker/worker_content_initializer.ts +++ b/src/worker/worker_content_initializer.ts @@ -145,7 +145,7 @@ export default class WorkerSideContentInitializer { sendMessage({ type: "manifest-update", contentId, - value: { manifest, updates }, + value: { manifest: manifest.getMetadataSnapshot(), updates }, }); }, contentCanceller.signal); unbindRejectOnCancellation();