Keep per-stream playback clocks on the shared audio output

This commit is contained in:
evgeny committed 2026-10-20 16:29:06 +02:00
1 parent a0b6dd7ef5
commit 103e0b6865
3 files changed
+52 -43

No files matched your search

+20 -4
View File
@@ -127,11 +127,11 @@ extern "C" ma_result __wrap_ma_context_init(const ma_backend*, ma_uint32, const
}
static void observeAudio(ma_device* device, void* out, const void* in, ma_uint32 frames) {
originalAudioCallback.load()(device, out, in, frames);
const auto* pcm = static_cast<const int16_t*>(out);
const auto* pcm = static_cast<const float*>(out);
uint64_t left = 0, right = 0, nonzero = 0;
for (unsigned i = 0; i < frames; i++) {
left += static_cast<int64_t>(pcm[2 * i]) * pcm[2 * i];
right += static_cast<int64_t>(pcm[2 * i + 1]) * pcm[2 * i + 1];
int64_t l = std::lround(pcm[2 * i] * 32768), r = std::lround(pcm[2 * i + 1] * 32768);
left += l * l; right += r * r;
nonzero += pcm[2 * i] != 0; nonzero += pcm[2 * i + 1] != 0;
if (pcm[2 * i] || pcm[2 * i + 1]) silentRun = 0;
else if (++silentRun == 48) silenceGaps.fetch_add(1);
@@ -140,7 +140,7 @@ static void observeAudio(ma_device* device, void* out, const void* in, ma_uint32
}
extern "C" ma_result __wrap_ma_device_init(ma_context* context, const ma_device_config* config, ma_device* device) {
ma_device_config copy = *config;
if (copy.deviceType == ma_device_type_playback && copy.playback.format == ma_format_s16 && copy.playback.channels == 2) {
if (copy.deviceType == ma_device_type_playback && copy.playback.format == ma_format_f32 && copy.playback.channels == 2) {
originalAudioCallback = copy.dataCallback; copy.dataCallback = observeAudio;
}
return __real_ma_device_init(context, &copy, device);
@@ -370,6 +370,22 @@ private slots:
QCOMPARE(stream_get_info(publisher, &info), STREAM_OK); QCOMPARE(info.owners, 1u);
}
void independentCatalogueOwners() {
int before = snapshots.size();
QVERIFY(gui_stream_watch(group, 77));
QTRY_VERIFY(snapshots.size() > before);
QVERIFY(gui_stream_watch(0)); QTest::qWait(20); // Основной чат перестал наблюдать, окно осталось.
before = snapshots.size();
QCOMPARE(stream_publish_finish(publisher), STREAM_OK);
QTRY_VERIFY(snapshots.size() > before);
QCOMPARE(snapshots.last().mid(9), QByteArray("[]")); QCOMPARE(snapshots.last().at(8), char(1));
stream_close(publisher); publisher = nullptr;
QCOMPARE(stream_publish_open(inst, group, nullptr, &publisher), STREAM_OK);
stream_info info{}; QCOMPARE(stream_get_info(publisher, &info), STREAM_OK); epoch = info.descriptor.source_epoch;
QTRY_VERIFY(snapshots.last().mid(9) != QByteArray("[]"));
QVERIFY(gui_stream_watch(0, 77)); QVERIFY(gui_stream_watch(group)); QTest::qWait(20);
}
void realH264RenderingAndClose() {
#ifdef HAVE_FFMPEG
/* Фикстура протокола выше содержит фиктивный H264; реальный decoder получает отдельную эпоху. */