Декодирование видео непосредственно в текстуру в отдельном потоке

Можно ли декодировать видео с помощью 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-декодирование.

Кроме того, чтобы снизить нагрузку на процессор, я разделяю все потоки декодирования на их собственные потоки.

Удачи. Что-нибудь еще, просто спросите.

Другие вопросы по тегам