Ограничения размера видео текстуры WebGL на Android - как использовать 3840 * 2160? - PullRequest
0 голосов
/ 03 мая 2018

Я занимаюсь разработкой приложения WebGL, которое получает поток текстур из видео HTML5 с использованием HLS.js. Он отлично работает на настольных ПК и работает с видео 1920 * 1080 на мобильном Android, но не для 3840 * 2160.

Я протестировал приложение на нескольких высокопроизводительных устройствах (Xperia X Performance, Samsung Galaxy S8), оба из которых не работают для видео 4K.

Я знаю, что видео можно воспроизводить на этих устройствах, потому что у меня также есть режим отладки, когда элемент видео подключен к DOM, и видео воспроизводится идеально.

Я также использовал http://webglreport.com/ на этих устройствах, и на этой странице показано, что я смогу использовать 4096 * 4096 текстур.

Я также вручную сгенерировал 3840 * 2160, используя Javascript ArrayBuffer, и эта текстура была правильно обработана.

Вот как я копирую видео

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, this.videoElement);

При выполнении этого звонка для видео размером 3840 * 2160 на Chrome Android я получаю следующую распечатку журнала

SurfaceUtils: настроить nativeWindow 0xc9ef2008 для 3840x2160, цвет 0x7fa30c04, вращение 0, использование 0x20002900

хром: [INFO: КОНСОЛЬ (11818)] "WebGL: INVALID_VALUE: texImage2D: ширина или высота вне диапазона "

Который соответствует этому коду ошибки из gl.getError():

GL_INVALID_VALUE, 0x0501

Это параметры, которые я использую для текстуры основы

const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

А вот как я генерирую и загружаю тестовую текстуру

const width = 3840;
const height = 2160;

const generateTex = (w: number, h: number): number[] => {
    const res = [];
    for (let i = 0; i < w * h; i++) {
        res.push(0, 255, 0);
    }
    return res;
};

const image = new Uint8Array(generateTex(width, height));
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, width, height, 0, gl.RGB, gl.UNSIGNED_BYTE, image);

Документация для texImage2D говорит

источник типа HTMLVideoElement

Ширина и высота текстуры установлены в ширину и высоту загруженного кадра видео в пиксели.

Вопрос: есть ли где-нибудь спецификация, которая может объяснить, почему моя текстура 3840 * 2160 не отображается?

TL; DR

  • Высокопроизводительные устройства (Xperia X Performance, Galaxy S8)
  • Android Chrome
  • Я могу загрузить пользовательскую текстуру размером 3840 * 2160 и отобразить ее
  • Я могу декодировать и воспроизводить видео размером 3840 * 2160, используя тег <video>
  • Я НЕ могу загрузить кадры из видео 3840 * 2160 в WebGL
  • С меньшим разрешением работает просто отлично

Спасибо!

1 Ответ

0 голосов
/ 12 мая 2018

После недели усилий, чтобы понять проблему, теперь ясно, что ошибка была на нашем конце.

Видео действительно было создано как 3840 x 2160, но оно было создано из исходного видео с разрешением 3840 x 4320. При преобразовании видео в 3840 x 2160 ffmpeg устанавливал соотношение сторон (3840/4320), ведущий Android, чтобы надуть видео обратно в этот размер. Накачанный размер имеет высоту> 4096, и по этой причине текстура не может быть создана.

Мы не видели эту проблему на других платформах (нативных приложениях), так что это может быть какой-то изюминкой мультимедийного проигрывателя Android.

Мы исправили проблему с нашей стороны, установив «правильное» соотношение сторон (3840/2160) вручную в качестве параметра ffmpeg.

Что я выучил:

Не думайте, что разрешение, сообщаемое такими приложениями, как VLC или QuickTime, будет правильно отражать то, что происходит на любой другой платформе. После реализации кода, необходимого для проверки разрешения HTML-видеоэлемента, стало очевидно, что на Android происходит нечто иное, чем на других платформах.

...