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

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

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

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

Заранее спасибо!


person simon.d    schedule 17.02.2012    source источник


Ответы (3)


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

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

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

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

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

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

person Duncan C    schedule 26.02.2012
comment
облом, похоже, мне нужно быть участником WWDC 2011, чтобы получить этот образец. Я все еще беспокоюсь, что по сути это транскодирование в реальном времени. Я хочу получить 15-кратную скорость (15 минут видео сканируется за 1 минуту). Я думаю, что узкое место в декодировании кадров. - person simon.d; 02.03.2012
comment
@simon.d - я описываю технику, использованную в примере ChromaKey, в моем ответе здесь: stackoverflow.com/a/9704392/19679 , и вы можете взять мой код GPUImage, чтобы увидеть это в действии для кодирования фильмов. Однако я еще не обновил свой код чтения фильмов, чтобы использовать быструю загрузку текстур. Из-за того, что устройства iOS имеют специальное оборудование для декодирования H.264, я с достаточной уверенностью могу сказать, что вы не получите более быстрого синтаксического анализа фильмов, чем с помощью AVFoundation с быстрой загрузкой текстур iOS 5.0. - person Brad Larson; 23.03.2012
comment
Пример кода RosyWriter от Apple также демонстрирует эту ссылку AVCaptureSession -> OpenGL. См. здесь. - person bcattle; 27.05.2014

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

person CIFilter    schedule 20.02.2012
comment
Спасибо @LucasTizma. Я посмотрю на vImage. Тем не менее, моя цель состоит в том, чтобы иметь более быструю обработку, чем в реальном времени. Вот почему я хотел делать только каждый 10-й кадр. Итак, представьте, что видео уже записано на телефон, и теперь я хочу попробовать отсканировать. Это исключает vImage? - person simon.d; 21.02.2012
comment
vImage — это просто средство для быстрого выполнения операций обработки изображений. Я думаю, ты будешь в порядке. По-видимому, кроме OpenGL, это ваше самое быстрое решение. Остальные, не стесняйтесь, поправьте меня, если я ошибаюсь. - person CIFilter; 22.02.2012
comment
но полезен ли vImage только после того, как я декодировал кадр? Если да, то я не уверен, что мне это нужно. 90% работы — это фактически декодирование кадра, а не обработка пикселей. - person simon.d; 23.02.2012

Предполагая, что узкое место вашего приложения находится в коде, который преобразует видеокадры в отображаемый формат (например, RGB), вас может заинтересовать код, которым я поделился, который использовался для преобразование одного кадра .mp4 (закодированного как YV12) в RGB с помощью Qt и OpenGL. Это приложение загружает кадр в GPU и активирует фрагментный шейдер 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);"
    "}"
person karlphillip    schedule 26.02.2012