gecko/media/libsydneyaudio/sydney_os2_moz.patch

391 lines
13 KiB
Diff

diff --git a/media/libsydneyaudio/src/sydney_audio_os2.c b/media/libsydneyaudio/src/sydney_audio_os2.c
--- a/media/libsydneyaudio/src/sydney_audio_os2.c
+++ b/media/libsydneyaudio/src/sydney_audio_os2.c
@@ -143,27 +143,42 @@ struct sa_stream {
int32_t readyCnt;
int32_t readyNdx;
HEV usedSem;
volatile int32_t usedCnt;
/* miscellaneous */
volatile int32_t state;
int64_t writePos;
+ /* workaround for Bug 495352 */
+ uint32_t zeroCnt;
};
/*****************************************************************************/
/* Private (static) Functions */
static int32_t os2_mixer_event(uint32_t ulStatus, PMCI_MIX_BUFFER pBuffer,
uint32_t ulFlags);
static int os2_write_to_device(sa_stream_t *s);
static void os2_stop_device(uint16_t hwDeviceID);
static int os2_pause_device(uint16_t hwDeviceID, uint32_t release);
static int os2_get_free_count(sa_stream_t *s, int32_t count);
+
+/*****************************************************************************/
+/* Mozilla-specific Additions */
+
+/* reset the decode thread's priority */
+static void os2_set_priority(void);
+
+/* load mdm.dll on demand */
+static int os2_load_mdm(void);
+
+/* invoke mciSendCommand() via a static variable */
+typedef ULONG _System MCISENDCOMMAND(USHORT, USHORT, ULONG, PVOID, USHORT);
+static MCISENDCOMMAND * _mciSendCommand = 0;
/*****************************************************************************/
/* Sydney Audio Functions */
/*****************************************************************************/
/** Normal way to open a PCM device */
int sa_stream_create_pcm(sa_stream_t ** s,
@@ -176,16 +191,20 @@ int sa_stream_create_pcm(sa_stream_t
uint32_t status = SA_SUCCESS;
uint32_t size;
uint32_t rc;
sa_stream_t * sTemp = 0;
/* this do{}while(0) "loop" makes it easy to ensure
* resources are freed on exit if there's an error */
do {
+ /* load mdm.dll if it isn't already loaded */
+ if (os2_load_mdm() != SA_SUCCESS)
+ return SA_ERROR_SYSTEM;
+
if (mode != SA_MODE_WRONLY || format != SA_PCM_FORMAT_S16_LE)
return os2_error(SA_ERROR_NOT_SUPPORTED, "sa_stream_create_pcm",
"invalid mode or format", 0);
if (!s)
return os2_error(SA_ERROR_INVALID, "sa_stream_create_pcm",
"s is null", 0);
*s = 0;
@@ -257,25 +276,28 @@ int sa_stream_open(sa_stream_t *s)
MCI_AMP_OPEN_PARMS AmpOpenParms;
MCI_MIXSETUP_PARMS MixSetupParms;
MCI_BUFFER_PARMS BufferParms;
if (!s)
return os2_error(SA_ERROR_NO_INIT, "sa_stream_open", "s is null", 0);
do {
+ /* set this thread's priority to 2-08 */
+ os2_set_priority();
+
/* s->bufCnt will be restored after successfully allocating buffers */
bufCntRequested = s->bufCnt;
s->bufCnt = 0;
/* open the Amp-Mixer using the default device in shared mode */
memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
AmpOpenParms.pszDeviceType = (PSZ)(MCI_DEVTYPE_AUDIO_AMPMIX | 0);
- rc = mciSendCommand(0, MCI_OPEN,
+ rc = _mciSendCommand(0, MCI_OPEN,
MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
(void*)&AmpOpenParms, 0);
if (LOUSHORT(rc)) {
status = os2_error(SA_ERROR_NO_DEVICE, "sa_stream_open",
"MCI_OPEN - rc=", LOUSHORT(rc));
break;
}
@@ -287,17 +309,17 @@ do {
MixSetupParms.ulBitsPerSample = 16;
MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
MixSetupParms.ulFormatMode = MCI_PLAY;
MixSetupParms.ulSamplesPerSec = s->rate;
MixSetupParms.ulChannels = s->nchannels;
MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
MixSetupParms.pmixEvent = (MIXEREVENT*)os2_mixer_event;
- rc = mciSendCommand(s->hwDeviceID, MCI_MIXSETUP,
+ rc = _mciSendCommand(s->hwDeviceID, MCI_MIXSETUP,
MCI_WAIT | MCI_MIXSETUP_INIT,
(void*)&MixSetupParms, 0);
if (LOUSHORT(rc)) {
status = os2_error(SA_ERROR_NOT_SUPPORTED, "sa_stream_open",
"MCI_MIXSETUP - rc=", LOUSHORT(rc));
break;
}
@@ -306,17 +328,17 @@ do {
s->hwWriteProc = MixSetupParms.pmixWrite;
/* allocate device buffers from the Amp-Mixer */
BufferParms.ulStructLength = sizeof(MCI_BUFFER_PARMS);
BufferParms.ulNumBuffers = bufCntRequested;
BufferParms.ulBufferSize = s->bufSize;
BufferParms.pBufList = s->bufList;
- rc = mciSendCommand(s->hwDeviceID, MCI_BUFFER,
+ rc = _mciSendCommand(s->hwDeviceID, MCI_BUFFER,
MCI_WAIT | MCI_ALLOCATE_MEMORY,
(void*)&BufferParms, 0);
if (LOUSHORT(rc)) {
status = os2_error(SA_ERROR_OOM, "sa_stream_open",
"MCI_ALLOCATE_MEMORY - rc=", LOUSHORT(rc));
break;
}
@@ -363,25 +385,25 @@ int sa_stream_destroy(sa_stream_t *s
/* if hardware buffers were allocated, free them */
if (s->bufCnt) {
BufferParms.hwndCallback = 0;
BufferParms.ulStructLength = sizeof(MCI_BUFFER_PARMS);
BufferParms.ulNumBuffers = s->bufCnt;
BufferParms.ulBufferSize = s->bufSize;
BufferParms.pBufList = s->bufList;
- rc = mciSendCommand(s->hwDeviceID, MCI_BUFFER,
+ rc = _mciSendCommand(s->hwDeviceID, MCI_BUFFER,
MCI_WAIT | MCI_DEALLOCATE_MEMORY,
(void*)&BufferParms, 0);
if (LOUSHORT(rc))
status = os2_error(SA_ERROR_SYSTEM, "sa_stream_destroy",
"MCI_DEALLOCATE_MEMORY - rc=", LOUSHORT(rc));
}
- rc = mciSendCommand(s->hwDeviceID, MCI_CLOSE,
+ rc = _mciSendCommand(s->hwDeviceID, MCI_CLOSE,
MCI_WAIT,
(void*)&GenericParms, 0);
if (LOUSHORT(rc))
status = os2_error(SA_ERROR_SYSTEM, "sa_stream_destroy",
"MCI_CLOSE - rc=", LOUSHORT(rc));
}
/* free other resources we allocated */
@@ -405,18 +427,28 @@ int sa_stream_write(sa_stream_t * s,
PMCI_MIX_BUFFER pHW;
if (!s)
return os2_error(SA_ERROR_NO_INIT, "sa_stream_write", "s is null", 0);
if (!data)
return os2_error(SA_ERROR_INVALID, "sa_stream_write", "data is null", 0);
/* exit if no data */
- if (!nbytes)
+ /* Bug 495352 - this function may get called repeatedly with no data;
+ * as a workaround to prevent as many as 30,000 such calls between valid
+ * writes (and 100% CPU usage), give up the remainder of the current
+ * time-slice every time 16 consecutive zero-byte writes are detected */
+ if (!nbytes) {
+ s->zeroCnt++;
+ if (!(s->zeroCnt & 0x0f)) {
+ s->zeroCnt = 0;
+ DosSleep(1);
+ }
return SA_SUCCESS;
+ }
/* This should only loop on the last write before sa_stream_drain()
* is called; at other times, 'nbytes' won't exceed 'bufSize'. */
while (nbytes) {
/* get the count of free buffers, wait until at least one
* is available (in practice, this should never block) */
if (os2_get_free_count(s, 1))
@@ -473,24 +505,24 @@ int sa_stream_resume(sa_stream_t *s)
{
uint32_t rc;
MCI_GENERIC_PARMS GenericParms = { 0 };
if (!s)
return os2_error(SA_ERROR_NO_INIT, "sa_stream_resume",
"s is null", 0);
- rc = mciSendCommand(s->hwDeviceID, MCI_ACQUIREDEVICE,
+ rc = _mciSendCommand(s->hwDeviceID, MCI_ACQUIREDEVICE,
MCI_WAIT,
(void*)&GenericParms, 0);
if (LOUSHORT(rc))
return os2_error(SA_ERROR_SYSTEM, "sa_stream_resume",
"MCI_ACQUIREDEVICE - rc=", LOUSHORT(rc));
- rc = mciSendCommand(s->hwDeviceID, MCI_RESUME,
+ rc = _mciSendCommand(s->hwDeviceID, MCI_RESUME,
MCI_WAIT,
(void*)&GenericParms, 0);
if (LOUSHORT(rc))
return os2_error(SA_ERROR_SYSTEM, "sa_stream_resume",
"MCI_RESUME - rc=", LOUSHORT(rc));
return SA_SUCCESS;
}
@@ -579,17 +611,17 @@ int sa_stream_set_volume_abs(sa_stre
return os2_error(SA_ERROR_NO_INIT, "sa_stream_set_volume_abs",
"s is null", 0);
/* convert f.p. value to an integer value ranging
* from 0 to 100 and apply to both channels */
SetParms.ulLevel = (vol * 100);
SetParms.ulAudio = MCI_SET_AUDIO_ALL;
- rc = mciSendCommand(s->hwDeviceID, MCI_SET,
+ rc = _mciSendCommand(s->hwDeviceID, MCI_SET,
MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
(void*)&SetParms, 0);
if (LOUSHORT(rc))
return os2_error(SA_ERROR_SYSTEM, "sa_stream_set_volume_abs",
"MCI_SET_VOLUME - rc=", LOUSHORT(rc));
return SA_SUCCESS;
}
@@ -606,17 +638,17 @@ int sa_stream_get_volume_abs(sa_stre
if (!s || !vol)
return os2_error(SA_ERROR_NO_INIT, "sa_stream_get_volume_abs",
"s or vol is null", 0);
memset(&StatusParms, 0, sizeof(MCI_STATUS_PARMS));
StatusParms.ulItem = MCI_STATUS_VOLUME;
- rc = mciSendCommand(s->hwDeviceID, MCI_STATUS,
+ rc = _mciSendCommand(s->hwDeviceID, MCI_STATUS,
MCI_WAIT | MCI_STATUS_ITEM,
(void*)&StatusParms, 0);
if (LOUSHORT(rc)) {
/* if there's an error, return a reasonable value */
StatusParms.ulReturn = (50 | 50 << 16);
status = os2_error(SA_ERROR_SYSTEM, "sa_stream_get_volume_abs",
"MCI_STATUS_VOLUME - rc=", LOUSHORT(rc));
}
@@ -737,17 +769,17 @@ static int os2_write_to_device(sa_strea
/** stop playback */
static void os2_stop_device(uint16_t hwDeviceID)
{
uint32_t rc;
MCI_GENERIC_PARMS GenericParms = { 0 };
- rc = mciSendCommand(hwDeviceID, MCI_STOP,
+ rc = _mciSendCommand(hwDeviceID, MCI_STOP,
MCI_WAIT,
(void*)&GenericParms, 0);
if (LOUSHORT(rc))
os2_error(0, "os2_stop_device", "MCI_STOP - rc=", LOUSHORT(rc));
return;
}
@@ -755,25 +787,25 @@ static void os2_stop_device(uint16_t hwD
/** pause playback and optionally release device */
static int os2_pause_device(uint16_t hwDeviceID, uint32_t release)
{
uint32_t rc;
MCI_GENERIC_PARMS GenericParms = { 0 };
- rc = mciSendCommand(hwDeviceID, MCI_PAUSE,
+ rc = _mciSendCommand(hwDeviceID, MCI_PAUSE,
MCI_WAIT,
(void*)&GenericParms, 0);
if (LOUSHORT(rc))
return os2_error(SA_ERROR_SYSTEM, "os2_pause_device",
"MCI_PAUSE - rc=", LOUSHORT(rc));
if (release)
- mciSendCommand(hwDeviceID, MCI_RELEASEDEVICE,
+ _mciSendCommand(hwDeviceID, MCI_RELEASEDEVICE,
MCI_WAIT,
(void*)&GenericParms, 0);
return SA_SUCCESS;
}
/*****************************************************************************/
@@ -816,16 +848,84 @@ static int os2_error_msg(int rtn, char
else
fprintf(stderr, "sa_os2 error - %s: %s %u\n", func, msg, err);
fflush(stderr);
return rtn;
}
#endif
+
+/*****************************************************************************/
+/* Mozilla-specific Functions */
+/*****************************************************************************/
+
+/** load mdm.dll & get the entrypoint for mciSendCommand() */
+
+static int os2_load_mdm(void)
+{
+ uint32_t rc;
+ HMODULE hmod;
+ char text[32];
+
+ if (_mciSendCommand)
+ return SA_SUCCESS;
+
+ rc = DosLoadModule(text, sizeof(text), "MDM", &hmod);
+ if (rc)
+ return os2_error(SA_ERROR_SYSTEM, "os2_load_mdm",
+ "DosLoadModule - rc=", rc);
+
+ /* the ordinal for mciSendCommand is '1' */
+ rc = DosQueryProcAddr(hmod, 1, 0, (PFN*)&_mciSendCommand);
+ if (rc) {
+ _mciSendCommand = 0;
+ return os2_error(SA_ERROR_SYSTEM, "os2_load_mdm",
+ "DosQueryProcAddr - rc=", rc);
+ }
+
+ return SA_SUCCESS;
+}
+
+/*****************************************************************************/
+
+/** adjust the decode thread's priority */
+
+static void os2_set_priority(void)
+{
+ uint32_t rc;
+ uint32_t priority;
+ int32_t delta;
+ int32_t newdelta;
+ PTIB ptib;
+ PPIB ppib;
+
+#define SAOS2_PRIORITY 8
+
+ DosGetInfoBlocks(&ptib, &ppib);
+ priority = ptib->tib_ptib2->tib2_ulpri;
+ delta = priority & 0xff;
+ priority >>= 8;
+
+ /* if the current priority class is other than "regular" (priority 2),
+ * don't change anything - otherwise, calculate a delta that will set
+ * the priority to SAOS2_PRIORITY */
+ if (priority != PRTYC_REGULAR)
+ newdelta = 0;
+ else
+ newdelta = SAOS2_PRIORITY - delta;
+
+ if (newdelta) {
+ rc = DosSetPriority(PRTYS_THREAD, PRTYC_NOCHANGE, newdelta, 0);
+ if (rc)
+ rc = os2_error(rc, "os2_set_priority", "DosSetPriority - rc=", rc);
+ }
+
+ return;
+}
/*****************************************************************************/
/* Not Implemented / Not Supported */
/*****************************************************************************/
#define UNSUPPORTED(func) func { return SA_ERROR_NOT_SUPPORTED; }
UNSUPPORTED(int sa_stream_create_opaque(sa_stream_t **s, const char *client_name, sa_mode_t mode, const char *codec))