|
|
|
|
@ -12,6 +12,8 @@
|
|
|
|
|
#include <condition_variable> |
|
|
|
|
#include <chrono> |
|
|
|
|
#include <atomic> |
|
|
|
|
#include <cstring> |
|
|
|
|
#include <climits> |
|
|
|
|
#include <algorithm> |
|
|
|
|
extern "C" { |
|
|
|
|
#include "opus_codec.h" |
|
|
|
|
@ -61,10 +63,14 @@ struct StreamPublishEngine::Impl {
|
|
|
|
|
|
|
|
|
|
StreamPublishEngine::StreamPublishEngine(QObject* parent) : QObject(parent), m(std::make_unique<Impl>()) { |
|
|
|
|
m_timer.setInterval(100); connect(&m_timer, &QTimer::timeout, this, &StreamPublishEngine::tick); m_timer.start(); |
|
|
|
|
m->probeThread = std::thread([this] { |
|
|
|
|
auto codecs = supported() ? StreamVideoEncoder::available() : QList<int>(); |
|
|
|
|
std::lock_guard<std::mutex> guard(m->lock); m->codecs = std::move(codecs); m->probeReady = true; |
|
|
|
|
}); |
|
|
|
|
try { |
|
|
|
|
m->probeThread = std::thread([this] { |
|
|
|
|
auto codecs = supported() ? StreamVideoEncoder::available() : QList<int>(); |
|
|
|
|
std::lock_guard<std::mutex> guard(m->lock); m->codecs = std::move(codecs); m->probeReady = true; |
|
|
|
|
}); |
|
|
|
|
} catch (const std::system_error& error) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "desktop codec probe worker failed: %s", error.what()); m->probeReady = true; |
|
|
|
|
} |
|
|
|
|
auto* sound = SoundManager::instance(); |
|
|
|
|
connect(sound, &SoundManager::contextAboutToReset, this, [this] { m_capture.close(); }); |
|
|
|
|
connect(sound, &SoundManager::contextRestored, this, [this] { if (m->running && m->wanted.audio) openMicrophone(); }); |
|
|
|
|
@ -315,8 +321,8 @@ void StreamPublishEngine::audioLoop() {
|
|
|
|
|
unsigned take = std::min(960 - used, record.frames - offset); |
|
|
|
|
memcpy(pcm + 2 * used, record.pcm + 2 * offset, take * 2 * sizeof(int16_t)); used += take; offset += take; |
|
|
|
|
if (used < 960) continue; |
|
|
|
|
stream_publisher_status stats; |
|
|
|
|
{ std::lock_guard<std::mutex> guard(m->lock); stats = m->stats; } |
|
|
|
|
stream_publisher_status stats{}; |
|
|
|
|
gui_stream_publish_status(m->id, stats); |
|
|
|
|
int wanted[] = {stats.compressor_enabled, stats.compressor_max_gain_db ? stats.compressor_max_gain_db : 15, |
|
|
|
|
stats.compressor_rise_rate ? stats.compressor_rise_rate : 2}; |
|
|
|
|
if (!std::equal(wanted, wanted + 3, settings)) { |
|
|
|
|
@ -378,7 +384,7 @@ void StreamPublishEngine::videoLoop() {
|
|
|
|
|
if (lastImage.isNull()) { DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "desktop captured frame conversion failed"); continue; } |
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) |
|
|
|
|
if (frame.rotation() != QtVideo::Rotation::None) lastImage = lastImage.transformed(QTransform().rotate(static_cast<int>(frame.rotation()))); |
|
|
|
|
if (frame.mirrored()) lastImage = lastImage.mirrored(true, false); |
|
|
|
|
if (frame.mirrored()) lastImage = lastImage.transformed(QTransform().scale(-1, 1)); |
|
|
|
|
#else |
|
|
|
|
if (frame.rotationAngle()) lastImage = lastImage.transformed(QTransform().rotate(frame.rotationAngle())); |
|
|
|
|
#endif |
|
|
|
|
|