obs_source_frame
+ -

obs_source_frame到纹理

2024-12-17 5 0

MP4的视频通过解码后为YUV格式的frame数据,其需要通过将该frame的YUV数据复制到纹理(source->async_textures),这样着色器就可以通过GPU将YUV进行采样的值转换成RGB,最终渲染到目标纹理(source->async_texrender )上。

入口函数:update_async_textures

bool update_async_textures(struct obs_source *source,
               const struct obs_source_frame *frame,
               gs_texture_t *tex[MAX_AV_PLANES],
               gs_texrender_t *texrender)

对于YUV需要使用着色器转换成RGB,调用update_async_texrender。

1.使用upload_raw_frame将frame中的YUV数据复制到纹理空间(source->async_textures)

static void upload_raw_frame(gs_texture_t *tex[MAX_AV_PLANES],
                 const struct obs_source_frame *frame)
{
    switch (get_convert_type(frame->format, frame->full_range)) {
    case CONVERT_422_PACK:
    case CONVERT_800:
    case CONVERT_RGB_LIMITED:
    case CONVERT_BGR3:
    case CONVERT_420:
    case CONVERT_422:
    case CONVERT_NV12:
    case CONVERT_444:
    case CONVERT_420_A:
    case CONVERT_422_A:
    case CONVERT_444_A:
    case CONVERT_444_A_PACK:
        for (size_t c = 0; c < MAX_AV_PLANES; c++) {
            if (tex[c])
                gs_texture_set_image(tex[c], frame->data[c], frame->linesize[c], false);
        }
        break;

    case CONVERT_NONE:
        assert(false && "No conversion requested");
        break;
    }
}

2.根据格式获取到合钐的tech,并在gs_texrender_begin设置渲染目标(source->async_texrender )上。

    uint32_t cx = source->async_width;
    uint32_t cy = source->async_height;

    gs_effect_t *conv = obs->video.conversion_effect;
    const char *tech_name =    select_conversion_technique(frame->format, frame->full_range);
    gs_technique_t *tech = gs_effect_get_technique(conv, tech_name);

    const bool success = gs_texrender_begin(texrender, cx, cy);

tech_name为I420_Reverse。
注意,这里不出图,是渲染到纹理上,故视图必须为实际图像的大小。

gs_set_viewport(0, 0, texrender->cx, texrender->cy);

3.二次绘制?obs_source_render_async_video

将source->async_texrender 绘制的纹理作为DrawNonlinearAlpha着色器的参数进行二次绘制.这次输出的目标是

    struct obs_core_video *video;
    tex = &obs->video.render_texture;

其是通过gs_texrender_end设置的。

void gs_texrender_end(gs_texrender_t *texrender)
{
    if (!texrender)
        return;

    //恢复原来的输出目标不视图
    gs_set_render_target(texrender->prev_target, texrender->prev_zs);

    //device->curProjMatrix
    gs_projection_pop();

    //视口
    gs_viewport_pop();

    texrender->rendered = true;
}

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!