Декодирование видеокадров на iPhone GPU

Я ищу самый быстрый способ декодирования локальных видеокадров mpeg-4 на iPhone. Меня просто интересуют значения яркости пикселей в каждом 10-м кадре. Мне не нужно показывать видео в любом месте.

Я пробовал ffmpeg, AVAssetReader, ImageAssetGenerator, OpenCV и MPMoviePlayer, но они слишком медленны. Самая быстрая скорость, которую я могу получить, составляет ~ 2x (2 минуты видео сканируется через минуту). Мне хотелось бы приблизиться к 10 раз.

Предполагая, что мои попытки выше не используют GPU, есть ли способ достичь моей цели с помощью чего-то, что работает на GPU? OpenGL кажется главным образом для вывода вывода, но я видел, что он используется в качестве фильтров для входящего видео. Может быть, это вариант?

Спасибо заранее!

Ответы

Ответ 1

Если вы хотите использовать только решение iOS 5, посмотрите пример приложения ChromaKey из сеанса WWDC 2011 года на AVCaputureSession.

Эта демонстрация захватывает 30 FPS видео со встроенной камеры и передает каждый кадр OpenGL в виде текстуры. Затем он использует OpenGL для управления фреймом и, возможно, записывает результат в выходной видеофайл.

В коде используется некоторая серьезная магия низкого уровня для привязки буфера базового видео пикселя от AVCaptureSession к OpenGL, поэтому они совместно используют память в графическом оборудовании.

Для AVCaptureSession довольно просто изменить использование видеофайла в качестве входных данных, а не ввода камеры.

Возможно, вы можете настроить сеанс для доставки кадров в форме Y/UV, а не в RGB, где компонент Y - яркость. В противном случае было бы довольно просто написать шейдер, который преобразует значения RGB для каждого пикселя в значения яркости.

Вы должны иметь возможность делать все это на ВСЕХ кадрах, а не только на каждом 10-м кадре.

Ответ 2

Похоже, что vImage может быть уместным, если вы можете использовать iOS 5. Каждой 10-й кадр, по-видимому, в разумных пределах используется инфраструктура, например, vImage. Однако любой тип фактической обработки в реальном времени почти наверняка потребует OpenGL.

Ответ 3

Предполагая, что узкое место вашего приложения находится в коде, который преобразует видеокадры в отображаемый формат (например, RGB), вам может быть интересен код, который я использовал, который использовался для конвертируйте один кадр .mp4 (закодированный как YV12) в RGB с помощью Qt и OpenGL. Это приложение загружает фрейм на графический процессор и активирует шейдер GLSL-фрагмента для преобразования с YV12 в RGB, поэтому его можно отобразить в QImage.

static const char *p_s_fragment_shader =
    "#extension GL_ARB_texture_rectangle : enable\n"
    "uniform sampler2DRect tex;"
    "uniform float ImgHeight, chromaHeight_Half, chromaWidth;"
    "void main()"
    "{"
    "    vec2 t = gl_TexCoord[0].xy;" // get texcoord from fixed-function pipeline
    "    float CbY = ImgHeight + floor(t.y / 4.0);"
    "    float CrY = ImgHeight + chromaHeight_Half + floor(t.y / 4.0);"
    "    float CbCrX = floor(t.x / 2.0) + chromaWidth * floor(mod(t.y, 2.0));"
    "    float Cb = texture2DRect(tex, vec2(CbCrX, CbY)).x - .5;"
    "    float Cr = texture2DRect(tex, vec2(CbCrX, CrY)).x - .5;"
    "    float y = texture2DRect(tex, t).x;" // redundant texture read optimized away by texture cache
    "    float r = y + 1.28033 * Cr;"
    "    float g = y - .21482 * Cb - .38059 * Cr;"
    "    float b = y + 2.12798 * Cb;"
    "    gl_FragColor = vec4(r, g, b, 1.0);"
    "}"