Как передать предварительный просмотр камеры на поверхность, созданный MediaCodec.createInputSurface ()?

В идеале я бы хотел достичь двух целей:

  1. Передайте данные предварительного просмотра Camera в кодер MediaCodec через Surface . Я могу создать Surface с помощью MediaCodec.createInputSurface() но Camera.setPreviewDisplay() принимает SurfaceHolder , а не Surface .
  2. Помимо передачи данных предварительного просмотра Camera в кодировщик, я также хотел бы отобразить предварительный просмотр на экране (чтобы пользователь мог действительно видеть, что они кодируют). Если кодер не был задействован, я бы использовал SurfaceView , но он не работает в этом сценарии, поскольку SurfaceView создает свою собственную Surface и я думаю, что мне нужно использовать созданную MediaCodec .

Я искал в Интернете довольно много для решения и не нашел его. Некоторые примеры на bigflake.com кажутся шагом в правильном направлении, но они используют подход, который добавляет кучу накладных расходов EGL / SurfaceTexture, которые я бы хотел избежать. Я надеюсь, что есть более простой пример или решение, в котором я могу напрямую MediaCodec к Camera and MediaCodec без участия EGL или текстур.

Solutions Collecting From Web of "Как передать предварительный просмотр камеры на поверхность, созданный MediaCodec.createInputSurface ()?"

Начиная с Android 4.3 (API 18), подход Bigflake CameraToMpegTest является правильным способом.

Накладные расходы EGL / SurfaceTexture в настоящее время неизбежны, особенно для того, что вы хотите сделать в цели №2. Идея такова:

  • Настройте камеру для отправки вывода в SurfaceTexture . Это делает выход камеры доступным для GLES в качестве «внешней текстуры».
  • Render SurfaceTexture к Surface возвращаемой MediaCodec#createInputSurface() . Это подает видеокодер.
  • SurfaceTexture визуализацию SurfaceTexture во второй раз, используя GLSurfaceView . Это выводит его на экран для предварительного просмотра в режиме реального времени.

Единственное копирование данных, которое происходит, выполняется драйвером GLES, поэтому вы выполняете аппаратные ускорения, которые будут быстрыми.

Единственный сложный бит – вы хотите, чтобы внешняя текстура была доступна для двух разных контекстов EGL (один для MediaCodec , один для GLSurfaceView ). Вы можете увидеть пример создания общего контекста в примере патча «Android Breakout game recorder patch» на Bigflake – он отображает игру дважды, один раз на экран, один раз для кодировщика MediaCodec .

Обновление: это реализовано в Grafika («Show + capture camera»).

Обновление: многоконтекстный подход в подходе «show + capture camera» несколько испорчен . Активность «непрерывного захвата» использует простой SurfaceView и способна выполнять как рендеринг экрана, так и видеозапись с одним контекстом EGL. Это рекомендуется.