Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • beta/202505231812
  • stable/20250523.0
  • nightly/20250523.0
  • nightly/20250515.0
  • nightly/20250510.0
  • nightly/20250509.1
  • nightly/20250509.0
  • stable/20250430.1
  • stable/20250430.0
  • beta/202504301614
  • nightly/20250430.0
  • stable/20250424.1
  • beta/202504241506
  • stable/20250424.0
  • nightly/20250424.1
  • nightly/20250424.0
  • nightly/20250422.0
  • beta/202504120241
  • stable/20250411.0
  • nightly/20250411.0
21 results

rendermanager.h

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    rendermanager.h 6.85 KiB
    /*
     * Copyright (C) 2019-2020 by Savoir-faire Linux
     * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
     * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 3 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program.  If not, see <https://www.gnu.org/licenses/>.
     */
    
    #pragma once
    
    #include "api/avmodel.h"
    #include "api/lrc.h"
    
    #include <QImage>
    #include <QMutex>
    #include <QObject>
    
    using namespace lrc::api;
    
    /*
     * This class acts as a QImage rendering sink and manages
     * signal/slot connections to it's underlying (AVModel) renderer
     * corresponding to the object's renderer id.
     * A QImage pointer is provisioned and updated once rendering
     * starts.
     */
    
    struct RenderConnections
    {
        QMetaObject::Connection started, stopped, updated;
    };
    
    class FrameWrapper final : public QObject
    {
        Q_OBJECT;
    
    public:
        FrameWrapper(AVModel& avModel, const QString& id = video::PREVIEW_RENDERER_ID);
        ~FrameWrapper();
    
        /*
         * Reconnect the started rendering connection for this object.
         */
        void connectStartRendering();
    
        /*
         * Get a pointer to the renderer and reconnect the update/stopped
         * rendering connections for this object.
         * @return whether the start succeeded or not
         */
        bool startRendering();
    
        /*
         * Get the most recently rendered frame as a QImage.
         * @return the rendered image of this object's id
         */
        QImage* getFrame();
    
        /*
         * Check if the object is updating actively.
         */
        bool isRendering();
    
    signals:
        /*
         * Emitted once in slotRenderingStarted.
         * @param id of the renderer
         */
        void renderingStarted(const QString& id);
        /*
         * Emitted each time a frame is ready to be displayed.
         * @param id of the renderer
         */
        void frameUpdated(const QString& id);
        /*
         * Emitted once in slotRenderingStopped.
         * @param id of the renderer
         */
        void renderingStopped(const QString& id);
    
    private slots:
        /*
         * Used to listen to AVModel::rendererStarted.
         * @param id of the renderer
         */
        void slotRenderingStarted(const QString& id = video::PREVIEW_RENDERER_ID);
        /*
         * Used to listen to AVModel::frameUpdated.
         * @param id of the renderer
         */
        void slotFrameUpdated(const QString& id = video::PREVIEW_RENDERER_ID);
        /*
         * Used to listen to AVModel::renderingStopped.
         * @param id of the renderer
         */
        void slotRenderingStopped(const QString& id = video::PREVIEW_RENDERER_ID);
    
    private:
        /*
         * The id of the renderer.
         */
        QString id_;
    
        /*
         * A pointer to the lrc renderer object.
         */
        video::Renderer* renderer_;
    
        /*
         * A local copy of the renderer's current frame.
         */
        video::Frame frame_;
    
        /*
         * A the frame's storage data used to set the image.
         */
        std::vector<uint8_t> buffer_;
    
        /*
         * The frame's paint ready QImage.
         */
        std::unique_ptr<QImage> image_;
    
        /*
         * Used to protect the buffer during QImage creation routine.
         */
        QMutex mutex_;
    
        /*
         * True if the object is rendering
         */
        std::atomic_bool isRendering_;
    
        /*
         * Convenience ref to avmodel
         */
        AVModel& avModel_;
    
        /*
         * Connections to the underlying renderer signals in avmodel
         */
        RenderConnections renderConnections_;
    };
    
    /**
     * RenderManager filters signals and ecapsulates preview and distant
     * frame wrappers, providing access to QImages for each and simplified
     * start/stop mechanisms for renderers. It should contain as much
     * renderer control logic as possible and prevent ui widgets from directly
     * interfacing the rendering logic.
     */
    class RenderManager final : public QObject
    {
        Q_OBJECT;
    
    public:
        explicit RenderManager(AVModel& avModel);
        ~RenderManager();
    
        /*
         * Check if the preview is active.
         */
        bool isPreviewing();
        /*
         * Get the most recently rendered preview frame as a QImage.
         * @return the rendered preview image
         */
        QImage* getPreviewFrame();
        /*
         * Start capturing and rendering preview frames.
         * @param force if the capture device should be started
         * @param async
         */
        void startPreviewing(bool force = false, bool async = true);
        /*
         * Stop capturing.
         * @param async
         */
        void stopPreviewing(bool async = true);
    
        /*
         * Get the most recently rendered distant frame for a given id
         * as a QImage.
         * @return the rendered preview image
         */
        QImage* getFrame(const QString& id);
        /*
         * Add and connect a distant renderer for a given id
         * to a FrameWrapper object
         * @param id
         */
        void addDistantRenderer(const QString& id);
        /*
         * Disconnect and remove a FrameWrapper object connected to a
         * distant renderer for a given id
         * @param id
         */
        void removeDistantRenderer(const QString& id);
    
    signals:
        /*
         * Emitted when the size of the video capture device list changes.
         */
        void videoDeviceListChanged();
    
        /*
         * Emitted when the preview is started.
         */
        void previewRenderingStarted();
    
        /*
         * Emitted when the preview has a new frame ready.
         */
        void previewFrameUpdated();
    
        /*
         * Emitted when the preview is stopped.
         */
        void previewRenderingStopped();
    
        /*
         * Emitted when a distant renderer is started for a given id.
         */
        void distantRenderingStarted(const QString& id);
    
        /*
         * Emitted when a distant renderer has a new frame ready for a given id.
         */
        void distantFrameUpdated(const QString& id);
    
        /*
         * Emitted when a distant renderer is stopped for a given id.
         */
        void distantRenderingStopped(const QString& id);
    
    private slots:
        /*
         * Used to listen to AVModel::deviceEvent.
         */
        void slotDeviceEvent();
    
    private:
        /*
         * Used to classify capture device events.
         */
        enum class DeviceEvent { Added, RemovedCurrent, None };
    
        /*
         * Used to track the capture device count.
         */
        int deviceListSize_;
    
        /*
         * One preview frame.
         */
        std::unique_ptr<FrameWrapper> previewFrameWrapper_;
    
        /*
         * Distant for each call/conf/conversation.
         */
        std::map<QString, std::unique_ptr<FrameWrapper>> distantFrameWrapperMap_;
        std::map<QString, RenderConnections> distantConnectionMap_;
    
        /*
         * Convenience ref to avmodel.
         */
        AVModel& avModel_;
    };
    Q_DECLARE_METATYPE(RenderManager*)