mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-25 16:11:20 -08:00
refactor(canvas): [PKG-CANVAS-03] own media and frame lifecycle in strict TypeScript
This commit is contained in:
1 parent
e931520e66
commit
2b319109cd
29 files changed
+2015
-362
No files matched your search
@@ -0,0 +1,55 @@
|
||||
import { hasDimensions } from './geometry'
|
||||
|
||||
export type DrawCallback = (context: CanvasRenderingContext2D, video: HTMLVideoElement) => void
|
||||
|
||||
export function createRenderer(canvas: HTMLCanvasElement, video: HTMLVideoElement, callback: DrawCallback | undefined, notify: DrawCallback, error: (failure: unknown) => void) {
|
||||
const context = canvas.getContext('2d')
|
||||
let reported = false
|
||||
return {
|
||||
available() {
|
||||
if (context)
|
||||
return true
|
||||
if (!reported) {
|
||||
reported = true
|
||||
error(new Error('Canvas 2D context is unavailable'))
|
||||
}
|
||||
return false
|
||||
},
|
||||
async draw(valid: () => boolean): Promise<void> {
|
||||
const usable = () => valid() && video.readyState >= 2 && !video.seeking
|
||||
if (!context || !usable() || !hasDimensions(video) || !canvas.width || !canvas.height)
|
||||
return
|
||||
let acquiring = false
|
||||
try {
|
||||
if (typeof createImageBitmap !== 'undefined') {
|
||||
acquiring = true
|
||||
const bitmap = await createImageBitmap(video)
|
||||
acquiring = false
|
||||
try {
|
||||
if (usable())
|
||||
context.drawImage(bitmap, 0, 0, canvas.width, canvas.height)
|
||||
}
|
||||
finally { bitmap.close() }
|
||||
}
|
||||
else {
|
||||
context.drawImage(video, 0, 0, canvas.width, canvas.height)
|
||||
}
|
||||
if (!usable())
|
||||
return
|
||||
if (callback)
|
||||
callback(context, video)
|
||||
if (usable())
|
||||
notify(context, video)
|
||||
}
|
||||
catch (failure) {
|
||||
// Chromium can expose readyState 4 before its first frame is usable.
|
||||
// Other engines report zero frame counts even while drawing successfully.
|
||||
const awaitingFirstFrame = acquiring && typeof failure === 'object' && failure !== null && 'name' in failure
|
||||
&& failure.name === 'InvalidStateError' && video.currentTime === 0
|
||||
&& typeof video.getVideoPlaybackQuality === 'function' && video.getVideoPlaybackQuality().totalVideoFrames === 0
|
||||
if (usable() && !awaitingFirstFrame)
|
||||
error(failure)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user