Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add audio streaming support for generic PCM devices. #209

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions janus/src/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ bool us_audio_probe(const char *name) {
return true;
}

us_audio_s *us_audio_init(const char *name, unsigned pcm_hz) {
us_audio_s *us_audio_init(const char *name, unsigned pcm_hz, unsigned pcm_channels) {
us_audio_s *audio;
US_CALLOC(audio, 1);
audio->pcm_hz = pcm_hz;
Expand All @@ -95,7 +95,7 @@ us_audio_s *us_audio_init(const char *name, unsigned pcm_hz) {

SET_PARAM("Can't initialize PCM params", snd_pcm_hw_params_any);
SET_PARAM("Can't set PCM access type", snd_pcm_hw_params_set_access, SND_PCM_ACCESS_RW_INTERLEAVED);
SET_PARAM("Can't set PCM channels numbre", snd_pcm_hw_params_set_channels, 2);
SET_PARAM("Can't set PCM channels numbre", snd_pcm_hw_params_set_channels, pcm_channels);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also fix numbre -> number?

SET_PARAM("Can't set PCM sampling format", snd_pcm_hw_params_set_format, SND_PCM_FORMAT_S16_LE);
SET_PARAM("Can't set PCM sampling rate", snd_pcm_hw_params_set_rate_near, &audio->pcm_hz, 0);
if (audio->pcm_hz < _MIN_PCM_HZ || audio->pcm_hz > _MAX_PCM_HZ) {
Expand All @@ -111,7 +111,7 @@ us_audio_s *us_audio_init(const char *name, unsigned pcm_hz) {
}

if (audio->pcm_hz != _ENCODER_INPUT_HZ) {
audio->res = speex_resampler_init(2, audio->pcm_hz, _ENCODER_INPUT_HZ, SPEEX_RESAMPLER_QUALITY_DESKTOP, &err);
audio->res = speex_resampler_init(pcm_channels, audio->pcm_hz, _ENCODER_INPUT_HZ, SPEEX_RESAMPLER_QUALITY_DESKTOP, &err);
if (err < 0) {
audio->res = NULL;
_JLOG_PERROR_RES(err, "audio", "Can't create resampler");
Expand All @@ -121,7 +121,7 @@ us_audio_s *us_audio_init(const char *name, unsigned pcm_hz) {

{
// OPUS_APPLICATION_VOIP, OPUS_APPLICATION_RESTRICTED_LOWDELAY
audio->enc = opus_encoder_create(_ENCODER_INPUT_HZ, 2, OPUS_APPLICATION_AUDIO, &err);
audio->enc = opus_encoder_create(_ENCODER_INPUT_HZ, pcm_channels, OPUS_APPLICATION_AUDIO, &err);
assert(err == 0);
assert(!opus_encoder_ctl(audio->enc, OPUS_SET_BITRATE(48000)));
assert(!opus_encoder_ctl(audio->enc, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)));
Expand Down
2 changes: 1 addition & 1 deletion janus/src/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ typedef struct {

bool us_audio_probe(const char *name);

us_audio_s *us_audio_init(const char *name, unsigned pcm_hz);
us_audio_s *us_audio_init(const char *name, unsigned pcm_hz, unsigned pcm_channels);
void us_audio_destroy(us_audio_s *audio);

int us_audio_get_encoded(us_audio_s *audio, uint8_t *data, size_t *size, uint64_t *pts);
17 changes: 15 additions & 2 deletions janus/src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,21 @@ us_config_s *us_config_init(const char *config_dir_path) {
}
if ((config->audio_dev_name = _get_value(jcfg, "audio", "device")) != NULL) {
if ((config->tc358743_dev_path = _get_value(jcfg, "audio", "tc358743")) == NULL) {
US_JLOG_INFO("config", "Missing config value: audio.tc358743");
goto error;
if((config->pcm_path = _get_value(jcfg, "audio", "pcm_path")) == NULL) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use just "pcm" for the config option name: config->pcm_path = _get_value(jcfg, "audio", "pcm")

Also the space required after if.

US_JLOG_INFO("config", "Missing config value: audio.tc358743 OR audio.pcm_path");
goto error;
}
else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use } else { on the same line

if ((config->pcm_sampling_rate = _get_value(jcfg, "audio", "pcm_sampling_rate")) == NULL) {
config->pcm_sampling_rate = "44100";
}
US_JLOG_INFO("config", "PCM sample rate set to %sHz", config->pcm_sampling_rate);

if ((config->pcm_channels = _get_value(jcfg, "audio", "pcm_channels")) == NULL) {
config->pcm_channels = "1";
}
US_JLOG_INFO("config", "Number of PCM channels set to %s", config->pcm_channels);
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions janus/src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ typedef struct {

char *audio_dev_name;
char *tc358743_dev_path;
char *pcm_path;
char *pcm_sampling_rate;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why char *

char *pcm_channels;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

} us_config_s;


Expand Down
99 changes: 72 additions & 27 deletions janus/src/plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ static void *_audio_thread(UNUSED void *arg) {
US_THREAD_RENAME("us_audio");
atomic_store(&_g_audio_tid_created, true);
assert(_g_config->audio_dev_name != NULL);
assert(_g_config->tc358743_dev_path != NULL);
assert(_g_config->tc358743_dev_path != NULL || _g_config->pcm_path != NULL);

int once = 0;

Expand All @@ -194,40 +194,85 @@ static void *_audio_thread(UNUSED void *arg) {
us_tc358743_info_s info = {0};
us_audio_s *audio = NULL;

if (us_tc358743_read_info(_g_config->tc358743_dev_path, &info) < 0) {
goto close_audio;
}
if (!info.has_audio) {
US_ONCE({ US_JLOG_INFO("audio", "No audio presented from the host"); });
goto close_audio;
}
US_ONCE({ US_JLOG_INFO("audio", "Detected host audio"); });
if ((audio = us_audio_init(_g_config->audio_dev_name, info.audio_hz)) == NULL) {
goto close_audio;
if(_g_config->pcm_path == NULL) {
if (us_tc358743_read_info(_g_config->tc358743_dev_path, &info) < 0) {
goto close_audio;
}
if (!info.has_audio) {
US_ONCE({ US_JLOG_INFO("audio", "No audio presented from the host"); });
goto close_audio;
}
US_ONCE({ US_JLOG_INFO("audio", "Detected host audio"); });
if ((audio = us_audio_init(_g_config->audio_dev_name, info.audio_hz, 2)) == NULL) {
goto close_audio;
}

once = 0;

while (!_STOP && _HAS_WATCHERS && _HAS_LISTENERS) {
if (
us_tc358743_read_info(_g_config->tc358743_dev_path, &info) < 0
|| !info.has_audio
|| audio->pcm_hz != info.audio_hz
) {
goto close_audio;
}

size_t size = US_RTP_DATAGRAM_SIZE - US_RTP_HEADER_SIZE;
uint8_t data[size];
uint64_t pts;
const int result = us_audio_get_encoded(audio, data, &size, &pts);
if (result == 0) {
_LOCK_AUDIO;
us_rtpa_wrap(_g_rtpa, data, size, pts);
_UNLOCK_AUDIO;
} else if (result == -1) {
goto close_audio;
}
}
}
else {
int fd = -1;
int audio_hz = -1;
int audio_channels = -1;
if (( fd = open(_g_config->pcm_path, O_RDWR) < 0 )) {
US_ONCE({ US_JLOG_INFO("audio", "Invalid PCM Path."); });
goto close_audio;
}

once = 0;
if (_g_config->pcm_sampling_rate == NULL) {
US_ONCE({ US_JLOG_INFO("audio", "Invalid PCM sampling rate."); });
goto close_audio;
} else if ((audio_hz = atoi(_g_config->pcm_sampling_rate)) <= 0) {
US_ONCE({ US_JLOG_INFO("audio", "Invalid PCM sampling rate."); });
goto close_audio;
}

while (!_STOP && _HAS_WATCHERS && _HAS_LISTENERS) {
if (
us_tc358743_read_info(_g_config->tc358743_dev_path, &info) < 0
|| !info.has_audio
|| audio->pcm_hz != info.audio_hz
) {
if (_g_config->pcm_channels == NULL) {
US_ONCE({ US_JLOG_INFO("audio", "Invalid number of PCM channels."); });
goto close_audio;
} else if ((audio_channels = atoi(_g_config->pcm_channels)) <= 0) {
US_ONCE({ US_JLOG_INFO("audio", "Invalid number of PCM channels (atoi)."); });
goto close_audio;
}

size_t size = US_RTP_DATAGRAM_SIZE - US_RTP_HEADER_SIZE;
uint8_t data[size];
uint64_t pts;
const int result = us_audio_get_encoded(audio, data, &size, &pts);
if (result == 0) {
_LOCK_AUDIO;
us_rtpa_wrap(_g_rtpa, data, size, pts);
_UNLOCK_AUDIO;
} else if (result == -1) {
if ((audio = us_audio_init(_g_config->audio_dev_name, (unsigned int)audio_hz, (unsigned int)audio_channels)) == NULL) {
US_ONCE({ US_JLOG_INFO("audio", "Couldn't initialize PCM audio."); });
goto close_audio;
}
while (!_STOP && _HAS_WATCHERS && _HAS_LISTENERS) {
size_t size = US_RTP_DATAGRAM_SIZE - US_RTP_HEADER_SIZE;
uint8_t data[size];
uint64_t pts;
const int result = us_audio_get_encoded(audio, data, &size, &pts);
if (result == 0) {
_LOCK_AUDIO;
us_rtpa_wrap(_g_rtpa, data, size, pts);
_UNLOCK_AUDIO;
} else if (result == -1) {
goto close_audio;
}
}
}

close_audio:
Expand Down