YUV to RGBA на Apple A4, я должен использовать шейдеры или NEON? - PullRequest
10 голосов
/ 10 декабря 2011

Я пишу фреймворк для медиаплеера для Apple TV, используя OpenGL ES и ffmpeg. Преобразование в RGBA требуется для рендеринга в OpenGL ES, мягкое преобразование с использованием swscale невыносимо медленно, поэтому, используя информацию в Интернете, я пришел к двум идеям: использовать неон (например, здесь ) или использовать фрагментные шейдеры и GL_LUMINANCE. и GL_LUMINANCE_ALPHA.

Поскольку я почти ничего не знаю об OpenGL, второй вариант все еще не работает:)

Можете ли вы дать мне какие-либо указания, как действовать? Заранее спасибо.

Ответы [ 2 ]

20 голосов
/ 28 декабря 2011

Определенно стоит изучить шейдеры OpenGL ES2.0:

  1. Вы можете балансировать нагрузку между GPU и CPU (например, декодирование видео последующих кадров, в то время как GPU отображает текущий кадр).
  2. Видеокадры в любом случае должны поступать в графический процессор: использование YCbCr экономит вам 25% полосы пропускания шины, если ваше видео имеет дискретизированный сигнал 4: 2: 0.
  3. Вы получаете бесплатное повышение сигнала цветности 4: 2: 0 с помощью аппаратного интерполятора графического процессора. (Ваш шейдер должен быть настроен на использование одинаковых координат вершин для текстур Y и C{b,r}, фактически растягивая текстуру цветности по одной и той же области.)
  4. На 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.

0 голосов
/ 03 октября 2012

Преобразование YUV в RGB с использованием NEON очень медленное.Используйте шейдер для разгрузки на графический процессор.

...