Commit a4339167 authored by Jean-Paul Saman's avatar Jean-Paul Saman

audio_output/amem.c: multiple buffers

Support multiple buffers appended after the shared header. Each buffer has
a small header that keeps the number of buffers in the samples buffer.
parent 2778fd64
...@@ -93,24 +93,32 @@ static const int format_int[] = { VLC_CODEC_U8, ...@@ -93,24 +93,32 @@ static const int format_int[] = { VLC_CODEC_U8,
/* Shared memory header structure */ /* Shared memory header structure */
typedef struct typedef struct
{ {
vlc_sem_t sem; /* handle to semaphore */ unsigned int i_nb_samples; /* number of samples in buffer */
void *samples; /* samples buffer */
} amem_buffer_t;
typedef struct
{
vlc_sem_t sem; /* handle to semaphore */
#if defined(_WIN32_WINNT) || defined(WIN32) #if defined(_WIN32_WINNT) || defined(WIN32)
WAVEFORMATEX wave; WAVEFORMATEX wave;
#else #else
vlc_fourcc_t i_format; vlc_fourcc_t i_format;
unsigned int i_rate; unsigned int i_rate;
unsigned int i_bytes_per_frame; unsigned int i_bytes_per_frame;
unsigned int i_frame_length; unsigned int i_frame_length;
unsigned i_bitspersample; unsigned i_bitspersample;
unsigned i_blockalign; unsigned i_blockalign;
uint8_t i_channels; unsigned i_channels;
#endif #endif
unsigned int i_read_samples; /* total samples read */ unsigned int i_max_samples; /* maximum samples per buffer */
unsigned int i_write_samples; /* total samples written */ unsigned int i_read_samples; /* total samples read */
unsigned int i_max_samples; /* maximum samples in buffer */ unsigned int i_write_samples; /* total samples written */
unsigned int i_nb_samples; /* number of samples in buffer */ /* if i_buf_write == i_buffers, then it will wrap around */
void *samples; /* buffer of samples */ unsigned int i_read; /* buffer being read */
unsigned int i_write; /* buffer being written */
unsigned int i_buffers; /* number of sample buffers used */
} amem_shared_t; } amem_shared_t;
/* Private structure */ /* Private structure */
...@@ -134,7 +142,7 @@ static int Open (vlc_object_t *); ...@@ -134,7 +142,7 @@ static int Open (vlc_object_t *);
static void Close(vlc_object_t *); static void Close(vlc_object_t *);
static void Play (aout_instance_t *); static void Play (aout_instance_t *);
static int SetupSharedMem(aout_instance_t *); static int SetupSharedMem(aout_instance_t *, unsigned int);
static void ExitSharedMem(aout_instance_t *); static void ExitSharedMem(aout_instance_t *);
/* /*
...@@ -216,7 +224,18 @@ static void amem_sem_destroy(vlc_sem_t *sem) ...@@ -216,7 +224,18 @@ static void amem_sem_destroy(vlc_sem_t *sem)
#endif #endif
} }
static int amem_shmem_create(aout_instance_t *aout, ssize_t len) static amem_buffer_t *amem_buffer_get(aout_instance_t *aout, unsigned int index)
{
aout_sys_t *sys = (aout_sys_t *)aout->output.p_sys;
amem_buffer_t *buffer = NULL;
size_t buflen = sizeof(amem_buffer_t) + aout->output.i_nb_samples * aout->output.output.i_bitspersample;
buffer = (amem_buffer_t *)((uint8_t*)sys->header + sizeof(amem_shared_t) + index * buflen);
buffer->samples = ((uint8_t *)buffer + sizeof(amem_buffer_t));
return buffer;
}
static int amem_shmem_create(aout_instance_t *aout, unsigned int i_buffers, ssize_t len)
{ {
aout_sys_t *sys = (aout_sys_t *)aout->output.p_sys; aout_sys_t *sys = (aout_sys_t *)aout->output.p_sys;
...@@ -273,7 +292,17 @@ static int amem_shmem_create(aout_instance_t *aout, ssize_t len) ...@@ -273,7 +292,17 @@ static int amem_shmem_create(aout_instance_t *aout, ssize_t len)
} }
#endif #endif
sys->header->samples = sys->header + sizeof(amem_shared_t); /* setup pointers in shared structures */
sys->header->i_buffers = i_buffers;
for (unsigned int i = 0; i < sys->header->i_buffers; i++)
{
amem_buffer_t *buffer = amem_buffer_get(aout, i);
if (buffer)
{
buffer->i_nb_samples = 0;
memset(buffer->samples, 0, (sys->header->i_max_samples * sys->header->i_bitspersample));
}
}
/* initialize unamed semaphore */ /* initialize unamed semaphore */
amem_sem_init(&sys->header->sem, 1); amem_sem_init(&sys->header->sem, 1);
...@@ -282,7 +311,7 @@ static int amem_shmem_create(aout_instance_t *aout, ssize_t len) ...@@ -282,7 +311,7 @@ static int amem_shmem_create(aout_instance_t *aout, ssize_t len)
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int amem_shmem_open(aout_instance_t *aout, ssize_t len) static int amem_shmem_open(aout_instance_t *aout, unsigned int i_buffers, ssize_t len)
{ {
aout_sys_t *sys = (aout_sys_t *)aout->output.p_sys; aout_sys_t *sys = (aout_sys_t *)aout->output.p_sys;
...@@ -333,7 +362,15 @@ static int amem_shmem_open(aout_instance_t *aout, ssize_t len) ...@@ -333,7 +362,15 @@ static int amem_shmem_open(aout_instance_t *aout, ssize_t len)
return VLC_EGENERIC; return VLC_EGENERIC;
} }
#endif #endif
sys->header->samples = sys->header + sizeof(amem_shared_t);
/* setup pointers in shared structures */
sys->header->i_buffers = i_buffers;
for (unsigned int i = 0; i < sys->header->i_buffers; i++)
{
amem_buffer_t *buffer = amem_buffer_get(aout, i);
if (buffer)
buffer->i_nb_samples = 0;
}
msg_Dbg(aout, "shared memory opened"); msg_Dbg(aout, "shared memory opened");
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -353,8 +390,8 @@ static void amem_shmem_close(aout_instance_t *aout) ...@@ -353,8 +390,8 @@ static void amem_shmem_close(aout_instance_t *aout)
/* Determine shared memory size */ /* Determine shared memory size */
if (sys->header != MAP_FAILED) if (sys->header != MAP_FAILED)
{ {
ssize_t len = sizeof(amem_shared_t) + aout->output.i_nb_samples ssize_t len = sizeof(amem_shared_t) + sys->header->i_buffers * (sizeof(amem_buffer_t)
* aout->output.output.i_bitspersample; + aout->output.i_nb_samples * aout->output.output.i_bitspersample);
if (munmap(sys->header, len) < 0) if (munmap(sys->header, len) < 0)
{ {
msg_Err(aout, "failed unmapping shared memory (%m)"); msg_Err(aout, "failed unmapping shared memory (%m)");
...@@ -379,13 +416,13 @@ static void amem_shmem_header(aout_instance_t *aout) ...@@ -379,13 +416,13 @@ static void amem_shmem_header(aout_instance_t *aout)
#if defined(_WIN32_WINNT) || defined(WIN32) #if defined(_WIN32_WINNT) || defined(WIN32)
uint16_t tag = 0; uint16_t tag = 0;
fourcc_to_wf_tag(aout->output.output.i_format, &tag); fourcc_to_wf_tag(aout->output.output.i_format, &tag);
sys->header->wave.wFormatTag = tag; header->wave.wFormatTag = tag;
sys->header->wave.nChannels = aout->output.output.i_channels; header->wave.nChannels = aout->output.output.i_channels;
sys->header->wave.nSamplesPerSec = aout->output.output.i_rate * aout->output.i_nb_samples; header->wave.nSamplesPerSec = aout->output.output.i_rate * aout->output.i_nb_samples;
//sys->header->wave.nAvgBytesPerSec = ; //header->wave.nAvgBytesPerSec = ;
sys->header->wave.nBlockAlign = aout->output.output.i_blockalign; header->wave.nBlockAlign = aout->output.output.i_blockalign;
sys->header->wave.wBitsPerSample = aout->output.output.i_bitspersample; header->wave.wBitsPerSample = aout->output.output.i_bitspersample;
sys->header->wave.cbSize = 0; /* No additional format metadata */ header->wave.cbSize = 0; /* No additional format metadata */
#else #else
header->i_format = aout->output.output.i_format; header->i_format = aout->output.output.i_format;
header->i_bitspersample = aout->output.output.i_bitspersample; header->i_bitspersample = aout->output.output.i_bitspersample;
...@@ -396,13 +433,9 @@ static void amem_shmem_header(aout_instance_t *aout) ...@@ -396,13 +433,9 @@ static void amem_shmem_header(aout_instance_t *aout)
header->i_blockalign = aout->output.output.i_blockalign; header->i_blockalign = aout->output.output.i_blockalign;
#endif #endif
header->i_read_samples = 0; header->i_read = header->i_write = 0;
header->i_write_samples = 0; header->i_read_samples = header->i_write_samples = 0;
header->i_max_samples = aout->output.i_nb_samples; header->i_max_samples = aout->output.i_nb_samples;
header->i_nb_samples = 0;
memset(header->samples, 0, (aout->output.i_nb_samples *
aout->output.output.i_bitspersample));
amem_sem_post(&header->sem); amem_sem_post(&header->sem);
} }
...@@ -412,21 +445,25 @@ static int amem_shmem_write(aout_instance_t *aout, aout_buffer_t *p_buffer) ...@@ -412,21 +445,25 @@ static int amem_shmem_write(aout_instance_t *aout, aout_buffer_t *p_buffer)
aout_sys_t *sys = (aout_sys_t *)aout->output.p_sys; aout_sys_t *sys = (aout_sys_t *)aout->output.p_sys;
amem_sem_wait(&sys->header->sem); amem_sem_wait(&sys->header->sem);
amem_buffer_t *buf = amem_buffer_get(aout, sys->header->i_write);
/* FIXME: do not assume we can fill the entire buffer */ if (buf == NULL)
{
amem_sem_post(&sys->header->sem);
return VLC_EGENERIC;
}
assert(p_buffer->i_nb_samples <= sys->header->i_max_samples); assert(p_buffer->i_nb_samples <= sys->header->i_max_samples);
#if defined(_WIN32_WINNT) || defined(WIN32) #if defined(_WIN32_WINNT) || defined(WIN32)
CopyMemory((PVOID)sys->header->samples, data->p_buffer, data->i_buffer); CopyMemory((PVOID)buf->samples, p_buffer->p_buffer, p_buffer->i_buffer);
#else #else
memcpy(sys->header->samples, p_buffer->p_buffer, p_buffer->i_buffer); memcpy(buf->samples, p_buffer->p_buffer, p_buffer->i_buffer);
#endif #endif
sys->header->i_nb_samples = p_buffer->i_nb_samples; buf->i_nb_samples = p_buffer->i_nb_samples;
sys->header->i_write_samples += p_buffer->i_nb_samples;
sys->header->i_write_samples += p_buffer->i_nb_samples;
sys->header->i_write = (sys->header->i_write + 1) % sys->header->i_buffers;
amem_sem_post(&sys->header->sem); amem_sem_post(&sys->header->sem);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -442,6 +479,10 @@ static int amem_shmem_write(aout_instance_t *aout, aout_buffer_t *p_buffer) ...@@ -442,6 +479,10 @@ static int amem_shmem_write(aout_instance_t *aout, aout_buffer_t *p_buffer)
#define ACHANS_LONGTEXT N_( \ #define ACHANS_LONGTEXT N_( \
"Number of audio channels in the audio output." ) "Number of audio channels in the audio output." )
#define ABUFS_TEXT N_("Number of shared audio buffers")
#define ABUFS_LONGTEXT N_( \
"Number of shared audio buffers to use.")
#define AFORMAT_TEXT N_("Output format") #define AFORMAT_TEXT N_("Output format")
#define AFORMAT_LONGTEXT N_( \ #define AFORMAT_LONGTEXT N_( \
"One of \"u8\", \"s8\", \"u16\", \"s16\", " \ "One of \"u8\", \"s8\", \"u16\", \"s16\", " \
...@@ -471,6 +512,8 @@ vlc_module_begin() ...@@ -471,6 +512,8 @@ vlc_module_begin()
add_string( AMEM_CFG_PREFIX "format", "s16", NULL, AFORMAT_TEXT, add_string( AMEM_CFG_PREFIX "format", "s16", NULL, AFORMAT_TEXT,
AFORMAT_LONGTEXT, true ) AFORMAT_LONGTEXT, true )
change_string_list( format_list, 0, 0 ) change_string_list( format_list, 0, 0 )
add_integer( AMEM_CFG_PREFIX "buffers", 2, NULL, ABUFS_TEXT,
ABUFS_LONGTEXT, false )
add_integer( AMEM_CFG_PREFIX "channels", 2, NULL, ACHANS_TEXT, add_integer( AMEM_CFG_PREFIX "channels", 2, NULL, ACHANS_TEXT,
ACHANS_LONGTEXT, false ) ACHANS_LONGTEXT, false )
change_integer_range( 0, CHANNELS_MAX ) change_integer_range( 0, CHANNELS_MAX )
...@@ -557,8 +600,15 @@ static int Open(vlc_object_t *p_this) ...@@ -557,8 +600,15 @@ static int Open(vlc_object_t *p_this)
pi_channels_maps[i_channels]; pi_channels_maps[i_channels];
} }
int i_buffers = var_CreateGetInteger(aout, AMEM_CFG_PREFIX "buffers");
if (i_buffers < 1)
{
msg_Err(aout, "insufficient shared audio buffers requested");
return VLC_EGENERIC;
}
/* Setup shared memory connection */ /* Setup shared memory connection */
if (SetupSharedMem(aout) != VLC_SUCCESS) if (SetupSharedMem(aout, i_buffers) != VLC_SUCCESS)
{ {
Close(p_this); Close(p_this);
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -602,14 +652,13 @@ static void Play(aout_instance_t *aout) ...@@ -602,14 +652,13 @@ static void Play(aout_instance_t *aout)
/***************************************************************************** /*****************************************************************************
* Shared Memory * Shared Memory
*****************************************************************************/ *****************************************************************************/
static int SetupSharedMem(aout_instance_t *aout) static int SetupSharedMem(aout_instance_t *aout, unsigned int i_buffers)
{ {
aout_sys_t *sys = (aout_sys_t *)aout->output.p_sys; aout_sys_t *sys = (aout_sys_t *)aout->output.p_sys;
/* Determine shared memory size */ /* Determine shared memory size */
ssize_t len = sizeof(amem_shared_t) + aout->output.i_nb_samples ssize_t len = sizeof(amem_shared_t) + i_buffers * (sizeof(amem_buffer_t)
* aout->output.output.i_bitspersample; + aout->output.i_nb_samples * aout->output.output.i_bitspersample);
if (*sys->psz_name != '/') if (*sys->psz_name != '/')
{ {
msg_Err(aout, "invalid shared segment name (does not begin with /)"); msg_Err(aout, "invalid shared segment name (does not begin with /)");
...@@ -622,7 +671,7 @@ static int SetupSharedMem(aout_instance_t *aout) ...@@ -622,7 +671,7 @@ static int SetupSharedMem(aout_instance_t *aout)
return VLC_EGENERIC; return VLC_EGENERIC;
} }
if (amem_shmem_open(aout, len) != VLC_SUCCESS) if (amem_shmem_open(aout, i_buffers, len) != VLC_SUCCESS)
return VLC_EGENERIC; return VLC_EGENERIC;
/* Fill header struct */ /* Fill header struct */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment