Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-1.1
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-1.1
Commits
96162813
Commit
96162813
authored
Nov 18, 2010
by
Jean-Paul Saman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
audio_output/amem.c: shared memory Audio output
parent
21dc16b0
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
677 additions
and
1 deletion
+677
-1
modules/audio_output/Modules.am
modules/audio_output/Modules.am
+3
-1
modules/audio_output/amem.c
modules/audio_output/amem.c
+674
-0
No files found.
modules/audio_output/Modules.am
View file @
96162813
...
...
@@ -9,5 +9,7 @@ SOURCES_portaudio = portaudio.c
SOURCES_auhal = auhal.c
SOURCES_jack = jack.c
SOURCES_pulse = pulse.c
SOURCES_amem = amem.c
libvlc_LTLIBRARIES += libaout_file_plugin.la
libvlc_LTLIBRARIES += libaout_file_plugin.la \
libamem_plugin.la
modules/audio_output/amem.c
0 → 100644
View file @
96162813
/*****************************************************************************
* amem.c: memory audio driver for vlc
*****************************************************************************
* Copyright (C) 2010 M2X BV
* $Id$
*
* Authors: Jean-Paul Saman <jpsaman@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_codecs.h>
#include <vlc_es.h>
#include <vlc_aout.h>
#include <vlc_playlist.h>
/* changing audio delay */
#if defined(_WIN32_WINNT) || defined(WIN32)
# include <windows.h>
# include <conio.h>
# include <tchar.h>
# define NAME_MAX 255
#else
# include <limits.h>
# include <errno.h>
# include <sys/types.h>
# include <sys/mman.h>
# include <sys/stat.h>
/* For mode constants */
# include <fcntl.h>
/* For O_* constants */
# include <semaphore.h>
#endif
#include <assert.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
#define FRAME_SIZE 2048
/* Audio channels */
#define CHANNELS_MAX 6
static
const
int
pi_channels_maps
[
CHANNELS_MAX
+
1
]
=
{
0
,
AOUT_CHAN_CENTER
,
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
,
AOUT_CHAN_CENTER
|
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
,
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
,
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
,
AOUT_CHAN_LEFT
|
AOUT_CHAN_RIGHT
|
AOUT_CHAN_CENTER
|
AOUT_CHAN_REARLEFT
|
AOUT_CHAN_REARRIGHT
|
AOUT_CHAN_LFE
};
/* Audio format */
static
const
char
*
const
format_list
[]
=
{
"u8"
,
"s8"
,
"u16"
,
"s16"
,
"u16_le"
,
"s16_le"
,
"u16_be"
,
"s16_be"
,
"fixed32"
,
"float32"
,
"spdif"
};
static
const
int
format_int
[]
=
{
VLC_CODEC_U8
,
VLC_CODEC_S8
,
VLC_CODEC_U16N
,
VLC_CODEC_S16N
,
VLC_CODEC_U16L
,
VLC_CODEC_S16L
,
VLC_CODEC_U16B
,
VLC_CODEC_S16B
,
VLC_CODEC_FI32
,
VLC_CODEC_FL32
,
VLC_CODEC_SPDIFL
};
/* Shared memory header structure */
typedef
struct
{
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
;
#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
;
unsigned
i_channels
;
#endif
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 */
struct
aout_sys_t
{
#if defined(_WIN32_WINNT) || defined(WIN32)
HANDLE
handle
;
#else
int
shm_fd
;
#endif
amem_shared_t
*
header
;
char
*
psz_name
;
bool
b_own_semaphore
;
};
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
static
void
Play
(
aout_instance_t
*
);
static
int
SetupSharedMem
(
aout_instance_t
*
,
unsigned
int
);
static
void
ExitSharedMem
(
aout_instance_t
*
);
/*
* Shared Memory helpers
*/
static
void
amem_sem_init
(
vlc_sem_t
*
sem
,
unsigned
value
)
{
#if defined(_WIN32_WINNT) || defined(WIN32)
sem
=
(
vlc_sem_t
*
)
CreateSemaphore
(
NULL
/*LPSECURITY_ATTRIBUTES*/
,
1
,
value
,
NULL
);
if
(
sem
==
NULL
)
abort
();
#else
if
(
unlikely
(
sem_init
(
sem
,
1
/* share between process*/
,
value
))
==
-
1
)
abort
();
#endif
}
static
int
amem_sem_trywait
(
vlc_sem_t
*
sem
)
{
int
again
=
0
;
do
{
#if defined(_WIN32_WINNT) || defined(WIN32)
DWORD
wait
=
WaitForSingleObject
((
HANDLE
)
*
sem
,
0L
);
switch
(
wait
)
{
case
WAIT_OBJECT_0
:
return
VLC_SUCCESS
;
case
WAIT_TIMEOUT
:
again
++
;
break
;
default:
return
VLC_EGENERIC
;
}
#else
if
(
sem_trywait
(
sem
)
==
0
)
break
;
if
(
errno
==
EAGAIN
)
again
++
;
#endif
if
(
again
==
3
)
return
VLC_EGENERIC
;
}
while
(
again
<
3
);
return
VLC_SUCCESS
;
}
static
void
amem_sem_wait
(
vlc_sem_t
*
sem
)
{
#if defined(_WIN32_WINNT) || defined(WIN32)
DWORD
wait
=
WaitForSingleObject
((
HANDLE
)
*
sem
,
INFINTE
);
assert
(
wait
==
WAIT_OBJECT_0
);
#else
vlc_sem_wait
(
sem
);
#endif
}
static
void
amem_sem_post
(
vlc_sem_t
*
sem
)
{
#if defined(_WIN32_WINNT) || defined(WIN32)
BOOL
ret
=
ReleaseSemaphore
((
HANDLE
)
*
sem
,
1
,
NULL
);
#else
int
ret
=
vlc_sem_post
(
sem
);
#endif
assert
(
ret
>=
0
);
}
static
void
amem_sem_destroy
(
vlc_sem_t
*
sem
)
{
#if defined(_WIN32_WINNT) || defined(WIN32)
BOOL
ret
=
CloseHandle
((
HANDLE
)
*
sem
);
assert
(
ret
>=
0
);
#else
vlc_sem_destroy
(
sem
);
#endif
}
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_open
(
aout_instance_t
*
aout
,
unsigned
int
i_buffers
,
ssize_t
len
,
bool
b_create
)
{
aout_sys_t
*
sys
=
(
aout_sys_t
*
)
aout
->
output
.
p_sys
;
#if defined(_WIN32_WINNT) || defined(WIN32)
TCHAR
szName
[
NAME_MAX
];
size_t
nameLen
=
strlen
(
sys
->
psz_name
);
if
(
nameLen
>
NAME_MAX
)
nameLen
=
NAME_MAX
-
1
;
if
(
nameLen
==
0
)
return
VLC_EGENERIC
;
memcpy
(
&
szName
,
TEXT
(
sys
->
psz_name
),
nameLen
);
szName
[
NAME_MAX
-
1
]
=
'\0'
;
if
(
b_create
)
{
sys
->
handle
=
CreateFileMapping
(
INVALID_HANDLE_VALUE
,
// use paging file
NULL
,
// default security
PAGE_READWRITE
,
// read/write access
0
,
// maximum object size (high-order DWORD)
len
,
// maximum object size (low-order DWORD)
szName
);
// name of mapping object
}
else
{
sys
->
handle
=
OpenFileMapping
(
FILE_MAP_ALL_ACCESS
,
FALSE
,
szName
);
}
if
(
sys
->
handle
==
NULL
)
{
msg_Err
(
aout
,
"could not %s file mapping object (%ld)."
,
b_create
?
"create"
:
"open"
,
GetLastError
());
return
VLC_EGENERIC
;
}
sys
->
header
=
(
amem_shared_t
*
)
MapViewOfFile
(
sys
->
handle
,
FILE_MAP_ALL_ACCESS
,
0
,
0
,
len
);
if
(
sys
->
header
==
NULL
)
{
msg_Err
(
aout
,
"could not map view of file (%ld)."
,
GetLastError
());
CloseHandle
(
sys
->
handle
);
return
VLC_EGENERIC
;
}
#else
int
flags
=
b_create
?
(
O_CREAT
|
O_EXCL
|
O_RDWR
)
:
O_RDWR
;
sys
->
shm_fd
=
shm_open
(
sys
->
psz_name
,
flags
,
(
S_IREAD
|
S_IWRITE
));
if
(
sys
->
shm_fd
<
0
)
{
msg_Err
(
aout
,
"could not %s shared memory object (%m)"
,
b_create
?
"create"
:
"open"
);
return
VLC_EGENERIC
;
}
/* set correct maximum size */
if
(
ftruncate
(
sys
->
shm_fd
,
len
)
<
0
)
{
msg_Err
(
aout
,
"failed setting shared memory size (%m)"
);
return
VLC_EGENERIC
;
}
/* mmap shared segment */
sys
->
header
=
mmap
(
0
,
len
,
(
PROT_READ
|
PROT_WRITE
),
MAP_SHARED
,
sys
->
shm_fd
,
0
);
if
(
sys
->
header
==
MAP_FAILED
)
{
msg_Err
(
aout
,
"could not mmap shared memory object (%m)"
);
return
VLC_EGENERIC
;
}
#endif
size_t
buflen
=
(
aout
->
output
.
i_nb_samples
*
aout
->
output
.
output
.
i_bitspersample
);
/* 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
;
if
(
b_create
)
memset
(
buffer
->
samples
,
0
,
buflen
);
}
}
/* initialize unamed semaphore */
if
(
b_create
)
{
amem_sem_init
(
&
sys
->
header
->
sem
,
1
);
sys
->
b_own_semaphore
=
true
;
}
msg_Dbg
(
aout
,
"shared memory %s"
,
b_create
?
"created"
:
"opened"
);
return
VLC_SUCCESS
;
}
static
void
amem_shmem_close
(
aout_instance_t
*
aout
)
{
aout_sys_t
*
sys
=
(
aout_sys_t
*
)
aout
->
output
.
p_sys
;
if
(
sys
->
b_own_semaphore
)
amem_sem_destroy
(
&
sys
->
header
->
sem
);
#if defined(_WIN32_WINNT) || defined(WIN32)
if
(
sys
->
header
)
UnmapViewOfFile
(
sys
->
header
);
CloseHandle
(
sys
->
handle
);
#else
/* Determine shared memory size */
if
(
sys
->
header
!=
MAP_FAILED
)
{
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)"
);
}
}
close
(
sys
->
shm_fd
);
#endif
msg_Dbg
(
aout
,
"shared memory closed"
);
}
static
void
amem_shmem_header
(
aout_instance_t
*
aout
)
{
aout_sys_t
*
sys
=
(
aout_sys_t
*
)
aout
->
output
.
p_sys
;
amem_shared_t
*
header
=
sys
->
header
;
msg_Dbg
(
aout
,
"syncing shared header"
);
amem_sem_wait
(
&
header
->
sem
);
/* Fill header struct */
#if defined(_WIN32_WINNT) || defined(WIN32)
uint16_t
tag
=
0
;
fourcc_to_wf_tag
(
aout
->
output
.
output
.
i_format
,
&
tag
);
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
.
wBitsPerSample
=
aout
->
output
.
output
.
i_bitspersample
;
header
->
wave
.
nBlockAlign
=
header
->
wave
.
wBitsPerSample
/
8
*
header
->
wave
.
nChannels
;
header
->
wave
.
nAvgBytesPerSec
=
header
->
wave
.
nSamplesPerSec
*
header
->
wave
.
nBlockAlign
;
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
;
header
->
i_bytes_per_frame
=
aout
->
output
.
output
.
i_bytes_per_frame
;
header
->
i_channels
=
aout
->
output
.
output
.
i_channels
;
header
->
i_frame_length
=
aout
->
output
.
output
.
i_frame_length
;
header
->
i_rate
=
aout
->
output
.
output
.
i_rate
;
header
->
i_blockalign
=
aout
->
output
.
output
.
i_blockalign
;
#endif
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
;
amem_sem_post
(
&
header
->
sem
);
}
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
);
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
)
buf
->
samples
,
p_buffer
->
p_buffer
,
p_buffer
->
i_buffer
);
#else
memcpy
(
buf
->
samples
,
p_buffer
->
p_buffer
,
p_buffer
->
i_buffer
);
#endif
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
;
}
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define ARATE_TEXT N_("Audio sample rate")
#define ARATE_LONGTEXT N_( \
"Sample rate of the audio stream (11250, 22500, 44100 or 48000).")
#define ACHANS_TEXT N_("Audio channels")
#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\", " \
"\"u16_le\", \"s16_le\", \"u16_be\", \"s16_be\", \"fixed32\", " \
"\"float32\" or \"spdif\"")
#define ADELAY_TEXT N_("Output delay")
#define ADELAY_LONGTEXT N_( \
"Initial delay for audio output" )
#define ANAME_TEXT N_("Name to use (default /amem.shared)")
#define ANAME_LONGTEXT N_( \
"Name to use as identifier to the (named) shared memory" )
#define AMEM_CFG_PREFIX "amem-"
vlc_module_begin
()
set_description
(
N_
(
"Audio memory output"
))
set_shortname
(
N_
(
"Audio memory"
))
set_category
(
CAT_AUDIO
)
set_subcategory
(
SUBCAT_AUDIO_AOUT
)
set_capability
(
"audio output"
,
0
)
add_string
(
AMEM_CFG_PREFIX
"name"
,
"/amem.shared"
,
NULL
,
ANAME_TEXT
,
ANAME_LONGTEXT
,
true
)
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
)
add_integer
(
AMEM_CFG_PREFIX
"samplerate"
,
44100
,
NULL
,
ARATE_TEXT
,
ARATE_LONGTEXT
,
true
)
add_integer
(
AMEM_CFG_PREFIX
"delay"
,
-
1
,
NULL
,
ADELAY_TEXT
,
ADELAY_TEXT
,
true
)
set_callbacks
(
Open
,
Close
)
vlc_module_end
()
/*****************************************************************************
* Open
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
p_this
)
{
aout_instance_t
*
aout
=
(
aout_instance_t
*
)
p_this
;
aout_sys_t
*
sys
;
char
*
psz_format
;
const
char
*
const
*
ppsz_compare
=
format_list
;
int
i
=
0
;
/* */
aout
->
output
.
p_sys
=
sys
=
(
aout_sys_t
*
)
malloc
(
sizeof
(
aout_sys_t
));
if
(
sys
==
NULL
)
return
VLC_ENOMEM
;
/* */
sys
->
header
=
NULL
;
sys
->
b_own_semaphore
=
false
;
/* */
aout
->
output
.
pf_play
=
Play
;
/* Name to use */
sys
->
psz_name
=
var_CreateGetString
(
p_this
,
AMEM_CFG_PREFIX
"name"
);
/* Audio sample rate */
aout
->
output
.
output
.
i_rate
=
var_CreateGetInteger
(
p_this
,
AMEM_CFG_PREFIX
"samplerate"
);
/* Audio format */
psz_format
=
var_CreateGetString
(
p_this
,
AMEM_CFG_PREFIX
"format"
);
while
(
*
ppsz_compare
!=
NULL
)
{
if
(
!
strncmp
(
*
ppsz_compare
,
psz_format
,
strlen
(
*
ppsz_compare
)))
{
break
;
}
ppsz_compare
++
;
i
++
;
}
if
(
*
ppsz_compare
==
NULL
)
{
msg_Err
(
aout
,
"cannot understand the format string (%s)"
,
psz_format
);
free
(
aout
->
output
.
p_sys
->
psz_name
);
free
(
aout
->
output
.
p_sys
);
free
(
psz_format
);
return
VLC_EGENERIC
;
}
free
(
psz_format
);
aout
->
output
.
output
.
i_format
=
format_int
[
i
];
aout
->
output
.
output
.
i_bitspersample
=
aout_BitsPerSample
(
aout
->
output
.
output
.
i_format
);
if
(
AOUT_FMT_NON_LINEAR
(
&
aout
->
output
.
output
))
{
aout
->
output
.
i_nb_samples
=
A52_FRAME_NB
;
aout
->
output
.
output
.
i_bytes_per_frame
=
AOUT_SPDIF_SIZE
;
aout
->
output
.
output
.
i_frame_length
=
A52_FRAME_NB
;
if
((
aout
->
output
.
output
.
i_bitspersample
==
0
)
&&
(
aout
->
output
.
output
.
i_format
==
VLC_CODEC_SPDIFL
))
aout
->
output
.
output
.
i_bitspersample
=
32
;
aout_VolumeNoneInit
(
aout
);
}
else
{
aout
->
output
.
i_nb_samples
=
FRAME_SIZE
;
aout_VolumeSoftInit
(
aout
);
}
/* Channels number */
int
i_channels
=
var_CreateGetInteger
(
p_this
,
AMEM_CFG_PREFIX
"channels"
);
if
((
i_channels
>
0
)
&&
(
i_channels
<=
CHANNELS_MAX
))
{
aout
->
output
.
output
.
i_physical_channels
=
pi_channels_maps
[
i_channels
];
}
/* Audio output buffers */
int
i_buffers
=
var_CreateGetInteger
(
aout
,
AMEM_CFG_PREFIX
"buffers"
);
if
(
i_buffers
<
1
)
{
msg_Err
(
aout
,
"insufficient shared audio buffers requested"
);
free
(
aout
->
output
.
p_sys
->
psz_name
);
free
(
aout
->
output
.
p_sys
);
return
VLC_EGENERIC
;
}
/* Audio output delay */
int64_t
i_delay
=
var_CreateGetInteger
(
aout
,
AMEM_CFG_PREFIX
"delay"
);
if
(
i_delay
>=
0
)
{
playlist_t
*
p_playlist
=
pl_Get
(
aout
);
/* Update the input */
input_thread_t
*
p_input
=
playlist_CurrentInput
(
p_playlist
);
if
(
p_input
==
NULL
)
{
free
(
aout
->
output
.
p_sys
->
psz_name
);
free
(
aout
->
output
.
p_sys
);
return
VLC_EGENERIC
;
}
if
(
var_GetTime
(
p_input
,
"audio-delay"
)
!=
i_delay
)
var_SetTime
(
p_input
,
"audio-delay"
,
i_delay
);
vlc_object_release
(
p_input
);
}
/* Setup shared memory connection */
if
(
SetupSharedMem
(
aout
,
i_buffers
)
!=
VLC_SUCCESS
)
{
Close
(
p_this
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Close
*****************************************************************************/
static
void
Close
(
vlc_object_t
*
p_this
)
{
aout_instance_t
*
aout
=
(
aout_instance_t
*
)
p_this
;
ExitSharedMem
(
aout
);
free
(
aout
->
output
.
p_sys
->
psz_name
);
free
(
aout
->
output
.
p_sys
);
}
/*****************************************************************************
* Play
*****************************************************************************/
static
void
Play
(
aout_instance_t
*
aout
)
{
aout_buffer_t
*
p_buffer
;
p_buffer
=
aout_FifoPop
(
aout
,
&
aout
->
output
.
fifo
);
if
(
p_buffer
==
NULL
)
return
;
if
(
amem_shmem_write
(
aout
,
p_buffer
)
!=
VLC_SUCCESS
)
{
msg_Err
(
aout
,
"write error (%m)"
);
}
aout_BufferFree
(
p_buffer
);
}
/*****************************************************************************
* Shared Memory
*****************************************************************************/
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
buflen
=
sizeof
(
amem_buffer_t
)
+
(
aout
->
output
.
i_nb_samples
*
aout
->
output
.
output
.
i_bitspersample
);
ssize_t
len
=
sizeof
(
amem_shared_t
)
+
(
i_buffers
*
buflen
);
if
(
*
sys
->
psz_name
!=
'/'
)
{
msg_Err
(
aout
,
"invalid shared segment name (does not begin with /)"
);
return
VLC_EGENERIC
;
}
if
(
strlen
(
sys
->
psz_name
)
>=
NAME_MAX
)
{
msg_Err
(
aout
,
"invalid shared segment name (string length >= %d)"
,
NAME_MAX
);
return
VLC_EGENERIC
;
}
if
(
amem_shmem_open
(
aout
,
i_buffers
,
len
,
false
)
!=
VLC_SUCCESS
)
return
VLC_EGENERIC
;
/* Fill header struct */
amem_shmem_header
(
aout
);
return
VLC_SUCCESS
;
}
static
void
ExitSharedMem
(
aout_instance_t
*
aout
)
{
amem_shmem_close
(
aout
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment