Open Wouter1 opened 9 years ago
This is a huge amount of work and tricky as well (one error and we have a failing driver). And I can't work on this for long stretches. So I'm doing this in small steps with testing between each commit.
The plan is to replace also the AD ringbuffer partially with this generic one. I will need to do some performance comparisons before and after replace as I don't have the highly optimized code of the old ringbuffer in the new ringbuffer
In the old ring buffer I see this performance (using Activity Monotor) while sampling stereo @96kHz
HALLab: 1.4% kernel_task: 7.0% (baseline: coreaudiod: 2.1% (baseline:
In-between CPU load test. Should not make any difference at this point - old ring buffer stil active at this point but we're close to removing I hope
HALLab: 1.4% kernel_task: 7.0% (baseline: coreaudiod: 2.1% (baseline:
identical to previous measurement.
Something seems broken badly. HALLab still starts up but Audacity hangs up. Really not sure what's going on, I always test these basic things before pushing. I reverted to last version after a panic but it keeps hanging up now. No panics, just hangs. I get this in the console
Nov 30 23:00:11 vlieland kernel[0]: USBF: 264.988 AppleUSBXHCI[0xffffff81a2e95000]::GenerateNextPhysicalSegment - Error generating segments, err: e00002e8, numsegments:1
Nov 30 23:00:11 vlieland kernel[0]: USBF: 264.988 AppleXHCIAsyncEndpoint[0xffffff802f3bae00]::Schedule - returned 0xe00002e8
Nov 30 23:00:11 vlieland kernel[0]: USBF: 264.988 AppleUSBXHCI[0xffffff81a2e95000]::GenerateNextPhysicalSegment - Error generating segments, err: e00002e8, numsegments:1
Nov 30 23:00:11 vlieland kernel[0]: USBF: 264.988 AppleXHCIAsyncEndpoint[0xffffff802f3bae00]::Schedule - returned 0xe00002e8
Nov 30 23:00:11 vlieland kernel[0]: USBF: 264.988 AppleUSBXHCI[0xffffff81a2e95000]::GenerateNextPhysicalSegment - Error generating segments, err: e00002e8, numsegments:1
Nov 30 23:00:11 vlieland kernel[0]: USBF: 264.988 AppleXHCIAsyncEndpoint[0xffffff802f3bae00]::Schedule - returned 0xe00002e8
but that does not help me .
This is the HALLab stack when it hangs (it does not hang anymore, but audacity has similar hang trace)
15 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12 (CoreFoundation) [0x7fff8449ce0c]
15 ??? (HALLab + 5388) [0x10cef250c]
15 ??? (HALLab + 84465) [0x10cf059f1]
15 ??? (HALLab + 102870) [0x10cf0a1d6]
15 AudioObjectAddPropertyListener + 129 (CoreAudio) [0x7fff9199905d]
15 HALSystem::CheckOutInstance() + 159 (CoreAudio) [0x7fff91961759]
15 HALSystem::InitializeDevices() + 9 (CoreAudio) [0x7fff91963729]
15 HALPlugInManagement::Initialize() + 324 (CoreAudio) [0x7fff9196387a]
15 HALPlugInManagement::CreateHALPlugIn(HALCFPlugIn const*) + 1258 (CoreAudio) [0x7fff91964726]
15 HAL_HardwarePlugIn_InitializeWithObjectID(AudioHardwarePlugInInterface**, unsigned int) + 56 (CoreAudio) [0x7fff919654c4]
15 HALC_ShellPlugIn::ConnectToServer() + 161 (CoreAudio) [0x7fff91967737]
15 HALC_ShellPlugIn::_ReconcileDeviceList(bool, bool) + 759 (CoreAudio) [0x7fff9196c4fb]
15 HALC_ProxyObjectMap::CopyObjectByObjectID(unsigned int) + 66 (CoreAudio) [0x7fff919677e0]
15 HALC_ProxyObjectMap::_CopyObjectByObjectID(unsigned int) + 240 (CoreAudio) [0x7fff9196798e]
15 HALC_ProxyObjectMap::_CreateObject(unsigned int, unsigned int, unsigned int, unsigned int) + 160 (CoreAudio) [0x7fff9196db6a]
15 HALC_ProxyObject::HALC_ProxyObject(unsigned int, unsigned int, unsigned int, unsigned int) + 244 (CoreAudio) [0x7fff91967eec]
15 HALC_ProxyObject::HasProperty(AudioObjectPropertyAddress const&, bool&) const + 37 (CoreAudio) [0x7fff9196df8d]
15 HALC_Object_HasProperty + 106 (CoreAudio) [0x7fff9196e00e]
15 mach_msg_trap + 10 (libsystem_kernel.dylib) [0x7fff8ef6fa1a]
*15 ipc_mqueue_receive_continue + 0 (mach_kernel) [0xffffff80002167d0]
I did nothing, just restarted today, rebuilt, install kext, and started Audacity. It now works all fine again??
I re-enabled the pop.
Apart from the first "warning. Ignoring overrun", it Audacity runs for 7.5 minutes without any hickup.
Tested another time, 3 minutes. Same, works without any issue.
Connected convertFromEMUUSBAudioInputStreamNoWrap with the ring buffer. This time, no problem at all!! Previous 2 times the machine panicked immediately
I checked the performance. Notice, at this point the OLD ring is also still fuly working so we are pumping around all USB input bytes through 2 rings
HALLab 0.6 %
kernel_task 0.6%
coreaudiod 3.3%
So coreaudiod is slightly more busy but kernel_task much lower. Not sure why but it looks all fine.
I had the hanging Audacity again. The problem persisted if I turned off the EMU device briefly. But if I kept it off longer, like 15 seconds, it worked ok again.
tested again, I really want to be sure it all is ok. Made 9 minute recording. No single hickup or any message during the recording. I think it's good to proceed. Next step will be to take out the old ring buffer and all associated variables with it entirely.
The code in EMUUSBAudioEngine::performFormatChangeInternal (which I copied from performFormatChange) has lot of duplicate code.
There is numerous occurrences of code to build a USB request block. All looks like this
IOReturn result = kIOReturnError;
IOUSBDevRequestDesc devReq;
IOBufferMemoryDescriptor* settingDesc = NULL;
ReturnIf(!mControlInterface, kIOReturnNoDevice);
settingDesc = IOBufferMemoryDescriptor::withBytes(&newValue, newValueLen, kIODirectionIn,true);
ReturnIf(!settingDesc, kIOReturnError);
devReq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
devReq.bRequest = requestType;
devReq.wValue =(controlSelector << 8) | channelNumber;
devReq.wIndex =(0xFF00 &(unitID << 8)) |(0x00FF & mInterfaceNum);
devReq.wLength = newValueLen;
devReq.pData = settingDesc;
debugIOLogC("EMUUSBAudioDevice::setFeatureUnitSetting sending device request %d", requestType);
if (TRUE != isInactive()) // In case we've been unplugged during sleep
result = deviceRequest(&devReq);
debugIOLogC("result= %d.", result);
settingDesc->release();
return result;
the only variation seems the data size/name/length.
That USB request block code was cleaned up
EMUUSBAudioEngine::CheckForAssociatedEndpoint is not used. Disabled.
There seems code related to this already in the EMUUSBAudioEngine. Search for aveSampleRateBuf.
The current audio input code was coded in the same style as the original code from sourceforge.
That is, all required code is inside the large EMUUSBAudioEngine.
It would be much better if this code could be pulled into the ADRingBuffer class (which was already made but the restructure did not yet materialize). The name ADRingBuffer was picked instead of something like InputRingBuffer because it is only input for the client; for the driver it's also an output buffer.
The USB input stream maybe can be moved to yet another class to keep it separate from the AD ring buffer.
The code around the locking is tricky. It would be nice if this can be done in a cleaner way that link properly to the two requirements for re-use of a USB framelist: