improved PaWasapi_ThreadPriorityBoost by providing enum PaWasapiThreadPriority with explicit thread priority values for convenience. it is possible to override default thread priority setting for Event/Poll-driven modes by specifying new flag paWinWasapiThreadPriority and setting priority value through PaWasapiStreamInfo::threadPriority member.

This commit is contained in:
dmitrykos 2010-02-17 10:11:40 +00:00
commit 75e59cb874
2 changed files with 101 additions and 38 deletions

View file

@ -68,12 +68,17 @@ typedef enum PaWasapiFlags
Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling
method can only provide 15-20ms latency. */
paWinWasapiPolling = (1 << 3),
/* forces custom thread priority setting. must be used if PaWasapiStreamInfo::threadPriority
is set to custom value. */
paWinWasapiThreadPriority = (1 << 4)
}
PaWasapiFlags;
#define paWinWasapiExclusive (paWinWasapiExclusive)
#define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor)
#define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask)
#define paWinWasapiPolling (paWinWasapiPolling)
#define paWinWasapiThreadPriority (paWinWasapiThreadPriority)
/* Host processor. Allows to skip internal PA processing completely.
@ -86,46 +91,6 @@ typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFra
void *outputBuffer, long outputFrames,
void *userData);
/* Stream descriptor. */
typedef struct PaWasapiStreamInfo
{
unsigned long size; /**< sizeof(PaWasapiStreamInfo) */
PaHostApiTypeId hostApiType; /**< paWASAPI */
unsigned long version; /**< 1 */
unsigned long flags; /**< collection of PaWasapiFlags */
/* Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
paWinWasapiUseChannelMask this allows you to specify which speakers
to address in a multichannel stream. Constants for channelMask
are specified in pa_win_waveformat.h
*/
PaWinWaveFormatChannelMask channelMask;
/* Delivers raw data to callback obtained from GetBuffer() methods skipping
internal PortAudio processing inventory completely. userData parameter will
be the same that was passed to Pa_OpenStream method.
*/
PaWasapiHostProcessorCallback hostProcessorOutput;
PaWasapiHostProcessorCallback hostProcessorInput;
}
PaWasapiStreamInfo;
/** Returns default sound format for device. Format is represented by PaWinWaveFormat or
WAVEFORMATEXTENSIBLE structure.
@param pFormat pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
@param nFormatSize pize of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
@param nDevice device index.
@return A non-negative value indicating the number of bytes copied into format decriptor
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
or an error is encountered.
*/
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceIndex nDevice );
/* Device role */
typedef enum PaWasapiDeviceRole
{
@ -144,6 +109,72 @@ typedef enum PaWasapiDeviceRole
PaWasapiDeviceRole;
/* Thread priority */
typedef enum PaWasapiThreadPriority
{
eThreadPriorityNone = 0,
eThreadPriorityAudio, //!< Default for Shared mode.
eThreadPriorityCapture,
eThreadPriorityDistribution,
eThreadPriorityGames,
eThreadPriorityPlayback,
eThreadPriorityProAudio, //!< Default for Exclusive mode.
eThreadPriorityWindowManager
}
PaWasapiThreadPriority;
/* Stream descriptor. */
typedef struct PaWasapiStreamInfo
{
unsigned long size; /**< sizeof(PaWasapiStreamInfo) */
PaHostApiTypeId hostApiType; /**< paWASAPI */
unsigned long version; /**< 1 */
unsigned long flags; /**< collection of PaWasapiFlags */
/* Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
paWinWasapiUseChannelMask this allows you to specify which speakers
to address in a multichannel stream. Constants for channelMask
are specified in pa_win_waveformat.h. Will be used only if
paWinWasapiUseChannelMask flag is specified.
*/
PaWinWaveFormatChannelMask channelMask;
/* Delivers raw data to callback obtained from GetBuffer() methods skipping
internal PortAudio processing inventory completely. userData parameter will
be the same that was passed to Pa_OpenStream method. Will be used only if
paWinWasapiRedirectHostProcessor flag is specified.
*/
PaWasapiHostProcessorCallback hostProcessorOutput;
PaWasapiHostProcessorCallback hostProcessorInput;
/* Specifies thread priority explicitly. Will be used only if paWinWasapiThreadPriority flag
is specified.
Please note, if Input/Output streams are opened simultaniously (Full-Duplex mode)
you shall specify same value for threadPriority or othervise one of the values will be used
to setup thread priority.
*/
PaWasapiThreadPriority threadPriority;
}
PaWasapiStreamInfo;
/** Returns default sound format for device. Format is represented by PaWinWaveFormat or
WAVEFORMATEXTENSIBLE structure.
@param pFormat pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
@param nFormatSize pize of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
@param nDevice device index.
@return A non-negative value indicating the number of bytes copied into format decriptor
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
or an error is encountered.
*/
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice );
/** Returns device role (PaWasapiDeviceRole enum).
@param nDevice device index.
@ -160,18 +191,13 @@ int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice );
@param hTask a handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority
method to revert thread priority to initial state.
@param nPriorityClass an Id of thread priority: 1 - Audio
2 - Capture
3 - Distribution
4 - Games
5 - Playback
6 - Pro Audio
7 - Window Manager
@param nPriorityClass an Id of thread priority of PaWasapiThreadPriority type. Specifying
eThreadPriorityNone does nothing.
@return Error code indicating success or failure.
@see PaWasapi_RevertThreadPriority
*/
PaError PaWasapi_ThreadPriorityBoost( void **hTask, int nPriorityClass );
PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass );
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread

