Changeset 88282 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Mar 24, 2021 6:57:14 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143493
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r88277 r88282 650 650 * 651 651 * @returns Pointer to matching conversion function, NULL if not supported. 652 * @param pProp 652 * @param pProps The audio format to find a "from" converter for. 653 653 */ 654 654 static PFNPDMAUDIOMIXBUFCONVFROM audioMixBufConvFromLookup(PCPDMAUDIOPCMPROPS pProps) … … 713 713 * 714 714 * @returns Pointer to matching conversion function, NULL if not supported. 715 * @param pProp 715 * @param pProps The audio format to find a "to" converter for. 716 716 */ 717 717 static PFNPDMAUDIOMIXBUFCONVTO audioMixBufConvToLookup(PCPDMAUDIOPCMPROPS pProps) -
trunk/src/VBox/Devices/Audio/DrvHostAudioAlsa.cpp
r88269 r88282 85 85 /** Pointer to allocated ALSA PCM configuration to use. */ 86 86 snd_pcm_t *phPCM; 87 /** Scratch buffer. */ 87 /** Scratch buffer. 88 * @todo r=bird: WHY THE *BEEEEP* DO WE NEED THIS? Do I have to go search svn 89 * history for this (probably just an 'updates' commit)? */ 88 90 void *pvBuf; 89 91 /** Size (in bytes) of allocated scratch buffer. */ … … 735 737 */ 736 738 static DECLCALLBACK(int) drvHostAlsaAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, 737 const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten)739 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten) 738 740 { 739 741 PALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream; 740 742 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 741 AssertPtrReturn(pStream, 742 AssertPtrReturn(pvBuf, 743 AssertReturn( uBufSize,VERR_INVALID_PARAMETER);744 /* puWritten is optional. */745 Log4Func(("pvBuf=%p uBufSize=%#x (%u) state=%s - %s\n", pvBuf, uBufSize, uBufSize,743 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 744 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 745 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 746 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER); 747 Log4Func(("pvBuf=%p uBufSize=%#x (%u) state=%s - %s\n", pvBuf, cbBuf, cbBuf, 746 748 snd_pcm_state_name(snd_pcm_state(pStreamALSA->phPCM)), pStreamALSA->pCfg->szName)); 747 749 748 PPDMAUDIOSTREAMCFG pCfg = pStreamALSA->pCfg; 749 AssertPtr(pCfg); 750 751 int rc; 752 753 uint32_t cbWrittenTotal = 0; 754 755 do 756 { 757 snd_pcm_sframes_t csAvail; 758 rc = alsaStreamGetAvail(pStreamALSA->phPCM, &csAvail); 759 if (RT_FAILURE(rc)) 760 { 761 LogFunc(("Error getting number of playback frames, rc=%Rrc\n", rc)); 762 break; 763 } 764 765 if (!csAvail) 766 break; 767 768 size_t cbToWrite = RT_MIN((unsigned)PDMAUDIOSTREAMCFG_F2B(pCfg, csAvail), pStreamALSA->cbBuf); 769 if (!cbToWrite) 770 break; 771 772 /* Do not write more than available. */ 773 if (cbToWrite > uBufSize) 774 cbToWrite = uBufSize; 775 776 memcpy(pStreamALSA->pvBuf, pvBuf, cbToWrite); 777 778 snd_pcm_sframes_t csWritten = 0; 779 780 /* Don't try infinitely on recoverable errors. */ 781 unsigned iTry; 782 for (iTry = 0; iTry < ALSA_RECOVERY_TRIES_MAX; iTry++) 783 { 784 csWritten = snd_pcm_writei(pStreamALSA->phPCM, pStreamALSA->pvBuf, 785 PDMAUDIOSTREAMCFG_B2F(pCfg, cbToWrite)); 786 Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [csAvail=%ld]\n", cbToWrite, csWritten, csAvail)); 787 if (csWritten <= 0) 750 /* 751 * Determine how much we can write (caller actually did this 752 * already, but we repeat it just to be sure or something). 753 */ 754 snd_pcm_sframes_t cFramesAvail; 755 int rc = alsaStreamGetAvail(pStreamALSA->phPCM, &cFramesAvail); 756 if (RT_SUCCESS(rc)) 757 { 758 Assert(cFramesAvail); 759 if (cFramesAvail) 760 { 761 PCPDMAUDIOPCMPROPS pProps = &pStreamALSA->pCfg->Props; 762 uint32_t cbToWrite = PDMAudioPropsFramesToBytes(pProps, (uint32_t)cFramesAvail); 763 cbToWrite = RT_MIN(cbToWrite, (uint32_t)pStreamALSA->cbBuf); 764 if (cbToWrite) 788 765 { 789 switch (csWritten) 766 if (cbToWrite > cbBuf) 767 cbToWrite = cbBuf; 768 769 /* 770 * Now we copy the stuff into our scratch buffer for some 771 * totally unexplained reason. 772 */ 773 memcpy(pStreamALSA->pvBuf, pvBuf, cbToWrite); 774 775 /* 776 * Try write the data. 777 */ 778 uint32_t cFramesToWrite = PDMAudioPropsBytesToFrames(pProps, cbToWrite); 779 snd_pcm_sframes_t cFramesWritten = snd_pcm_writei(pStreamALSA->phPCM, pStreamALSA->pvBuf, cFramesToWrite); 780 if (cFramesWritten > 0) 790 781 { 791 case 0: 782 Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [cFramesAvail=%ld]\n", 783 cbToWrite, cFramesWritten, cFramesAvail)); 784 *pcbWritten = PDMAudioPropsFramesToBytes(pProps, cFramesWritten); 785 return VINF_SUCCESS; 786 } 787 LogFunc(("snd_pcm_writei w/ cbToWrite=%u -> %ld [cFramesAvail=%ld]\n", cbToWrite, cFramesWritten, cFramesAvail)); 788 789 790 /* 791 * There are a couple of error we can recover from, try to do so. 792 * Only don't try too many times. 793 */ 794 for (unsigned iTry = 0; 795 (cFramesWritten == -EPIPE || cFramesWritten == -ESTRPIPE) && iTry < ALSA_RECOVERY_TRIES_MAX; 796 iTry++) 797 { 798 if (cFramesWritten == -EPIPE) 792 799 { 793 LogFunc(("Failed to write %zu bytes\n", cbToWrite)); 794 rc = VERR_ACCESS_DENIED; 795 break; 800 /* underrun occurred */ 801 rc = alsaStreamRecover(pStreamALSA->phPCM); 802 if (RT_SUCCESS(rc)) 803 LogFlowFunc(("Recovered from playback (iTry=%u)\n", iTry)); 804 else 805 break; 796 806 } 797 798 case -EPIPE: 807 else 799 808 { 800 rc = alsaStreamRecover(pStreamALSA->phPCM); 801 if (RT_FAILURE(rc)) 802 break; 803 804 LogFlowFunc(("Recovered from playback\n")); 805 continue; 806 } 807 808 case -ESTRPIPE: 809 { 810 /* Stream was suspended and waiting for a recovery. */ 809 /* an suspended event occurred, needs resuming. */ 811 810 rc = alsaStreamResume(pStreamALSA->phPCM); 812 if (RT_FAILURE(rc)) 811 if (RT_SUCCESS(rc)) 812 LogFlowFunc(("Resumed suspended output stream (iTry=%u)\n", iTry)); 813 else 813 814 { 814 LogRel(("ALSA: Failed to resume output stream \n"));815 LogRel(("ALSA: Failed to resume output stream (iTry=%u, rc=%Rrc)\n", iTry, rc)); 815 816 break; 816 817 } 817 818 LogFlowFunc(("Resumed suspended output stream\n"));819 continue;820 818 } 821 819 822 default: 823 LogFlowFunc(("Failed to write %RU32 bytes, error unknown\n", cbToWrite)); 824 rc = VERR_GENERAL_FAILURE; /** @todo */ 825 break; 820 cFramesWritten = snd_pcm_writei(pStreamALSA->phPCM, pStreamALSA->pvBuf, cFramesToWrite); 821 if (cFramesWritten > 0) 822 { 823 Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [cFramesAvail=%ld]\n", 824 cbToWrite, cFramesWritten, cFramesAvail)); 825 *pcbWritten = PDMAudioPropsFramesToBytes(pProps, cFramesWritten); 826 return VINF_SUCCESS; 827 } 828 LogFunc(("snd_pcm_writei w/ cbToWrite=%u -> %ld [cFramesAvail=%ld, iTry=%d]\n", cbToWrite, cFramesWritten, cFramesAvail, iTry)); 829 } /* For number of tries. */ 830 831 /* Make sure we return with an error. */ 832 if (RT_SUCCESS_NP(rc)) 833 { 834 if (cFramesWritten == 0) 835 rc = VERR_ACCESS_DENIED; 836 else 837 { 838 rc = RTErrConvertFromErrno(-cFramesWritten); 839 LogFunc(("Failed to write %RU32 bytes: %ld (%Rrc)\n", cbToWrite, cFramesWritten, rc)); 840 } 826 841 } 827 842 } 828 else 829 break; 830 } /* For number of tries. */ 831 832 if ( iTry == ALSA_RECOVERY_TRIES_MAX 833 && csWritten <= 0) 834 rc = VERR_BROKEN_PIPE; 835 836 if (RT_FAILURE(rc)) 837 break; 838 839 cbWrittenTotal = PDMAUDIOSTREAMCFG_F2B(pCfg, csWritten); 840 841 } while (0); 842 843 if (RT_SUCCESS(rc)) 844 { 845 if (puWritten) 846 *puWritten = cbWrittenTotal; 847 } 848 843 } 844 } 845 else 846 LogFunc(("Error getting number of playback frames, rc=%Rrc\n", rc)); 847 *pcbWritten = 0; 849 848 return rc; 850 849 } -
trunk/src/VBox/Devices/Audio/DrvHostAudioPulseAudio.cpp
r88269 r88282 991 991 */ 992 992 static DECLCALLBACK(int) drvHostPulseAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, 993 const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten) 994 { 995 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 996 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 997 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 998 AssertReturn(uBufSize, VERR_INVALID_PARAMETER); 999 /* puWritten is optional. */ 1000 1001 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1002 PPULSEAUDIOSTREAM pPAStream = (PPULSEAUDIOSTREAM)pStream; 1003 1004 int rc = VINF_SUCCESS; 1005 1006 uint32_t cbWrittenTotal = 0; 993 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten) 994 { 995 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 996 AssertPtr(pThis); 997 PPULSEAUDIOSTREAM pPAStream = (PPULSEAUDIOSTREAM)pStream; 998 AssertPtrReturn(pPAStream, VERR_INVALID_POINTER); 999 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1000 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 1001 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER); 1007 1002 1008 1003 pa_threaded_mainloop_lock(pThis->pMainLoop); … … 1011 1006 const pa_usec_t tsNowUs = pa_rtclock_now(); 1012 1007 const pa_usec_t tsDeltaPlayedUs = tsNowUs - pPAStream->tsLastReadWrittenUs; 1013 1014 Log3Func(("tsDeltaPlayedMs=%RU64\n", tsDeltaPlayedUs / 1000 /* ms */));1015 1016 1008 pPAStream->tsLastReadWrittenUs = tsNowUs; 1009 Log3Func(("tsDeltaPlayedMs=%RU64\n", tsDeltaPlayedUs / RT_US_1MS)); 1017 1010 #endif 1018 1011 1019 do 1020 { 1021 size_t cbWriteable = pa_stream_writable_size(pPAStream->pStream); 1022 if (cbWriteable == (size_t)-1) 1023 { 1024 rc = paError(pPAStream->pDrv, "Failed to determine output data size"); 1025 break; 1026 } 1027 1028 size_t cbLeft = RT_MIN(cbWriteable, uBufSize); 1029 Assert(cbLeft); /* At this point we better have *something* to write. */ 1030 1031 while (cbLeft) 1032 { 1033 uint32_t cbChunk = cbLeft; /* Write all at once for now. */ 1034 1035 if (pa_stream_write(pPAStream->pStream, (uint8_t *)pvBuf + cbWrittenTotal, cbChunk, NULL /* Cleanup callback */, 1036 0, PA_SEEK_RELATIVE) < 0) 1037 { 1038 rc = paError(pPAStream->pDrv, "Failed to write to output stream"); 1039 break; 1040 } 1041 1042 Assert(cbLeft >= cbChunk); 1043 cbLeft -= cbChunk; 1044 cbWrittenTotal += cbChunk; 1045 } 1046 1047 } while (0); 1012 int rc; 1013 size_t const cbWriteable = pa_stream_writable_size(pPAStream->pStream); 1014 if (cbWriteable != (size_t)-1) 1015 { 1016 size_t cbLeft = RT_MIN(cbWriteable, cbBuf); 1017 Assert(cbLeft > 0 /* At this point we better have *something* to write (DrvAudio checked before calling). */); 1018 if (pa_stream_write(pPAStream->pStream, pvBuf, cbLeft, NULL /*pfnFree*/, 0 /*offset*/, PA_SEEK_RELATIVE) >= 0) 1019 { 1020 *pcbWritten = (uint32_t)cbLeft; 1021 rc = VINF_SUCCESS; 1022 } 1023 else 1024 rc = paError(pPAStream->pDrv, "Failed to write to output stream"); 1025 } 1026 else 1027 rc = paError(pPAStream->pDrv, "Failed to determine output data size"); 1048 1028 1049 1029 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1050 1051 if (RT_SUCCESS(rc))1052 {1053 if (puWritten)1054 *puWritten = cbWrittenTotal;1055 }1056 1057 1030 return rc; 1058 1031 }
Note:
See TracChangeset
for help on using the changeset viewer.