How to get Cocoa to detect USB webcam device - macos

Cannot access webcam from browser
My aim is to access a USB webcam (video / camera) device from any web browsers on OS X. Using Flash, I cannot see the USB webcam that is plugged in, switched on and active.
Similarly, I cannot detect the webcam video source using HTML5 getUserMedia() https://www.webrtc-experiment.com/DetectRTC/. Though the Audio stream from the USB device is listed
ImageSnap (Cocoa)
To verify if the USB device is in fact accessible in OSX, I use the open source tool ImageSnap .
$ imagesnap -l
Video Devices:
FaceTime HD Camera (Built-in)
Only the built-in iSight camera is detected, not the attached USB camera.
ImageSnap uses the Cocoa framework.
wacaw (Carbon)
Next, using wacaw, I can list out the attached USB camera, and even correctly take snapshots.
$ wacaw -L
DVFreeThread - CFMachPortCreateWithPort hack = 0x116970, fPowerNotifyPort= 0x1158d0
There are 5 devices in the list.
The current selection is 0.
0 - AVer Virtual Camera [is available] [has inputs]
There are 1 inputs for this device (0).
The current selection is 0.
0 - AVer Virtual Camera [is available]
1 - DV Video [is available] [has no inputs]
2 - IIDC FireWire Video [is available] [has no inputs]
3 - USB Video Camera for AverVision Digital Presenter 2 [is available] [has no inputs]
4 - USB Video Class Video [is available] [has inputs]
There are 1 inputs for this device (4).
The current selection is 0.
0 - FaceTime HD Camera (Built-in) [is available]
wacaw uses Carbon framework.
Problem
How can I make the USB camera accessible via Cocoa, which will also make it accessible through web browsers?

Obviously that camera needs a driver to make it work. Apps on Mac are running in 64-bit nowadays, and the carbon driver (should be implemented with sequence grabber framework) is 32-bit only.
It might work if the camera producer offers driver written with cocoa, or just use a UVC camera instead.

Related

Mac OS X video capture device hot plug driver support

I'm developing driver for USB video capture device. First of all, I've started with CoreMediaIO sample:
https://developer.apple.com/library/content/samplecode/CoreMediaIO/Introduction/Intro.html
The kernel extension is based on IOVideoSample. It gets data from the USB device and sends to the assistant. Kext has IOKitPersonalities based on the USB device. So the device is real and should support HotPlug. Kext main class loads when the device is plugged in and unloads when the device is plugged out.
SampleAssistant was changed only to detect my kext class. PlugIn has NoCMIOHardwarePluginLazyLoadingInfo property.
When all video capture apps are closed - hotplug works well. Terminate function is being called from kext and kext object is being unloaded without any problem.
Even if you start video capture app with the stream from the device, then close it and plug out device - hotplug also works.
It works well with QuickTime player. It can find a stream and show an image, but there is one problem.
When QuickTime (or any other video capture app) works and show stream from the device - hotplug doesn't work. If you try to plug out the device it will remain in the system and USB port won't work until you reboot Mac. According to logs - terminate function wasn't called at all. Seems that something retains a link to the device.
I've started digging into the problem.
First of all, I figured out that SampleAssistant doesn't support hotplug by default. It has notification only for device arriving (DeviceArrived). I've added "interest" notification and handle only "kIOMessageSeviceIsTerminated" message - executing DeviceRemoved function and force deleting device object, but it didn't help.
There is also a file CMIO_DPA_Sample_Server_Stream.cpp. If you go to Stream::Start function and delete "mIOSAStream.Open;" and "mIOSAStream.Start();" lines - hotplug works.
Can you please advise what can be done to solve this problem?

Recording both headset input and internal mic input at the same time

On a newer Mac, it appears that OS X treats the 'microphone' as a special device. When no headset is attached, it uses the "internal mic". When I add a headset it transparently switches over to the headset mic (in this case from an iPhone headset).
Is there any way (low-level code perhaps?) I can have it record from the internal mic AND the headphone mic concurrently? I have an application where this is essential.
I could probably use a USB mic instead of the headset, then they would be two separate devices - but I'd like to support headset style devices (or any line-in input) as well.

Hide Audio device using codeless kext

I am developing a audio driver to do some custom audio processing using audio reflector driver sample code from Apple. Output from audio reflector driver is passed to real USB audio hardware device using core audio application. Now I want to hide USB audio hardware device from the system preferences so that user is not able to select the USB audio hardware output device as the default output device. Using the "SampleUSBAudioOverrideDriver" codeless kext I am able to change the name of output interface but not hide it. Any idea on how I will be able to hide USB audio hardware output device.
Thanks in advance.
Vin Pai
After a lof of R&D on this topic, I found that codeless kext provided in the sample code, SampleUSBAudioOverrideDriver doesn't use the property set to hide the device interface.

Hide USB Audio device on MAC OS X using custom kext

I am developing an application which does custom audio processing and sends the processed audio to the USB headset. My requirement is that the USB headset should not be visible to the user in the list of Audio output devices in System Preferences. Using "SampleUSBAudioOverrideDriver" code-less kext sample code from Apple, I'm able to change the interface name but I really need to hide it.
Is subclassing AppleUSBAudioDevice an option?
The recommended way to do pre-processing of a USB audio device's input and output streams in kernel space is to use the AppleUSBAudioPlugin API. This kext does not appear in the list of devices because it isn't an instance of IOAudioEngine, so there is no "hiding" involved.

Pre-Amplify Audio OS X

There are two apps for OS X that allow you to pre-amplify audio before it gets played by the hardware: Audio Hijack (pre-amplifies output from particular applications) and Boom (pre-amplifies all system audio). These apps work by applying equalization to pre-existing audio streams - with a high pre-amp setting - before they are sent to the sound card.
My question is: how to hijack the system audio stream and then send it along to the sound card. Is this somewhere in an API, or would it require altering a system library ?
1) Create a standard sound device that shows up in audio system preferences. This has to be in the form of a kernel extension (kext). Difficult to create by just reading apple docs - try looking at an app called Soundflower.
2) Once you've loaded the kext and have the new audio device available, select it in preferences as the default output device for system audio.
3) Now you need to alter the audio and pipe it to the real system output. This can be done in an accompanying application that adds callback "IOProc" functions to a) the new device and b) your computer's built-in output device. You can then copy audio buffers from one device to the other, to pipe the audio to your speakers. To increase the volume, multiply all the bytes in the buffer by some factor. See Soundflower's accompanying app.

Resources