在Chrome70中CanvasRenderingContext2D#drawImage()是异步方法吗

时间:2018-11-07 10:50:14

标签: javascript google-chrome html5-canvas

我想在25fps或更高的画布上渲染视频。因此,我使用CanvasRenderingContext2D#drawImage()渲染画布中的每一帧。它适用于chrome69和FireFox。但是它不适用于chrome70。

下面是代码片段:

if (frame >= this.inFrame && frame <= this.outFrame) {
    // this.ctx.drawImage(this.video,
    //    this.sourceRect.x, this.sourceRect.y, this.sourceRect.width, this.sourceRect.height,
    //    this.rect.x, this.rect.y, this.rect.width, this.rect.height);

    this.frame.init(this.canvas);   // line 6, breakpoint here.
    this.frame.isPlaying = this.isPlaying;
    let image = this.frame;

    for (let i = 0; i<this.filters.length;i++) {
        image = this.filters[i].getImageWithFilter(frame, image);
    }

    return image;
}

我在第6行放置了一个断点。这时,视频已加载。

this.video.readyState=4

然后我在开发工具中执行此命令。

document.getElementById("test_canvas").getContext('2d').drawImage(this.video, 0, 0);

有时,测试画布显示正确的视频帧,有时不显示,只是没有显示。 让我们继续运行程序,画布最终将显示正确的视频帧。

因此,我怀疑CanvasRenderingContext2D#drawImage()是Chrome70中的异步方法。但是我在Chrome网站上找不到任何内容。

有人可以帮助我解决这个问题,还是可以帮助我在每个帧中正确渲染。

1 个答案:

答案 0 :(得分:0)

您可以通过隐式调用getImageData()或什至在fillRect()之后仅调用drawImage()进行检查。 如果返回的ImageData为空,或者在视频帧上未绘制任何矩形,那么是的,它可能是异步的,这是一个可怕的错误,应立即报告。

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var vid = document.createElement('video');
vid.muted = true;
vid.crossOrigin = 'anonymous';
vid.src = 'https://upload.wikimedia.org/wikipedia/commons/transcoded/a/a4/BBH_gravitational_lensing_of_gw150914.webm/BBH_gravitational_lensing_of_gw150914.webm.480p.webm'
vid.play().then(() => {
  ctx.drawImage(vid, 0, 0);
  console.log(
    "imageData empty",
    ctx.getImageData(0, 0, canvas.width, canvas.height).data.some(d => !!d) === false
  );
  ctx.fillStyle = 'green';
  ctx.fillRect(0, 0, 50, 50);
});
document.body.append(canvas);

因此,为了更好地解释您所看到的内容,调试器将停止整个事件循环,并且Chrome可能已决定在调用调试器时不遵循下一个CSS框架图形。因此,在屏幕上绘制的仍然是调用脚本时(没有绘制图像时)的帧。

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var vid = document.createElement('video');
vid.muted = true;
vid.crossOrigin = 'anonymous';
vid.src = 'https://upload.wikimedia.org/wikipedia/commons/transcoded/a/a4/BBH_gravitational_lensing_of_gw150914.webm/BBH_gravitational_lensing_of_gw150914.webm.480p.webm'
vid.play().then(() => {
  ctx.drawImage(vid, 0, 0);
  const hasPixels = ctx.getImageData(0, 0, canvas.width, canvas.height).data.some(d => !!d);
  alert('That should also block the Event loop and css painting. But drawImage already happened: ' + hasPixels)
});
document.body.append(canvas);
canvas{
  border:1px solid;
}