CanvasRenderingContext2D # drawImage () является асинхронным методом в Chrome70 - PullRequest
0 голосов
/ 07 ноября 2018

Я хочу сделать видео на холсте с частотой 25 кадров в секунду и более. Поэтому я использую 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 голосов
/ 08 ноября 2018

Вы можете проверить это, подразумевая вызов 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...