2012-02-17 19 views
14

Poszukuję najszybszego sposobu dekodowania lokalnych klatek wideo mpeg-4 na telefonie iPhone. Interesuje mnie po prostu wartość luminancji pikseli w każdej dziesiątej klatce. Nie muszę renderować wideo w dowolnym miejscu.Dekodowanie klatek wideo na iPhonie GPU

Próbowałem już ffmpeg, AVAssetReader, ImageAssetGenerator, OpenCV i MPMoviePlayer, ale wszystkie są zbyt wolne. Najszybszą możliwą szybkością jest ~ 2x (2 minuty wideo zeskanowane w ciągu minuty). Chciałbym coś bliżej 10x.

Zakładając moje próby powyżej nie wykorzystują GPU, czy jest jakiś sposób, aby osiągnąć swój cel z czymś, co działa na GPU? Wygląda na to, że OpenGL służy głównie do renderowania danych wyjściowych, ale widziałem, że był używany jako filtr dla przychodzących wideo. Może to opcja?

Z góry dziękuję!

Odpowiedz

3

Jeśli są chętni do korzystania z iOS 5 tylko rozwiązanie, warto zapoznać się z próbki app Chromakey od 2011 WWDC sesji AVCaputureSession.

To demo przechwytuje 30 klatek na sekundę wideo z wbudowanej kamery i przekazuje każdą klatkę do OpenGL jako teksturę. Następnie wykorzystuje OpenGL do manipulowania ramką i opcjonalnie zapisuje wynik do wyjściowego pliku wideo.

Kod wykorzystuje jakąś poważną magię niskopoziomowe związać bufor Rdzeń video Pixel z AVCaptureSession do OpenGL więc dzielą pamięci w kartach graficznych.

Powinna być dość prosta zmiana ustawienia AVCaptureSession, aby używał pliku wideo jako wejścia, a nie wejścia kamery.

Można prawdopodobnie skonfigurować sesję aby dostarczać w postaci ramek/UV Y zamiast RGB, gdzie składowa Y oznacza luminancji. W przeciwnym razie byłoby całkiem proste napisanie modułu cieniującego, który konwertowałby wartości RGB dla każdego piksela na wartości luminancji.

Powinieneś być w stanie zrobić to wszystko na WSZYSTKICH Ramkach, a nie tylko na 10 klatce.

+0

Bummer wygląda na to, że potrzebuję być uczestnikiem WWDC 2011, aby otrzymać tę próbkę. Nadal martwię się, że to jest transkodowanie w czasie rzeczywistym. Chcę uzyskać 15-krotne prędkości (15 minut wideo zeskanowanego w ciągu 1 minuty). Myślę, że szyjka butelki znajduje się w dekodowaniu ramki. –

+0

@imon.d - opisuję technikę zastosowaną w przykładzie ChromaKey w mojej odpowiedzi tutaj: http://stackoverflow.com/a/9704392/19679, i możesz pobrać mój kod GPUImage, aby zobaczyć to w akcji do kodowania filmów. Jednak nie zaktualizowałem jeszcze kodu do czytania filmu, aby korzystać z szybkich transferów tekstur. Z uwagi na to, że urządzenia z iOS mają dedykowany sprzęt do dekodowania H.264, wydaje mi się dość pewne, że nie otrzymasz szybszego analizowania filmów niż użycie AVFoundation z szybkim przesyłaniem tekstur iOS 5.0. –

+0

Przykładowy kod Apple RosyWriter demonstruje również to łącze AVCaptureSession -> OpenGL. Zobacz [tutaj] (https://developer.apple.com/library/ios/samplecode/RosyWriter/Introduction/Intro.html). – bcattle

0

Pozornie vImage może być odpowiednie, zakładając, że można korzystać z iOS 5. Co 10. rama wydaje się być w granicach rozsądku za pomocą ramy jak vImage. Jednak każdy rodzaj rzeczywistego przetwarzania w czasie rzeczywistym prawie na pewno będzie wymagał OpenGL.

+0

Dzięki @LucasTizma. Przyjrzę się vImage. Jednak moim celem jest szybsze niż przetwarzanie w czasie rzeczywistym. Właśnie dlatego chciałem zrobić co 10 klatkę. Wyobraź sobie, że wideo jest już nagrane w telefonie, a teraz chcę spróbować skanować. Czy to wyklucza vImage? –

+0

vImage jest po prostu środkiem do szybkiego wykonywania operacji przetwarzania obrazu. Myślę, że będziesz w porządku. Pozornie, poza OpenGL, jest to najszybsze z możliwych rozwiązań. Inni, możesz mnie poprawić, jeśli się mylę. – LucasTizma

+0

, ale czy vImage jest przydatny dopiero po odkodowaniu ramki? Jeśli tak, nie jestem pewien, czy tego potrzebuję. 90% pracy to dekodowanie ramki, a nie przetwarzanie pikseli. –

0

Zakładając, że wąskie gardło twojej aplikacji jest w kodzie, który konwertuje klatki wideo do formatu możliwego do wyświetlenia (np. RGB), mógłbyś być zainteresowany udostępnionym przeze mnie kodem, który był używany do convert one .mp4 frame (encoded as YV12) to RGB using Qt and OpenGL. Ta aplikacja przesyła ramkę do GPU i aktywuje GLSL fragment shader, aby wykonać konwersję z YV12 na RGB, aby mogła być wyświetlana w postaci 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);" 
    "}"