我之前也没接触过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成员,就能够实现画面显示和切换的效果了。