Mercurial > almixer_isolated
comparison ALmixer.c @ 50:db5bc1c80057
Workaround for terrible iOS 5.0 regression bug in Apple's OpenAL implementation with regards to resetting streaming sources. The fix uses a version check to determine if the workaround is employed. Once Apple fixes the problem, an upper bounds version check should be added.
author | Eric Wing <ewing@anscamobile.com> |
---|---|
date | Fri, 21 Oct 2011 17:14:19 -0700 |
parents | 4b0268d86298 |
children | e2687188aea5 |
comparison
equal
deleted
inserted
replaced
49:4b0268d86298 | 50:db5bc1c80057 |
---|---|
1730 * for these constants since iOS 4.2, so I don't know if the value is also catching 4.3. | 1730 * for these constants since iOS 4.2, so I don't know if the value is also catching 4.3. |
1731 * TODO: Once I learn which version Apple fixes the bug in, I need to update the range so this check is not run on fixed versions. | 1731 * TODO: Once I learn which version Apple fixes the bug in, I need to update the range so this check is not run on fixed versions. |
1732 */ | 1732 */ |
1733 if(kCFCoreFoundationVersionNumber >= 674.0) | 1733 if(kCFCoreFoundationVersionNumber >= 674.0) |
1734 { | 1734 { |
1735 if(AL_FALSE == is_predecoded) | 1735 /* For OpenAL experts, this is contrary to what you know, but must be done because the OpenAL implementation is broken. |
1736 Instead of unqueuing buffers on only streaming sources, it appears that alSourcei(source, AL_BUFFER, AL_NONE) is not reliable at all. | |
1737 In cases where I switch between stream and non-stream on the same source and then stream again, the bug breaks playback on the third playback | |
1738 and only one buffer plays. | |
1739 The workaround seems to be to always unqueue buffers regardless of whether the source is streamed or not. | |
1740 And then avoid calling (source, AL_BUFFER, AL_NONE) | |
1741 From past experience, I know it is a bad idea to try to unqueue buffers from a non-streamed source (which is the contrary to OpenAL part), | |
1742 but this seems to work for this bug. | |
1743 */ | |
1744 ALint buffers_processed; | |
1745 /* Wow this is the bug that just keeps on sucking. There is even a race condition bug where the unqueue may not actually work. | |
1746 * So I have to keep doing it until it does. | |
1747 */ | |
1748 do | |
1736 { | 1749 { |
1737 ALint buffers_processed; | 1750 ALint temp_count; |
1751 | |
1738 /* Wow this is the bug that just keeps on sucking. There is even a race condition bug where the unqueue may not actually work. | 1752 /* Wow this is the bug that just keeps on sucking. There is even a race condition bug where the unqueue may not actually work. |
1739 * So I have to keep doing it until it does. | 1753 * So I have to keep doing it until it does. |
1754 * Sleeping for 20ms seems to help. 10ms was not long enough. (iPad 2) | |
1740 */ | 1755 */ |
1741 do | 1756 ALmixer_Delay(20); |
1757 | |
1758 alGetSourcei( | |
1759 source_id, | |
1760 AL_BUFFERS_PROCESSED, &buffers_processed | |
1761 ); | |
1762 if((error = alGetError()) != AL_NO_ERROR) | |
1742 { | 1763 { |
1743 ALint temp_count; | 1764 fprintf(stderr, "17aTesting Error with buffers_processed on Halt. (You may be seeing this because of a bad Apple OpenAL iOS 5.0 regression bug): %s", |
1744 | 1765 alGetString(error)); |
1745 /* Wow this is the bug that just keeps on sucking. There is even a race condition bug where the unqueue may not actually work. | 1766 ALmixer_SetError("Failed detecting still processed buffers: %s", |
1746 * So I have to keep doing it until it does. | 1767 alGetString(error) ); |
1747 * Sleeping for 20ms seems to help. 10ms was not long enough. (iPad 2) | 1768 /* This whole iOS 5.0 bug is so messed up that returning an error value probably isn't helpful. |
1748 */ | 1769 retval = AL_FALSE; |
1749 ALmixer_Delay(20); | 1770 */ |
1750 | 1771 } |
1751 alGetSourcei( | 1772 /* |
1773 fprintf(stderr, "Going to unqueue %d buffers\n", buffers_processed); | |
1774 */ | |
1775 for(temp_count=0; temp_count<buffers_processed; temp_count++) | |
1776 { | |
1777 ALuint unqueued_buffer_id; | |
1778 | |
1779 alSourceUnqueueBuffers( | |
1752 source_id, | 1780 source_id, |
1753 AL_BUFFERS_PROCESSED, &buffers_processed | 1781 1, &unqueued_buffer_id |
1754 ); | 1782 ); |
1755 if((error = alGetError()) != AL_NO_ERROR) | 1783 if((error = alGetError()) != AL_NO_ERROR) |
1756 { | 1784 { |
1757 fprintf(stderr, "17aTesting Error with buffers_processed on Halt. (You may be seeing this because of a bad Apple OpenAL iOS 5.0 regression bug): %s", | 1785 fprintf(stderr, "17bTesting error with unqueuing buffers on Halt (You may be seeing this because of a bad Apple OpenAL iOS 5.0 regression bug): %s\n", |
1758 alGetString(error)); | 1786 alGetString(error)); |
1759 ALmixer_SetError("Failed detecting still processed buffers: %s", | |
1760 alGetString(error) ); | |
1761 /* This whole iOS 5.0 bug is so messed up that returning an error value probably isn't helpful. | |
1762 retval = AL_FALSE; | |
1763 */ | |
1764 } | |
1765 /* | |
1766 fprintf(stderr, "Going to unqueue %d buffers\n", buffers_processed); | |
1767 */ | |
1768 for(temp_count=0; temp_count<buffers_processed; temp_count++) | |
1769 { | |
1770 ALuint unqueued_buffer_id; | |
1771 | |
1772 alSourceUnqueueBuffers( | |
1773 source_id, | |
1774 1, &unqueued_buffer_id | |
1775 ); | |
1776 if((error = alGetError()) != AL_NO_ERROR) | |
1777 { | |
1778 fprintf(stderr, "17bTesting error with unqueuing buffers on Halt (You may be seeing this because of a bad Apple OpenAL iOS 5.0 regression bug): %s\n", | |
1779 alGetString(error)); | |
1780 /* This whole iOS 5.0 bug is so messed up that returning an error value probably isn't helpful. | |
1781 retval = AL_FALSE; | |
1782 */ | |
1783 } | |
1784 } | |
1785 | |
1786 alGetSourcei( | |
1787 source_id, | |
1788 AL_BUFFERS_PROCESSED, &buffers_processed | |
1789 ); | |
1790 if((error = alGetError()) != AL_NO_ERROR) | |
1791 { | |
1792 fprintf(stderr, "17cTesting Error with buffers_processed on Halt. (You may be seeing this because of a bad Apple OpenAL iOS 5.0 regression bug): %s", | |
1793 alGetString(error)); | |
1794 ALmixer_SetError("Failed detecting still processed buffers: %s", | |
1795 alGetString(error) ); | |
1796 /* This whole iOS 5.0 bug is so messed up that returning an error value probably isn't helpful. | 1787 /* This whole iOS 5.0 bug is so messed up that returning an error value probably isn't helpful. |
1797 retval = AL_FALSE; | 1788 retval = AL_FALSE; |
1798 */ | 1789 */ |
1799 } | 1790 } |
1800 /* | 1791 } |
1801 fprintf(stderr, "unqueued buffers should be 0. Actual value is %d\n", buffers_processed); | 1792 |
1802 */ | 1793 alGetSourcei( |
1803 /* Wow this is the bug that just keeps on sucking. There is an additional race condition bug where the unqueue may not actually work. | 1794 source_id, |
1804 * So I have to keep doing it until it does. | 1795 AL_BUFFERS_PROCESSED, &buffers_processed |
1805 * I hope this doesn't infinite loop. | 1796 ); |
1797 if((error = alGetError()) != AL_NO_ERROR) | |
1798 { | |
1799 fprintf(stderr, "17cTesting Error with buffers_processed on Halt. (You may be seeing this because of a bad Apple OpenAL iOS 5.0 regression bug): %s", | |
1800 alGetString(error)); | |
1801 ALmixer_SetError("Failed detecting still processed buffers: %s", | |
1802 alGetString(error) ); | |
1803 /* This whole iOS 5.0 bug is so messed up that returning an error value probably isn't helpful. | |
1804 retval = AL_FALSE; | |
1806 */ | 1805 */ |
1807 if(0 != buffers_processed) | 1806 } |
1808 { | 1807 /* |
1809 fprintf(stderr, "Evil Apple OpenAL iOS 5.0 race condition. Buffers didn't actually unqueue. Repeating unqueue loop.\n"); | 1808 fprintf(stderr, "unqueued buffers should be 0. Actual value is %d\n", buffers_processed); |
1810 } | 1809 */ |
1811 } while(0 != buffers_processed); | 1810 /* Wow this is the bug that just keeps on sucking. There is an additional race condition bug where the unqueue may not actually work. |
1812 | 1811 * So I have to keep doing it until it does. |
1813 } | 1812 * I hope this doesn't infinite loop. |
1813 */ | |
1814 if(0 != buffers_processed) | |
1815 { | |
1816 fprintf(stderr, "Evil Apple OpenAL iOS 5.0 race condition. Buffers didn't actually unqueue. Repeating unqueue loop.\n"); | |
1817 } | |
1818 } while(0 != buffers_processed); | |
1819 | |
1820 /* Avoid calling the normal cleanup because part of this bug seems to be triggered by alSourcei(source_id, AL_BUFFER, AL_NONE); */ | |
1821 return retval; | |
1814 } | 1822 } |
1815 | 1823 |
1816 | |
1817 #endif | 1824 #endif |
1818 #endif /* iOS 5.0 workaround */ | 1825 #endif /* iOS 5.0 workaround */ |
1819 | 1826 |
1820 /* According to the spec, this is the best way to clear a source. | 1827 /* According to the spec, this is the best way to clear a source. |
1821 * This is supposed to work for both streamed and non-streamed sources. | 1828 * This is supposed to work for both streamed and non-streamed sources. |