OBS源码使用学习(四)之投屏(window-projector)

在步入正题之前,大家可以先了解一下obs的预览框显示相关内容:

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

一.投屏理念与方法

我们先实际操作一下,看看投屏后效果是什么?

 
 

原来是新建了一个界面容器,并在那个画面上绘图啊。

我们都知道,obs的预览框是通过OBSQTDisplay这个类实现的,这个类继承了QWidget,也就是说他也是一个QWidget。

在不看代码的情况下,根据猜测,我们可以猜测出,应该是新建了一个QWidget,并将OBSQTDisplay插入进去,或者干脆直接就是一个OBSQTDisplay。

我们可以通过OBS源码使用学习(二)之预览框显示 中提到方法,自己写一个QWidget,然后把预览框加进去实现效果,或者再次拿出我们系列的老本行——借鉴源码。

二.修改OBS投屏的相关源码

投屏相关的源码,是window-projector.hpp和window-projector.cpp,通过代码我们可以看出,这个代码中的类OBSProjector,就是继承了OBSQTDisplay

我们直接将源代码添加进自己的工程文件即可,当然,并不是里面所有的都需要,我们需要的仅仅是投屏而已,因此,裁剪后的代码如下:

#include <QAction>
#include <QGuiApplication>
#include <QMouseEvent>
#include <QMenu>
#include <QScreen>
#include "window-projector.hpp"

OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,ProjectorType type_)
    : OBSQTDisplay(widget, Qt::Window),
      source(source_),
      removedSignal(obs_source_get_signal_handler(source), "remove",
            OBSSourceRemoved, this)
{
    source = source_;
    type_ = ProjectorType::Source;

    SetMonitor(monitor);

    auto addDrawCallback = [this]() {
            obs_display_add_draw_callback(GetDisplay(), &OBSRender,this);
            obs_display_set_background_color(GetDisplay(), 0x000000);
        };

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

    if (source)
        obs_source_inc_showing(source);

    ready = true;
    show();
    activateWindow();

}

OBSProjector::~OBSProjector()
{

    auto addDrawCallback = [this]() {
            obs_display_remove_draw_callback(GetDisplay(), &OBSRender,this);
            obs_display_set_background_color(GetDisplay(), 0x000000);
        };
    connect(this, &OBSQTDisplay::destroyed, addDrawCallback);

    if (source)
        obs_source_dec_showing(source);

}
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();
}


void OBSProjector::OBSSourceRemoved(void *data, calldata_t *params)
{
    OBSProjector *window = reinterpret_cast<OBSProjector *>(data);
}

void OBSProjector::SetMonitor(int monitor)
{
    savedMonitor = monitor;
    screen = QGuiApplication::screens()[monitor];
    setGeometry(screen->geometry());
    showFullScreen();
    SetHideCursor();
}
void OBSProjector::SetHideCursor()
{
    setCursor(Qt::BlankCursor);
}

void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy)
{
    OBSProjector *window = reinterpret_cast<OBSProjector *>(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函数
        obs_source_video_render(source);
    else
        obs_render_main_texture();

    endRegion();

}

三.使用OBSProjector

话不多说,直接上代码:

QList<QScreen*> screen_list = QGuiApplication::screens();
//获取屏幕
if (screen_list.count() > 1)
{
    projector = new OBSProjector(this, source, 1, ProjectorType::Source);
    //obs类的老传统,直接实例化就能用,连方法都不用调用,直接实例化就能搞定
}
else
{
    QMessageBox::information(this, "提示","没有配置第二屏幕");
}

这个类的第二个参数就是源,第三个就是屏幕号, 0号是主屏,1号是外接屏1,以此类推。

输入不同的源,就能得到不同的投屏效果,我们可以投不同的源,投到不同的屏幕。

猜你喜欢

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