You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

87 lines
3.3 KiB

/* Desktop publisher: GUI управляет источниками и AudioDevice, workers кодируют видео/Opus.
* Окно не владеет трансляцией. Stop закрывает callbacks, joins 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();
void videoLoop(StreamPublishConfig initial);
void audioLoop();
void captureAudio(const AudioCapture::Frame& frame);
};