OBS源码使用学习(二)之预览框显示

我之前也没接触过obs相关的东西,磕磕绊绊可好一阵,因此特把obs的研究心得记录下来,也希望学习这个的萌新们能够少走弯路。

一.OBS的预览框

从obs的源码可以得知,obs的预览框是依靠 OBSQTDisplay()实现的,这个类我们可以直接从obs源码中获取,并将对应的obsqtdisplay.h和obsqtdisplay.cpp加入工程来使用:

#include "obsqtdisplay.h"
#include "display-helpers.hpp"

有些小伙伴反映没有找到obsqtdisplay.h这个文件,很抱歉这里是我疏忽了,obsqtdisplay是我自己创建的类,里面的内容是将qt-display.hpp的全部内容拷贝进来的。

这个文件的原名,在obs源码中这个文件叫做qt-display.hpp。

之后,我们将其实例化: 

QPointer<OBSQTDisplay> program;
program = new OBSQTDisplay();

实例化之后怎么使用呢?

我们从源码可以发现,这个OBSQTDisplay被addDrawCallback所使用的,我们直接从obs源码中将对应代码使用即可:

program = new OBSQTDisplay();
    auto addDrawCallback = [this]() {
            obs_display_add_draw_callback(program->GetDisplay(), &OBSRender,this);
            obs_display_set_background_color(program->GetDisplay(), 0x000000);
        };

connect(program, &OBSQTDisplay::DisplayCreated, addDrawCallback);

最后我们把实例化后的OBSQTDisplay填入ui中:

ui->cameraview->addWidget(program);

至此,预览框就创建完毕了,但是,当前的预览框是没法显示内容的,原因就是,我们还没有把源(source) 添加到这个预览框中。

那么source应该怎么样才能添加到预览框中呢?

二.源(source)图像显示在预览框中

我们发现,有一个函数OBSRender我们还没有实现,我们先实现这个函数。

这个函数我们从源码直接拷贝过来就行(我是在Widget类中定义和实现的,请大家根据自己的实际情况自行更改即可):

void Widget::OBSRender(void *data, uint32_t cx, uint32_t cy)
{
    Widget *window = reinterpret_cast<Widget *>(data);
    OBSSource source = window->source;

    uint32_t targetCX;
    uint32_t targetCY;
    int x, y;
    int newCX, newCY;
    float scale;

    if (source) {
        targetCX = std::max(obs_source_get_width(source), 1u);
        targetCY = std::max(obs_source_get_height(source), 1u);
    } else {
        struct obs_video_info ovi;

        ovi.fps_num = 30;
        ovi.fps_den = 1;

        obs_get_video_info(&ovi);
        targetCX = ovi.base_width;
        targetCY = ovi.base_height;
    }

    GetScaleAndCenterPos(targetCX, targetCY, cx, cy, x, y, scale);

    newCX = int(scale * float(targetCX));
    newCY = int(scale * float(targetCY));

    startRegion(x, y, newCX, newCY, 0.0f, float(targetCX), 0.0f,
            float(targetCY));

    if (source)
        obs_source_video_render(source);
    else
        obs_render_main_texture();

    endRegion();
}

从这段代码中,我们可以看出,这个window->source就是我们要显示的源,只要这个source被填入到了obs_source_video_render()函数中就可以显示了。

最后我们把这个函数里另外两个函数startRegion()和endRegion()的代码也全都拷贝过来:

static inline void startRegion(int vX, int vY, int vCX, int vCY, float oL,
                   float oR, float oT, float oB)
{
    gs_projection_push();
    gs_viewport_push();
    gs_set_viewport(vX, vY, vCX, vCY);
    gs_ortho(oL, oR, oT, oB, -100.0f, 100.0f);
}

static inline void endRegion()
{
    gs_viewport_pop();
    gs_projection_pop();
}

至此,OBS的预览框显示就可以大功告成了,只要将创建出来的源,赋给类中的source成员,就能够实现画面显示和切换的效果了。

猜你喜欢

转载自blog.csdn.net/weixin_44838243/article/details/127692757