2012-02-17 3 views
14

iPhone에서 로컬 mpeg-4 비디오 프레임을 디코딩하는 가장 빠른 방법을 찾고 있습니다. 저는 매 10 번째 프레임마다 픽셀의 휘도 값에 관심이 있습니다. 비디오를 아무 곳에 나 렌더링 할 필요가 없습니다.iPhone에서 비디오 프레임 디코딩 GPU

저는 ffmpeg, AVAssetReader, ImageAssetGenerator, OpenCV 및 MPMoviePlayer를 시도했지만 너무 느립니다. 내가 얻을 수있는 가장 빠른 속도는 ~ 2x (분당 2 분의 비디오 스캔)입니다. 나는 10x에 더 가까운 것을 원할 것이다.

위의 시도에서 GPU를 사용하지 않았다고 가정하면 GPU에서 실행되는 무언가로 내 목표를 달성 할 수있는 방법이 있습니까? OpenGL은 대부분 렌더링 출력을위한 것 같지만 들어오는 비디오의 필터로 사용되는 것을 보았습니다. 어쩌면 그게 옵션일까요?

미리 감사드립니다.

답변

3

iOS 5 전용 솔루션을 사용하려는 경우 AVCaputureSession의 2011 WWDC 세션에서 제공하는 샘플 앱 ChromaKey를 살펴보세요.

데모는 내장 카메라에서 30FPS의 비디오를 캡처하고 각 프레임을 텍스처로 OpenGL에 전달합니다. 그런 다음 OpenGL을 사용하여 프레임을 조작하고 선택적으로 결과를 출력 비디오 파일에 씁니다.

코드는 그래픽 하드웨어에서 메모리를 공유 할 수 있도록 AVCaptureSession의 Core Video Pixel 버퍼를 OpenGL에 바인딩하기 위해 심각한 저수준 마법을 사용합니다.

카메라 입력보다는 동영상 파일을 입력으로 사용하도록 AVCaptureSession을 변경하는 것이 매우 간단해야합니다.

Y 구성 요소가 휘도 인 RGB가 아닌 Y/UV 형식의 프레임을 제공하도록 세션을 설정할 수 있습니다. 그렇게하지 않으면 각 픽셀의 RGB 값을 휘도 값으로 변환하는 셰이더를 작성하는 것이 매우 간단합니다.

모든 10 번째 프레임이 아닌 모든 프레임에서이 모든 작업을 수행 할 수 있어야합니다.

+0

그 샘플을 얻으려면 WWDC 2011 참석자가되어야 할 것처럼 보입니다. 나는 여전히 실시간 트랜스 코딩 (transcoding)이 효과적이라는 점에 대해 걱정하고있다. 15 배속을 원합니다 (1 분 안에 15 분간 비디오를 스캔했습니다). 병 목이 프레임 디코딩에 있다고 생각합니다. –

+0

@ 사이먼.d - ChromaKey 예제에서 사용 된 기술에 대한 내 대답은 http://stackoverflow.com/a/9704392/19679이며, GPUImage 코드를 가져 와서 영화 인코딩에 대한 동작을 확인할 수 있습니다. 빠른 텍스쳐 업로드를 사용하기 위해 아직 영화 읽기 코드를 업데이트하지 않았습니다. iOS 디바이스에는 H.264를 디코딩하기위한 전용 하드웨어가 있기 때문에 iOS 5.0 빠른 텍스처 업로드로 AVFoundation을 사용하는 것보다 더 빨리 영화 파싱을하지 않을 것이라고 확신합니다. –

+0

Apple의 RosyWriter 예제 코드는이 AVCaptureSession -> OpenGL 링크도 보여줍니다. [here] (https://developer.apple.com/library/ios/samplecode/RosyWriter/Introduction/Intro.html)를 참조하십시오. – bcattle

0

겉으로보기에 vImage는 iOS 5를 사용할 수 있다고 가정 할 때 적절할 수 있습니다. 모든 10 번째 프레임은 vImage와 같은 프레임 워크를 사용하는 이유가있는 것으로 보입니다. 그러나 실제 실시간 처리의 모든 유형은 거의 확실히 OpenGL이 필요합니다.

+0

감사합니다. @LucasTizma. vImage를 살펴 보겠습니다. 그러나, 제 목표는 실시간 처리보다 빠르다는 것입니다. 그래서 나는 단지 10 번째 프레임마다하고 싶었다. 비디오가 이미 전화기에 녹화되어 있고 이제 스캔을 시도하고 싶다고 상상해보십시오. 그것은 vImage를 배제합니까? –

+0

vImage는 이미지 처리 작업을 신속하게 수행하기위한 수단 일뿐입니다. 네가 괜찮을거야. OpenGL 외에도 가장 빠른 솔루션입니다. 다른 사람들은 내가 틀렸다면 나를 바로 잡을 수 있습니다. – LucasTizma

+0

하지만 vImage는 프레임을 디코딩 한 후에 만 ​​유용합니다. 그렇다면, 나는 그것을 필요로하는지 잘 모르겠다. 작품의 90 %가 실제로 픽셀을 처리하지 않고 프레임을 디코딩합니다. –

0

응용 프로그램의 병목 현상이 비디오 프레임을 표시 가능한 형식 (예 : RGB)으로 변환하는 코드에 있다고 가정하면 convert one .mp4 frame (encoded as YV12) to RGB using Qt and OpenGL에 사용 된 공유 코드에 관심이있을 수 있습니다. 이 응용 프로그램은 GPU에 프레임을 업로드하고 YV12에서 RGB로 변환하기 위해 GLSL fragment shader을 활성화하므로 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);" 
    "}" 
관련 문제