Определенно стоит изучить шейдеры OpenGL ES2.0:
- Вы можете балансировать нагрузку между GPU и CPU (например, декодирование видео последующих кадров, в то время как GPU отображает текущий кадр).
- Видеокадры в любом случае должны поступать в графический процессор: использование
YCbCr
экономит вам 25% полосы пропускания шины, если ваше видео имеет дискретизированный сигнал 4: 2: 0.
- Вы получаете бесплатное повышение сигнала цветности 4: 2: 0 с помощью аппаратного интерполятора графического процессора. (Ваш шейдер должен быть настроен на использование одинаковых координат вершин для текстур
Y
и C{b,r}
, фактически растягивая текстуру цветности по одной и той же области.)
- На iOS5 загрузка текстур
YCbCr
в графический процессор выполняется быстро (без копирования или перебора данных) с помощью кэша текстур (см. Функции API CVOpenGLESTextureCache*
). Вы сэкономите 1-2 копии данных по сравнению с NEON.
Я использую эти методы для достижения максимального эффекта в своем сверхбыстром приложении для iPhone на iPhone, SnappyCam .
Вы на правильном пути для реализации: используйте текстуру GL_LUMINANCE
для Y
и GL_LUMINANCE_ALPHA
, если ваш CbCr
чередуется. В противном случае используйте три GL_LUMINANCE
текстуры, если все ваши YCbCr
компоненты не чередуются.
Создание двух текстур для бипланарного 4: 2: 0 YCbCr
(где CbCr
чередуется) просто:
glBindTexture(GL_TEXTURE_2D, texture_y);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_LUMINANCE, // Texture format (8bit)
width,
height,
0, // No border
GL_LUMINANCE, // Source format (8bit)
GL_UNSIGNED_BYTE, // Source data format
NULL
);
glBindTexture(GL_TEXTURE_2D, texture_cbcr);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_LUMINANCE_ALPHA, // Texture format (16-bit)
width / 2,
height / 2,
0, // No border
GL_LUMINANCE_ALPHA, // Source format (16-bits)
GL_UNSIGNED_BYTE, // Source data format
NULL
);
где вы бы затем использовали glTexSubImage2D()
или кеш текстуры iOS5 для обновления этих текстур.
Я бы также рекомендовал использовать 2D varying
, который охватывает пространство координат текстуры (x: [0,1], y: [0,1])
, чтобы избежать любых зависимых чтений текстуры в вашем фрагментном шейдере. Конечный результат очень быстрый и, по моему опыту, не загружает GPU.