Browse Source

End desktop publication on fatal audio worker failure

master
evgeny 5 days ago
parent
commit
470001bbab
  1. 20
      tools/chatgui/src/stream_publish_engine.cpp
  2. 1
      tools/chatgui/src/stream_publish_engine.h

20
tools/chatgui/src/stream_publish_engine.cpp

@ -250,7 +250,7 @@ bool StreamPublishEngine::start(uint64_t group, const StreamPublishConfig& confi
try {
m->videoThread = std::thread(&StreamPublishEngine::videoLoop, this);
if (config.audio) m->audioThread = std::thread(&StreamPublishEngine::audioLoop, this);
} catch (const std::system_error& error) { sourceFailed(m->generation, QString::fromUtf8(error.what())); return false; }
} catch (const std::system_error& error) { publicationFailed(m->id, QString::fromUtf8(error.what())); return false; }
if (!openSource(config) || (config.audio && !openMicrophone())) {
sourceFailed(m->generation, text("Could not open the selected capture device")); return false;
}
@ -288,6 +288,13 @@ void StreamPublishEngine::sourceFailed(uint64_t generation, const QString& error
if (rollback) reconfigure(restore); else stop();
}
/* Ошибку общего audio worker нельзя исправить заменой только video encoder. */
void StreamPublishEngine::publicationFailed(uint64_t id, const QString& error) {
if (id != m->id || !m->running) return;
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop publication failed id=%llu reason=%s", (unsigned long long)id, qPrintable(error));
emit errorOccurred(error); stop();
}
/* Сначала callbacks, затем workers; FIN не обгоняет уже принятые access units. */
void StreamPublishEngine::stop() {
if (!m->running.exchange(false)) return;
@ -303,9 +310,11 @@ bool StreamPublishEngine::openMicrophone() {
m_capture.close();
m->audioAnchor = -1; m->audioFrames = 0;
auto config = this->config(); auto* context = SoundManager::instance()->context();
if (!context) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop stream audio context unavailable"); return false; }
if (!context) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop stream audio context unavailable"); m_capture.retryLater(); return false; }
ma_device_id device; bool selected = SoundManager::deviceId(config.microphone, &device);
if (!config.microphone.isEmpty() && !selected) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop selected microphone ID is unavailable"); return false; }
if (!config.microphone.isEmpty() && !selected) {
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop selected microphone ID is unavailable"); m_capture.retryLater(); return false;
}
for (int channels : {2, 1}) {
ma_device_config capture = ma_device_config_init(ma_device_type_capture);
capture.capture.format = ma_format_s16; capture.capture.channels = channels; capture.sampleRate = 48000;
@ -347,12 +356,13 @@ void StreamPublishEngine::captureAudio(const void* input, unsigned frames) {
}
void StreamPublishEngine::audioLoop() {
const uint64_t id = m->id;
auto* encoder = opus_codec_encoder_create(48000, 2); auto* compressor = audio_compressor_create();
int result = encoder && compressor ? opus_codec_encoder_application_set(encoder, OPUS_CODEC_APP_AUDIO) : -1;
if (result >= 0) result = opus_codec_encoder_bitrate_set(encoder, 128000);
if (result < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop stream audio encoder initialization failed");
QMetaObject::invokeMethod(this, [this] { sourceFailed(m->generation, text("Audio encoder initialization failed")); });
QMetaObject::invokeMethod(this, [this, id] { publicationFailed(id, text("Audio encoder initialization failed")); });
} else {
int16_t pcm[1920]{}; unsigned used = 0; uint64_t sequence = 0;
int64_t pts = 0, expected = -1, lastSent = -1; int settings[3] = {-1, -1, -1};
@ -396,7 +406,7 @@ void StreamPublishEngine::audioLoop() {
used = 0;
}
if (result < 0) {
QMetaObject::invokeMethod(this, [this] { sourceFailed(m->generation, text("Audio encoding failed")); }); break;
QMetaObject::invokeMethod(this, [this, id] { publicationFailed(id, text("Audio encoding failed")); }); break;
}
}
}

1
tools/chatgui/src/stream_publish_engine.h

@ -61,6 +61,7 @@ private:
void closeSource();
bool openMicrophone();
void sourceFailed(uint64_t generation, const QString& error);
void publicationFailed(uint64_t id, const QString& error);
void tick();
void videoLoop();
void audioLoop();

Loading…
Cancel
Save