2017-01-14 21 views
3

簡而言之,我需要做的就是在Android中顯示實時視頻幀流(每幀爲YUV420格式)。我有一個回調函數,我接收單個幀作爲字節數組。看起來像這樣的東西:有效地繪製字節數組流的選項在Android中顯示

public void onFrameReceived(byte[] frame, int height, int width, int format) { 
    // display this frame to surfaceview/textureview. 
} 

一個可行但速度慢的選項是將字節數組轉換爲位圖並在SurfaceView上繪製到畫布。在未來,我希望能夠改變這個幀的亮度,對比度等,因此我希望我可以使用OpenGL-ES。我有什麼其他選擇可以有效地做到這一點?

記住,不像在CameraMediaPlayer類的實現,我無法將輸出定向到使用camera.setPreviewTexture(surfaceTexture);,因爲我在C.

接收使用的Gstreamer單個幀
+0

我就直降直接與openGLES渲染YUV幀的路線。如果有幫助,我可以從我的代碼發佈片段着色器和其他任何源代碼。 – WLGfx

+0

您如何設法呈現這些YUV幀正是我需要知道的!你是否像我一樣以字節數組的形式接收這些幀? (源代碼會很有幫助,謝謝!) –

回答

1

我使用的ffmpeg的surfaceview/textureview我的項目,但渲染YUV幀的主體應該與你自己一樣。

例如,如果一個幀是756 x 576,那麼Y幀將是那個尺寸。 U和V框架是Y框架寬度和高度的一半,因此您必須確保您考慮到尺寸差異。

我不知道相機API,但是我從DVB源獲得的幀具有寬度,並且每行都有一個步幅。在幀中每行的末尾添加像素。以防萬一你的是相同的,那麼在計算你的紋理座標時考慮這一點。

調整紋理座標佔寬度和跨度(LINESIZE):

float u = 1.0f/buffer->y_linesize * buffer->wid; // adjust texture coord for edge 

我使用的頂點着色器採用屏幕座標從0.0到1.0,但你可以改變這些,以適應。它還需要紋理座標和顏色輸入。我已經使用的顏色輸入,使得我可以添加衰落等

頂點着色器:

#ifdef GL_ES 
precision mediump float; 
const float c1 = 1.0; 
const float c2 = 2.0; 
#else 
const float c1 = 1.0f; 
const float c2 = 2.0f; 
#endif 

attribute vec4 a_vertex; 
attribute vec2 a_texcoord; 
attribute vec4 a_colorin; 
varying vec2 v_texcoord; 
varying vec4 v_colorout; 



void main(void) 
{ 
    v_texcoord = a_texcoord; 
    v_colorout = a_colorin; 

    float x = a_vertex.x * c2 - c1; 
    float y = -(a_vertex.y * c2 - c1); 

    gl_Position = vec4(x, y, a_vertex.z, c1); 
} 

片段着色器,其有三個均勻紋理,一個用於每個Y,U和V framges和轉換到RGB。這也乘以從頂點着色器傳遞的顏色:

#ifdef GL_ES 
precision mediump float; 
#endif 

uniform sampler2D u_texturey; 
uniform sampler2D u_textureu; 
uniform sampler2D u_texturev; 
varying vec2 v_texcoord; 
varying vec4 v_colorout; 

void main(void) 
{ 
    float y = texture2D(u_texturey, v_texcoord).r; 
    float u = texture2D(u_textureu, v_texcoord).r - 0.5; 
    float v = texture2D(u_texturev, v_texcoord).r - 0.5; 
    vec4 rgb = vec4(y + 1.403 * v, 
        y - 0.344 * u - 0.714 * v, 
        y + 1.770 * u, 
        1.0); 
    gl_FragColor = rgb * v_colorout; 
} 

使用的頂點是:

float x, y, z; // coords 
float s, t;  // texture coords 
uint8_t r, g, b, a; // colour and alpha 

希望這有助於!

編輯:

對於NV12格式,你仍然可以使用一個片段着色器,雖然我還沒有嘗試過自己。它將交錯紫外線作爲亮度α通道或類似物。

在這裏看到一個人是如何回答的:https://stackoverflow.com/a/22456885/2979092

+0

我的原始問題實際上是如何將這些字節幀顯示到表面(框架將如何繪製的實際機制)。因此我不能接受這個答案。但是,這是有幫助的!非常感謝。我的相框的真實格式是NV12。 (UV成分交錯)。你知道我將如何分別提取U和V組件? –

+0

我已經添加了一個參考NV12着色器答案的編輯。 – WLGfx

+0

是的,我最終使用了它。再次感謝!我將發佈我的解決方案,以便我有效地將單個字節幀顯示到紋理視圖。不過,我會提高你的答案,因爲這是非常有用的,一旦我有足夠的聲譽這樣做! –

相關問題