Changeset 88253 in vbox
- Timestamp:
- Mar 22, 2021 6:14:09 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143453
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/pdmaudioifs.h
r88144 r88253 1824 1824 * @param pStream Pointer to audio stream. 1825 1825 * @param pvBuf Pointer to audio data buffer to play. 1826 * @param uBufSize The audio data buffer size (see note below for unit). 1827 * @param puWritten Number of unit written. 1828 * @note The @a uBufSize and @a puWritten values are in bytes for non-raw 1829 * layout streams and in frames for raw layout ones. 1826 * @param cbBuf The number of bytes of audio data to play. 1827 * @param pcbWritten Where to return the actual number of bytes played. 1830 1828 */ 1831 1829 DECLR3CALLBACKMEMBER(int, pfnStreamPlay, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, 1832 const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten));1830 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)); 1833 1831 1834 1832 /** … … 1874 1872 1875 1873 /** PDMIHOSTAUDIO interface ID. */ 1876 #define PDMIHOSTAUDIO_IID " 007847a0-0075-4964-007d-343f0010f081"1874 #define PDMIHOSTAUDIO_IID "be34182b-d579-41e8-96e0-abb94900460f" 1877 1875 1878 1876 /** @} */ -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r88061 r88253 149 149 * @remark This function is not thread safe! 150 150 */ 151 /** @todo r=bird: This isn't a 'ing Peek function, it's a Read function! 152 * Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaarg!!!!!!!!!!!!!!!!!!! */ 151 153 int AudioMixBufPeek(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToRead, 152 154 PPDMAUDIOFRAME paFrameBuf, uint32_t cFrameBuf, uint32_t *pcFramesRead) … … 1541 1543 * Reads audio frames. The audio format of the mixing buffer will be used. 1542 1544 * 1543 * @return IPRT status code. 1544 * @param pMixBuf Mixing buffer to read audio frames from. 1545 * @param pvBuf Pointer to buffer to write output to. 1546 * @param cbBuf Size (in bytes) of buffer to write to. 1547 * @param pcBlock Returns acquired block to read (in audio frames). 1548 */ 1549 int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcBlock) 1550 { 1551 return AudioMixBufAcquireReadBlockEx(pMixBuf, pMixBuf->uAudioFmt, pvBuf, cbBuf, pcBlock); 1545 * @returns VBox status code. 1546 * @param pMixBuf Mixing buffer to read audio frames from. 1547 * @param pvBuf Pointer to buffer to write output to. 1548 * @param cbBuf Size (in bytes) of buffer to write to. 1549 * @param pcAcquiredFrames Where to return the number of frames in 1550 * the block that was acquired. 1551 */ 1552 int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames) 1553 { 1554 return AudioMixBufAcquireReadBlockEx(pMixBuf, pMixBuf->uAudioFmt, pvBuf, cbBuf, pcAcquiredFrames); 1552 1555 } 1553 1556 … … 1558 1561 * 1559 1562 * @return IPRT status code. 1560 * @param pMixBuf Mixing buffer to read audio frames from. 1561 * @param enmFmt Audio format to use for output. 1562 * @param pvBuf Pointer to buffer to write output to. 1563 * @param cbBuf Size (in bytes) of buffer to write to. 1564 * @param pcBlock Returns acquired block to read (in audio frames). 1565 */ 1566 int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, uint32_t cbBuf, 1567 uint32_t *pcBlock) 1563 * @param pMixBuf Mixing buffer to read audio frames from. 1564 * @param enmFmt Audio format to use for output. 1565 * @param pvBuf Pointer to buffer to write output to. 1566 * @param cbBuf Size (in bytes) of buffer to write to. 1567 * @param pcAcquiredFrames Where to return the number of frames in 1568 * the block that was acquired. 1569 */ 1570 int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, 1571 void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames) 1568 1572 { 1569 1573 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); 1570 AssertReturn(cbBuf, 1571 AssertPtrReturn(pvBuf, 1572 AssertPtrReturn(pc Block, VERR_INVALID_POINTER);1574 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 1575 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1576 AssertPtrReturn(pcAcquiredFrames, VERR_INVALID_POINTER); 1573 1577 1574 1578 /* Make sure that we at least have space for a full audio frame. */ 1575 1579 AssertReturn(AUDIOMIXBUF_B2F(pMixBuf, cbBuf), VERR_INVALID_PARAMETER); 1576 1580 1577 uint32_t c ToRead = RT_MIN(pMixBuf->cUsed, AUDIOMIXBUF_B2F(pMixBuf, cbBuf));1578 1579 AUDMIXBUF_LOG(("%s: cbBuf=%RU32 (%RU32 frames), c ToRead=%RU32, fmtSrc=0x%x, fmtDst=0x%x\n",1580 pMixBuf->pszName, cbBuf, AUDIOMIXBUF_B2F(pMixBuf, cbBuf), c ToRead, pMixBuf->uAudioFmt, enmFmt));1581 1582 if (!c ToRead)1581 uint32_t cFramesToRead = RT_MIN(pMixBuf->cUsed, AUDIOMIXBUF_B2F(pMixBuf, cbBuf)); 1582 1583 AUDMIXBUF_LOG(("%s: cbBuf=%RU32 (%RU32 frames), cFramesToRead=%RU32, fmtSrc=0x%x, fmtDst=0x%x\n", 1584 pMixBuf->pszName, cbBuf, AUDIOMIXBUF_B2F(pMixBuf, cbBuf), cFramesToRead, pMixBuf->uAudioFmt, enmFmt)); 1585 1586 if (!cFramesToRead) 1583 1587 { 1584 1588 #ifdef DEBUG 1585 1589 audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__); 1586 1590 #endif 1587 *pc Block= 0;1591 *pcAcquiredFrames = 0; 1588 1592 return VINF_SUCCESS; 1589 1593 } 1590 1594 1591 PFNPDMAUDIOMIXBUFCONVTO pfnConvTo = NULL; 1592 if (pMixBuf->uAudioFmt != enmFmt) 1595 PFNPDMAUDIOMIXBUFCONVTO pfnConvTo; 1596 if (pMixBuf->uAudioFmt == enmFmt) 1597 pfnConvTo = pMixBuf->pfnConvTo; 1598 else 1593 1599 pfnConvTo = audioMixBufConvToLookup(enmFmt); 1594 else 1595 pfnConvTo = pMixBuf->pfnConvTo; 1596 1597 if (!pfnConvTo) /* Audio format not supported. */ 1598 { 1599 AssertFailed(); 1600 return VERR_NOT_SUPPORTED; 1601 } 1602 1603 cToRead = RT_MIN(cToRead, pMixBuf->cFrames - pMixBuf->offRead); 1604 if (cToRead) 1600 AssertReturn(pfnConvTo, VERR_NOT_SUPPORTED); 1601 1602 cFramesToRead = RT_MIN(cFramesToRead, pMixBuf->cFrames - pMixBuf->offRead); 1603 if (cFramesToRead) 1605 1604 { 1606 1605 PDMAUDMIXBUFCONVOPTS convOpts; 1607 1606 RT_ZERO(convOpts); 1608 convOpts.cFrames = c ToRead;1609 1610 AUDMIXBUF_LOG(("c ToRead=%RU32\n", cToRead));1607 convOpts.cFrames = cFramesToRead; 1608 1609 AUDMIXBUF_LOG(("cFramesToRead=%RU32\n", cFramesToRead)); 1611 1610 1612 1611 pfnConvTo(pvBuf, pMixBuf->pFrames + pMixBuf->offRead, &convOpts); … … 1618 1617 if (RT_SUCCESS(rc2)) 1619 1618 { 1620 RTFileWrite(fh, pvBuf, AUDIOMIXBUF_F2B(pMixBuf, c ToRead), NULL);1619 RTFileWrite(fh, pvBuf, AUDIOMIXBUF_F2B(pMixBuf, cFramesToRead), NULL); 1621 1620 RTFileClose(fh); 1622 1621 } … … 1624 1623 } 1625 1624 1626 *pc Block = cToRead;1625 *pcAcquiredFrames = cFramesToRead; 1627 1626 1628 1627 #ifdef DEBUG … … 1630 1629 #endif 1631 1630 1632 AUDMIXBUF_LOG((" cRead=%RU32 (%RU32 bytes)\n", cToRead, AUDIOMIXBUF_F2B(pMixBuf, cToRead)));1631 AUDMIXBUF_LOG(("*pcAcquiredFrames=%RU32 (%RU32 bytes)\n", cFramesToRead, AUDIOMIXBUF_F2B(pMixBuf, cFramesToRead))); 1633 1632 return VINF_SUCCESS; 1634 1633 } 1635 1634 1636 1635 /** 1637 * Releases a formerly acquired read block again. 1638 * 1639 * @param pMixBuf Mixing buffer to release acquired read block for. 1640 * @param cBlock Size of the block to release (in audio frames). 1641 */ 1642 void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cBlock) 1636 * Releases a formerly acquired read block. 1637 * 1638 * @param pMixBuf Mixing buffer to release acquired read block for. 1639 * @param cFrames The number of frames to release. (Can be less than the 1640 * acquired count.) 1641 */ 1642 void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames) 1643 1643 { 1644 1644 AssertPtrReturnVoid(pMixBuf); 1645 1645 1646 if ( !cBlock)1647 return;1648 1649 pMixBuf->offRead = (pMixBuf->offRead + cBlock) % pMixBuf->cFrames;1650 Assert(pMixBuf->cUsed >= cBlock);1651 pMixBuf->cUsed -= RT_MIN(cBlock, pMixBuf->cUsed);1646 if (cFrames) 1647 { 1648 AssertStmt(pMixBuf->cUsed >= cFrames, cFrames = pMixBuf->cUsed); 1649 pMixBuf->offRead = (pMixBuf->offRead + cFrames) % pMixBuf->cFrames; 1650 pMixBuf->cUsed -= cFrames; 1651 } 1652 1652 } 1653 1653 -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.h
r82968 r88253 70 70 int AudioMixBufReadAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead); 71 71 int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead); 72 int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pc Block);73 int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, uint32_t cbBuf, uint32_t *pc Block);74 void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t c Block);72 int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames); 73 int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames); 74 void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames); 75 75 uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf); 76 76 void AudioMixBufReset(PPDMAUDIOMIXBUF pMixBuf); -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r88243 r88253 1446 1446 1447 1447 /** 1448 * Plays an audio host output stream which has been configured for non-interleaved (layout) data. 1448 * Worker for drvAudioStreamPlay that plays non-interleaved data. 1449 * 1450 * @returns VBox status code. 1451 * @param pThis The audio driver instance data. 1452 * @param pStream The stream to play. 1453 * @param cFramesToPlay Number of audio frames to play. 1454 * @param pcFramesPlayed Where to return the number of audio frames played. 1455 */ 1456 static int drvAudioStreamPlayNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, 1457 uint32_t cFramesToPlay, uint32_t *pcFramesPlayed) 1458 { 1459 Assert(pStream->enmDir == PDMAUDIODIR_OUT); 1460 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED); 1461 1462 /* 1463 * Push data to the host device. 1464 */ 1465 int rc = VINF_SUCCESS; 1466 uint32_t cFramesLeft = cFramesToPlay; 1467 while (cFramesLeft > 0) 1468 { 1469 /* 1470 * Grab a chunk of audio data in the backend format. 1471 */ 1472 uint8_t abChunk[_4K]; 1473 uint32_t cFramesRead = 0; 1474 rc = AudioMixBufAcquireReadBlock(&pStream->Host.MixBuf, abChunk, 1475 RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cFramesLeft)), 1476 &cFramesRead); 1477 AssertRCBreak(rc); 1478 1479 uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cFramesRead); 1480 Assert(cbRead <= sizeof(abChunk)); 1481 1482 /* 1483 * Feed it to the backend. 1484 */ 1485 uint32_t cFramesPlayed = 0; 1486 uint32_t cbPlayed = 0; 1487 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, abChunk, cbRead, &cbPlayed); 1488 if (RT_SUCCESS(rc)) 1489 { 1490 if (cbPlayed) 1491 { 1492 if (pThis->Out.Cfg.Dbg.fEnabled) 1493 AudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */); 1494 1495 if (cbRead != cbPlayed) 1496 LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n", 1497 pStream->szName, cbRead, cbPlayed)); 1498 1499 cFramesPlayed = AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbPlayed); 1500 AssertStmt(cFramesLeft >= cFramesPlayed, cFramesPlayed = cFramesLeft); 1501 cFramesLeft -= cFramesPlayed; 1502 } 1503 else 1504 { 1505 /** @todo r=bird: If the backend is doing non-blocking writes, we'll probably 1506 * be spinning like crazy here... The ALSA backend is non-blocking. */ 1507 } 1508 } 1509 1510 AudioMixBufReleaseReadBlock(&pStream->Host.MixBuf, cFramesPlayed); 1511 1512 AssertRCBreak(rc); /* (this is here for Acquire/Release symmetry - which isn't at all necessary) */ 1513 } 1514 1515 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc)); 1516 *pcFramesPlayed = cFramesToPlay - cFramesLeft; 1517 return rc; 1518 } 1519 1520 /** 1521 * Plays an audio host output stream which has been configured for raw audio (layout) data. 1449 1522 * 1450 1523 * @returns VBox status code. 1451 1524 * @param pThis Pointer to driver instance. 1452 1525 * @param pStream Stream to play. 1453 * @param cfToPlay Number of audio frames to play. 1454 * @param pcfPlayed Returns number of audio frames played. Optional. 1455 */ 1456 static int drvAudioStreamPlayNonInterleaved(PDRVAUDIO pThis, 1457 PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed) 1458 { 1459 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1460 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1461 AssertPtrNullReturn(pcfPlayed, VERR_INVALID_POINTER); 1526 * @param cFramesToPlay Number of audio frames to play. 1527 * @param pcFramesPlayed Where to return number of audio frames played. 1528 */ 1529 static int drvAudioStreamPlayRaw(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t cFramesToPlay, uint32_t *pcFramesPlayed) 1530 { 1462 1531 Assert(pStream->enmDir == PDMAUDIODIR_OUT); 1463 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_ NON_INTERLEAVED);1532 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 1464 1533 1465 1534 /* 1466 1535 * ... 1467 1536 */ 1468 if (!cfToPlay) 1469 { 1470 if (pcfPlayed) 1471 *pcfPlayed = 0; 1472 return VINF_SUCCESS; 1473 } 1474 1475 /* 1476 * ... 1477 */ 1478 int rc = VINF_SUCCESS; 1479 uint32_t cfPlayedTotal = 0; 1480 uint32_t cfLeft = cfToPlay; 1481 while (cfLeft) 1482 { 1483 uint8_t abChunk[_4K]; 1484 uint32_t cfRead = 0; 1485 rc = AudioMixBufAcquireReadBlock(&pStream->Host.MixBuf, 1486 abChunk, RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfLeft)), 1487 &cfRead); 1488 if (RT_FAILURE(rc)) 1489 break; 1490 1491 uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfRead); 1492 Assert(cbRead <= sizeof(abChunk)); 1493 1494 uint32_t cfPlayed = 0; 1495 uint32_t cbPlayed = 0; 1496 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, abChunk, cbRead, &cbPlayed); 1497 if ( RT_SUCCESS(rc) 1498 && cbPlayed) 1499 { 1500 if (pThis->Out.Cfg.Dbg.fEnabled) 1501 AudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */); 1502 1503 if (cbRead != cbPlayed) 1504 LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n", 1505 pStream->szName, cbRead, cbPlayed)); 1506 1507 cfPlayed = AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbPlayed); 1508 cfPlayedTotal += cfPlayed; 1509 1510 Assert(cfLeft >= cfPlayed); 1511 cfLeft -= cfPlayed; 1512 } 1513 1514 AudioMixBufReleaseReadBlock(&pStream->Host.MixBuf, cfPlayed); 1515 1516 if (RT_FAILURE(rc)) 1517 break; 1518 } 1519 1520 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cfPlayedTotal, cfToPlay, rc)); 1521 1522 if (RT_SUCCESS(rc)) 1523 { 1524 if (pcfPlayed) 1525 *pcfPlayed = cfPlayedTotal; 1526 } 1527 1528 return rc; 1529 } 1530 1531 /** 1532 * Plays an audio host output stream which has been configured for raw audio (layout) data. 1533 * 1534 * @returns VBox status code. 1535 * @param pThis Pointer to driver instance. 1536 * @param pStream Stream to play. 1537 * @param cfToPlay Number of audio frames to play. 1538 * @param pcfPlayed Returns number of audio frames played. Optional. 1539 */ 1540 static int drvAudioStreamPlayRaw(PDRVAUDIO pThis, 1541 PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed) 1542 { 1543 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1544 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1545 AssertPtrNullReturn(pcfPlayed, VERR_INVALID_POINTER); 1546 Assert(pStream->enmDir == PDMAUDIODIR_OUT); 1547 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 1548 1549 /* 1550 * ... 1551 */ 1552 if (!cfToPlay) 1553 { 1554 if (pcfPlayed) 1555 *pcfPlayed = 0; 1556 return VINF_SUCCESS; 1557 } 1558 1559 /* 1560 * ... 1561 */ 1562 int rc = VINF_SUCCESS; 1563 uint32_t cfPlayedTotal = 0; 1564 uint32_t cfLeft = cfToPlay; 1565 while (cfLeft) 1537 int rc = VINF_SUCCESS; 1538 uint32_t cFramesLeft = cFramesToPlay; 1539 while (cFramesLeft > 0) 1566 1540 { 1567 1541 PDMAUDIOFRAME aFrames[_2K]; 1568 uint32_t cfRead = 0; 1569 rc = AudioMixBufPeek(&pStream->Host.MixBuf, cfLeft, aFrames, RT_MIN(cfLeft, RT_ELEMENTS(aFrames)), &cfRead); 1542 uint32_t cFramesRead = 0; 1543 /** @todo r=bird: Peek functions do _not_ generally drop stuff from what they're 1544 * peeking into. We normally name such functions Read. (Oh man, am I 1545 * getting tired of this kind of crap.) */ 1546 rc = AudioMixBufPeek(&pStream->Host.MixBuf, cFramesLeft, aFrames, 1547 RT_MIN(cFramesLeft, RT_ELEMENTS(aFrames)), &cFramesRead); 1570 1548 if (RT_SUCCESS(rc)) 1571 1549 { 1572 if (cfRead) 1573 { 1574 /* Note: As the stream layout is RPDMAUDIOSTREAMLAYOUT_RAW, operate on audio frames rather on bytes. */ 1575 Assert(cfRead <= RT_ELEMENTS(aFrames)); 1576 uint32_t cfPlayed = 0; 1577 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, aFrames, cfRead, &cfPlayed); 1578 if ( RT_FAILURE(rc) 1579 || !cfPlayed) 1580 break; 1581 1582 cfPlayedTotal += cfPlayed; 1583 Assert(cfPlayedTotal <= cfToPlay); 1584 1585 Assert(cfLeft >= cfRead); 1586 cfLeft -= cfRead; 1550 Assert(cFramesRead <= RT_ELEMENTS(aFrames)); 1551 if (cFramesRead) 1552 { 1553 uint32_t cbPlayed = 0; 1554 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, 1555 aFrames, cFramesRead * sizeof(aFrames[0]), &cbPlayed); 1556 AssertRCBreak(rc); 1557 /** @todo r=bird: This is a natural follow up to the non-peeking peek crap 1558 * above. It works because VRDE is the only consumer and it always 1559 * processes all that it gets. */ 1560 AssertBreakStmt(cbPlayed == cFramesRead * sizeof(aFrames[0]), rc = VERR_INTERNAL_ERROR_2); 1561 1562 Assert(cFramesRead <= cFramesLeft); 1563 cFramesLeft -= cFramesRead; 1587 1564 } 1588 1565 else … … 1599 1576 } 1600 1577 1601 if (RT_SUCCESS(rc) && pcfPlayed) 1602 *pcfPlayed = cfPlayedTotal; 1603 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cfPlayedTotal, cfToPlay, rc)); 1578 *pcFramesPlayed = cFramesToPlay - cFramesLeft; 1579 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc)); 1604 1580 return rc; 1605 1581 } … … 1614 1590 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1615 1591 AssertPtrNullReturn(pcFramesPlayed, VERR_INVALID_POINTER); 1616 1617 int rc = RTCritSectEnter(&pThis->CritSect);1618 AssertRCReturn(rc, rc);1619 1620 1592 AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, 1621 1593 ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n", 1622 1594 pStream->szName, pStream->enmDir)); 1595 int rc = RTCritSectEnter(&pThis->CritSect); 1596 AssertRCReturn(rc, rc); 1623 1597 1624 1598 uint32_t cfPlayedTotal = 0; … … 1737 1711 pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStream->pvBackend); 1738 1712 1713 /** @todo r=bird: I don't honestly see any difference in interleaved, 1714 * non-interrleaved, raw, complicate, or whatever frame format we're 1715 * dealing with here. We'll be formatting a chunk of audio data and feed 1716 * it to the backend, the formatting is taken care of by the mixer and 1717 * we don't really care about the format anywhere here. 1718 * 1719 * Raw audio is just stereo S64, btw. Since drvAudioStreamPlayRaw 1720 * actually copies the mixer data instead of accessing the internal mixer 1721 * buffer directly, there is no advantage to having separate code paths 1722 * here. It only leads to more incomplete crappy code (I find the code 1723 * quality quite appaling, given the amount of time spent on it). 1724 * 1725 * What's more, I think the non-interleaved designation here is wrong 1726 * anyway. Non-interleaved means a stereo chunk of 8 frames is 1727 * formatted: 1728 * - LLLLLLLLRRRRRRRR 1729 * whereas I'm pretty darn sure we do: 1730 * - LRLRLRLRLRLRLRLR 1731 * given that the mixer doesn't know how to output the former. See the 1732 * audioMixBufConvTo##a_Name##Stereo() code, it clearly output LR pairs. 1733 * 1734 * https://stackoverflow.com/questions/17879933/whats-the-interleaved-audio 1735 */ 1739 1736 if (RT_LIKELY(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED)) 1740 1737 rc = drvAudioStreamPlayNonInterleaved(pThis, pStream, cfToPlay, &cfPlayedTotal); -
trunk/src/VBox/Main/include/ConsoleVRDPServer.h
r82968 r88253 136 136 void SendUpdateBitmap (unsigned uScreenId, uint32_t x, uint32_t y, uint32_t w, uint32_t h) const; 137 137 138 void SendAudioSamples (void *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format) const;138 void SendAudioSamples (void const *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format) const; 139 139 void SendAudioVolume (uint16_t left, uint16_t right) const; 140 140 void SendUSBRequest (uint32_t u32ClientId, void *pvParms, uint32_t cbParms) const; -
trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp
r82968 r88253 3730 3730 } 3731 3731 3732 void ConsoleVRDPServer::SendAudioSamples(void *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format) const3732 void ConsoleVRDPServer::SendAudioSamples(void const *pvSamples, uint32_t cSamples, VRDEAUDIOFORMAT format) const 3733 3733 { 3734 3734 if (mpEntryPoints && mhServer) -
trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp
r88028 r88253 106 106 pCfgAcq->enmLayout = PDMAUDIOSTREAMLAYOUT_RAW; 107 107 pCfgAcq->Backend.cFramesPeriod = cFramesVrdpServer; 108 pCfgAcq->Backend.cFramesBufferSize = pCfgAcq->Backend.cFramesPeriod * 2; /* Use "double buffering". */ 109 pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesPeriod; 108 /** @todo r=bird: This is inconsistent with the above buffer allocation and I 109 * think also ALSA and Pulse backends way of setting cFramesBufferSize. */ 110 pCfgAcq->Backend.cFramesBufferSize = cFramesVrdpServer * 2; /* Use "double buffering". */ 111 pCfgAcq->Backend.cFramesPreBuffering = cFramesVrdpServer; 110 112 } 111 113 … … 270 272 */ 271 273 static DECLCALLBACK(int) drvAudioVrdeHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, 272 const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten) 273 { 274 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 275 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 276 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 277 AssertReturn(uBufSize, VERR_INVALID_PARAMETER); 278 /* puWritten is optional. */ 279 280 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio); 281 PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream; 274 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten) 275 { 276 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio); 277 AssertPtr(pDrv); 278 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 279 PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream; 280 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 281 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 282 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER); 282 283 283 284 if (!pDrv->pConsoleVRDPServer) 284 285 return VERR_NOT_AVAILABLE; 285 286 286 /* Note: We get the number of *frames* in uBufSize 287 * (since we specified PDMAUDIOSTREAMLAYOUT_RAW as the audio data layout) on stream creation. */ 288 uint32_t cFramesLive = uBufSize; 289 287 /* Prepate the format. */ 290 288 PPDMAUDIOPCMPROPS pProps = &pStreamVRDE->pCfg->Props; 291 292 VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pProps->uHz, 293 pProps->cChannels, 294 pProps->cbSample * 8 /* Bit */, 295 pProps->fSigned); 296 297 /* Use the internal counter to track if we (still) can write to the VRDP server 298 * or if we need to wait another round (time slot). */ 299 uint32_t cFramesToWrite = cFramesLive; 300 301 Log3Func(("cFramesLive=%RU32, cFramesToWrite=%RU32\n", cFramesLive, cFramesToWrite)); 302 303 /* Don't play more than available. */ 304 if (cFramesToWrite > cFramesLive) 305 cFramesToWrite = cFramesLive; 306 307 int rc = VINF_SUCCESS; 308 309 PPDMAUDIOFRAME paSampleBuf = (PPDMAUDIOFRAME)pvBuf; 310 AssertPtr(paSampleBuf); 289 VRDEAUDIOFORMAT const VrdpFormat = VRDE_AUDIO_FMT_MAKE(pProps->uHz, 290 pProps->cChannels, 291 pProps->cbSample * 8 /* Bit */, 292 pProps->fSigned); 293 294 /* We specified PDMAUDIOSTREAMLAYOUT_RAW (== S64), so 295 convert the buffer pointe and size accordingly: */ 296 PCPDMAUDIOFRAME paSampleBuf = (PCPDMAUDIOFRAME)pvBuf; 297 uint32_t const cFramesToWrite = cbBuf / sizeof(paSampleBuf[0]); 298 Assert(cFramesToWrite * sizeof(paSampleBuf[0]) == cbBuf); 299 300 /** @todo r=bird: there was some incoherent mumbling about "using the 301 * internal counter to track if we (still) can write to the VRDP 302 * server or if need to wait anothe round (time slot)". However it 303 * wasn't accessing any internal counter nor doing anything else 304 * sensible, so I've removed it. */ 311 305 312 306 /* 313 307 * Call the VRDP server with the data. 314 308 */ 315 uint32_t cfWritten = 0; 316 while (cFramesToWrite) 317 { 318 uint32_t cfChunk = cFramesToWrite; /** @todo For now write all at once. */ 319 320 if (!cfChunk) /* Nothing to send. Bail out. */ 321 break; 322 323 /* Note: The VRDP server expects int64_t samples per channel, regardless of the actual 324 * sample bits (e.g 8 or 16 bits). */ 325 pDrv->pConsoleVRDPServer->SendAudioSamples(paSampleBuf + cfWritten, cfChunk /* Frames */, format); 326 327 cfWritten += cfChunk; 328 Assert(cfWritten <= cFramesLive); 329 330 Assert(cFramesToWrite >= cfChunk); 331 cFramesToWrite -= cfChunk; 332 } 333 334 if (RT_SUCCESS(rc)) 335 { 336 /* Return frames instead of bytes here 337 * (since we specified PDMAUDIOSTREAMLAYOUT_RAW as the audio data layout). */ 338 if (puWritten) 339 *puWritten = cfWritten; 340 } 341 342 return rc; 309 uint32_t cFramesWritten = 0; 310 while (cFramesWritten < cFramesToWrite) 311 { 312 uint32_t const cFramesChunk = cFramesToWrite - cFramesWritten; /** @todo For now write all at once. */ 313 314 /* Note: The VRDP server expects int64_t samples per channel, regardless 315 of the actual sample bits (e.g 8 or 16 bits). */ 316 pDrv->pConsoleVRDPServer->SendAudioSamples(&paSampleBuf[cFramesWritten], cFramesChunk /* Frames */, VrdpFormat); 317 318 cFramesWritten += cFramesChunk; 319 } 320 321 Log3Func(("cFramesWritten=%RU32\n", cFramesWritten)); 322 if (pcbWritten) 323 *pcbWritten = cFramesWritten * sizeof(PDMAUDIOFRAME); 324 return VINF_SUCCESS; 343 325 } 344 326
Note:
See TracChangeset
for help on using the changeset viewer.