File size: 3,226 Bytes
034d0a2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright 2018 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <string>
#include <unordered_map>
#include <QCamera>
#include <QImage>
#include <QMediaCaptureSession>
#include <QVideoSink>
#include "citra_qt/camera/camera_util.h"
#include "citra_qt/camera/qt_camera_base.h"
#include "core/frontend/camera/interface.h"

namespace Camera {

// NOTE: Must be created on the Qt thread. QtMultimediaCameraHandlerFactory ensures this.
class QtMultimediaCameraHandler final : public QObject {
    Q_OBJECT

public:
    explicit QtMultimediaCameraHandler(const std::string& camera_name);
    ~QtMultimediaCameraHandler();

    void StartCapture();
    void StopCapture();

    QImage QtReceiveFrame() {
        return camera_surface->videoFrame().toImage();
    }

    bool IsPreviewAvailable() {
        return camera->isAvailable();
    }

    bool IsActive() {
        return camera->isActive();
    }

    [[nodiscard]] bool IsPaused() {
        return paused;
    }

    void PauseCapture() {
        StopCapture();
        paused = true;
    }

private:
    std::unique_ptr<QCamera> camera;
    std::unique_ptr<QVideoSink> camera_surface;
    QMediaCaptureSession capture_session{};
    bool paused = false; // was previously started but was paused, to be resumed
};

// NOTE: Must be created on the Qt thread.
class QtMultimediaCameraHandlerFactory final : public QObject {
    Q_OBJECT

public:
    Q_INVOKABLE std::shared_ptr<QtMultimediaCameraHandler> Create(const std::string& camera_name);
    void PauseCameras();
    void ResumeCameras();

private:
    std::unordered_map<std::string, std::weak_ptr<QtMultimediaCameraHandler>> handlers;
};

/// This class is only an interface. It just calls QtMultimediaCameraHandler.
class QtMultimediaCamera final : public QtCameraInterface {
public:
    QtMultimediaCamera(const std::shared_ptr<QtMultimediaCameraHandler>& handler,
                       const Service::CAM::Flip& flip)
        : QtCameraInterface(flip), handler(handler) {}

    void StartCapture() override {
        handler->StartCapture();
    }

    void StopCapture() override {
        handler->StopCapture();
    }

    void SetFrameRate(Service::CAM::FrameRate frame_rate) override {}

    QImage QtReceiveFrame() override {
        return handler->QtReceiveFrame();
    }

    bool IsPreviewAvailable() override {
        return handler->IsPreviewAvailable();
    }

private:
    std::shared_ptr<QtMultimediaCameraHandler> handler;
};

/// This class is only an interface. It just calls QtMultimediaCameraHandlerFactory.
class QtMultimediaCameraFactory final : public QtCameraFactory {
public:
    QtMultimediaCameraFactory(
        const std::shared_ptr<QtMultimediaCameraHandlerFactory>& handler_factory)
        : handler_factory(handler_factory) {}

    std::unique_ptr<CameraInterface> Create(const std::string& config,
                                            const Service::CAM::Flip& flip) override {
        return std::make_unique<QtMultimediaCamera>(handler_factory->Create(config), flip);
    }

private:
    std::shared_ptr<QtMultimediaCameraHandlerFactory> handler_factory;
};

} // namespace Camera