rx-player
Version:
Canal+ HTML5 Video Player
110 lines (101 loc) • 3.46 kB
text/typescript
/**
* Copyright 2015 CANAL+ Group
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import EventEmitter from "../utils/event_emitter";
import globalScope from "../utils/global_scope";
import isNode from "../utils/is_node";
import isNullOrUndefined from "../utils/is_null_or_undefined";
import queueMicrotask from "../utils/queue_microtask";
interface IWebKitSourceBufferConstructor {
new (): IWebKitSourceBuffer;
prototype: IWebKitSourceBuffer;
}
interface IWebKitSourceBuffer
extends EventEmitter<{
updatestart: Event;
update: Event;
updateend: Event;
error: Event | Error;
}> {
_emitUpdate?: (eventName: "error" | "update", val: unknown) => void;
appendBuffer?: (data: BufferSource) => void;
updating: boolean;
append(data: BufferSource): void;
remove(from: number, to: number): void;
}
// TODO This is the last ugly side-effect here.
// Either remove it or find the best way to implement that
export default function patchWebkitSourceBuffer(): void {
// old WebKit SourceBuffer implementation,
// where a synchronous append is used instead of appendBuffer
if (
!isNode &&
!isNullOrUndefined(
(
globalScope as typeof globalScope & {
WebKitSourceBuffer?: IWebKitSourceBufferConstructor;
}
).WebKitSourceBuffer,
) &&
(
globalScope as typeof globalScope & {
WebKitSourceBuffer: IWebKitSourceBufferConstructor;
}
).WebKitSourceBuffer.prototype.addEventListener === undefined
) {
const sourceBufferWebkitRef: IWebKitSourceBufferConstructor = (
globalScope as unknown as {
WebKitSourceBuffer: IWebKitSourceBufferConstructor;
}
).WebKitSourceBuffer;
const sourceBufferWebkitProto = sourceBufferWebkitRef.prototype;
for (const fnName in EventEmitter.prototype) {
if (Object.prototype.hasOwnProperty.call(EventEmitter.prototype, fnName)) {
(sourceBufferWebkitProto as unknown as Record<string, unknown>)[fnName] = (
EventEmitter.prototype as unknown as Record<string, unknown>
)[fnName];
}
}
(
sourceBufferWebkitProto as unknown as {
_listeners: Array<() => void>;
}
)._listeners = [];
sourceBufferWebkitProto._emitUpdate = function (
eventName: "error" | "update",
val: unknown,
) {
queueMicrotask(() => {
this.trigger(eventName, val as Event);
this.updating = false;
this.trigger("updateend", new Event("updateend"));
});
};
sourceBufferWebkitProto.appendBuffer = function (data: BufferSource) {
if (this.updating) {
throw new Error("updating");
}
this.trigger("updatestart", new Event("updatestart"));
this.updating = true;
try {
this.append(data);
} catch (error) {
this._emitUpdate?.("error", error);
return;
}
this._emitUpdate?.("update", new Event("update"));
};
}
}