obs_add_raw_video_callback/obs_remove_raw_video_callback接口使用

1 背景

    在基于OBS做二次开发时,有时候需要获取OBS的缺省主窗口YUV数据,输出到自定义窗口上。本文使用Qt获取Video数据,然后在自定义窗口上进行绘制。

2 范例

1)获取主窗口的yuv数据

void CameraService::Start()
{
    if (m_bExit) {
        m_bExit = false;
        width_ = App()->GetMainWindowWidth();
        height_ = App()->GetMainWindowHeigh();
        obs_add_raw_video_callback(NULL, &CameraService::RawVideo,
                       this);

    }
}

void CameraService::Stop()
{
    if (!m_bExit) {
        m_bExit = true;
        obs_remove_raw_video_callback(&CameraService::RawVideo, this);
    }
}

void CameraService::RawVideo(void *param, video_data *frame)
{
    CameraService *window = reinterpret_cast<CameraService *>(param);
    if (window) {
        window->Yuv2Rgb(frame);
    }
}

void CameraService::Yuv2Rgb(video_data *frame)
{

    // 1.将obs底层callback的yuv数据转换成rgb像素数据
    uint8_t *pData =
        (uint8_t *)malloc(sizeof(uint8_t) * width_ * height_ * 4);
    libyuv::NV12ToARGB(frame->data[0], width_, frame->data[1], width_,
               pData, width_ * 4, width_, height_);
    // 2.保存在Qimage类中
    QImage *image = new QImage(pData, width_, height_, QImage::Format_RGB32,
                               OnRgbCleanupHandler, pData);

    // 3.发信号给自定义video显示窗口 
    emit FrameReady(image);
}

2)信号插槽函数

    connect(&camera_service_, SIGNAL(FrameReady(QImage*)), this, SLOT(OnRefreshVideo(QImage*)));

3)输出到自定义窗口上

void MiddleWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter paint(this);
    paint.drawImage(0, 0, m_image);
}

void MiddleWidget::OnRefreshVideo(QImage *rgb)
{
#ifdef _DEBUG
    qInfo("%s", __FUNCTION__);
#endif
    if (rgb && !rgb->isNull()) {
#if _DEBUG
        qInfo("%s scaled", __FUNCTION__);
#endif
        m_image = rgb->scaled(size(), Qt::KeepAspectRatio,
                      Qt::SmoothTransformation);

        // 触发paintEvent()回调,在自定义窗口上进行绘制
        update();
    }

    // 此处记得delete掉QImage资源,不然有内存泄漏问题
    delete rgb;
}

3 样本助解 

obs主窗口显示

自定义窗口显示

    由此可见,用此法,可见obs主窗口画面copy到自定义窗口显示。

4 性能问题

4.1 cpu开销

    本文画面参数:3840x2160分辨率,30fps,YUV420 8bit位深,AVC/H264编码格式

    Win机器配置:6核心12线程

1)单主窗口显示cpu消耗

2)增加1个自定义窗口cpu消耗

 

    可以清楚的看到,使用此法将obs主窗口视频数据copy到自定义窗口显示,会显著提升cpu开销。

4.2 原因分析

  • 分析了obs源码,原因在于obs_add_raw_video_callback回调后,有一个像素格式转换,就是调用了libyuv::NV12ToARGB(),此函数使用CPU将yuv转rgb,由于每帧都要转换,因此cpu开销显著提升;

5 解决方案

  • 放弃使用libyuv库或sws_scale接口,利用OpenGL使用GPU加速来处理像素格式的转换然后绘制;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值