Декодирование видео непосредственно в текстуру в отдельном потоке
Можно ли декодировать видео с помощью ffmpeg
возможности напрямую в текстуру асинхронно? Мне нужно вывести видео на геометрию.
Есть mpv
видеопроигрыватель, который может выводить видео непосредственно в кадровый буфер и использовать другие близкие к железу функции, но есть ли минималистичный пример, который подходит для встроенных устройств (OpenGL ES 2.0 или 3.0)?
Было бы хорошо, если бы текстура не оставляла память GPU в течение всего времени кадра.
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, который экономит много ресурсов:
// 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 and V".
Как упоминалось в комментариях, сборка FFMpegs будет автоматически использовать HW-декодирование.
Кроме того, чтобы снизить нагрузку на процессор, я разделяю все потоки декодирования на их собственные потоки.
Удачи. Что-нибудь еще, просто спросите.