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,
/* Shared memory header structure */
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)
WAVEFORMATEX wave;
WAVEFORMATEX wave;
#else
vlc_fourcc_t i_format;
unsigned int i_rate;
unsigned int i_bytes_per_frame;
unsigned int i_frame_length;
unsigned i_bitspersample;
unsigned i_blockalign;
uint8_t i_channels;
vlc_fourcc_t i_format;
unsigned int i_rate;
unsigned int i_bytes_per_frame;
unsigned int i_frame_length;
unsigned i_bitspersample;
unsigned i_blockalign;
unsigned i_channels;
#endif
unsigned int i_read_samples; /* total samples read */
unsigned int i_write_samples; /* total samples written */
unsigned int i_max_samples; /* maximum samples in buffer */
unsigned int i_nb_samples; /* number of samples in buffer */
void *samples; /* buffer of samples */
unsigned int i_max_samples; /* maximum samples per buffer */
unsigned int i_read_samples; /* total samples read */
unsigned int i_write_samples; /* total samples written */
/* if i_buf_write == i_buffers, then it will wrap around */
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;
/* Private structure */
......@@ -134,7 +142,7 @@ static int Open (vlc_object_t *);
static void Close(vlc_object_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 *);
/*
......@@ -216,7 +224,18 @@ static void amem_sem_destroy(vlc_sem_t *sem)
#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;
......@@ -273,7 +292,17 @@ static int amem_shmem_create(aout_instance_t *aout, ssize_t len)
}
#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 */
amem_sem_init(&sys->header->sem, 1);
......@@ -282,7 +311,7 @@ static int amem_shmem_create(aout_instance_t *aout, ssize_t len)
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;
......@@ -333,7 +362,15 @@ static int amem_shmem_open(aout_instance_t *aout, ssize_t len)
return VLC_EGENERIC;
}
#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");
return VLC_SUCCESS;
......@@ -353,8 +390,8 @@ static void amem_shmem_close(aout_instance_t *aout)
/* Determine shared memory size */
if (sys->header != MAP_FAILED)
{
ssize_t len = sizeof(amem_shared_t) + aout->output.i_nb_samples
* aout->output.output.i_bitspersample;
ssize_t len = sizeof(amem_shared_t) + sys->header->i_buffers * (sizeof(amem_buffer_t)
+ aout->output.i_nb_samples * aout->output.output.i_bitspersample);
if (munmap(sys->header, len) < 0)
{
msg_Err(aout, "failed unmapping shared memory (%m)");
......@@ -379,13 +416,13 @@ static void amem_shmem_header(aout_instance_t *aout)
#if defined(_WIN32_WINNT) || defined(WIN32)
uint16_t tag = 0;
fourcc_to_wf_tag(aout->output.output.i_format, &tag);
sys->header->wave.wFormatTag = tag;
sys->header->wave.nChannels = aout->output.output.i_channels;
sys->header->wave.nSamplesPerSec = aout->output.output.i_rate * aout->output.i_nb_samples;
//sys->header->wave.nAvgBytesPerSec = ;
sys->header->wave.nBlockAlign = aout->output.output.i_blockalign;
sys->header->wave.wBitsPerSample = aout->output.output.i_bitspersample;
sys->header->wave.cbSize = 0; /* No additional format metadata */
header->wave.wFormatTag = tag;
header->wave.nChannels = aout->output.output.i_channels;
header->wave.nSamplesPerSec = aout->output.output.i_rate * aout->output.i_nb_samples;
//header->wave.nAvgBytesPerSec = ;
header->wave.nBlockAlign = aout->output.output.i_blockalign;
header->wave.wBitsPerSample = aout->output.output.i_bitspersample;
header->wave.cbSize = 0; /* No additional format metadata */
#else
header->i_format = aout->output.output.i_format;
header->i_bitspersample = aout->output.output.i_bitspersample;
......@@ -396,13 +433,9 @@ static void amem_shmem_header(aout_instance_t *aout)
header->i_blockalign = aout->output.output.i_blockalign;
#endif
header->i_read_samples = 0;
header->i_write_samples = 0;
header->i_read = header->i_write = 0;
header->i_read_samples = header->i_write_samples = 0;
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);
}
......@@ -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;
amem_sem_wait(&sys->header->sem);
/* FIXME: do not assume we can fill the entire buffer */
amem_buffer_t *buf = amem_buffer_get(aout, sys->header->i_write);
if (buf == NULL)
{
amem_sem_post(&sys->header->sem);
return VLC_EGENERIC;
}
assert(p_buffer->i_nb_samples <= sys->header->i_max_samples);
#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
memcpy(sys->header->samples, p_buffer->p_buffer, p_buffer->i_buffer);
memcpy(buf->samples, p_buffer->p_buffer, p_buffer->i_buffer);
#endif
sys->header->i_nb_samples = p_buffer->i_nb_samples;
sys->header->i_write_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 = (sys->header->i_write + 1) % sys->header->i_buffers;
amem_sem_post(&sys->header->sem);
return VLC_SUCCESS;
}
......@@ -442,6 +479,10 @@ static int amem_shmem_write(aout_instance_t *aout, aout_buffer_t *p_buffer)
#define ACHANS_LONGTEXT N_( \
"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_LONGTEXT N_( \
"One of \"u8\", \"s8\", \"u16\", \"s16\", " \
......@@ -471,6 +512,8 @@ vlc_module_begin()
add_string( AMEM_CFG_PREFIX "format", "s16", NULL, AFORMAT_TEXT,
AFORMAT_LONGTEXT, true )
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,
ACHANS_LONGTEXT, false )
change_integer_range( 0, CHANNELS_MAX )
......@@ -557,8 +600,15 @@ static int Open(vlc_object_t *p_this)
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 */
if (SetupSharedMem(aout) != VLC_SUCCESS)
if (SetupSharedMem(aout, i_buffers) != VLC_SUCCESS)
{
Close(p_this);
return VLC_EGENERIC;
......@@ -602,14 +652,13 @@ static void Play(aout_instance_t *aout)
/*****************************************************************************
* 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;
/* Determine shared memory size */
ssize_t len = sizeof(amem_shared_t) + aout->output.i_nb_samples
* aout->output.output.i_bitspersample;
ssize_t len = sizeof(amem_shared_t) + i_buffers * (sizeof(amem_buffer_t)
+ aout->output.i_nb_samples * aout->output.output.i_bitspersample);
if (*sys->psz_name != '/')
{
msg_Err(aout, "invalid shared segment name (does not begin with /)");
......@@ -622,7 +671,7 @@ static int SetupSharedMem(aout_instance_t *aout)
return VLC_EGENERIC;
}
if (amem_shmem_open(aout, len) != VLC_SUCCESS)
if (amem_shmem_open(aout, i_buffers, len) != VLC_SUCCESS)
return VLC_EGENERIC;
/* 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