90 lines
3.4 KiB
C++
90 lines
3.4 KiB
C++
/* Desktop publisher: GUI управляет источниками и AudioDevice, workers кодируют видео/Opus.
|
|
* Окно не владеет трансляцией. Stop закрывает callbacks; GUI ждёт workers асинхронно, затем отправляет FIN.
|
|
* Captured video/preview хранят только последний кадр; публикация использует общий C actor. */
|
|
#pragma once
|
|
#include <QObject>
|
|
#include <QTimer>
|
|
#include <QVariant>
|
|
#include <QImage>
|
|
#include <QList>
|
|
#include <QPointer>
|
|
#include <QScreen>
|
|
#include <memory>
|
|
#include "live_video_encoder.h"
|
|
#include "stream_video_modes.h"
|
|
#include "audio_capture.h"
|
|
#include "audio_capture_lease.h"
|
|
#include "../../../src/stream/stream_publisher.h"
|
|
|
|
struct StreamVideoSource {
|
|
enum Kind { Camera, Screen, Window };
|
|
Kind kind = Camera;
|
|
QString name;
|
|
QByteArray id;
|
|
QVariant window;
|
|
QSize size;
|
|
QList<StreamVideoMode> modes;
|
|
QPointer<QScreen> screen; // Живой монитор; удаление устройства не должно переключать захват на его одноимённого соседа.
|
|
bool sameSource(const StreamVideoSource& other) const {
|
|
return kind == other.kind && id == other.id && window == other.window && screen == other.screen;
|
|
}
|
|
};
|
|
struct StreamPublishConfig {
|
|
StreamVideoSource source;
|
|
LiveVideoConfig video;
|
|
QString microphone;
|
|
bool audio = true;
|
|
bool showCursor = true;
|
|
bool nativeSize = false, automaticBitrate = false;
|
|
};
|
|
class StreamPublishEngine : public QObject {
|
|
Q_OBJECT
|
|
public:
|
|
explicit StreamPublishEngine(QObject* parent = nullptr);
|
|
~StreamPublishEngine() override;
|
|
bool start(uint64_t group, const StreamPublishConfig& config);
|
|
bool reconfigure(const StreamPublishConfig& config);
|
|
void stop();
|
|
bool active() const;
|
|
bool running() const;
|
|
uint64_t group() const;
|
|
StreamPublishConfig config() const;
|
|
QVariant previewFrame() const;
|
|
QList<int> codecs() const;
|
|
static QList<StreamVideoSource> sources();
|
|
static bool supported();
|
|
static bool cursorSupported(const StreamVideoSource& source);
|
|
void setMuted(bool muted);
|
|
bool muted() const;
|
|
uint64_t softwareEncodingRequest() const;
|
|
void answerSoftwareEncoding(uint64_t generation, bool allow);
|
|
signals:
|
|
void codecsChanged();
|
|
void sourcesChanged();
|
|
void stateChanged(const QString& state);
|
|
void configurationChanged();
|
|
void previewVideoChanged(const QVariant& frame);
|
|
void telemetryChanged(const stream_publisher_status& status);
|
|
void errorOccurred(const QString& error);
|
|
void audioChannelsChanged(int channels);
|
|
void softwareEncodingRequested(uint64_t generation, const QString& codec, const QString& details);
|
|
private:
|
|
struct Impl;
|
|
std::unique_ptr<Impl> m;
|
|
AudioCapture m_capture;
|
|
AudioCaptureLease m_microphone{AudioCaptureLease::Mode::Exclusive};
|
|
QTimer m_timer;
|
|
QTimer m_previewTimer;
|
|
bool openSource(const StreamPublishConfig& config);
|
|
void closeSource();
|
|
bool openMicrophone();
|
|
void sourceFailed(uint64_t generation, const QString& error);
|
|
void publicationFailed(uint64_t id, const QString& error);
|
|
void tick();
|
|
bool finishStop();
|
|
void imageLoop();
|
|
void videoLoop(StreamPublishConfig initial);
|
|
void audioLoop();
|
|
void captureAudio(const AudioCapture::Frame& frame);
|
|
};
|