- Timestamp:
- Aug 22, 2018 3:40:27 PM (6 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r73565 r73833 1363 1363 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1364 1364 hdaR3StreamAsyncIOLock(pStream); 1365 hdaR3StreamAsyncIOEnable(pStream, false /* fEnable */);1366 1365 # endif 1367 1366 /* Make sure to remove the run bit before doing the actual stream reset. */ … … 1397 1396 if (fRun) 1398 1397 { 1399 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO1400 hdaR3StreamAsyncIOEnable(pStream, fRun /* fEnable */);1401 # endif1402 1398 /* (Re-)initialize the stream with current values. */ 1403 1399 rc2 = hdaR3StreamInit(pStream, pStream->u8SD); -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r73651 r73833 839 839 rc = ichac97R3StreamAsyncIOCreate(pThis, pStream); 840 840 if (RT_SUCCESS(rc)) 841 {842 841 ichac97R3StreamAsyncIOLock(pStream); 843 ichac97R3StreamAsyncIOEnable(pStream, fEnable);844 }845 842 # endif 846 843 … … 1288 1285 { 1289 1286 pAIO->fShutdown = false; 1287 pAIO->fEnabled = true; /* Enabled by default. */ 1290 1288 1291 1289 rc = RTSemEventCreate(&pAIO->Event); … … 1421 1419 * The host sink(s) set the overall pace. 1422 1420 * 1423 * This routine is called by both, the synchronous and the asynchronous, implementations. 1421 * This routine is called by both, the synchronous and the asynchronous 1422 * (VBOX_WITH_AUDIO_AC97_ASYNC_IO), implementations. 1423 * 1424 * When running synchronously, the device DMA transfers *and* the mixer sink 1425 * processing is within the device timer. 1426 * 1427 * When running asynchronously, only the device DMA transfers are done in the 1428 * device timer, whereas the mixer sink processing then is done in the stream's 1429 * own async I/O thread. This thread also will call this function 1430 * (with fInTimer set to @c false). 1424 1431 * 1425 1432 * @param pThis AC'97 state. … … 1430 1437 static void ichac97R3StreamUpdate(PAC97STATE pThis, PAC97STREAM pStream, bool fInTimer) 1431 1438 { 1439 RT_NOREF(fInTimer); 1440 1432 1441 PAUDMIXSINK pSink = ichac97R3IndexToSink(pThis, pStream->u8SD); 1433 1442 AssertPtr(pSink); … … 1440 1449 if (pStream->u8SD == AC97SOUNDSOURCE_PO_INDEX) /* Output (SDO). */ 1441 1450 { 1442 #ifdef LOG_ENABLED 1443 const uint64_t deltaLastUpdateNs = RTTimeNanoTS() - pStream->State.tsLastUpdateNs; 1444 #endif 1445 pStream->State.tsLastUpdateNs = RTTimeNanoTS(); 1446 1447 PPDMAUDIOPCMPROPS pProps = &pStream->State.Cfg.Props; 1448 1449 /* Make sure that we don't transfer more than we need for this slot. */ 1450 uint32_t cbToTransfer = DrvAudioHlpMilliToBytes(pStream->State.Cfg.Device.uSchedulingHintMs, pProps); 1451 1452 /* Make sure that the transfer is frame-aligned. 1453 * Add one additional frame to not transfer too little because of the alignment; 1454 * ichac97R3StreamTransfer() will take care of clamping to the correct value then. */ 1455 cbToTransfer = DrvAudioHlpBytesAlign(cbToTransfer, pProps) + PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */); 1456 1457 Log3Func(("[SD%RU8] cbToTransfer=%RU32, deltaLastUpdateNs=%RU64\n", pStream->u8SD, cbToTransfer, deltaLastUpdateNs / RT_NS_1MS)); 1458 1459 if ( fInTimer 1460 && cbToTransfer) 1461 { 1462 /* Do the DMA transfer. */ 1463 rc2 = ichac97R3StreamTransfer(pThis, pStream, cbToTransfer); 1451 /* How much (guest output) data is available at the moment for the AC'97 stream? */ 1452 /* Only read from the AC'97 stream at the given scheduling rate. */ 1453 bool fDoRead = false; /* Whether to read from the AC'97 stream or not. */ 1454 1455 # ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO 1456 if (fInTimer) 1457 # endif 1458 { 1459 const uint32_t cbStreamFree = ichac97R3StreamGetFree(pStream); 1460 if (cbStreamFree) 1461 { 1462 /* Do the DMA transfer. */ 1463 rc2 = ichac97R3StreamTransfer(pThis, pStream, cbStreamFree); 1464 AssertRC(rc2); 1465 } 1466 1467 /* Only read from the AC'97 stream at the given scheduling rate. */ 1468 const uint64_t tsNowNs = RTTimeNanoTS(); 1469 if (tsNowNs - pStream->State.tsLastUpdateNs >= pStream->State.Cfg.Device.uSchedulingHintMs * RT_NS_1MS) 1470 { 1471 fDoRead = true; 1472 pStream->State.tsLastUpdateNs = tsNowNs; 1473 } 1474 } 1475 1476 Log3Func(("[SD%RU8] fInTimer=%RTbool, fDoRead=%RTbool\n", pStream->u8SD, fInTimer, fDoRead)); 1477 1478 # ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO 1479 if (fDoRead) 1480 { 1481 rc2 = ichac97R3StreamAsyncIONotify(pStream); 1464 1482 AssertRC(rc2); 1465 1483 } 1466 1467 /* Make sure that we don't write more than we need for this slot. */ 1468 uint32_t cbToWrite = RT_MIN(cbToTransfer, ichac97R3StreamGetUsed(pStream)); 1469 1470 /* Make sure that the write is byte-aligned. */ 1471 cbToWrite = DrvAudioHlpBytesAlign(cbToWrite, pProps); 1472 1473 Log3Func(("[SD%RU8] cbToWrite=%RU32, deltaLastUpdateNs=%RU64\n", pStream->u8SD, cbToWrite, deltaLastUpdateNs / RT_NS_1MS)); 1484 # endif 1474 1485 1475 1486 # ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO 1476 if ( fInTimer 1477 && cbToWrite) 1478 { 1479 rc2 = ichac97R3StreamAsyncIONotify(pThis, pStream); 1480 AssertRC(rc2); 1481 } 1482 else 1487 if (!fInTimer) /* In async I/O thread */ 1488 { 1489 # else 1490 if (fDoRead) 1491 { 1483 1492 # endif 1484 { 1485 if (cbToWrite) 1493 const uint32_t cbSinkWritable = AudioMixerSinkGetWritable(pSink); 1494 const uint32_t cbStreamReadable = ichac97R3StreamGetUsed(pStream); 1495 const uint32_t cbToReadFromStream = RT_MIN(cbStreamReadable, cbSinkWritable); 1496 1497 Log3Func(("[SD%RU8] cbSinkWritable=%RU32, cbStreamReadable=%RU32\n", pStream->u8SD, cbSinkWritable, cbStreamReadable)); 1498 1499 if (cbToReadFromStream) 1486 1500 { 1487 1501 /* Read (guest output) data and write it to the stream's sink. */ 1488 uint32_t cbRead; 1489 rc2 = ichac97R3StreamRead(pThis, pStream, pSink, cbToWrite, &cbRead); 1502 rc2 = ichac97R3StreamRead(pThis, pStream, pSink, cbToReadFromStream, NULL); 1490 1503 AssertRC(rc2); 1491 1504 } 1492 1493 /* When running synchronously, update the associated sink here. 1494 * Otherwise this will be done in the device timer. */ 1495 rc2 = AudioMixerSinkUpdate(pSink); 1496 AssertRC(rc2); 1497 1498 } 1505 } 1506 1507 /* When running synchronously, update the associated sink here. 1508 * Otherwise this will be done in the async I/O thread. */ 1509 rc2 = AudioMixerSinkUpdate(pSink); 1510 AssertRC(rc2); 1499 1511 } 1500 1512 else /* Input (SDI). */ -
trunk/src/VBox/Devices/Audio/HDAStream.cpp
r73529 r73833 67 67 rc = hdaR3StreamPeriodCreate(&pStream->State.Period); 68 68 AssertRCReturn(rc, rc); 69 70 pStream->State.tsLastUpdateNs = 0; 69 71 70 72 #ifdef DEBUG … … 378 380 pStream->State.cTransferPendingInterrupts = 0; 379 381 pStream->State.cbDMALeft = 0; 382 pStream->State.tsLastUpdateNs = 0; 380 383 381 384 const uint64_t cTicksPerHz = TMTimerGetFreq(pStream->pTimer) / pThis->u16TimerHz; … … 785 788 786 789 Assert(cbSrc >= cbWritten); 787 Log2Func(("[SD%RU8]: % zu/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc));790 Log2Func(("[SD%RU8]: %RU32/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc)); 788 791 } 789 792 … … 891 894 if (cbToProcess > cbToProcessMax) 892 895 { 893 if (pStream->State.Cfg.enmDir == PDMAUDIODIR_IN) 894 LogRelMax2(64, ("HDA: Warning: DMA buffer underflow for stream #%RU8 (still %RU32 bytes needed)\n", 895 pStream->u8SD, cbToProcess - cbToProcessMax)); 896 else 897 LogRelMax2(64, ("HDA: Warning: DMA buffer overflow for stream #%RU8 (%RU32 bytes outstanding)\n", 898 pStream->u8SD, cbToProcess - cbToProcessMax)); 899 900 LogFunc(("[SD%RU8] Warning: Limiting transfer (cbToProcess=%RU32, cbToProcessMax=%RU32)\n", 896 LogFunc(("[SD%RU8] Limiting transfer (cbToProcess=%RU32, cbToProcessMax=%RU32)\n", 901 897 pStream->u8SD, cbToProcess, cbToProcessMax)); 902 898 … … 982 978 { 983 979 const uint32_t cbDMAFree = (uint32_t)RTCircBufFree(pCircBuf); 984 985 if (cbDMAFree < cbDMA) 986 LogRelMax2(64, ("HDA: Warning: DMA buffer overflow of stream #%RU8 (discarding %RU32 bytes)\n", 987 pStream->u8SD, cbDMA - cbDMAFree)); 980 Assert(cbDMAFree >= cbDMA); /* This must always hold. */ 988 981 989 982 #ifndef VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT … … 1275 1268 * This routine is called by both, the synchronous and the asynchronous, implementations. 1276 1269 * 1270 * This routine is called by both, the synchronous and the asynchronous 1271 * (VBOX_WITH_AUDIO_HDA_ASYNC_IO), implementations. 1272 * 1273 * When running synchronously, the device DMA transfers *and* the mixer sink 1274 * processing is within the device timer. 1275 * 1276 * When running asynchronously, only the device DMA transfers are done in the 1277 * device timer, whereas the mixer sink processing then is done in the stream's 1278 * own async I/O thread. This thread also will call this function 1279 * (with fInTimer set to @c false). 1280 * 1277 1281 * @param pStream HDA stream to update. 1278 1282 * @param fInTimer Whether to this function was called from the timer … … 1298 1302 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */ 1299 1303 { 1300 /* Is the HDA stream ready to be written (guest output data) to? If so, by how much? */ 1301 const uint32_t cbFree = hdaR3StreamGetFree(pStream); 1302 1303 if ( fInTimer 1304 && cbFree) 1305 { 1306 Log3Func(("[SD%RU8] cbFree=%RU32\n", pStream->u8SD, cbFree)); 1307 1308 /* Do the DMA transfer. */ 1309 rc2 = hdaR3StreamTransfer(pStream, cbFree); 1310 AssertRC(rc2); 1311 } 1312 1313 /* How much (guest output) data is available at the moment for the HDA stream? */ 1314 uint32_t cbUsed = hdaR3StreamGetUsed(pStream); 1315 1316 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1317 if ( fInTimer 1318 && cbUsed) 1304 bool fDoRead = false; /* Whether to read from the HDA stream or not. */ 1305 1306 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1307 if (fInTimer) 1308 # endif 1309 { 1310 const uint32_t cbStreamFree = hdaR3StreamGetFree(pStream); 1311 if (cbStreamFree) 1312 { 1313 /* Do the DMA transfer. */ 1314 rc2 = hdaR3StreamTransfer(pStream, cbStreamFree); 1315 AssertRC(rc2); 1316 } 1317 1318 /* Only read from the HDA stream at the given scheduling rate. */ 1319 const uint64_t tsNowNs = RTTimeNanoTS(); 1320 if (tsNowNs - pStream->State.tsLastUpdateNs >= pStream->State.Cfg.Device.uSchedulingHintMs * RT_NS_1MS) 1321 { 1322 fDoRead = true; 1323 pStream->State.tsLastUpdateNs = tsNowNs; 1324 } 1325 } 1326 1327 Log3Func(("[SD%RU8] fInTimer=%RTbool, fDoRead=%RTbool\n", pStream->u8SD, fInTimer, fDoRead)); 1328 1329 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1330 if (fDoRead) 1319 1331 { 1320 1332 rc2 = hdaR3StreamAsyncIONotify(pStream); 1321 1333 AssertRC(rc2); 1322 1334 } 1323 else 1324 { 1325 #endif 1326 const uint32_t cbSinkWritable = AudioMixerSinkGetWritable(pSink); 1327 1328 Log3Func(("[SD%RU8] cbWritable=%RU32, cbUsed=%RU32\n", pStream->u8SD, cbSinkWritable, cbUsed)); 1329 1330 /* Do not write more than the sink can hold at the moment. 1331 * The host sets the overall pace. */ 1332 if (cbUsed > cbSinkWritable) 1333 cbUsed = cbSinkWritable; 1334 1335 if (cbUsed) 1335 # endif 1336 1337 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1338 if (!fInTimer) /* In async I/O thread */ 1339 { 1340 # else 1341 if (fDoRead) 1342 { 1343 # endif 1344 const uint32_t cbSinkWritable = AudioMixerSinkGetWritable(pSink); 1345 const uint32_t cbStreamReadable = hdaR3StreamGetUsed(pStream); 1346 const uint32_t cbToReadFromStream = RT_MIN(cbStreamReadable, cbSinkWritable); 1347 1348 Log3Func(("[SD%RU8] cbSinkWritable=%RU32, cbStreamReadable=%RU32\n", pStream->u8SD, cbSinkWritable, cbStreamReadable)); 1349 1350 if (cbToReadFromStream) 1336 1351 { 1337 1352 /* Read (guest output) data and write it to the stream's sink. */ 1338 rc2 = hdaR3StreamRead(pStream, cb Used, NULL /* pcbRead */);1353 rc2 = hdaR3StreamRead(pStream, cbToReadFromStream, NULL); 1339 1354 AssertRC(rc2); 1340 1355 } 1341 1356 1342 1357 /* When running synchronously, update the associated sink here. 1343 * Otherwise this will be done in the stream's dedicatedasync I/O thread. */1358 * Otherwise this will be done in the async I/O thread. */ 1344 1359 rc2 = AudioMixerSinkUpdate(pSink); 1345 1360 AssertRC(rc2); 1346 1347 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1348 } 1349 #endif 1361 } 1350 1362 } 1351 1363 else /* Input (SDI). */ 1352 1364 { 1353 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO1365 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1354 1366 if (!fInTimer) 1355 1367 { 1356 # endif1368 # endif 1357 1369 rc2 = AudioMixerSinkUpdate(pSink); 1358 1370 AssertRC(rc2); 1359 1371 1360 1372 /* Is the sink ready to be read (host input data) from? If so, by how much? */ 1361 uint32_t cb Readable = AudioMixerSinkGetReadable(pSink);1373 uint32_t cbSinkReadable = AudioMixerSinkGetReadable(pSink); 1362 1374 1363 1375 /* How much (guest input) data is available for writing at the moment for the HDA stream? */ 1364 const uint32_t cb Free = hdaR3StreamGetFree(pStream);1365 1366 Log3Func(("[SD%RU8] cb Readable=%RU32, cbFree=%RU32\n", pStream->u8SD, cbReadable, cbFree));1367 1368 /* Do not write more than the sinkcan hold at the moment.1376 const uint32_t cbStreamFree = hdaR3StreamGetFree(pStream); 1377 1378 Log3Func(("[SD%RU8] cbSinkReadable=%RU32, cbStreamFree=%RU32\n", pStream->u8SD, cbSinkReadable, cbStreamFree)); 1379 1380 /* Do not read more than the HDA stream can hold at the moment. 1369 1381 * The host sets the overall pace. */ 1370 if (cb Readable > cbFree)1371 cb Readable = cbFree;1372 1373 if (cb Readable)1382 if (cbSinkReadable > cbStreamFree) 1383 cbSinkReadable = cbStreamFree; 1384 1385 if (cbSinkReadable) 1374 1386 { 1375 1387 uint8_t abFIFO[HDA_FIFO_MAX + 1]; 1376 while (cb Readable)1388 while (cbSinkReadable) 1377 1389 { 1378 1390 uint32_t cbRead; 1379 1391 rc2 = AudioMixerSinkRead(pSink, AUDMIXOP_COPY, 1380 abFIFO, RT_MIN(cb Readable, (uint32_t)sizeof(abFIFO)), &cbRead);1392 abFIFO, RT_MIN(cbSinkReadable, (uint32_t)sizeof(abFIFO)), &cbRead); 1381 1393 AssertRCBreak(rc2); 1382 1394 1383 1395 if (!cbRead) 1384 1396 { 1385 AssertMsgFailed(("Nothing read from sink, even if %RU32 bytes were (still) announced\n", cb Readable));1397 AssertMsgFailed(("Nothing read from sink, even if %RU32 bytes were (still) announced\n", cbSinkReadable)); 1386 1398 break; 1387 1399 } … … 1398 1410 } 1399 1411 1400 Assert(cb Readable >= cbRead);1401 cb Readable -= cbRead;1412 Assert(cbSinkReadable >= cbRead); 1413 cbSinkReadable -= cbRead; 1402 1414 } 1403 1415 } 1404 #if 0 1405 else /* Send silence as input. */ 1406 { 1407 cbReadable = pStream->State.cbTransferSize - pStream->State.cbTransferProcessed; 1408 1409 Log3Func(("[SD%RU8] Sending silence (%RU32 bytes)\n", pStream->u8SD, cbReadable)); 1410 1411 if (cbReadable) 1412 { 1413 rc2 = hdaR3StreamWrite(pStream, NULL /* Silence */, cbReadable, NULL /* pcbWritten */); 1414 AssertRC(rc2); 1415 } 1416 } 1417 #endif 1418 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1416 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1419 1417 } 1420 1418 else /* fInTimer */ 1421 1419 { 1422 #endif 1423 const uint64_t tsNow = RTTimeMilliTS(); 1424 static uint64_t s_lasti = 0; 1425 if (s_lasti == 0) 1426 s_lasti = tsNow; 1427 1428 if (tsNow - s_lasti >= 10) /** @todo Fix this properly. */ 1420 # endif 1421 1422 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1423 const uint64_t tsNowNs = RTTimeNanoTS(); 1424 if (tsNowNs - pStream->State.tsLastUpdateNs >= pStream->State.Cfg.Device.uSchedulingHintMs * RT_NS_1MS) 1429 1425 { 1430 1426 rc2 = hdaR3StreamAsyncIONotify(pStream); 1431 1427 AssertRC(rc2); 1432 1428 1433 s_lasti = tsNow;1434 } 1435 1436 const uint32_t cb ToTransfer= hdaR3StreamGetUsed(pStream);1437 if (cb ToTransfer)1438 { 1439 rc2 = hdaR3StreamTransfer(pStream, cb ToTransfer);1429 pStream->State.tsLastUpdateNs = tsNowNs; 1430 } 1431 # endif 1432 const uint32_t cbStreamFree = hdaR3StreamGetUsed(pStream); 1433 if (cbStreamFree) 1434 { 1435 rc2 = hdaR3StreamTransfer(pStream, cbStreamFree); 1440 1436 AssertRC(rc2); 1441 1437 } 1442 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO1443 } 1444 # endif1438 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 1439 } 1440 # endif 1445 1441 } 1446 1442 } … … 1754 1750 { 1755 1751 pAIO->fShutdown = false; 1752 pAIO->fEnabled = true; /* Enabled by default. */ 1756 1753 1757 1754 rc = RTSemEventCreate(&pAIO->Event); -
trunk/src/VBox/Devices/Audio/HDAStream.h
r73370 r73833 177 177 /** Unused, padding. */ 178 178 uint8_t abPadding4[2+4]; 179 /** Timestamp (in ns) of last stream update. */ 180 uint64_t tsLastUpdateNs; 179 181 } HDASTREAMSTATE; 180 182 AssertCompileSizeAlignment(HDASTREAMSTATE, 8);
Note:
See TracChangeset
for help on using the changeset viewer.