View file

@ -97,6 +97,8 @@ PA_THREAD_FUNC ProcThreadPoll(void *param);
enum { S_INPUT = 0, S_OUTPUT, S_COUNT };
#define STATIC_ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
#define PRINT(x) PA_DEBUG(x);
#define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \
@ -315,6 +317,9 @@ typedef struct PaWasapiStream
// Av Task (MM thread management)
HANDLE hAvTask;
// Thread priority level
PaWasapiThreadPriority nThreadPriority;
}
PaWasapiStream;
@ -893,7 +898,7 @@ static inline PaWasapiHostApiRepresentation *GetHostApi(PaError *_error = NULL)
}
// ------------------------------------------------------------------------------------------
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceIndex nDevice )
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice )
{
if (pFormat == NULL)
return paBadBufferPtr;
@ -907,10 +912,10 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceInd
if (paWasapi == NULL)
return ret;
if (nDevice >= (int)paWasapi->deviceCount)
if ((UINT32)nDevice >= paWasapi->deviceCount)
return paInvalidDevice;
int size = min(nFormatSize, sizeof(paWasapi->devInfo[ nDevice ].DefaultFormat));
UINT32 size = min(nFormatSize, (UINT32)sizeof(paWasapi->devInfo[ nDevice ].DefaultFormat));
memcpy(pFormat, &paWasapi->devInfo[ nDevice ].DefaultFormat, size);
return size;
@ -1560,6 +1565,9 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
goto error;
}
// Default thread priority is Audio: for exclusive mode we will use Pro Audio.
stream->nThreadPriority = eThreadPriorityAudio;
// Try create device: Input
if (inputParameters != NULL)
{
@ -1572,7 +1580,20 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
// Select Exclusive/Shared mode
stream->in.shareMode = AUDCLNT_SHAREMODE_SHARED;
if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiExclusive))
{
// Boost thread priority
stream->nThreadPriority = eThreadPriorityProAudio;
// Make Exclusive
stream->in.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;
}
// If user provided explicit thread priority level, use it
if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiThreadPriority))
{
if ((inputStreamInfo->threadPriority > eThreadPriorityNone) &&
(inputStreamInfo->threadPriority <= eThreadPriorityWindowManager))
stream->nThreadPriority = inputStreamInfo->threadPriority;
}
// Choose processing mode
stream->in.streamFlags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
@ -1661,7 +1682,20 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
// Select Exclusive/Shared mode
stream->out.shareMode = AUDCLNT_SHAREMODE_SHARED;
if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiExclusive))
{
// Boost thread priority
stream->nThreadPriority = eThreadPriorityProAudio;
// Make Exclusive
stream->out.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;
}
// If user provided explicit thread priority level, use it
if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiThreadPriority))
{
if ((outputStreamInfo->threadPriority > eThreadPriorityNone) &&
(outputStreamInfo->threadPriority <= eThreadPriorityWindowManager))
stream->nThreadPriority = outputStreamInfo->threadPriority;
}
// Choose processing mode
stream->out.streamFlags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
@ -2440,13 +2474,14 @@ void MMCSS_deactivate(HANDLE hTask)
}
// ------------------------------------------------------------------------------------------
PaError PaWasapi_ThreadPriorityBoost(void **hTask, int nPriorityClass)
PaError PaWasapi_ThreadPriorityBoost(void **hTask, PaWasapiThreadPriority nPriorityClass)
{
if (hTask == NULL)
return paUnanticipatedHostError;
static const char *mmcs_name[7] =
static const char *mmcs_name[] =
{
NULL,
"Audio",
"Capture",
"Distribution",
@ -2455,7 +2490,7 @@ PaError PaWasapi_ThreadPriorityBoost(void **hTask, int nPriorityClass)
"Pro Audio",
"Window Manager"
};
if ((UINT32)nPriorityClass >= 7)
if ((UINT32)nPriorityClass >= STATIC_ARRAY_SIZE(mmcs_name))
return paUnanticipatedHostError;
HANDLE task = MMCSS_activate(mmcs_name[nPriorityClass]);
@ -2546,7 +2581,7 @@ void _OnStreamStop(PaWasapiStream *stream)
// Restore thread priority
if (stream->hAvTask != NULL)
{
MMCSS_deactivate(stream->hAvTask);
PaWasapi_ThreadPriorityRevert(stream->hAvTask);
stream->hAvTask = NULL;
}
@ -2584,7 +2619,8 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
}
// Boost thread priority
stream->hAvTask = MMCSS_activate("Pro Audio");
stream->hAvTask = NULL;
PaWasapi_ThreadPriorityBoost((void **)&stream->hAvTask, stream->nThreadPriority);
// Initialize event & start INPUT stream
if (stream->in.client)
@ -2693,7 +2729,8 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
processor[S_OUTPUT] = (stream->hostProcessOverrideOutput.processor != NULL ? stream->hostProcessOverrideOutput : defaultProcessor);
// Boost thread priority
stream->hAvTask = MMCSS_activate("Pro Audio");
stream->hAvTask = NULL;
PaWasapi_ThreadPriorityBoost((void **)&stream->hAvTask, stream->nThreadPriority);
// Initialize event & start INPUT stream
if (stream->in.client)