是否可以使用ffmpeg
功能将视频异步解码到纹理中?我需要将视频输出到几何体上。
有mpv
个视频播放器,它可以直接将视频输出到帧缓冲区并使用其他接近金属的功能,但是是否有简约的例子,适用于嵌入式设备(OpenGL ES 2.0或3.0)?
如果纹理在整个帧时间内不会留下GPU内存,那就太好了。
答案 0 :(得分: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开销,我将所有解码流分离到它们自己的线程中。
祝你好运。别的,只要问一下。