Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
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
Commits
21e2557b
Commit
21e2557b
authored
Feb 04, 2013
by
Denis Charmet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove aout_Packet from directsound audio output
parent
8cbd52ac
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
178 additions
and
236 deletions
+178
-236
modules/audio_output/directx.c
modules/audio_output/directx.c
+178
-236
No files found.
modules/audio_output/directx.c
View file @
21e2557b
...
...
@@ -35,25 +35,10 @@
#include <vlc_plugin.h>
#include <vlc_aout.h>
#include <vlc_charset.h>
#include <vlc_atomic.h>
#include "windows_audio_common.h"
/*****************************************************************************
* notification_thread_t: DirectX event thread
*****************************************************************************/
typedef
struct
notification_thread_t
{
int
i_frame_size
;
/* size in bytes of one frame */
int
i_write_slot
;
/* current write position in our circular buffer */
mtime_t
start_date
;
HANDLE
event
;
vlc_thread_t
thread
;
vlc_atomic_t
abort
;
}
notification_thread_t
;
#define DS_BUF_SIZE (1024*1024)
/*****************************************************************************
* aout_sys_t: directx audio output method descriptor
...
...
@@ -63,30 +48,33 @@ typedef struct notification_thread_t
*****************************************************************************/
struct
aout_sys_t
{
aout_packet_t
packet
;
HINSTANCE
hdsound_dll
;
/* handle of the opened dsound dll */
HINSTANCE
hdsound_dll
;
/* handle of the opened dsound dll */
LPDIRECTSOUND
p_dsobject
;
/* main Direct Sound object */
LPDIRECTSOUND
p_dsobject
;
/* main Direct Sound object */
LPDIRECTSOUNDBUFFER
p_dsbuffer
;
/* the sound buffer we use (direct sound
* takes care of mixing all the
* secondary buffers into the primary) */
LPDIRECTSOUNDNOTIFY
p_notify
;
HANDLE
hnotify_evt
;
struct
{
LONG
volume
;
float
volume
;
LONG
mb
;
bool
mute
;
}
volume
;
notification_thread_t
notif
;
/* DirectSoundThread id */
int
i_frame_size
;
/* Size in bytes of one frame */
int
i_bytes_per_sample
;
/* Size in bytes of one frame */
int
i_rate
;
/* Sample rate */
int
i_speaker_setup
;
/* Speaker setup override */
int
i_speaker_setup
;
/* Speaker setup override */
uint8_t
chans_to_reorder
;
/* do we need channel reordering */
uint8_t
chans_to_reorder
;
/* do we need channel reordering */
uint8_t
chan_table
[
AOUT_CHAN_MAX
];
uint32_t
i_channel_mask
;
vlc_fourcc_t
format
;
size_t
i_write
;
};
/*****************************************************************************
...
...
@@ -95,18 +83,20 @@ struct aout_sys_t
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
static
void
Stop
(
audio_output_t
*
);
static
void
Play
(
audio_output_t
*
,
block_t
*
);
static
int
VolumeSet
(
audio_output_t
*
,
float
);
static
int
MuteSet
(
audio_output_t
*
,
bool
);
static
void
Play
(
audio_output_t
*
,
block_t
*
);
static
int
VolumeSet
(
audio_output_t
*
,
float
);
static
int
MuteSet
(
audio_output_t
*
,
bool
);
static
void
Flush
(
audio_output_t
*
,
bool
);
static
void
Pause
(
audio_output_t
*
,
bool
,
mtime_t
);
static
int
TimeGet
(
audio_output_t
*
,
mtime_t
*
);
/* local functions */
static
void
Probe
(
audio_output_t
*
,
const
audio_sample_format_t
*
);
static
int
InitDirectSound
(
audio_output_t
*
);
static
int
CreateDSBuffer
(
audio_output_t
*
,
int
,
int
,
int
,
int
,
int
,
bool
);
static
int
CreateDSBuffer
(
audio_output_t
*
,
int
,
int
,
int
,
int
,
bool
);
static
int
CreateDSBufferPCM
(
audio_output_t
*
,
vlc_fourcc_t
*
,
int
,
int
,
bool
);
static
void
DestroyDSBuffer
(
audio_output_t
*
);
static
void
*
DirectSoundThread
(
void
*
);
static
int
FillBuffer
(
audio_output_t
*
,
int
,
block_t
*
);
static
int
FillBuffer
(
audio_output_t
*
,
block_t
*
);
static
int
ReloadDirectXDevices
(
vlc_object_t
*
,
const
char
*
,
char
***
,
char
***
);
...
...
@@ -145,7 +135,7 @@ vlc_module_begin ()
add_string
(
"directx-audio-speaker"
,
"Windows default"
,
SPEAKER_TEXT
,
SPEAKER_LONGTEXT
,
true
)
change_string_list
(
speaker_list
,
speaker_list
)
add_
integer
(
"directx-volume"
,
DSBVOLUME_MAX
,
add_
float
(
"directx-volume"
,
1
.
0
f
,
VOLUME_TEXT
,
VOLUME_LONGTEXT
,
true
)
change_integer_range
(
DSBVOLUME_MIN
,
DSBVOLUME_MAX
)
...
...
@@ -216,19 +206,15 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
/* Calculate the frame size in bytes */
fmt
->
i_bytes_per_frame
=
AOUT_SPDIF_SIZE
;
fmt
->
i_frame_length
=
A52_FRAME_NB
;
p_aout
->
sys
->
i_frame_size
=
fmt
->
i_bytes_per_frame
;
if
(
CreateDSBuffer
(
p_aout
,
VLC_CODEC_SPDIFL
,
fmt
->
i_physical_channels
,
aout_FormatNbChannels
(
fmt
),
fmt
->
i_rate
,
p_aout
->
sys
->
i_frame_size
,
false
)
aout_FormatNbChannels
(
fmt
),
fmt
->
i_rate
,
false
)
!=
VLC_SUCCESS
)
{
msg_Err
(
p_aout
,
"cannot open directx audio device"
);
goto
error
;
}
aout_PacketInit
(
p_aout
,
&
p_aout
->
sys
->
packet
,
A52_FRAME_NB
,
fmt
);
}
else
{
...
...
@@ -254,37 +240,19 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
msg_Err
(
p_aout
,
"cannot open directx audio device"
);
goto
error
;
}
/* Calculate the frame size in bytes */
aout_PacketInit
(
p_aout
,
&
p_aout
->
sys
->
packet
,
fmt
->
i_rate
/
20
,
fmt
);
}
p_aout
->
sys
->
i_write
=
0
;
/* Force volume update in thread. TODO: use session volume on Vista+ */
p_aout
->
sys
->
volume
.
volume
=
p_aout
->
sys
->
volume
.
mb
;
/* Now we need to setup our DirectSound play notification structure */
vlc_atomic_set
(
&
p_aout
->
sys
->
notif
.
abort
,
0
);
p_aout
->
sys
->
notif
.
event
=
CreateEvent
(
0
,
FALSE
,
FALSE
,
0
);
if
(
unlikely
(
p_aout
->
sys
->
notif
.
event
==
NULL
)
)
abort
();
p_aout
->
sys
->
notif
.
i_frame_size
=
p_aout
->
sys
->
i_frame_size
;
/* Force volume update */
VolumeSet
(
p_aout
,
p_aout
->
sys
->
volume
.
volume
);
MuteSet
(
p_aout
,
p_aout
->
sys
->
volume
.
mute
);
/* then launch the notification thread */
msg_Dbg
(
p_aout
,
"creating DirectSoundThread"
);
if
(
vlc_clone
(
&
p_aout
->
sys
->
notif
.
thread
,
DirectSoundThread
,
p_aout
,
VLC_THREAD_PRIORITY_HIGHEST
)
)
{
msg_Err
(
p_aout
,
"cannot create DirectSoundThread"
);
CloseHandle
(
p_aout
->
sys
->
notif
.
event
);
p_aout
->
sys
->
notif
.
event
=
NULL
;
aout_PacketDestroy
(
p_aout
);
goto
error
;
}
p_aout
->
time_get
=
aout_PacketTimeGet
;
p_aout
->
time_get
=
TimeGet
;
p_aout
->
play
=
Play
;
p_aout
->
pause
=
NULL
;
p_aout
->
flush
=
aout_PacketFlush
;
p_aout
->
pause
=
Pause
;
p_aout
->
flush
=
Flush
;
return
VLC_SUCCESS
;
error:
...
...
@@ -479,8 +447,7 @@ static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
{
if
(
CreateDSBuffer
(
p_aout
,
VLC_CODEC_SPDIFL
,
fmt
->
i_physical_channels
,
aout_FormatNbChannels
(
fmt
),
fmt
->
i_rate
,
AOUT_SPDIF_SIZE
,
true
)
aout_FormatNbChannels
(
fmt
),
fmt
->
i_rate
,
true
)
==
VLC_SUCCESS
)
{
msg_Dbg
(
p_aout
,
"device supports A/52 over S/PDIF"
);
...
...
@@ -511,26 +478,29 @@ static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
*****************************************************************************/
static
void
Play
(
audio_output_t
*
p_aout
,
block_t
*
p_buffer
)
{
/* get the playing date of the first aout buffer */
p_aout
->
sys
->
notif
.
start_date
=
p_buffer
->
i_pts
;
/* fill in the first samples (zeroes) */
FillBuffer
(
p_aout
,
0
,
NULL
);
/* wake up the audio output thread */
SetEvent
(
p_aout
->
sys
->
notif
.
event
);
aout_PacketPlay
(
p_aout
,
p_buffer
);
p_aout
->
play
=
aout_PacketPlay
;
if
(
FillBuffer
(
p_aout
,
p_buffer
)
==
VLC_SUCCESS
)
{
/* start playing the buffer */
HRESULT
dsresult
=
IDirectSoundBuffer_Play
(
p_aout
->
sys
->
p_dsbuffer
,
0
,
0
,
DSBPLAY_LOOPING
);
if
(
dsresult
==
DSERR_BUFFERLOST
)
{
IDirectSoundBuffer_Restore
(
p_aout
->
sys
->
p_dsbuffer
);
dsresult
=
IDirectSoundBuffer_Play
(
p_aout
->
sys
->
p_dsbuffer
,
0
,
0
,
DSBPLAY_LOOPING
);
}
if
(
dsresult
!=
DS_OK
)
msg_Err
(
p_aout
,
"cannot start playing buffer"
);
}
}
static
int
VolumeSet
(
audio_output_t
*
p_aout
,
float
vol
)
static
int
VolumeSet
(
audio_output_t
*
p_aout
,
float
vol
ume
)
{
aout_sys_t
*
sys
=
p_aout
->
sys
;
int
ret
=
0
;
/* Convert UI volume to linear factor (cube) */
vol
=
vol
*
vol
*
vol
;
float
vol
=
volume
*
volume
*
volume
;
/* millibels from linear amplification */
LONG
mb
=
lroundf
(
2000
.
f
*
log10f
(
vol
));
...
...
@@ -546,28 +516,31 @@ static int VolumeSet( audio_output_t *p_aout, float vol )
mb
=
DSBVOLUME_MIN
;
sys
->
volume
.
mb
=
mb
;
if
(
!
sys
->
volume
.
mute
)
InterlockedExchange
(
&
sys
->
volume
.
volume
,
mb
);
sys
->
volume
.
volume
=
volume
;
if
(
!
sys
->
volume
.
mute
&&
sys
->
p_dsbuffer
&&
IDirectSoundBuffer_SetVolume
(
sys
->
p_dsbuffer
,
mb
)
!=
DS_OK
)
return
-
1
;
/* Convert back to UI volume */
vol
=
cbrtf
(
powf
(
10
.
f
,
((
float
)
mb
)
/
2000
.
f
));
aout_VolumeReport
(
p_aout
,
vol
);
aout_VolumeReport
(
p_aout
,
volume
);
if
(
var_InheritBool
(
p_aout
,
"volume-save"
)
)
config_Put
Int
(
p_aout
,
"directx-volume"
,
mb
);
config_Put
Float
(
p_aout
,
"directx-volume"
,
volume
);
return
ret
;
}
static
int
MuteSet
(
audio_output_t
*
p_aout
,
bool
mute
)
{
HRESULT
res
=
DS_OK
;
aout_sys_t
*
sys
=
p_aout
->
sys
;
sys
->
volume
.
mute
=
mute
;
InterlockedExchange
(
&
sys
->
volume
.
volume
,
mute
?
DSBVOLUME_MIN
:
sys
->
volume
.
mb
);
if
(
sys
->
p_dsbuffer
)
res
=
IDirectSoundBuffer_SetVolume
(
sys
->
p_dsbuffer
,
mute
?
DSBVOLUME_MIN
:
sys
->
volume
.
mb
);
aout_MuteReport
(
p_aout
,
mute
);
return
0
;
return
(
res
!=
DS_OK
)
;
}
/*****************************************************************************
...
...
@@ -576,27 +549,19 @@ static int MuteSet( audio_output_t *p_aout, bool mute )
static
void
Stop
(
audio_output_t
*
p_aout
)
{
aout_sys_t
*
p_sys
=
p_aout
->
sys
;
msg_Dbg
(
p_aout
,
"closing audio device"
);
/* kill the position notification thread, if any */
if
(
p_sys
->
notif
.
event
!=
NULL
)
{
vlc_atomic_set
(
&
p_aout
->
sys
->
notif
.
abort
,
1
);
/* wake up the audio thread if needed */
if
(
p_aout
->
play
==
Play
)
SetEvent
(
p_sys
->
notif
.
event
);
vlc_join
(
p_sys
->
notif
.
thread
,
NULL
);
CloseHandle
(
p_sys
->
notif
.
event
);
aout_PacketDestroy
(
p_aout
);
}
if
(
p_sys
->
p_notify
)
IDirectSoundNotify_Release
(
p_sys
->
p_notify
);
p_sys
->
p_notify
=
NULL
;
IDirectSoundBuffer_Stop
(
p_sys
->
p_dsbuffer
);
/* release the secondary buffer */
DestroyDSBuffer
(
p_aout
);
/* finally release the DirectSound object */
if
(
p_sys
->
p_dsobject
)
IDirectSound_Release
(
p_sys
->
p_dsobject
);
if
(
p_sys
->
p_dsobject
)
IDirectSound_Release
(
p_sys
->
p_dsobject
);
}
/*****************************************************************************
...
...
@@ -675,7 +640,7 @@ static int InitDirectSound( audio_output_t *p_aout )
*****************************************************************************/
static
int
CreateDSBuffer
(
audio_output_t
*
p_aout
,
int
i_format
,
int
i_channels
,
int
i_nb_channels
,
int
i_rate
,
int
i_bytes_per_frame
,
bool
b_probe
)
bool
b_probe
)
{
WAVEFORMATEXTENSIBLE
waveformat
;
DSBUFFERDESC
dsbdesc
;
...
...
@@ -723,14 +688,16 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
waveformat
.
Format
.
nAvgBytesPerSec
=
waveformat
.
Format
.
nSamplesPerSec
*
waveformat
.
Format
.
nBlockAlign
;
p_aout
->
sys
->
i_bytes_per_sample
=
waveformat
.
Format
.
nBlockAlign
;
p_aout
->
sys
->
format
=
i_format
;
/* Then fill in the direct sound descriptor */
memset
(
&
dsbdesc
,
0
,
sizeof
(
DSBUFFERDESC
));
dsbdesc
.
dwSize
=
sizeof
(
DSBUFFERDESC
);
dsbdesc
.
dwFlags
=
DSBCAPS_GETCURRENTPOSITION2
/* Better position accuracy */
|
DSBCAPS_GLOBALFOCUS
/* Allows background playing */
|
DSBCAPS_CTRLVOLUME
;
/* Allows volume control */
dsbdesc
.
dwFlags
=
DSBCAPS_GETCURRENTPOSITION2
/* Better position accuracy */
|
DSBCAPS_GLOBALFOCUS
/* Allows background playing */
|
DSBCAPS_CTRLVOLUME
/* Allows volume control */
|
DSBCAPS_CTRLPOSITIONNOTIFY
;
/* Allow position notifications */
/* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
if
(
i_nb_channels
<=
2
)
...
...
@@ -747,7 +714,7 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
dsbdesc
.
dwFlags
|=
DSBCAPS_LOCHARDWARE
;
}
dsbdesc
.
dwBufferBytes
=
FRAMES_NUM
*
i_bytes_per_frame
;
/* buffer size */
dsbdesc
.
dwBufferBytes
=
DS_BUF_SIZE
;
/* buffer size */
dsbdesc
.
lpwfxFormat
=
(
WAVEFORMATEX
*
)
&
waveformat
;
if
FAILED
(
IDirectSound_CreateSoundBuffer
(
...
...
@@ -781,7 +748,7 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
return
VLC_SUCCESS
;
}
p_aout
->
sys
->
i_
frame_size
=
i_bytes_per_fram
e
;
p_aout
->
sys
->
i_
rate
=
i_rat
e
;
p_aout
->
sys
->
i_channel_mask
=
waveformat
.
dwChannelMask
;
p_aout
->
sys
->
chans_to_reorder
=
aout_CheckChannelReorder
(
pi_channels_in
,
pi_channels_out
,
...
...
@@ -792,6 +759,18 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
msg_Dbg
(
p_aout
,
"channel reordering needed"
);
}
if
(
IDirectSoundBuffer_QueryInterface
(
p_aout
->
sys
->
p_dsbuffer
,
&
IID_IDirectSoundNotify
,
(
void
**
)
&
p_aout
->
sys
->
p_notify
)
!=
DS_OK
)
{
msg_Err
(
p_aout
,
"Couldn't query IDirectSoundNotify"
);
p_aout
->
sys
->
p_notify
=
NULL
;
}
FillBuffer
(
p_aout
,
NULL
);
return
VLC_SUCCESS
;
}
...
...
@@ -810,13 +789,11 @@ static int CreateDSBufferPCM( audio_output_t *p_aout, vlc_fourcc_t *i_format,
if
(
!
var_GetBool
(
p_aout
,
"directx-audio-float32"
)
||
i_nb_channels
>
2
||
CreateDSBuffer
(
p_aout
,
VLC_CODEC_FL32
,
i_channels
,
i_nb_channels
,
i_rate
,
(
i_rate
/
20
)
*
4
*
i_nb_channels
,
b_probe
)
i_channels
,
i_nb_channels
,
i_rate
,
b_probe
)
!=
VLC_SUCCESS
)
{
if
(
CreateDSBuffer
(
p_aout
,
VLC_CODEC_S16N
,
i_channels
,
i_nb_channels
,
i_rate
,
(
i_rate
/
20
)
*
2
*
i_nb_channels
,
b_probe
)
i_channels
,
i_nb_channels
,
i_rate
,
b_probe
)
!=
VLC_SUCCESS
)
{
return
VLC_EGENERIC
;
...
...
@@ -853,31 +830,32 @@ static void DestroyDSBuffer( audio_output_t *p_aout )
*****************************************************************************
* Returns VLC_SUCCESS on success.
*****************************************************************************/
static
int
FillBuffer
(
audio_output_t
*
p_aout
,
int
i_frame
,
block_t
*
p_buffer
)
static
int
FillBuffer
(
audio_output_t
*
p_aout
,
block_t
*
p_buffer
)
{
aout_sys_t
*
p_sys
=
p_aout
->
sys
;
notification_thread_t
*
p_notif
=
&
p_sys
->
notif
;
size_t
towrite
=
(
p_buffer
)
?
p_buffer
->
i_buffer
:
DS_BUF_SIZE
;
void
*
p_write_position
,
*
p_wrap_around
;
unsigned
long
l_bytes1
,
l_bytes2
;
HRESULT
dsresult
;
/* Before copying anything, we have to lock the buffer */
dsresult
=
IDirectSoundBuffer_Lock
(
p_sys
->
p_dsbuffer
,
/* DS buffer */
i_frame
*
p_notif
->
i_frame_size
,
/* Start offset */
p_notif
->
i_frame_size
,
/* Number of bytes */
&
p_write_position
,
/* Address of lock start */
&
l_bytes1
,
/* Count of bytes locked before wrap around */
&
p_wrap_around
,
/* Buffer address (if wrap around) */
&
l_bytes2
,
/* Count of bytes after wrap around */
0
);
/* Flags
*/
p_sys
->
p_dsbuffer
,
/* DS buffer */
p_aout
->
sys
->
i_write
,
/* Start offset */
towrite
,
/* Number of bytes */
&
p_write_position
,
/* Address of lock start */
&
l_bytes1
,
/* Count of bytes locked before wrap around */
&
p_wrap_around
,
/* Buffer address (if wrap around) */
&
l_bytes2
,
/* Count of bytes after wrap around */
0
);
/* Flags: DSBLOCK_FROMWRITECURSOR is buggy
*/
if
(
dsresult
==
DSERR_BUFFERLOST
)
{
IDirectSoundBuffer_Restore
(
p_sys
->
p_dsbuffer
);
dsresult
=
IDirectSoundBuffer_Lock
(
p_sys
->
p_dsbuffer
,
i_frame
*
p_notif
->
i_frame_siz
e
,
p_notif
->
i_frame_siz
e
,
p_aout
->
sys
->
i_writ
e
,
towrit
e
,
&
p_write_position
,
&
l_bytes1
,
&
p_wrap_around
,
...
...
@@ -904,6 +882,8 @@ static int FillBuffer( audio_output_t *p_aout, int i_frame, block_t *p_buffer )
p_sys
->
format
);
memcpy
(
p_write_position
,
p_buffer
->
p_buffer
,
l_bytes1
);
if
(
l_bytes1
<
p_buffer
->
i_buffer
)
memcpy
(
p_wrap_around
,
p_buffer
->
p_buffer
+
l_bytes1
,
l_bytes2
);
block_Release
(
p_buffer
);
}
...
...
@@ -911,117 +891,10 @@ static int FillBuffer( audio_output_t *p_aout, int i_frame, block_t *p_buffer )
IDirectSoundBuffer_Unlock
(
p_sys
->
p_dsbuffer
,
p_write_position
,
l_bytes1
,
p_wrap_around
,
l_bytes2
);
p_notif
->
i_write_slot
=
(
i_frame
+
1
)
%
FRAMES_NUM
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
* DirectSoundThread: this thread will capture play notification events.
*****************************************************************************
* We use this thread to emulate a callback mechanism. The thread probes for
* event notification and fills up the DS secondary buffer when needed.
*****************************************************************************/
static
void
*
DirectSoundThread
(
void
*
data
)
{
audio_output_t
*
p_aout
=
(
audio_output_t
*
)
data
;
notification_thread_t
*
p_notif
=
&
p_aout
->
sys
->
notif
;
mtime_t
last_time
;
msg_Dbg
(
p_aout
,
"DirectSoundThread ready"
);
/* Wait here until Play() is called */
WaitForSingleObject
(
p_notif
->
event
,
INFINITE
);
if
(
!
vlc_atomic_get
(
&
p_notif
->
abort
)
)
{
HRESULT
dsresult
;
mwait
(
p_notif
->
start_date
-
AOUT_MAX_PTS_ADVANCE
/
2
);
/* start playing the buffer */
dsresult
=
IDirectSoundBuffer_Play
(
p_aout
->
sys
->
p_dsbuffer
,
0
,
/* Unused */
0
,
/* Unused */
DSBPLAY_LOOPING
);
/* Flags */
if
(
dsresult
==
DSERR_BUFFERLOST
)
{
IDirectSoundBuffer_Restore
(
p_aout
->
sys
->
p_dsbuffer
);
dsresult
=
IDirectSoundBuffer_Play
(
p_aout
->
sys
->
p_dsbuffer
,
0
,
/* Unused */
0
,
/* Unused */
DSBPLAY_LOOPING
);
/* Flags */
}
if
(
dsresult
!=
DS_OK
)
{
msg_Err
(
p_aout
,
"cannot start playing buffer"
);
}
}
last_time
=
mdate
();
while
(
!
vlc_atomic_get
(
&
p_notif
->
abort
)
)
{
DWORD
l_read
;
int
l_queued
=
0
,
l_free_slots
;
unsigned
i_frame_siz
=
p_aout
->
sys
->
packet
.
samples
;
mtime_t
mtime
=
mdate
();
int
i
;
/* Update volume if required */
LONG
volume
=
InterlockedExchange
(
&
p_aout
->
sys
->
volume
.
volume
,
-
1
);
if
(
unlikely
(
volume
!=
-
1
)
)
IDirectSoundBuffer_SetVolume
(
p_aout
->
sys
->
p_dsbuffer
,
volume
);
/*
* Fill in as much audio data as we can in our circular buffer
*/
/* Find out current play position */
if
FAILED
(
IDirectSoundBuffer_GetCurrentPosition
(
p_aout
->
sys
->
p_dsbuffer
,
&
l_read
,
NULL
)
)
{
msg_Err
(
p_aout
,
"GetCurrentPosition() failed!"
);
l_read
=
0
;
}
p_sys
->
i_write
+=
towrite
;
p_sys
->
i_write
%=
DS_BUF_SIZE
;
/* Detect underruns */
if
(
l_queued
&&
mtime
-
last_time
>
INT64_C
(
1000000
)
*
l_queued
/
p_aout
->
sys
->
packet
.
format
.
i_rate
)
{
msg_Dbg
(
p_aout
,
"detected underrun!"
);
}
last_time
=
mtime
;
/* Try to fill in as many frame buffers as possible */
l_read
/=
(
p_aout
->
sys
->
packet
.
format
.
i_bytes_per_frame
/
p_aout
->
sys
->
packet
.
format
.
i_frame_length
);
l_queued
=
p_notif
->
i_write_slot
*
i_frame_siz
-
l_read
;
if
(
l_queued
<
0
)
l_queued
+=
(
i_frame_siz
*
FRAMES_NUM
);
l_free_slots
=
(
FRAMES_NUM
*
i_frame_siz
-
l_queued
)
/
i_frame_siz
;
for
(
i
=
0
;
i
<
l_free_slots
;
i
++
)
{
block_t
*
p_buffer
=
aout_PacketNext
(
p_aout
,
mtime
+
INT64_C
(
1000000
)
*
(
i
*
i_frame_siz
+
l_queued
)
/
p_aout
->
sys
->
packet
.
format
.
i_rate
);
/* If there is no audio data available and we have some buffered
* already, then just wait for the next time */
if
(
!
p_buffer
&&
(
i
||
l_queued
/
i_frame_siz
)
)
break
;
if
(
FillBuffer
(
p_aout
,
p_notif
->
i_write_slot
%
FRAMES_NUM
,
p_buffer
)
!=
VLC_SUCCESS
)
break
;
}
/* Sleep a reasonable amount of time */
l_queued
+=
(
i
*
i_frame_siz
);
msleep
(
INT64_C
(
1000000
)
*
l_queued
/
p_aout
->
sys
->
packet
.
format
.
i_rate
/
2
);
}
/* make sure the buffer isn't playing */
IDirectSoundBuffer_Stop
(
p_aout
->
sys
->
p_dsbuffer
);
msg_Dbg
(
p_aout
,
"DirectSoundThread exiting"
);
return
NULL
;
return
VLC_SUCCESS
;
}
typedef
struct
...
...
@@ -1106,11 +979,19 @@ static int Open(vlc_object_t *obj)
aout
->
mute_set
=
MuteSet
;
/* Volume */
LONG
mb
=
var_InheritInteger
(
aout
,
"directx-volume"
);
sys
->
volume
.
mb
=
mb
;
aout_VolumeReport
(
aout
,
cbrtf
(
powf
(
10
.
f
,
((
float
)
mb
)
/
2000
.
f
)));
sys
->
volume
.
volume
=
var_InheritFloat
(
aout
,
"directx-volume"
);
aout_VolumeReport
(
aout
,
sys
->
volume
.
volume
);
MuteSet
(
aout
,
var_InheritBool
(
aout
,
"mute"
));
sys
->
hnotify_evt
=
CreateEvent
(
NULL
,
FALSE
,
TRUE
,
NULL
);
if
(
!
sys
->
hnotify_evt
)
{
msg_Err
(
aout
,
"cannot create Event"
);
FreeLibrary
(
sys
->
hdsound_dll
);
free
(
sys
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
...
...
@@ -1119,6 +1000,67 @@ static void Close(vlc_object_t *obj)
audio_output_t
*
aout
=
(
audio_output_t
*
)
obj
;
aout_sys_t
*
sys
=
aout
->
sys
;
CloseHandle
(
sys
->
hnotify_evt
);
FreeLibrary
(
sys
->
hdsound_dll
);
/* free DSOUND.DLL */
free
(
sys
);
}
static
void
Flush
(
audio_output_t
*
aout
,
bool
drain
)
{
aout_sys_t
*
sys
=
aout
->
sys
;
size_t
read
;
if
(
drain
)
{
if
(
sys
->
p_notify
)
{
DSBPOSITIONNOTIFY
notif
=
{.
dwOffset
=
aout
->
sys
->
i_write
,
.
hEventNotify
=
sys
->
hnotify_evt
}
;
if
(
IDirectSoundNotify_SetNotificationPositions
(
sys
->
p_notify
,
1
,
&
notif
)
==
DS_OK
)
{
WaitForSingleObject
(
sys
->
hnotify_evt
,
INFINITE
);
IDirectSoundBuffer_Stop
(
aout
->
sys
->
p_dsbuffer
);
}
}
else
while
(
IDirectSoundBuffer_GetCurrentPosition
(
aout
->
sys
->
p_dsbuffer
,(
LPDWORD
)
&
read
,
NULL
)
==
DS_OK
)
{
read
%=
DS_BUF_SIZE
;
if
(
read
==
aout
->
sys
->
i_write
)
break
;
msleep
(
10000
);
}
}
else
{
IDirectSoundBuffer_Stop
(
aout
->
sys
->
p_dsbuffer
);
IDirectSoundBuffer_SetCurrentPosition
(
aout
->
sys
->
p_dsbuffer
,
aout
->
sys
->
i_write
);
}
}
static
void
Pause
(
audio_output_t
*
aout
,
bool
pause
,
mtime_t
date
)
{
(
void
)
date
;
if
(
pause
)
IDirectSoundBuffer_Stop
(
aout
->
sys
->
p_dsbuffer
);
else
IDirectSoundBuffer_Play
(
aout
->
sys
->
p_dsbuffer
,
0
,
0
,
DSBPLAY_LOOPING
);
}
static
int
TimeGet
(
audio_output_t
*
aout
,
mtime_t
*
delay
)
{
uint32_t
read
;
mtime_t
size
;
if
(
IDirectSoundBuffer_GetCurrentPosition
(
aout
->
sys
->
p_dsbuffer
,
(
LPDWORD
)
&
read
,
NULL
)
!=
DS_OK
)
return
1
;
read
%=
DS_BUF_SIZE
;
size
=
(
mtime_t
)
aout
->
sys
->
i_write
-
(
mtime_t
)
read
;
if
(
size
<
0
)
size
+=
DS_BUF_SIZE
;
*
delay
=
(
size
/
aout
->
sys
->
i_bytes_per_sample
)
*
CLOCK_FREQ
/
aout
->
sys
->
i_rate
;
return
0
;
}
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