Текстура поверхности

SurfaceTexture — это комбинация поверхности и текстуры OpenGL ES (GLES) . SurfaceTexture используются для предоставления поверхностей, которые выводятся в текстуры GLES.

SurfaceTexture содержит экземпляр BufferQueue для которого приложения являются потребителем. Обратный вызов onFrameAvailable() уведомляет приложения, когда производитель ставит в очередь новый буфер. Затем приложения вызывают updateTexImage() , который освобождает ранее удерживаемый буфер, получает новый буфер из очереди и выполняет вызовы EGL , чтобы сделать буфер доступным для GLES в качестве внешней текстуры.

Внешние текстуры GLES

Внешние текстуры GLES ( GL_TEXTURE_EXTERNAL_OES ) отличаются от традиционных текстур GLES ( GL_TEXTURE_2D ) следующим образом:

  • Внешние текстуры отображают текстурированные полигоны непосредственно из данных, полученных от BufferQueue .
  • Внешние средства визуализации текстур настроены иначе, чем традиционные средства визуализации текстур GLES.
  • Внешние текстуры не могут выполнять все традиционные операции с текстурами GLES.

Основным преимуществом внешних текстур является их возможность рендеринга непосредственно из данных BufferQueue . SurfaceTexture устанавливают флаги использования потребителя на GRALLOC_USAGE_HW_TEXTURE при создании экземпляров BufferQueue для внешних текстур, чтобы гарантировать, что данные в буфере распознаются GLES.

Поскольку экземпляры SurfaceTexture взаимодействуют с контекстом EGL, приложение может вызывать свои методы только тогда, когда контекст EGL, которому принадлежит текстура, является текущим в вызывающем потоке. Дополнительные сведения см. в документации по классу SurfaceTexture .

Временные метки и преобразования

SurfaceTexture включают метод getTimeStamp() , который извлекает метку времени, и getTransformMatrix() , который извлекает матрицу преобразования. Вызов updateTexImage() устанавливает как метку времени, так и матрицу преобразования. Каждый буфер, который передает BufferQueue , включает параметры преобразования и метку времени.

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

Временная метка полезна для источников буфера, зависящих от времени. Например, когда setPreviewTexture() подключает интерфейс производителя к выходу камеры, кадры с камеры можно использовать для создания видео. Каждый кадр должен иметь временную метку представления с момента захвата кадра, а не с момента получения кадра приложением. Код камеры устанавливает временную метку, предоставляемую буфером, что приводит к более последовательной серии временных меток.

Практический пример: непрерывный захват Grafika

Непрерывный захват Grafika включает в себя запись кадров с камеры устройства и отображение этих кадров на экране. Для записи кадров создайте поверхность с помощью метода createInputSurface() класса MediaCodec и передайте поверхность камере. Чтобы отображать кадры, создайте экземпляр SurfaceView и передайте поверхность в setPreviewDisplay() . Обратите внимание, что запись кадров и их одновременное отображение — более сложный процесс.

Непрерывный захват отображает видео с камеры во время записи видео. В этом случае закодированное видео записывается в кольцевой буфер в памяти, который в любой момент можно сохранить на диск.

Этот поток включает в себя три буферные очереди:

  • App — приложение использует экземпляр SurfaceTexture для получения кадров с камеры и преобразования их во внешнюю текстуру GLES.
  • SurfaceFlinger — приложение объявляет экземпляр SurfaceView для отображения кадров.
  • MediaServer — Настройте кодировщик MediaCodec с поверхностью ввода для создания видео.

На рисунке ниже стрелками показано распространение данных с камеры. BufferQueue в цвет (производители — бирюзовые, потребители — зеленые).

Графика непрерывного захвата активности

Рисунок 1. Непрерывная активность захвата Grafika

Закодированное видео H.264 отправляется в кольцевой буфер в ОЗУ в процессе приложения. Когда пользователь нажимает кнопку захвата, класс MediaMuxer записывает закодированное видео в файл MP4 на диске.

Все экземпляры BufferQueue обрабатываются в одном контексте EGL в приложении, в то время как операции GLES выполняются в потоке пользовательского интерфейса. Обработка закодированных данных (управление кольцевым буфером и запись его на диск) выполняется в отдельном потоке.

При использовании класса SurfaceView обратный вызов surfaceCreated() создает EGLContext и EGLSurface для дисплея и видеокодера. Когда поступает новый кадр, SurfaceTexture выполняет четыре действия:
  1. Приобретает рамку.
  2. Делает кадр доступным в виде текстуры GLES.
  3. Визуализирует кадр с помощью команд GLES.
  4. Направляет преобразование и отметку времени для каждого экземпляра EGLSurface .

Затем поток кодировщика извлекает закодированный вывод из MediaCodec и сохраняет его в памяти.

Безопасное воспроизведение видео текстур

Android поддерживает постобработку защищенного видеоконтента с помощью графического процессора. Это позволяет приложениям использовать GPU для создания сложных нелинейных видеоэффектов (таких как деформации), наложения защищенного видеоконтента на текстуры для использования в обычных графических сценах (например, с использованием GLES) и виртуальной реальности (VR).

Безопасное воспроизведение видео текстур

Рис. 2. Безопасное воспроизведение текстурного видео

Поддержка включена с помощью следующих двух расширений:

  • Расширение EGL — ( EGL_EXT_protected_content ) Позволяет создавать защищенные контексты и поверхности GL, которые могут работать с защищенным содержимым.
  • Расширение GLES — ( GL_EXT_protected_textures ) позволяет помечать текстуры как защищенные, чтобы их можно было использовать в качестве прикрепленных текстур буфера кадра.

Android позволяет SurfaceTexture и ACodec ( libstagefright.so ) отправлять защищенное содержимое, даже если поверхность окна не ставится в очередь на SurfaceFlinger , и предоставляет защищенную поверхность видео для использования в защищенном контексте. Это делается путем установки бита защищенного потребителя ( GRALLOC_USAGE_PROTECTED ) на поверхностях, созданных в защищенном контексте (проверено ACodec).

Безопасное воспроизведение видео с текстурами закладывает основу для надежной реализации DRM в среде OpenGL ES. Без надежной реализации DRM, такой как Widevine Level 1, многие поставщики контента не разрешают рендеринг своего ценного контента в среде OpenGL ES, что предотвращает важные случаи использования виртуальной реальности, такие как просмотр контента, защищенного DRM, в виртуальной реальности.

AOSP включает фреймворк для безопасного воспроизведения видео с текстурами. Поддержка драйверов осуществляется OEM-производителями. Разработчики устройств должны реализовать расширения EGL_EXT_protected_content и GL_EXT_protected_textures extensions . При использовании собственной библиотеки кодеков (для замены libstagefright ) обратите внимание на изменения в /frameworks/av/media/libstagefright/SurfaceUtils.cpp , которые позволяют отправлять буферы, отмеченные GRALLOC_USAGE_PROTECTED , в ANativeWindow (даже если ANativeWindow не ставится в очередь непосредственно в оконный композитор) до тех пор, пока биты использования потребителя содержат GRALLOC_USAGE_PROTECTED . Для получения подробной документации по реализации расширений обратитесь к реестрам Khronos ( EGL_EXT_protected_content и GL_EXT_protected_textures ).