QML Video Preview (libobs)

Peter Akakpo

New Member
good morning everyone

am experimenting with QML and wants the best and efficient way to preview video (display) using a sub class of QQuickItem. this is what i came up with
attached is the full source codes of the MainVideoOut. this works, but i want to know if it is the most efficient way to do this with the OBS library. will be glad if someone will offer me a sample code showing how to best achieve this

Code:
MainVideoOut::MainVideoOut(QQuickItem *parent) : QQuickItem(parent)
{
    setFlag(ItemHasContents, true);
    obs_add_raw_video_callback(nullptr, render, this);
}

MainVideoOut::~MainVideoOut()
{
    obs_remove_raw_video_callback(render, this);
}

void MainVideoOut::render(void *data, video_data *frame)
{
    MainVideoOut *videoOut = static_cast<MainVideoOut *>(data);
    videoOut->_frame =
        frame QMetaObject::invokeMethod(videoOut, "updateFrame");
}

void MainVideoOut::updateFrame()
{
    update();
}

QSGNode *MainVideoOut::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    if (_frame != nullptr) {
        QSGSimpleTextureNode *node =
            static_cast<QSGSimpleTextureNode *>(oldNode);
        if (!node) {
            node = new QSGSimpleTextureNode();
        }

        obs_video_info vi obs_get_video_info(&vi);

        QImage image(reinterpret_cast<uchar *>(_frame->data[0]),
                 vi.base_width, vi.base_height,
                 QImage::Format::Format_RGBA8888);
        QSGTexture *texture = window()->createTextureFromImage(image);
        QSGTexture *oldTexture = node->texture();
        node->setTexture(texture);
        node->setRect(boundingRect());
        node->setSourceRect(0, 0, vi.base_width, vi.base_height);

        if (oldTexture) {
            delete oldTexture;
            oldTexture = nullptr;
        }
        return node;
    }
    return nullptr;
}
 

Attachments

  • main-video-out.cpp.txt
    1.5 KB · Views: 13
  • main-video-out.h.txt
    466 bytes · Views: 12
Last edited by a moderator:

Lain

Forum Admin
Lain
Forum Moderator
Developer
You could do this, sure. But this can never really be an ideal or efficient way due to the fact that you have to download it from the GPU only to upload it again via QtQuick. Ideally, sharing textures (or devices) is the way to do it, but sharing textures is much more difficult via QtQuick; especially depending on whether you're using Qt5 or Qt6 (I would not recommend using Qt5 anymore if you're going to use QML). I know this because I've done these experiments myself. I can't help you accomplish it, but I can just say that the ideal way is via texture sharing. It is possible to accomplish but just a pain because you need to create a custom native surface via quick. Then you'll be able to manipulate it like any QtQuick/QML surface.
 
Top