Пиксельные форматы, CVPixelBufferRefs и glReadPixels

я использую glReadPixels для чтения данных в CVPixelBufferRef. Я использую CVPixelBufferRef в качестве параметра AVAssetWriter. К сожалению, форматы пикселей, похоже, не совпадают.

Я думаю glReadPixels возвращает пиксельные данные в RGBA и пока AVAssetWriter хочет пиксельные данные в формате ARGB. Каков наилучший способ преобразования RGBA и to формате ARGB?

вот что я пробовал до сих пор:

  • немного манипуляций по линиям argb = (rgba >> 8) | (rgba
  • С помощью CGImageRef в качестве промежуточного шага

битовая манипуляция не сработала, потому что CVPixelBufferRef, похоже, не поддерживает индексы. The CGImageRef промежуточный шаг работает... но я бы предпочел не иметь 50 дополнительных строк кода, которые потенциально могли бы быть удар по производительности.

5 ответов


лучше, чем использовать CPU для замены компонентов, было бы написать простой шейдер фрагментов, чтобы эффективно сделать это на GPU при рендеринге изображения.

и лучший лучший способ-полностью удалить этап копирования с помощью iOS5 CoreVideo CVOpenGLESTextureCache, который позволяет визуализировать прямо в CVPixelBufferRef, устраняя вызов glReadPixels.

p.s. Я уверен, что AVAssetWriter хочет получить данные в формате BGRA (на самом деле он, вероятно, хочет это в ЮВ, но это уже другая история).

UPDATE: что касается ссылок, doco, похоже, все еще находится под NDA, но есть две части свободно загружаемого кода примера:

GLCameraRipple и RosyWriter

сами заголовочные файлы содержат хорошую документацию, а эквивалент mac очень похож (CVOpenGLTextureCache), поэтому у вас должно быть много, чтобы начать работу.


Что касается битовой манипуляции, вы можете получить указатель на необработанные данные пиксельного буфера:

CVPixelBufferLockBaseAddress(buffer, 0);
size_t stride = CVPixelBufferGetBytesPerRow(buffer);
char *data = (char *)CVPixelBufferGetBaseAddress(buffer);
for (size_t y = 0; y < CVPixelBufferGetHeight(buffer); ++y) {
    uint32_t *pixels = (uint32_t *)(data + stride * y);
    for (size_t x = 0; x < CVPixelBufferGetWidth(buffer); ++x)
        pixels[x] = (pixels[x] >> 8) | (pixels[x] << 24);
}
CVPixelBufferUnlockBaseAddress(buffer, 0);

это своего рода выстрел в темноте, но вы не пробовали GL_BGRA на glReadPixels С kCVPixelFormatType_32BGRA на CVPixelBufferCreate?

Я предлагаю это, потому что технические вопросы QA1501 не перечисляет поддерживаемый формат RGBA.


glReadPixels (0, 0, w*s, h*s, GL_BGRA, GL_UNSIGNED_BYTE, buffer);

используйте GL_BGRA в glReadPixels. Это работает, просто попробовал сам.


    glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, _buffer);
    CVPixelBufferRef buffer = NULL;
    CVReturn ret = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,_size.width,_size.height,kCVPixelFormatType_32BGRA,glubyte,_size.width*4,NULL,NULL,NULL,&buffer);