2012-02-17 108 views
14

我正在尋找最快的方式來解碼iPhone上的本地mpeg-4視頻幀。我只關心每10幀中像素的亮度值。我不需要在任何地方渲染視頻。解碼iPhone GPU上的視頻幀

我試過ffmpeg,AVAssetReader,ImageAssetGenerator,OpenCV和MPMoviePlayer,但它們都太慢了。我能得到的最快速度是〜2x(一分鐘內掃描2分鐘的視頻)。我想要更接近10倍的東西。

假設我上面的嘗試沒有使用GPU,是否有任何方法可以通過GPU上運行的某些東西來實現我的目標? OpenGL似乎主要用於渲染輸出,但我已經看到它用作傳入視頻的過濾器。也許這是一個選擇?

在此先感謝!

回答

3

如果您願意使用僅適用於iOS 5的解決方案,請查看AVCaputureSession上2011年WWDC會話中的示例應用程序ChromaKey。

該演示從內置攝像頭捕獲30幀FPS視頻,並將每幀作爲紋理傳遞給OpenGL。然後它使用OpenGL來處理該幀,並可選擇將結果寫入輸出視頻文件。

該代碼使用一些嚴重的低級魔法將AVCaptureSession的Core Video Pixel緩衝區綁定到OpenGL,以便它們在圖形硬件中共享內存。

將AVCaptureSession更改爲使用電影文件作爲輸入而不是相機輸入應該相當簡單。

您可能可以設置會話以Y/UV形式傳遞幀,而不是RGB,其中Y分量是亮度。如果不這樣做,編寫一個將每個像素的RGB值轉換爲亮度值的着色器將非常簡單。

你應該可以在所有幀上做所有這些,而不是每10幀。

+0

看起來好像我需要成爲WWDC 2011的參與者才能獲得該示例。我仍然擔心這是實時轉碼。我想獲得15倍的速度(1分鐘內掃描15分鐘的視頻)。我認爲瓶頸在幀解碼中。 – 2012-03-02 17:35:34

+0

@simon。d - 我在我的答案中描述了ChromaKey示例中使用的技術:http://stackoverflow.com/a/9704392/19679,您可以抓住我的GPUImage代碼來查看編碼影片的動作。不過,我還沒有更新我的電影閱讀代碼以使用快速紋理上傳。由於iOS設備具有用於解碼H.264的專用硬件,我感到有理由肯定的說,與使用iOS 5.0快速紋理上傳的AVFoundation相比,您無法獲得更快的電影解析。 – 2012-03-22 23:34:25

+0

Apple的RosyWriter示例代碼還演示了此AVCaptureSession - > OpenGL鏈接。請參閱[這裏](https://developer.apple.com/library/ios/samplecode/RosyWriter/Introduction/Intro.html)。 – bcattle 2014-05-27 18:57:16

0

看似vImage可能是合適的,假設你可以使用iOS 5.每個第10幀似乎都是使用像vImage這樣的框架的理由。但是,任何類型的實時實時處理幾乎肯定會需要OpenGL。

+0

Thanks @LucasTizma。我會看看vImage。不過,我的目標是比實時處理更快。這就是爲什麼我只想每10幀做一次。所以想象一下,視頻已經記錄在手機上,現在我想嘗試掃描。這是否排除vImage? – 2012-02-21 06:55:36

+0

vImage只是快速執行圖像處理操作的一種手段。我想你會沒事的。看起來,除了OpenGL以外,這是您最快的解決方案。其他人,如果我錯了,隨時糾正我。 – LucasTizma 2012-02-22 02:00:09

+0

但是vImage只有在解碼幀後纔有用?如果是這樣,我不知道我需要它。 90%的工作實際上是對幀進行解碼,而不是處理像素。 – 2012-02-23 19:15:06

0

假設你的應用的瓶頸是在視頻幀轉換爲可顯示的格式(如RGB)的代碼,你可能會感興趣的代碼共享我曾用於convert one .mp4 frame (encoded as YV12) to RGB using Qt and OpenGL。此應用程序將該幀上傳到GPU並激活GLSL fragment shader以執行從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);" 
    "}"