Я пытаюсь понять использование/поток графической памяти в Android и, в частности, в отношении кодирования кадров с камеры с использованием MediaCodec
. Чтобы сделать это, мне нужно понять кучу терминологии/концепций графики, OpenGL и Android, которые мне непонятны. Я прочитал материал по графической архитектуре Android, кучу вопросов SO и кучу источников, но я все еще сбит с толку, прежде всего потому, что кажется, что термины имеют разные значения в разных контекстах.
Я просмотрел CameraToMpegTest с сайта Фаддена здесь. Мой конкретный вопрос заключается в том, как MediaCodec::createInputSurface()
работает в сочетании с Camera::setPreviewTexture()
. Кажется, создается текстура OpenGL, а затем она используется для создания Android SurfaceTexture
, которую затем можно передать setPreviewTexture()
. Мои конкретные вопросы:
- Что на самом деле делает вызов
setPreviewTexture()
с точки зрения того, в какой буфер памяти попадают кадры с камеры? - Насколько я понимаю, текстура OpenGL — это кусок памяти, доступный графическому процессору. На Android это должно быть выделено с помощью galloc с правильными флагами использования. В описании
SurfaceTexture
для Android упоминается, что он позволяет «передавать изображения в заданную текстуру OpenGL»: https://developer.android.com/reference/android/graphics/SurfaceTexture.html#SurfaceTexture(int). Что делаетSurfaceTexture
поверх текстуры OpenGL? MediaCodec::createInputSurface()
возвращает AndroidSurface
. Насколько я понимаю, AndroidSurface
представляет сторону производителя буферной очереди, поэтому может быть несколько буферов. В справочнике по API упоминается, что "поверхность должна быть с аппаратным ускорением API, например OpenGL ES». Как кадры, снятые камерой, попадают изSurfaceTexture
в этотSurface
, который поступает на вход кодировщика? Я вижу, что CameraToMpegTest каким-то образом создаетEGLSurface
, используя этотSurface
, но, не зная много об EGL, я не понимаю эту часть.- Может ли кто-нибудь прояснить использование «рендеринга»? Я вижу такие вещи, как «рендеринг на поверхность», «рендеринг на экран» среди других вариантов использования, которые, кажется, могут означать разные вещи.
Изменить: продолжение ответов mstorsjo:
- Я еще немного покопался в коде для
SurfaceTexture
иCameraClient::setPreviewTarget()
вCameraService
, чтобы попытаться лучше понять внутреннюю работуCamera::setPreviewTexture()
и задать еще несколько вопросов. На мой первоначальный вопрос о понимании распределения памяти кажется, чтоSurfaceTexture
создаетBufferQueue
, аCameraService
передает связанныйIGraphicBufferProducer
реализации HAL платформы платформы. Затем HAL камеры может соответствующим образом установить флаги использования gralloc (например,GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_NEVER | GRALLOC_USAGE_HW_TEXTURE
), а также удалить буферы из очереди из этогоBufferQueue
. Таким образом, буферы, в которые камера захватывает кадры, являются буферами, выделенными gralloc, с некоторыми специальными флагами использования, такими какGRALLOC_USAGE_HW_TEXTURE
. Я работаю на платформах ARM с унифицированной архитектурой памяти, поэтому GPU и CPU могут обращаться к одной и той же памяти. Какое влияние окажет флагGRALLOC_USAGE_HW_TEXTURE
на распределение буфера? - Часть OpenGL (ES)
SurfaceTexture
, по-видимому, в основном реализована как частьGLConsumer
, а волшебство, похоже, кроется вupdateTexImage()
. Выделяются ли дополнительные буферы для текстуры OpenGL (ES) или можно использовать тот же буфер gralloc, который был заполнен камерой? Есть ли какое-то копирование памяти, которое должно произойти здесь, чтобы получить данные о пикселях камеры из буфера gralloc в текстуру OpenGL (ES)? Наверное, я не понимаю, что делает вызовupdateTexImage()
.