diff --git a/src/audio/alsa.c b/src/audio/alsa.c index 89a593c..d95bb3d 100644 --- a/src/audio/alsa.c +++ b/src/audio/alsa.c @@ -29,7 +29,8 @@ static snd_pcm_t *handle; static OpusMSDecoder* decoder; -static short pcmBuffer[FRAME_SIZE * AUDIO_CONFIGURATION_MAX_CHANNEL_COUNT]; +static short* pcmBuffer; +static int samplesPerFrame; static int alsa_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig, void* context, int arFlags) { int rc; @@ -47,11 +48,16 @@ static int alsa_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGUR alsaMapping[5] = opusConfig->mapping[3]; } + samplesPerFrame = opusConfig->samplesPerFrame; + pcmBuffer = malloc(sizeof(short) * opusConfig->channelCount * samplesPerFrame); + if (pcmBuffer == NULL) + return -1; + decoder = opus_multistream_decoder_create(opusConfig->sampleRate, opusConfig->channelCount, opusConfig->streams, opusConfig->coupledStreams, alsaMapping, &rc); snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; - snd_pcm_uframes_t period_size = FRAME_SIZE * FRAME_BUFFER; + snd_pcm_uframes_t period_size = samplesPerFrame * FRAME_BUFFER; snd_pcm_uframes_t buffer_size = 2 * period_size; unsigned int sampleRate = opusConfig->sampleRate; @@ -88,17 +94,25 @@ static int alsa_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGUR } static void alsa_renderer_cleanup() { - if (decoder != NULL) + if (decoder != NULL) { opus_multistream_decoder_destroy(decoder); + decoder = NULL; + } if (handle != NULL) { snd_pcm_drain(handle); snd_pcm_close(handle); + handle = NULL; + } + + if (pcmBuffer != NULL) { + free(pcmBuffer); + pcmBuffer = NULL; } } static void alsa_renderer_decode_and_play_sample(char* data, int length) { - int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0); + int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, samplesPerFrame, 0); if (decodeLen > 0) { int rc = snd_pcm_writei(handle, pcmBuffer, decodeLen); if (rc == -EPIPE) @@ -117,5 +131,5 @@ AUDIO_RENDERER_CALLBACKS audio_callbacks_alsa = { .init = alsa_renderer_init, .cleanup = alsa_renderer_cleanup, .decodeAndPlaySample = alsa_renderer_decode_and_play_sample, - .capabilities = CAPABILITY_DIRECT_SUBMIT, + .capabilities = CAPABILITY_DIRECT_SUBMIT | CAPABILITY_SUPPORTS_ARBITRARY_AUDIO_DURATION, }; diff --git a/src/audio/audio.h b/src/audio/audio.h index 470c307..fe1fbfa 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -21,7 +21,6 @@ #include -#define FRAME_SIZE 240 #define FRAME_BUFFER 12 #ifdef HAVE_ALSA diff --git a/src/audio/omx.c b/src/audio/omx.c index 21cec30..65deaad 100644 --- a/src/audio/omx.c +++ b/src/audio/omx.c @@ -29,8 +29,9 @@ static OpusMSDecoder* decoder; ILCLIENT_T* handle; COMPONENT_T* component; static OMX_BUFFERHEADERTYPE *buf; -static short pcmBuffer[FRAME_SIZE * AUDIO_CONFIGURATION_MAX_CHANNEL_COUNT]; +static short* pcmBuffer; static int channelCount; +static int samplesPerFrame; static int omx_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig, void* context, int arFlags) { int rc, error; @@ -39,6 +40,11 @@ static int omx_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURA char* componentName = "audio_render"; channelCount = opusConfig->channelCount; + samplesPerFrame = opusConfig->samplesPerFrame; + pcmBuffer = malloc(sizeof(short) * channelCount * samplesPerFrame); + if (pcmBuffer == NULL) + return -1; + /* The supplied mapping array has order: FL-FR-C-LFE-RL-RR-SL-SR * OMX expects the order: FL-FR-LFE-C-RL-RR-SL-SR * We need copy the mapping locally and swap the channels around. @@ -155,8 +161,10 @@ static int omx_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURA } static void omx_renderer_cleanup() { - if (decoder != NULL) + if (decoder != NULL) { opus_multistream_decoder_destroy(decoder); + decoder = NULL; + } if (handle != NULL) { if((buf = ilclient_get_input_buffer(component, 100, 1)) == NULL){ fprintf(stderr, "Can't get audio buffer\n"); @@ -174,11 +182,16 @@ static void omx_renderer_cleanup() { ilclient_disable_port_buffers(component, 100, NULL, NULL, NULL); ilclient_change_component_state(component, OMX_StateIdle); ilclient_change_component_state(component, OMX_StateLoaded); + handle = NULL; + } + if (pcmBuffer != NULL) { + free(pcmBuffer); + pcmBuffer = NULL; } } static void omx_renderer_decode_and_play_sample(char* data, int length) { - int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0); + int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, samplesPerFrame, 0); if (decodeLen > 0) { buf = ilclient_get_input_buffer(component, 100, 1); buf->nOffset = 0; @@ -199,5 +212,5 @@ AUDIO_RENDERER_CALLBACKS audio_callbacks_omx = { .init = omx_renderer_init, .cleanup = omx_renderer_cleanup, .decodeAndPlaySample = omx_renderer_decode_and_play_sample, - .capabilities = CAPABILITY_DIRECT_SUBMIT, + .capabilities = CAPABILITY_DIRECT_SUBMIT | CAPABILITY_SUPPORTS_ARBITRARY_AUDIO_DURATION, }; diff --git a/src/audio/pulse.c b/src/audio/pulse.c index c10c57b..596cde2 100644 --- a/src/audio/pulse.c +++ b/src/audio/pulse.c @@ -29,7 +29,8 @@ static OpusMSDecoder* decoder; static pa_simple *dev = NULL; -static short pcmBuffer[FRAME_SIZE * AUDIO_CONFIGURATION_MAX_CHANNEL_COUNT]; +static short* pcmBuffer; +static int samplesPerFrame; static int channelCount; bool audio_pulse_init(char* audio_device) { @@ -53,6 +54,10 @@ static int pulse_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGU unsigned char alsaMapping[AUDIO_CONFIGURATION_MAX_CHANNEL_COUNT]; channelCount = opusConfig->channelCount; + samplesPerFrame = opusConfig->samplesPerFrame; + pcmBuffer = malloc(sizeof(short) * channelCount * samplesPerFrame); + if (pcmBuffer == NULL) + return -1; /* The supplied mapping array has order: FL-FR-C-LFE-RL-RR-SL-SR * ALSA expects the order: FL-FR-RL-RR-C-LFE-SL-SR @@ -86,7 +91,7 @@ static int pulse_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGU } static void pulse_renderer_decode_and_play_sample(char* data, int length) { - int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0); + int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, samplesPerFrame, 0); if (decodeLen > 0) { int error; int rc = pa_simple_write(dev, pcmBuffer, decodeLen * sizeof(short) * channelCount, &error); @@ -99,12 +104,23 @@ static void pulse_renderer_decode_and_play_sample(char* data, int length) { } static void pulse_renderer_cleanup() { - pa_simple_free(dev); + if (decoder != NULL) { + opus_multistream_decoder_destroy(decoder); + decoder = NULL; + } + if (dev != NULL) { + pa_simple_free(dev); + dev = NULL; + } + if (pcmBuffer != NULL) { + free(pcmBuffer); + pcmBuffer = NULL; + } } AUDIO_RENDERER_CALLBACKS audio_callbacks_pulse = { .init = pulse_renderer_init, .cleanup = pulse_renderer_cleanup, .decodeAndPlaySample = pulse_renderer_decode_and_play_sample, - .capabilities = CAPABILITY_DIRECT_SUBMIT, + .capabilities = CAPABILITY_DIRECT_SUBMIT | CAPABILITY_SUPPORTS_ARBITRARY_AUDIO_DURATION, }; diff --git a/src/audio/sdl.c b/src/audio/sdl.c index 34633ea..96a30cd 100644 --- a/src/audio/sdl.c +++ b/src/audio/sdl.c @@ -26,7 +26,8 @@ #include static OpusMSDecoder* decoder; -static short pcmBuffer[FRAME_SIZE * AUDIO_CONFIGURATION_MAX_CHANNEL_COUNT]; +static short* pcmBuffer; +static int samplesPerFrame; static SDL_AudioDeviceID dev; static int channelCount; @@ -35,6 +36,10 @@ static int sdl_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURA decoder = opus_multistream_decoder_create(opusConfig->sampleRate, opusConfig->channelCount, opusConfig->streams, opusConfig->coupledStreams, opusConfig->mapping, &rc); channelCount = opusConfig->channelCount; + samplesPerFrame = opusConfig->samplesPerFrame; + pcmBuffer = malloc(sizeof(short) * channelCount * samplesPerFrame); + if (pcmBuffer == NULL) + return -1; SDL_InitSubSystem(SDL_INIT_AUDIO); @@ -45,13 +50,11 @@ static int sdl_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURA want.channels = opusConfig->channelCount; want.samples = 4096; - dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FORMAT_CHANGE); + dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0); if (dev == 0) { printf("Failed to open audio: %s\n", SDL_GetError()); return -1; } else { - if (have.format != want.format) // we let this one thing change. - printf("We didn't get requested audio format.\n"); SDL_PauseAudioDevice(dev, 0); // start audio playing. } @@ -59,14 +62,24 @@ static int sdl_renderer_init(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURA } static void sdl_renderer_cleanup() { - if (decoder != NULL) + if (decoder != NULL) { opus_multistream_decoder_destroy(decoder); + decoder = NULL; + } - SDL_CloseAudioDevice(dev); + if (pcmBuffer != NULL) { + free(pcmBuffer); + pcmBuffer = NULL; + } + + if (dev != 0) { + SDL_CloseAudioDevice(dev); + dev = 0; + } } static void sdl_renderer_decode_and_play_sample(char* data, int length) { - int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, FRAME_SIZE, 0); + int decodeLen = opus_multistream_decode(decoder, data, length, pcmBuffer, samplesPerFrame, 0); if (decodeLen > 0) { SDL_QueueAudio(dev, pcmBuffer, decodeLen * channelCount * sizeof(short)); } else { @@ -78,5 +91,5 @@ AUDIO_RENDERER_CALLBACKS audio_callbacks_sdl = { .init = sdl_renderer_init, .cleanup = sdl_renderer_cleanup, .decodeAndPlaySample = sdl_renderer_decode_and_play_sample, - .capabilities = CAPABILITY_DIRECT_SUBMIT, + .capabilities = CAPABILITY_DIRECT_SUBMIT | CAPABILITY_SUPPORTS_ARBITRARY_AUDIO_DURATION, };