This source file includes following definitions.
- sdl_close_audio
- sdl_fill_audio
- SDLAud_Setup
- SDLAud_Shutdown
- SDL_DeleteAudio
- SDLAud_ConfigureOutput
- SDLAud_GetAudioDelay
- SDLAud_GetTotalBufferTime
- SDLAud_SetVolume
- SDLAud_SetPan
- SDLAud_Play
- SDLAud_SetPriority
- SDLAud_QueryOutputSampleRate
- SDL_NewAudio
#include "sdl_out.h"
#define SDLAUD() SDLAudCtx *ctx = (SDLAudCtx *)dr->opaque
static void sdl_close_audio() {
SDL_CloseAudio();
}
void sdl_fill_audio(void *udata, Uint8 *stream, int len)
{
GF_AudioOutput *dr = (GF_AudioOutput *)udata;
SDLAUD();
if (ctx->volume != SDL_MIX_MAXVOLUME) {
u32 written;
if (ctx->alloc_size < (u32) len) {
ctx->audioBuff = (Uint8*)gf_realloc( ctx->audioBuff, sizeof(Uint8) * len);
ctx->alloc_size = len;
}
memset(stream, 0, len);
written = dr->FillBuffer(dr->audio_renderer, (char *) ctx->audioBuff, (u32) len);
if (written)
SDL_MixAudio(stream, ctx->audioBuff, len, ctx->volume);
} else {
dr->FillBuffer(dr->audio_renderer, (char *) stream, (u32) len);
}
}
static GF_Err SDLAud_Setup(GF_AudioOutput *dr, void *os_handle, u32 num_buffers, u32 total_duration)
{
u32 flags;
SDL_AudioSpec want_format, got_format;
SDLAUD();
if (!SDLOUT_InitSDL()) return GF_IO_ERR;
flags = SDL_WasInit(SDL_INIT_AUDIO);
if (!(flags & SDL_INIT_AUDIO)) {
if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[SDL] Audio output initialization error\n"));
SDLOUT_CloseSDL();
return GF_IO_ERR;
}
}
memset(&want_format, 0, sizeof(SDL_AudioSpec));
want_format.freq = 44100;
want_format.format = AUDIO_S16SYS;
want_format.channels = 2;
want_format.samples = 1024;
want_format.callback = sdl_fill_audio;
want_format.userdata = dr;
if ( SDL_OpenAudio(&want_format, &got_format) < 0 ) {
sdl_close_audio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
SDLOUT_CloseSDL();
GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[SDL] Audio output format not supported\n"));
return GF_IO_ERR;
}
sdl_close_audio();
ctx->is_init = GF_TRUE;
ctx->num_buffers = num_buffers;
ctx->total_duration = total_duration;
GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[SDL] Audio output setup\n"));
return GF_OK;
}
static void SDLAud_Shutdown(GF_AudioOutput *dr)
{
SDLAUD();
sdl_close_audio();
if (ctx->is_init) {
SDL_QuitSubSystem(SDL_INIT_AUDIO);
SDLOUT_CloseSDL();
ctx->is_init = GF_FALSE;
}
}
void SDL_DeleteAudio(void *ifce) {
SDLAudCtx *ctx;
GF_AudioOutput * dr;
if (!ifce)
return;
dr = ( GF_AudioOutput *) ifce;
ctx = (SDLAudCtx *)dr->opaque;
if (!ctx)
return;
if (ctx->audioBuff)
gf_free(ctx->audioBuff);
ctx->audioBuff = NULL;
gf_free( ctx );
dr->opaque = NULL;
gf_free( dr );
}
static GF_Err SDLAud_ConfigureOutput(GF_AudioOutput *dr, u32 *SampleRate, u32 *NbChannels, u32 *nbBitsPerSample, u32 channel_cfg)
{
s32 nb_samples;
SDL_AudioSpec want_format, got_format;
SDLAUD();
sdl_close_audio();
ctx->is_running = GF_FALSE;
memset(&want_format, 0, sizeof(SDL_AudioSpec));
want_format.freq = *SampleRate;
want_format.format = (*nbBitsPerSample==16) ? AUDIO_S16SYS : AUDIO_S8;
want_format.channels = *NbChannels;
want_format.callback = sdl_fill_audio;
want_format.userdata = dr;
if (ctx->num_buffers && ctx->total_duration) {
nb_samples = want_format.freq * ctx->total_duration;
nb_samples /= (1000 * ctx->num_buffers);
if (nb_samples % 2) nb_samples++;
} else {
nb_samples = 1024;
}
want_format.samples = 1;
while (want_format.samples*2<nb_samples) want_format.samples *= 2;
if ( SDL_OpenAudio(&want_format, &got_format) < 0 ) return GF_IO_ERR;
ctx->is_running = GF_TRUE;
ctx->delay_ms = (got_format.samples * 1000) / got_format.freq;
ctx->total_size = got_format.samples;
*SampleRate = got_format.freq;
*NbChannels = got_format.channels;
switch (got_format.format) {
case AUDIO_S8:
case AUDIO_U8:
*nbBitsPerSample = 8;
break;
default:
*nbBitsPerSample = 16;
break;
}
SDL_PauseAudio(0);
GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[SDL] Audio output setup - SampleRate %d Nb Channels %d - %d ms delay\n", got_format.freq, got_format.channels, ctx->delay_ms));
return GF_OK;
}
static u32 SDLAud_GetAudioDelay(GF_AudioOutput *dr)
{
SDLAUD();
return ctx->delay_ms;
}
static u32 SDLAud_GetTotalBufferTime(GF_AudioOutput *dr)
{
SDLAUD();
return ctx->delay_ms;
}
static void SDLAud_SetVolume(GF_AudioOutput *dr, u32 Volume)
{
SDLAUD();
if (Volume == 100)
ctx->volume = SDL_MIX_MAXVOLUME;
else
ctx->volume = Volume * SDL_MIX_MAXVOLUME / 100;
}
static void SDLAud_SetPan(GF_AudioOutput *dr, u32 pan)
{
}
static void SDLAud_Play(GF_AudioOutput *dr, u32 PlayType)
{
SDL_PauseAudio(PlayType ? 0 : 1);
}
static void SDLAud_SetPriority(GF_AudioOutput *dr, u32 priority)
{
}
static GF_Err SDLAud_QueryOutputSampleRate(GF_AudioOutput *dr, u32 *desired_samplerate, u32 *NbChannels, u32 *nbBitsPerSample)
{
return GF_OK;
}
void *SDL_NewAudio()
{
SDLAudCtx *ctx;
GF_AudioOutput *dr;
ctx = (SDLAudCtx*)gf_malloc(sizeof(SDLAudCtx));
memset(ctx, 0, sizeof(SDLAudCtx));
dr = (GF_AudioOutput*)gf_malloc(sizeof(GF_AudioOutput));
memset(dr, 0, sizeof(GF_AudioOutput));
GF_REGISTER_MODULE_INTERFACE(dr, GF_AUDIO_OUTPUT_INTERFACE, "SDL Audio Output", "gpac distribution");
dr->opaque = ctx;
dr->Setup = SDLAud_Setup;
dr->Shutdown = SDLAud_Shutdown;
dr->ConfigureOutput = SDLAud_ConfigureOutput;
dr->SetVolume = SDLAud_SetVolume;
dr->SetPan = SDLAud_SetPan;
dr->Play = SDLAud_Play;
dr->SetPriority = SDLAud_SetPriority;
dr->GetAudioDelay = SDLAud_GetAudioDelay;
dr->GetTotalBufferTime = SDLAud_GetTotalBufferTime;
dr->QueryOutputSampleRate = SDLAud_QueryOutputSampleRate;
dr->SelfThreaded = GF_TRUE;
ctx->audioBuff = NULL;
ctx->volume = SDL_MIX_MAXVOLUME;
return dr;
}