11 #if defined(AJA_WINDOWS)
27 #include <linux/videodev2.h>
28 #include <sys/ioctl.h>
30 #include <alsa/asoundlib.h>
41 #define AUDIO_BYTESPERSAMPLE 4
43 #define AJA_MISSING_DEV_V4L2LOOPBACK // Uncomment if /dev/v4l2loopback missing
44 #if !defined(AJA_MISSING_DEV_V4L2LOOPBACK)
45 #define V4L2_DRIVER_NAME "/dev/v4l2loopback"
51 #define AJA_VW_SUCCESS 0
52 #define AJA_VW_INVALIDARGS 1
53 #define AJA_VW_INVALIDAJADEVICE 2
54 #define AJA_VW_AJADEVICENOTREADY 3
55 #define AJA_VW_AJADEVICENOCAPTURE 4
56 #define AJA_VW_INVALIDPIXELFORMAT 5
57 #define AJA_VW_AJADEVICENOPIXELFORMAT 6
58 #define AJA_VW_NOTSISUPPORT 7
59 #define AJA_VW_INVALIDINPUTCHANNEL 8
60 #define AJA_VW_INVALIDINPUTSOURCE 9
61 #define AJA_VW_ENABLECHANNELSFAILED 10
62 #define AJA_VW_ENABLEINPUTINTERRUPTFAILED 11
63 #define AJA_VW_SUBSCRIBEINPUTVERTICALEVENTFAILED 12
64 #define AJA_VW_SUBSCRIBEOUTPUTVERTICALEVENTFAILED 13
65 #define AJA_VW_SETSDITRANSITENABLEFAILED 14
66 #define AJA_VW_WAITFOROUTPUTVERTICALINTERRUPTFAILED 14
67 #define AJA_VW_INVALIDVIDEOFORMAT 15
68 #define AJA_VW_SETCAPTUREMODEFAILED 16
69 #define AJA_VW_SETFREERUNREFERENCEFAILED 17
70 #define AJA_VW_SETVIDEOFORMATFAILED 18
71 #define AJA_VW_SETVANCMODEOFFFAILED 19
72 #define AJA_VW_SETTSIFRAMEENABLEFAILED 20
73 #define AJA_VW_SET4KSQUARESENABLEFAILED 21
74 #define AJA_VW_SETFRAMEBUFFERFORMATFAILED 22
75 #define AJA_VW_INCORRECTMULTILINKAUDIOCHANNEL 23
76 #define AJA_VW_APPLYSIGNALROUTEFAILED 24
77 #define AJA_VW_ACINITFORINPUTFAILED 25
78 #define AJA_VW_ACSTARTFAILED 26
79 #define AJA_VW_ACSETVIDEOBUFFERFAILED 27
80 #define AJA_VW_ACSETAUDIOBUFFERFAILED 28
81 #define AJA_VW_ACSETANCBUFFERSFAILED 29
82 #define AJA_VW_V4L2DRIVEROPENFAILED 30
83 #define AJA_VW_V4L2DEVICECREATEFAILED 31
84 #define AJA_VW_V4L2DEVICEOPENFAILED 32
85 #define AJA_VW_ACTRANSFERFAILED 33
86 #define AJA_VW_ACGETINPUTTIMECODESFAILED 34
87 #define AJA_VW_ACSTOPFAILED 35
88 #define AJA_VW_V4L2DEVICEREMOVEFAILED 36
89 #define AJA_VW_ALSESETUPFAILED 37
90 #define AJA_VW_CONFIGAUDIOSYSTEMFAILED 38
91 #define AJA_VW_NOHDMISUPPORT 39
92 #define AJA_VW_GETFRAMESERVICESFAILED 40
93 #define AJA_VW_SETFRAMESERVICESFAILED 41
94 #define AJA_VW_GETDEVICEOWNERFAILED 42
95 #define AJA_VW_GETINPUTROUTEFAILED 43
96 #define AJA_VW_SETACFRAMERANGEFAILED 44
97 #define AJA_VW_MISSINGARGS 45
98 #define AJA_VW_GETPOINTERFAILED 46
99 #define AJA_VW_SAMPLEBUFFERSIZEMISMATCH 47
101 #if defined(AJA_WINDOWS)
102 #define VCAM_FILTER_NAME_W L"AJA Virtual Webcam"
103 #define VCAM_VIDEO_PIN_NAME_W L"AJA Virtual Webcam Video Output Pin"
104 #define VCAM_AUDIO_PIN_NAME_W L"AJA Virtual Webcam Audio Output Pin"
106 #define VCAM_FILTER_NAME "AJA Virtual Webcam"
107 #define VCAM_VIDEO_PIN_NAME "AJA Virtual Webcam Video Output Pin"
108 #define VCAM_AUDIO_PIN_NAME "AJA Virtual Webcam Audio Output Pin"
110 const GUID CLSID_VirtualWebcam=
111 { 0xac313179, 0xa0af, 0x4110, { 0xa7, 0x15, 0xe5, 0xff, 0xe7, 0x26, 0x3c, 0xf0 } };
114 0x97d9d47a, 0x3851, 0x4298, 0xb8, 0x7c, 0x8a, 0xd, 0x11, 0xac, 0x9a, 0x19);
115 #endif // if defined(AJA_WINDOWS)
127 #if defined(AJA_WINDOWS)
128 #define MAX_VIDEOS 24
129 #define MAX_AUDIOS 24
131 template <
typename T>
135 std::vector<T> buffer;
143 CircularBuffer(
size_t size)
144 : buffer(size), head(0), tail(0), maxSize(size), isFull(
false)
148 bool isEmpty()
const {
return !isFull && (head == tail);}
149 size_t capacity()
const {
return maxSize;}
153 std::lock_guard<std::mutex> lock(mtx);
159 bool push (
const T& item)
161 std::lock_guard<std::mutex> lock(mtx);
163 head = (head + 1) % maxSize;
165 tail = (tail + 1) % maxSize;
166 isFull = head == tail;
172 std::lock_guard<std::mutex> lock(mtx);
177 tail = (tail + 1) % maxSize;
184 size_t size = maxSize;
190 size = maxSize + head - tail;
199 virtual ~OutputPin() {}
202 class OutputVideoPin :
public OutputPin,
public CSourceStream,
public IKsPropertySet,
public IAMStreamConfig
204 friend class NTV2VCAM;
206 OutputVideoPin (HRESULT* phr,
CSource* pFilter, LPCWSTR pPinName);
208 NTV2VCAM * VCAM (
void)
const {
return reinterpret_cast<NTV2VCAM*
>(m_pFilter);}
210 STDMETHODIMP QueryInterface(REFIID
riid,
void** ppv)
override;
215 STDMETHODIMP CheckMediaType(
const CMediaType* pMediaType)
override;
216 STDMETHODIMP GetMediaType(
CMediaType* pMediaType)
override;
217 STDMETHODIMP FillBuffer(IMediaSample* pSample)
override;
220 STDMETHODIMP DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pRequest)
override;
223 STDMETHODIMP EnumMediaTypes(IEnumMediaTypes** ppEnum)
override;
226 STDMETHODIMP Notify(IBaseFilter* pSender, Quality q)
override;
229 STDMETHODIMP Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData)
override;
230 STDMETHODIMP Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD* pcbReturned)
override;
231 STDMETHODIMP QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD* pTypeSupport)
override;
234 STDMETHODIMP SetFormat(AM_MEDIA_TYPE* pmt)
override;
235 STDMETHODIMP GetFormat(AM_MEDIA_TYPE** ppmt)
override;
236 STDMETHODIMP GetNumberOfCapabilities(
int* piCount,
int* piSize)
override;
237 STDMETHODIMP GetStreamCaps(
int iIndex, AM_MEDIA_TYPE** ppmt, BYTE* pSCC)
override;
240 class OutputAudioPin :
public OutputPin,
public CSourceStream,
public IKsPropertySet,
public IAMStreamConfig
242 friend class NTV2VCAM;
244 OutputAudioPin(HRESULT* phr,
CSource* pFilter, LPCWSTR pPinName);
246 NTV2VCAM * VCAM (
void)
const {
return reinterpret_cast<NTV2VCAM*
>(m_pFilter);}
248 STDMETHODIMP QueryInterface(REFIID
riid,
void** ppv)
override;
253 STDMETHODIMP CheckMediaType(
const CMediaType* pMediaType)
override;
254 STDMETHODIMP GetMediaType(
CMediaType* pMediaType)
override;
255 STDMETHODIMP FillBuffer(IMediaSample* pSample)
override;
258 STDMETHODIMP DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pRequest)
override;
261 STDMETHODIMP EnumMediaTypes(IEnumMediaTypes** ppEnum)
override;
264 STDMETHODIMP Notify(IBaseFilter* pSender, Quality q)
override;
267 STDMETHODIMP Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData)
override;
268 STDMETHODIMP Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD* pcbReturned)
override;
269 STDMETHODIMP QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD* pTypeSupport)
override;
272 STDMETHODIMP SetFormat(AM_MEDIA_TYPE* pmt)
override;
273 STDMETHODIMP GetFormat(AM_MEDIA_TYPE** ppmt)
override;
274 STDMETHODIMP GetNumberOfCapabilities(
int* piCount,
int* piSize)
override;
275 STDMETHODIMP GetStreamCaps(
int iIndex, AM_MEDIA_TYPE** ppmt, BYTE* pSCC)
override;
278 class NTV2VCAM :
public CSource
281 static CUnknown* WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT* phr);
284 STDMETHODIMP QueryInterface(REFIID
riid,
void** ppv)
override;
289 STDMETHODIMP EnumPins(IEnumPins** ppEnum)
override;
290 STDMETHODIMP FindPin(LPCWSTR Id, IPin** ppPin)
override;
291 STDMETHODIMP QueryFilterInfo(FILTER_INFO* pInfo)
override;
292 STDMETHODIMP JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR
pName)
override;
293 STDMETHODIMP QueryVendorInfo(LPWSTR* pVendorInfo)
override;
295 NTV2VCAM(LPUNKNOWN pUnk, HRESULT* phr);
299 HRESULT GetNextFrame(OutputPin* pPin, IMediaSample* pSample);
300 ULWord GetNumAudioChannels() {
return mNumAudioChannels; }
301 ULWord GetAudioSampleRate() {
return mSampleRate; }
302 ULWord GetAudioBitsPerSample() {
return mBitsPerSample; }
303 ULWord GetNumAudioLinks() {
return mNumAudioLinks; }
304 #endif // if defined(AJA_WINDOWS)
306 #if defined(AJALinux)
312 bool Initialize (
int argc,
const char** argv);
314 #endif // if defined(AJALinux)
317 string ULWordToString(
const ULWord inNum);
322 #if defined(AJALinux)
323 int ExtractNumber(
const char* str);
324 #endif // if defined(AJALinux)
331 string mPixelFormatStr;
332 #if defined(AJALinux)
335 #endif // if defined(AJALinux)
337 bool mIsKonaHDMI =
false;
339 bool mDoMultiFormat =
false;
340 bool mDoTSIRouting =
true;
343 UWord mNumSpigots = 0;
354 UWord mNumAudioLinks = 1;
355 ULWord mNumAudioChannels = 1;
356 unsigned int mSampleRate = 48000;
357 ULWord mBitsPerSample = 32;
360 #if defined(AJALinux)
362 snd_pcm_uframes_t mAudioFrames = 2;
363 #if !defined(AJA_MISSING_DEV_V4L2LOOPBACK)
366 int mLbDeviceNR = -1;
368 #endif // if defined(AJALinux)
369 #if defined(AJA_WINDOWS)
370 bool mInitialized =
false;
371 bool mRunning =
false;
372 CircularBuffer<NTV2Buffer> mVideos;
373 CircularBuffer<NTV2Buffer> mAudios;
374 #endif // if defined(AJA_WINDOWS)
377 #if defined(AJA_WINDOWS)
378 class EnumPins :
public IEnumPins
381 volatile long mRefCount = 1;
382 NTV2VCAM* mpFilter =
nullptr;
386 EnumPins(NTV2VCAM* mpFilter, EnumPins* pEnum);
389 STDMETHODIMP QueryInterface(REFIID
riid,
void** ppv);
394 STDMETHODIMP Next(
ULONG cPins, IPin** ppPins,
ULONG* pcFetched);
395 STDMETHODIMP Skip(
ULONG cPins);
396 STDMETHODIMP Reset();
397 STDMETHODIMP Clone(IEnumPins** ppEnum);
400 class EnumMediaTypes :
public IEnumMediaTypes
403 volatile long mRefCount = 1;
404 OutputVideoPin* pin =
nullptr;
408 EnumMediaTypes(OutputVideoPin* pin);
411 STDMETHODIMP QueryInterface(REFIID
riid,
void** ppv);
416 STDMETHODIMP Next(
ULONG cMediaTypes, AM_MEDIA_TYPE** ppMediaTypes,
ULONG* pcFetched);
417 STDMETHODIMP Skip(
ULONG cMediaTypes);
418 STDMETHODIMP Reset();
419 STDMETHODIMP Clone(IEnumMediaTypes** ppEnum);
421 #endif // if defined(AJA_WINDOWS)
423 #endif // _NTV2VCAM_H