2017-07-18 73 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开销,我将所有解码流分离到它们自己的线程中。

祝你好运。别的,只要问。