2017-07-18 41 views
0

是否可以使用ffmpeg功能直接將視頻解碼爲異步紋理?我需要將視頻輸出到幾何圖形上。將視頻直接解碼爲單獨線程中的紋理

mpv視頻播放器,它可以直接將視頻輸出到幀緩衝區,並使用其他接近金屬功能,但有簡單的例子,適合嵌入式設備(OpenGL ES 2.0或3.0)?

如果在整個幀時間內紋理不會離開GPU內存,那將會很不錯。

+0

它不應該離開內存,除非你告訴它這樣做。 – Reaper

+0

您仍然需要將幀數據傳輸到GPU,但是您可以使用YUV片段着色器即時轉換爲RGB。 – WLGfx

+0

@WLGfx如果我使用VDPAU,該怎麼辦?我認爲有可能管理幀不會離開GPU內存。 – Orient

回答

1

我目前使用sws_scale修剪mpegts流幀的邊緣,因爲一些幀在解碼時使用的邊緣會有16甚至32個額外的像素。對於大多數用途來說這不是必需的。相反,我用它直接複製到我自己的緩衝區中。

ff->scale_context = sws_getContext(wid, hgt, ff->vid_ctx->pix_fmt, // usually YUV420 
           wid, hgt, AV_PIX_FMT_YUV420P,  // trim edges and copy 
           SWS_FAST_BILINEAR, NULL, NULL, NULL); 

// setup my buffer to copy the frame into 

uint8_t *data[] = { vframe->yframe, vframe->uframe, vframe->vframe }; 
int linesize[4] = { vid_ctx->width, vid_ctx->width/2, vid_ctx->width/2, 0 }; 

int ret = sws_scale(scale_context, 
      (const uint8_t **)frame->data, frame->linesize, 
      0, vid_ctx->height, 
      data, linesize); 

如果幀是另一種格式,您將需要調整。

使用的OpenGL ES的GPU渲染從而節省了大量的開銷:

// YUV shader (converts YUV planes to RGB on the fly) 

static char vertexYUV[] = "attribute vec4 qt_Vertex; \ 
attribute vec2 qt_InUVCoords; \ 
varying vec2 qt_TexCoord0; \ 
\ 
void main(void) \ 
{ \ 
    gl_Position = qt_Vertex; \ 
    gl_Position.z = 0.0;\ 
    qt_TexCoord0 = qt_InUVCoords; \ 
} \ 
"; 

static char fragmentYUV[] = "precision mediump float; \ 
uniform sampler2D qt_TextureY; \ 
uniform sampler2D qt_TextureU; \ 
uniform sampler2D qt_TextureV; \ 
varying vec2 qt_TexCoord0; \ 
void main(void) \ 
{ \ 
    float y = texture2D(qt_TextureY, qt_TexCoord0).r; \ 
    float u = texture2D(qt_TextureU, qt_TexCoord0).r - 0.5; \ 
    float v = texture2D(qt_TextureV, qt_TexCoord0).r - 0.5; \ 
    gl_FragColor = vec4(y + 1.403 * v, \ 
         y - 0.344 * u - 0.714 * v, \ 
         y + 1.770 * u, 1.0); \ 
}"; 

如果使用NV12格式而不是YUV420那麼UV幀交錯,你只取使用或者「R值, g「或」x,y「。

緩衝區中的每個YUV幀都會上傳到「qt_TextureY,U和V」。

正如在評論中提到的,FFMpegs構建將自動使用硬件解碼。另外,爲了削減CPU開銷,我將所有解碼流分離到它們自己的線程中。

祝你好運。別的,只要問。