Декодирование видеокадров на 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);"
"}"