Как применить фрагментный шейдер к GLSurfaceView / TextureView?

Моя цель - сделать так, чтобы ExoPlayer отображал цветное видео как черно-белое.

Согласно этой этой проблеме Github, я должен добиться этого с помощью Open GL:

ExoPlayer будет рендерить видео на любую поверхность. Вы можете использовать SurfaceTexture, после чего видео будет отображаться в текстуру OpenGL ES. После этого вы можете делать все, что позволяет OpenGL, включая использование пиксельного шейдера для преобразования видео в черно-белое.

В более раннем, но связанном обсуждении в группе Google для разработчиков Android Ромен Гай подробно описывает, как это нужно делать:

  • Создать контекст OpenGL
  • Сгенерировать имя текстуры OpenGL
  • Создайте SurfaceTexture с именем текстуры
  • Передайте SurfaceTexture в камеру
  • Следите за обновлениями При обновлении SurfaceTexture нарисуйте текстуру с помощью OpenGL, используя нужный шейдер.

Простой :)

Поигравшись с примером проекта Google Cardboard, я определил, что фрагментный шейдер, подобный следующему, должен быть примерно правым:

precision mediump float;
varying vec4 v_Color;

void main() {
    float grayscale = v_Color[0] * 0.3 + v_Color[1] * 0.59 + v_Color[2] * 0.11;
    gl_FragColor = vec4(grayscale, grayscale, grayscale, 0.1);
}

Мне также удалось сделать рендеринг ExoPlayer в TextureView вместо обычного SurfaceView:

mPlayer.sendMessage(
    videoRenderer,
    MediaCodecVideoTrackRenderer.MSG_SET_SURFACE,
    new Surface(mVideoTextureView.getSurfaceTexture())
);

Как все соединить вместе?

Где я могу "применить" шейдер к TextureView? Это вообще возможно, или мне лучше использовать GLSurfaceView? Что мне нужно делать в Renderer?


person david.mihola    schedule 26.02.2016    source источник
comment
Вы видели это: github.com/google/ExoPlayer/issues/1220 и ссылка внутри него?   -  person Morrison Chang    schedule 26.02.2016
comment
Спасибо, связанное сообщение в блоге действительно предоставило рабочее решение! Большое спасибо!   -  person david.mihola    schedule 09.03.2016
comment
Привет, Дэвид, я тоже пытаюсь сделать то же самое, но я застрял на этом последние 2 дня. Я взглянул на код VidEffect VideoSurfaceView, но когда я интегрирую exoplayer, видео становится черным, но со звуком. Если у вас все еще есть рабочее решение, это будет много значить, если вы сможете им поделиться.   -  person Udit Mukherjee    schedule 15.02.2017


Ответы (1)


Раньше я применял фрагментные шейдеры к видео, воспроизводимому ExoPlayer. Кажется, что наиболее эффективным способом является воспроизведение видео на GLSurfaceView, поскольку они хорошо поддерживают настраиваемые средства визуализации.

Рабочий пример применения шейдеров OpenGL к GLSurfaceView доступен здесь. У него даже есть шейдер фрагмента шкалы серого как часть его библиотека эффектов. Существующий код потребует небольшого рефакторинга, поскольку он использует MediaPlayer, а не ExoPlayer.

person Michael    schedule 05.03.2016
comment
Спасибо! Я построил свое решение на основе сообщения в блоге, к которому меня привел комментарий @Morrison Chang - он использует TextureView и передает Surface ExoPlayer. Но, возможно, мне все равно придется переключиться на GLSurfaceView, потому что мне также нужно будет поддерживать VisualOn, а этот проигрыватель принимает только SurfaceView (а не Surface напрямую). - person david.mihola; 09.03.2016