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
7ae23ab6
Commit
7ae23ab6
authored
Nov 25, 2005
by
Gildas Bazin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* modules/audio_output/directx.c: backport of directx audio changes (13374). Needs heavy testing.
parent
bade4231
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
68 additions
and
134 deletions
+68
-134
modules/audio_output/directx.c
modules/audio_output/directx.c
+68
-134
No files found.
modules/audio_output/directx.c
View file @
7ae23ab6
...
...
@@ -41,17 +41,12 @@
#define FRAME_SIZE ((int)p_aout->output.output.i_rate/20)
/* Size in samples */
#define FRAMES_NUM 8
/* Needs to be > 3 */
/* frame buffer status */
#define FRAME_QUEUED 0
#define FRAME_EMPTY 1
/*****************************************************************************
* DirectSound GUIDs.
* Defining them here allows us to get rid of the dxguid library during
* the linking stage.
*****************************************************************************/
#include <initguid.h>
DEFINE_GUID
(
IID_IDirectSoundNotify
,
0xb0210783
,
0x89cd
,
0x11d0
,
0xaf
,
0x8
,
0x0
,
0xa0
,
0xc9
,
0x25
,
0xcd
,
0x16
);
/*****************************************************************************
* Useful macros
...
...
@@ -134,12 +129,12 @@ typedef struct notification_thread_t
{
VLC_COMMON_MEMBERS
aout_instance_t
*
p_aout
;
int
i_frame_status
[
FRAMES_NUM
];
/* status of each frame buffer */
DSBPOSITIONNOTIFY
p_events
[
FRAMES_NUM
];
/* play notification events */
int
i_frame_size
;
/* Size in bytes of one frame */
aout_instance_t
*
p_aout
;
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
;
}
notification_thread_t
;
...
...
@@ -161,7 +156,6 @@ struct aout_sys_t
* takes care of mixing all the
* secondary buffers into the primary) */
LPDIRECTSOUNDNOTIFY
p_dsnotify
;
/* the position notify interface */
notification_thread_t
*
p_notif
;
/* DirectSoundThread id */
int
b_playing
;
/* playing status */
...
...
@@ -242,7 +236,6 @@ static int OpenAudio( vlc_object_t *p_this )
{
aout_instance_t
*
p_aout
=
(
aout_instance_t
*
)
p_this
;
vlc_value_t
val
;
int
i
;
msg_Dbg
(
p_aout
,
"OpenAudio"
);
...
...
@@ -257,7 +250,6 @@ static int OpenAudio( vlc_object_t *p_this )
/* Initialize some variables */
p_aout
->
output
.
p_sys
->
p_dsobject
=
NULL
;
p_aout
->
output
.
p_sys
->
p_dsbuffer
=
NULL
;
p_aout
->
output
.
p_sys
->
p_dsnotify
=
NULL
;
p_aout
->
output
.
p_sys
->
p_notif
=
NULL
;
p_aout
->
output
.
p_sys
->
b_playing
=
0
;
...
...
@@ -291,16 +283,6 @@ static int OpenAudio( vlc_object_t *p_this )
goto
error
;
}
/* Now we need to setup our DirectSound play notification structure */
p_aout
->
output
.
p_sys
->
p_notif
=
vlc_object_create
(
p_aout
,
sizeof
(
notification_thread_t
)
);
p_aout
->
output
.
p_sys
->
p_notif
->
p_aout
=
p_aout
;
/* Then create the notification events */
for
(
i
=
0
;
i
<
FRAMES_NUM
;
i
++
)
p_aout
->
output
.
p_sys
->
p_notif
->
p_events
[
i
].
hEventNotify
=
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
);
/* Open the device */
if
(
val
.
i_int
==
AOUT_VAR_SPDIF
)
{
...
...
@@ -372,12 +354,18 @@ static int OpenAudio( vlc_object_t *p_this )
/* Calculate the frame size in bytes */
p_aout
->
output
.
i_nb_samples
=
FRAME_SIZE
;
aout_FormatPrepare
(
&
p_aout
->
output
.
output
);
p_aout
->
output
.
p_sys
->
i_frame_size
=
FRAME_SIZE
*
p_aout
->
output
.
output
.
i_bytes_per_frame
;
aout_VolumeSoftInit
(
p_aout
);
}
/* Now we need to setup our DirectSound play notification structure */
p_aout
->
output
.
p_sys
->
p_notif
=
vlc_object_create
(
p_aout
,
sizeof
(
notification_thread_t
)
);
p_aout
->
output
.
p_sys
->
p_notif
->
p_aout
=
p_aout
;
p_aout
->
output
.
p_sys
->
p_notif
->
event
=
CreateEvent
(
0
,
FALSE
,
FALSE
,
0
);
p_aout
->
output
.
p_sys
->
p_notif
->
i_frame_size
=
p_aout
->
output
.
p_sys
->
i_frame_size
;
/* then launch the notification thread */
msg_Dbg
(
p_aout
,
"creating DirectSoundThread"
);
if
(
vlc_thread_create
(
p_aout
->
output
.
p_sys
->
p_notif
,
...
...
@@ -386,6 +374,9 @@ static int OpenAudio( vlc_object_t *p_this )
VLC_THREAD_PRIORITY_HIGHEST
,
VLC_FALSE
)
)
{
msg_Err
(
p_aout
,
"cannot create DirectSoundThread"
);
CloseHandle
(
p_aout
->
output
.
p_sys
->
p_notif
->
event
);
vlc_object_destroy
(
p_aout
->
output
.
p_sys
->
p_notif
);
p_aout
->
output
.
p_sys
->
p_notif
=
0
;
goto
error
;
}
...
...
@@ -564,6 +555,7 @@ static void Play( aout_instance_t *p_aout )
if
(
!
p_aout
->
output
.
p_sys
->
b_playing
)
{
aout_buffer_t
*
p_buffer
;
int
i
;
p_aout
->
output
.
p_sys
->
b_playing
=
1
;
...
...
@@ -572,11 +564,15 @@ static void Play( aout_instance_t *p_aout )
aout_FifoFirstDate
(
p_aout
,
&
p_aout
->
output
.
fifo
);
/* fill in the first samples */
p_buffer
=
aout_FifoPop
(
p_aout
,
&
p_aout
->
output
.
fifo
);
FillBuffer
(
p_aout
,
0
,
p_buffer
);
for
(
i
=
0
;
i
<
FRAMES_NUM
;
i
++
)
{
p_buffer
=
aout_FifoPop
(
p_aout
,
&
p_aout
->
output
.
fifo
);
if
(
!
p_buffer
)
break
;
FillBuffer
(
p_aout
,
i
,
p_buffer
);
}
/* wake up the audio output thread */
SetEvent
(
p_aout
->
output
.
p_sys
->
p_notif
->
p_events
[
0
].
hEventNotify
);
SetEvent
(
p_aout
->
output
.
p_sys
->
p_notif
->
event
);
}
}
...
...
@@ -598,9 +594,8 @@ static void CloseAudio( vlc_object_t *p_this )
{
p_sys
->
p_notif
->
b_die
=
1
;
if
(
!
p_sys
->
b_playing
)
/* wake up the audio thread */
SetEvent
(
p_sys
->
p_notif
->
p_events
[
0
].
hEventNotify
);
/* wake up the audio thread if needed */
if
(
!
p_sys
->
b_playing
)
SetEvent
(
p_sys
->
p_notif
->
event
);
vlc_thread_join
(
p_sys
->
p_notif
);
}
...
...
@@ -792,7 +787,6 @@ static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
memset
(
&
dsbdesc
,
0
,
sizeof
(
DSBUFFERDESC
));
dsbdesc
.
dwSize
=
sizeof
(
DSBUFFERDESC
);
dsbdesc
.
dwFlags
=
DSBCAPS_GETCURRENTPOSITION2
/* Better position accuracy */
|
DSBCAPS_CTRLPOSITIONNOTIFY
/* We need notification */
|
DSBCAPS_GLOBALFOCUS
;
/* Allows background playing */
/* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
...
...
@@ -844,40 +838,8 @@ static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
return
VLC_SUCCESS
;
}
/* Backup the size of a frame */
p_aout
->
output
.
p_sys
->
p_notif
->
i_frame_size
=
i_bytes_per_frame
;
/* Now the secondary buffer is created, we need to setup its position
* notification */
for
(
i
=
0
;
i
<
FRAMES_NUM
;
i
++
)
{
p_aout
->
output
.
p_sys
->
p_notif
->
p_events
[
i
].
dwOffset
=
i
*
p_aout
->
output
.
p_sys
->
p_notif
->
i_frame_size
;
p_aout
->
output
.
p_sys
->
p_notif
->
i_frame_status
[
i
]
=
FRAME_EMPTY
;
}
/* Get the IDirectSoundNotify interface */
if
FAILED
(
IDirectSoundBuffer_QueryInterface
(
p_aout
->
output
.
p_sys
->
p_dsbuffer
,
&
IID_IDirectSoundNotify
,
(
LPVOID
*
)
&
p_aout
->
output
.
p_sys
->
p_dsnotify
)
)
{
msg_Err
(
p_aout
,
"cannot get IDirectSoundNotify interface"
);
goto
error
;
}
if
FAILED
(
IDirectSoundNotify_SetNotificationPositions
(
p_aout
->
output
.
p_sys
->
p_dsnotify
,
FRAMES_NUM
,
p_aout
->
output
.
p_sys
->
p_notif
->
p_events
)
)
{
msg_Err
(
p_aout
,
"cannot set position notification"
);
goto
error
;
}
p_aout
->
output
.
p_sys
->
i_frame_size
=
i_bytes_per_frame
;
p_aout
->
output
.
p_sys
->
i_channel_mask
=
waveformat
.
dwChannelMask
;
p_aout
->
output
.
p_sys
->
b_chan_reorder
=
aout_CheckChannelReorder
(
pi_channels_in
,
pi_channels_out
,
waveformat
.
dwChannelMask
,
i_nb_channels
,
...
...
@@ -889,10 +851,6 @@ static int CreateDSBuffer( aout_instance_t *p_aout, int i_format,
}
return
VLC_SUCCESS
;
error:
DestroyDSBuffer
(
p_aout
);
return
VLC_EGENERIC
;
}
/*****************************************************************************
...
...
@@ -944,12 +902,6 @@ static int CreateDSBufferPCM( aout_instance_t *p_aout, int *i_format,
*****************************************************************************/
static
void
DestroyDSBuffer
(
aout_instance_t
*
p_aout
)
{
if
(
p_aout
->
output
.
p_sys
->
p_dsnotify
)
{
IDirectSoundNotify_Release
(
p_aout
->
output
.
p_sys
->
p_dsnotify
);
p_aout
->
output
.
p_sys
->
p_dsnotify
=
NULL
;
}
if
(
p_aout
->
output
.
p_sys
->
p_dsbuffer
)
{
IDirectSoundBuffer_Release
(
p_aout
->
output
.
p_sys
->
p_dsbuffer
);
...
...
@@ -1024,6 +976,7 @@ static int FillBuffer( aout_instance_t *p_aout, int i_frame,
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
;
}
...
...
@@ -1035,15 +988,11 @@ static int FillBuffer( aout_instance_t *p_aout, int i_frame,
*****************************************************************************/
static
void
DirectSoundThread
(
notification_thread_t
*
p_notif
)
{
HANDLE
notification_events
[
FRAMES_NUM
];
HRESULT
dsresult
;
aout_instance_t
*
p_aout
=
p_notif
->
p_aout
;
int
i
,
i_which_frame
,
i_last_frame
;
mtime_t
mtime
;
vlc_bool_t
b_sleek
;
for
(
i
=
0
;
i
<
FRAMES_NUM
;
i
++
)
notification_events
[
i
]
=
p_notif
->
p_events
[
i
].
hEventNotify
;
mtime_t
last_time
;
HRESULT
dsresult
;
long
l_queued
=
0
;
/* We don't want any resampling when using S/PDIF output */
b_sleek
=
p_aout
->
output
.
output
.
i_format
==
VLC_FOURCC
(
's'
,
'p'
,
'd'
,
'i'
);
...
...
@@ -1054,7 +1003,7 @@ static void DirectSoundThread( notification_thread_t *p_notif )
msg_Dbg
(
p_notif
,
"DirectSoundThread ready"
);
/* Wait here until Play() is called */
WaitForSingleObject
(
notification_events
[
0
]
,
INFINITE
);
WaitForSingleObject
(
p_notif
->
event
,
INFINITE
);
if
(
!
p_notif
->
b_die
)
{
...
...
@@ -1079,79 +1028,64 @@ static void DirectSoundThread( notification_thread_t *p_notif )
msg_Err
(
p_aout
,
"cannot start playing buffer"
);
}
}
last_time
=
mdate
();
while
(
!
p_notif
->
b_die
)
{
aout_buffer_t
*
p_buffer
;
long
l_position
,
l_latency
=
0
;
/* wait for the position notification */
i_which_frame
=
WaitForMultipleObjects
(
FRAMES_NUM
,
notification_events
,
0
,
INFINITE
)
-
WAIT_OBJECT_0
;
long
l_read
,
l_free_slots
;
mtime_t
mtime
=
mdate
();
int
i
;
if
(
p_notif
->
b_die
)
break
;
/*
* Fill in as much audio data as we can in our circular buffer
*/
mtime
=
mdate
();
/* We take into account the current latency */
if
SUCCEEDED
(
IDirectSoundBuffer_GetCurrentPosition
(
p_aout
->
output
.
p_sys
->
p_dsbuffer
,
&
l_position
,
NULL
)
)
/* Find out current play position */
if
FAILED
(
IDirectSoundBuffer_GetCurrentPosition
(
p_aout
->
output
.
p_sys
->
p_dsbuffer
,
&
l_read
,
NULL
)
)
{
/* Latency is in samples */
l_position
/=
p_aout
->
output
.
output
.
i_bytes_per_frame
;
l_latency
=
l_position
-
i_which_frame
*
FRAME_SIZE
;
/* That sucks but latency can apparently be negative up to -FRAME_SIZE
* ie. the notification is done in advance. */
if
(
l_latency
>
FRAME_SIZE
*
(
FRAMES_NUM
-
1
)
)
l_latency
-=
(
FRAME_SIZE
*
FRAMES_NUM
);
else
if
(
l_latency
<
-
FRAME_SIZE
)
l_latency
+=
(
FRAME_SIZE
*
FRAMES_NUM
);
msg_Err
(
p_aout
,
"GetCurrentPosition() failed!"
);
l_read
=
0
;
}
/* Mark last frame as empty */
i_last_frame
=
(
i_which_frame
+
FRAMES_NUM
-
1
)
%
FRAMES_NUM
;
p_notif
->
i_frame_status
[
i_last_frame
]
=
FRAME_EMPTY
;
/* Try to fill in as many frame buffers as possible */
for
(
i
=
i_which_frame
+
1
;
i
<
i_which_frame
+
FRAMES_NUM
;
i
++
)
/* Detect underruns */
if
(
l_queued
&&
mtime
-
last_time
>
I64C
(
1000000
)
*
l_queued
/
p_aout
->
output
.
output
.
i_rate
)
{
/* Check if frame buf is already filled */
if
(
p_notif
->
i_frame_status
[
i
%
FRAMES_NUM
]
==
FRAME_QUEUED
)
continu
e
;
msg_Dbg
(
p_aout
,
"detected underrun!"
);
}
last_time
=
mtim
e
;
if
(
((
i
-
i_which_frame
)
*
FRAME_SIZE
-
l_latency
)
<
0
)
{
msg_Warn
(
p_aout
,
"dectected underrun!"
);
}
/* Try to fill in as many frame buffers as possible */
l_read
/=
p_aout
->
output
.
output
.
i_bytes_per_frame
;
l_queued
=
p_notif
->
i_write_slot
*
FRAME_SIZE
-
l_read
;
if
(
l_queued
<
0
)
l_queued
+=
(
FRAME_SIZE
*
FRAMES_NUM
);
l_free_slots
=
(
FRAMES_NUM
*
FRAME_SIZE
-
l_queued
)
/
FRAME_SIZE
;
p_buffer
=
aout_OutputNextBuffer
(
p_aout
,
mtime
+
I64C
(
1000000
)
*
((
i
-
i_which_frame
)
*
FRAME_SIZE
-
l_latency
)
/
p_aout
->
output
.
output
.
i_rate
,
b_sleek
);
for
(
i
=
0
;
i
<
l_free_slots
;
i
++
)
{
aout_buffer_t
*
p_buffer
=
aout_OutputNextBuffer
(
p_aout
,
mtime
+
I64C
(
1000000
)
*
(
i
*
FRAME_SIZE
+
l_queued
)
/
p_aout
->
output
.
output
.
i_rate
,
b_sleek
);
/* If there is no audio data available and we have some buffered
* already, then just wait for the next time */
if
(
!
p_buffer
&&
(
i
!=
i_which_frame
+
1
)
)
break
;
if
(
FillBuffer
(
p_aout
,
(
i
%
FRAMES_NUM
),
p_buffer
)
!=
VLC_SUCCESS
)
break
;
if
(
!
p_buffer
&&
(
i
||
l_queued
/
FRAME_SIZE
)
)
break
;
/* Mark the frame buffer as QUEUED */
p_notif
->
i_frame_status
[
i
%
FRAMES_NUM
]
=
FRAME_QUEUED
;
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
*
FRAME_SIZE
);
msleep
(
I64C
(
1000000
)
*
l_queued
/
p_aout
->
output
.
output
.
i_rate
/
2
);
}
/* make sure the buffer isn't playing */
IDirectSoundBuffer_Stop
(
p_aout
->
output
.
p_sys
->
p_dsbuffer
);
/* free the events */
for
(
i
=
0
;
i
<
FRAMES_NUM
;
i
++
)
CloseHandle
(
notification_events
[
i
]
);
/* free the event */
CloseHandle
(
p_notif
->
event
);
msg_Dbg
(
p_notif
,
"DirectSoundThread exiting"
);
}
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