| /* |
| * 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 *) |