mirror of
https://github.com/pikvm/ustreamer.git
synced 2025-12-24 03:00:01 +00:00
bunch of mic fixes
This commit is contained in:
parent
37e79995fe
commit
3d7685ac48
@ -43,11 +43,6 @@
|
||||
#include "logging.h"
|
||||
|
||||
|
||||
#define _JLOG_PERROR_ALSA(_err, _prefix, _msg, ...) US_JLOG_ERROR(_prefix, _msg ": %s", ##__VA_ARGS__, snd_strerror(_err))
|
||||
#define _JLOG_PERROR_RES(_err, _prefix, _msg, ...) US_JLOG_ERROR(_prefix, _msg ": %s", ##__VA_ARGS__, speex_resampler_strerror(_err))
|
||||
#define _JLOG_PERROR_OPUS(_err, _prefix, _msg, ...) US_JLOG_ERROR(_prefix, _msg ": %s", ##__VA_ARGS__, opus_strerror(_err))
|
||||
|
||||
|
||||
static void *_pcm_thread(void *v_acap);
|
||||
static void *_encoder_thread(void *v_acap);
|
||||
|
||||
@ -57,7 +52,7 @@ bool us_acap_probe(const char *name) {
|
||||
int err;
|
||||
US_JLOG_INFO("acap", "Probing PCM capture ...");
|
||||
if ((err = snd_pcm_open(&dev, name, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
|
||||
_JLOG_PERROR_ALSA(err, "acap", "Can't probe PCM capture");
|
||||
US_JLOG_PERROR_ALSA(err, "acap", "Can't probe PCM capture");
|
||||
return false;
|
||||
}
|
||||
snd_pcm_close(dev);
|
||||
@ -78,14 +73,14 @@ us_acap_s *us_acap_init(const char *name, uint pcm_hz) {
|
||||
{
|
||||
if ((err = snd_pcm_open(&acap->dev, name, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
|
||||
acap->dev = NULL;
|
||||
_JLOG_PERROR_ALSA(err, "acap", "Can't open PCM capture");
|
||||
US_JLOG_PERROR_ALSA(err, "acap", "Can't open PCM capture");
|
||||
goto error;
|
||||
}
|
||||
assert(!snd_pcm_hw_params_malloc(&acap->dev_params));
|
||||
|
||||
# define SET_PARAM(_msg, _func, ...) { \
|
||||
if ((err = _func(acap->dev, acap->dev_params, ##__VA_ARGS__)) < 0) { \
|
||||
_JLOG_PERROR_ALSA(err, "acap", _msg); \
|
||||
US_JLOG_PERROR_ALSA(err, "acap", _msg); \
|
||||
goto error; \
|
||||
} \
|
||||
}
|
||||
@ -111,7 +106,7 @@ us_acap_s *us_acap_init(const char *name, uint pcm_hz) {
|
||||
acap->res = speex_resampler_init(US_RTP_OPUS_CH, acap->pcm_hz, US_RTP_OPUS_HZ, SPEEX_RESAMPLER_QUALITY_DESKTOP, &err);
|
||||
if (err < 0) {
|
||||
acap->res = NULL;
|
||||
_JLOG_PERROR_RES(err, "acap", "Can't create resampler");
|
||||
US_JLOG_PERROR_RES(err, "acap", "Can't create resampler");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@ -128,7 +123,7 @@ us_acap_s *us_acap_init(const char *name, uint pcm_hz) {
|
||||
// OPUS_SET_INBAND_FEC(1), OPUS_SET_PACKET_LOSS_PERC(10): see rtpa.c
|
||||
}
|
||||
|
||||
US_JLOG_INFO("acap", "Pipeline configured on %uHz; capturing ...", acap->pcm_hz);
|
||||
US_JLOG_INFO("acap", "Capture configured on %uHz; capturing ...", acap->pcm_hz);
|
||||
acap->tids_created = true;
|
||||
US_THREAD_CREATE(acap->enc_tid, _encoder_thread, acap);
|
||||
US_THREAD_CREATE(acap->pcm_tid, _pcm_thread, acap);
|
||||
@ -153,7 +148,7 @@ void us_acap_destroy(us_acap_s *acap) {
|
||||
US_RING_DELETE_WITH_ITEMS(acap->enc_ring, us_au_encoded_destroy);
|
||||
US_RING_DELETE_WITH_ITEMS(acap->pcm_ring, us_au_pcm_destroy);
|
||||
if (acap->tids_created) {
|
||||
US_JLOG_INFO("acap", "Pipeline closed");
|
||||
US_JLOG_INFO("acap", "Capture closed");
|
||||
}
|
||||
free(acap);
|
||||
}
|
||||
@ -187,7 +182,7 @@ static void *_pcm_thread(void *v_acap) {
|
||||
while (!atomic_load(&acap->stop)) {
|
||||
const int frames = snd_pcm_readi(acap->dev, in, acap->pcm_frames);
|
||||
if (frames < 0) {
|
||||
_JLOG_PERROR_ALSA(frames, "acap", "Fatal: Can't capture PCM frames");
|
||||
US_JLOG_PERROR_ALSA(frames, "acap", "Fatal: Can't capture PCM frames");
|
||||
break;
|
||||
} else if (frames < (int)acap->pcm_frames) {
|
||||
US_JLOG_ERROR("acap", "Fatal: Too few PCM frames captured");
|
||||
@ -251,7 +246,7 @@ static void *_encoder_thread(void *v_acap) {
|
||||
acap->pts += US_AU_HZ_TO_FRAMES(US_RTP_OPUS_HZ);
|
||||
} else {
|
||||
out->used = 0;
|
||||
_JLOG_PERROR_OPUS(size, "acap", "Fatal: Can't encode PCM frame to OPUS");
|
||||
US_JLOG_PERROR_OPUS(size, "acap", "Fatal: Can't encode PCM frame to OPUS");
|
||||
}
|
||||
us_ring_producer_release(acap->enc_ring, out_ri);
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ static void *_aplay_thread(void *v_client) {
|
||||
out->frames = frames;
|
||||
} else {
|
||||
out->frames = 0;
|
||||
US_JLOG_ERROR("aplay", "Fatal: Can't decode OPUS to PCM frame: %s", opus_strerror(frames));
|
||||
US_JLOG_PERROR_OPUS(frames, "aplay", "Fatal: Can't decode OPUS to PCM frame");
|
||||
}
|
||||
us_ring_producer_release(client->aplay_pcm_ring, out_ri);
|
||||
}
|
||||
|
||||
@ -36,3 +36,8 @@
|
||||
JANUS_LOG(LOG_ERR, "[%s/%-9s] " x_msg ": %s\n", US_PLUGIN_NAME, x_prefix, ##__VA_ARGS__, m_perror_str); \
|
||||
free(m_perror_str); \
|
||||
}
|
||||
|
||||
// We don't include alsa, speex and opus headers here
|
||||
#define US_JLOG_PERROR_ALSA(_err, _prefix, _msg, ...) US_JLOG_ERROR(_prefix, _msg ": %s", ##__VA_ARGS__, snd_strerror(_err))
|
||||
#define US_JLOG_PERROR_RES(_err, _prefix, _msg, ...) US_JLOG_ERROR(_prefix, _msg ": %s", ##__VA_ARGS__, speex_resampler_strerror(_err))
|
||||
#define US_JLOG_PERROR_OPUS(_err, _prefix, _msg, ...) US_JLOG_ERROR(_prefix, _msg ": %s", ##__VA_ARGS__, opus_strerror(_err))
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
@ -292,79 +293,100 @@ static void *_aplay_thread(void *arg) {
|
||||
assert(_g_config->aplay_dev_name != NULL);
|
||||
|
||||
int once = 0;
|
||||
snd_pcm_t *dev = NULL;
|
||||
bool skip = false;
|
||||
|
||||
while (!_STOP) {
|
||||
usleep(US_AU_FRAME_MS * 1000 / 4);
|
||||
snd_pcm_t *dev = NULL;
|
||||
bool skip = true;
|
||||
|
||||
us_au_pcm_s mixed = {0};
|
||||
_LOCK_APLAY;
|
||||
US_LIST_ITERATE(_g_clients, client, {
|
||||
us_au_pcm_s last = {0};
|
||||
do {
|
||||
const int ri = us_ring_consumer_acquire(client->aplay_pcm_ring, 0);
|
||||
if (ri >= 0) {
|
||||
const us_au_pcm_s *pcm = client->aplay_pcm_ring->items[ri];
|
||||
memcpy(&last, pcm, sizeof(us_au_pcm_s));
|
||||
us_ring_consumer_release(client->aplay_pcm_ring, ri);
|
||||
while (!_STOP) {
|
||||
usleep((US_AU_FRAME_MS / 4) * 1000);
|
||||
|
||||
us_au_pcm_s mixed = {0};
|
||||
_LOCK_APLAY;
|
||||
US_LIST_ITERATE(_g_clients, client, {
|
||||
us_au_pcm_s last = {0};
|
||||
do {
|
||||
const int ri = us_ring_consumer_acquire(client->aplay_pcm_ring, 0);
|
||||
if (ri >= 0) {
|
||||
const us_au_pcm_s *pcm = client->aplay_pcm_ring->items[ri];
|
||||
memcpy(&last, pcm, sizeof(us_au_pcm_s));
|
||||
us_ring_consumer_release(client->aplay_pcm_ring, ri);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (skip && !_STOP);
|
||||
us_au_pcm_mix(&mixed, &last);
|
||||
// US_JLOG_INFO("++++++", "mixed %p", client);
|
||||
});
|
||||
_UNLOCK_APLAY;
|
||||
// US_JLOG_INFO("++++++", "--------------");
|
||||
|
||||
if (skip) {
|
||||
static uint skipped = 0;
|
||||
if (skipped < (1000 / (US_AU_FRAME_MS / 4))) {
|
||||
++skipped;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
skipped = 0;
|
||||
}
|
||||
} while (skip && !_STOP);
|
||||
us_au_pcm_mix(&mixed, &last);
|
||||
// US_JLOG_INFO("++++++", "mixed %p", client);
|
||||
});
|
||||
_UNLOCK_APLAY;
|
||||
// US_JLOG_INFO("++++++", "--------------");
|
||||
}
|
||||
|
||||
if (!_HAS_WATCHERS || !_HAS_LISTENERS || !_HAS_SPEAKERS) {
|
||||
skip = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dev == NULL) {
|
||||
int err = snd_pcm_open(&dev, _g_config->aplay_dev_name, SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (err < 0) {
|
||||
US_ONCE({ US_JLOG_ERROR("aplay", "Can't open PCM playback: %s", snd_strerror(err)); });
|
||||
if (!_HAS_WATCHERS || !_HAS_LISTENERS || !_HAS_SPEAKERS) {
|
||||
goto close_aplay;
|
||||
}
|
||||
|
||||
err = snd_pcm_set_params(
|
||||
dev,
|
||||
SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
US_RTP_OPUS_CH, US_RTP_OPUS_HZ,
|
||||
1 /* soft resample */, 50000 /* 50000 = 0.05sec */
|
||||
);
|
||||
if (err < 0) {
|
||||
US_ONCE({ US_JLOG_ERROR("aplay", "Can't configure PCM playback: %s", snd_strerror(err)); });
|
||||
goto close_aplay;
|
||||
if (dev == NULL) {
|
||||
int err = snd_pcm_open(&dev, _g_config->aplay_dev_name, SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (err < 0) {
|
||||
US_ONCE({ US_JLOG_PERROR_ALSA(err, "aplay", "Can't open PCM playback"); });
|
||||
goto close_aplay;
|
||||
}
|
||||
|
||||
err = snd_pcm_set_params(dev, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED,
|
||||
US_RTP_OPUS_CH, US_RTP_OPUS_HZ, 1 /* soft resample */, 50000 /* 50000 = 0.05sec */
|
||||
);
|
||||
if (err < 0) {
|
||||
US_ONCE({ US_JLOG_PERROR_ALSA(err, "aplay", "Can't configure PCM playback"); });
|
||||
goto close_aplay;
|
||||
}
|
||||
|
||||
US_JLOG_INFO("aplay", "Playback opened, playing ...");
|
||||
once = 0;
|
||||
}
|
||||
|
||||
US_JLOG_INFO("aplay", "Playback opened, playing ...");
|
||||
}
|
||||
|
||||
if (dev != NULL && mixed.frames > 0) {
|
||||
snd_pcm_sframes_t frames = snd_pcm_writei(dev, mixed.data, mixed.frames);
|
||||
if (frames < 0) {
|
||||
frames = snd_pcm_recover(dev, frames, 1);
|
||||
} else {
|
||||
skip = false;
|
||||
}
|
||||
if (frames < 0) {
|
||||
US_ONCE({ US_JLOG_ERROR("aplay", "Can't play to PCM: %s", snd_strerror(frames)); });
|
||||
skip = true;
|
||||
} else {
|
||||
skip = false;
|
||||
if (dev != NULL && mixed.frames > 0) {
|
||||
snd_pcm_sframes_t frames = snd_pcm_writei(dev, mixed.data, mixed.frames);
|
||||
if (frames < 0) {
|
||||
frames = snd_pcm_recover(dev, frames, 1);
|
||||
} else {
|
||||
if (once != 0) {
|
||||
US_JLOG_INFO("aplay", "Playing resumed (snd_pcm_writei) ...");
|
||||
}
|
||||
once = 0;
|
||||
skip = false;
|
||||
}
|
||||
if (frames < 0) {
|
||||
US_ONCE({ US_JLOG_PERROR_ALSA(frames, "aplay", "Can't play to PCM playback"); });
|
||||
if (frames == -ENODEV) {
|
||||
goto close_aplay;
|
||||
}
|
||||
skip = true;
|
||||
} else {
|
||||
if (once != 0) {
|
||||
US_JLOG_INFO("aplay", "Playing resumed (snd_pcm_recover) ...");
|
||||
}
|
||||
once = 0;
|
||||
skip = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
close_aplay:
|
||||
US_DELETE(dev, snd_pcm_close);
|
||||
if (dev != NULL) {
|
||||
US_DELETE(dev, snd_pcm_close);
|
||||
US_JLOG_INFO("aplay", "Playback closed");
|
||||
}
|
||||
}
|
||||
|
||||
US_DELETE(dev, snd_pcm_close);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -374,6 +396,14 @@ static void _relay_rtp_clients(const us_rtp_s *rtp) {
|
||||
});
|
||||
}
|
||||
|
||||
static void _alsa_quiet(const char *file, int line, const char *func, int err, const char *fmt, ...) {
|
||||
(void)file;
|
||||
(void)line;
|
||||
(void)func;
|
||||
(void)err;
|
||||
(void)fmt;
|
||||
}
|
||||
|
||||
static int _plugin_init(janus_callbacks *gw, const char *config_dir_path) {
|
||||
// https://groups.google.com/g/meetecho-janus/c/xoWIQfaoJm8
|
||||
// sysctl -w net.core.rmem_default=500000
|
||||
@ -387,6 +417,8 @@ static int _plugin_init(janus_callbacks *gw, const char *config_dir_path) {
|
||||
}
|
||||
_g_gw = gw;
|
||||
|
||||
snd_lib_error_set_handler(_alsa_quiet);
|
||||
|
||||
US_RING_INIT_WITH_ITEMS(_g_video_ring, 64, us_frame_init);
|
||||
_g_rtpv = us_rtpv_init(_relay_rtp_clients);
|
||||
if (_g_config->acap_dev_name != NULL && us_acap_probe(_g_config->acap_dev_name)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user