32 ULONG Webcam::AddRef()
37 ULONG Webcam::Release()
49 static const QITAB qit[] = {QITABENT(
Webcam, IMFSourceReaderCallback),{
nullptr},};
50 return QISearch(
this, qit, riid, ppv);
53 HRESULT
Webcam::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimeStamp, IMFSample* pSample)
71 if (dwStreamIndex == 0)
84 hr = pSample->SetSampleTime(llTimeStamp);
100 hr =
m_pReader->ReadSample(static_cast<DWORD>(MF_SOURCE_READER_ANY_STREAM), 0,
nullptr,
nullptr,
nullptr,
nullptr);
115 hr = pSample->SetSampleTime(llTimeStamp);
131 hr =
m_pReader->ReadSample(static_cast<DWORD>(MF_SOURCE_READER_ANY_STREAM), 0,
nullptr,
nullptr,
nullptr,
nullptr);
142 *ppAggSource =
nullptr;
144 IMFCollection* pCollection =
nullptr;
147 if (FAILED(hr = MFCreateCollection(&pCollection)))
153 if (FAILED(hr = pCollection->AddElement(pSource1)))
159 if (FAILED(hr = pCollection->AddElement(pSource2)))
165 if (FAILED(hr = MFCreateAggregateSource(pCollection, ppAggSource)))
171 SAFE_RELEASE(pCollection);
177 IMFAttributes* pAttributes =
nullptr;
180 if (FAILED(hr = MFCreateAttributes(&pAttributes, 2)))
186 if (FAILED(hr = pAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK,
this)))
189 SAFE_RELEASE(pAttributes);
193 if (FAILED(hr = MFCreateSourceReaderFromMediaSource(
pSource, pAttributes, &
m_pReader)))
198 SAFE_RELEASE(pAttributes);
206 IMFMediaType* pVideoNativeMediaType =
nullptr;
207 IMFMediaType* pVideoTargetMediaType =
nullptr;
208 IMFMediaType* pAudioNativeMediaType =
nullptr;
209 IMFMediaType* pAudioTargetMediaType =
nullptr;
211 #pragma region Configure Video 214 if (FAILED(hr =
m_pReader->GetNativeMediaType(static_cast<DWORD>(MF_SOURCE_READER_FIRST_VIDEO_STREAM), 0, &pVideoNativeMediaType)))
243 #pragma region Configure Audio 246 if (FAILED(hr =
m_pReader->GetNativeMediaType(static_cast<DWORD>(MF_SOURCE_READER_FIRST_AUDIO_STREAM), 0, &pAudioNativeMediaType)))
276 if (FAILED(hr =
m_pWriter->BeginWriting()))
282 SAFE_RELEASE(pVideoTargetMediaType);
283 SAFE_RELEASE(pVideoNativeMediaType);
284 SAFE_RELEASE(pAudioTargetMediaType);
285 SAFE_RELEASE(pAudioNativeMediaType);
293 IMFMediaType* pTargetMediaType =
nullptr;
298 UINT32 unDenominator;
301 UINT32 unInterlaceMode;
304 *ppTargetMediaType =
nullptr;
306 HRESULT hr = MFCreateMediaType(&pTargetMediaType);
309 hr = pTargetMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
314 hr = pTargetMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
319 hr = MFGetAttributeSize(pNativeMediaType, MF_MT_FRAME_SIZE, &unWidth, &unHeight);
325 sprintf_s(msg, 99,
"Webcam::CreateTargetVideoMediaType Native unWidth: %i unHeight: %i", unWidth, unHeight);
335 hr = MFGetAttributeRatio(pNativeMediaType, MF_MT_FRAME_RATE, &unNumerator, &unDenominator);
341 sprintf_s(msg, 99,
"Webcam::CreateTargetVideoMediaType Native unNumerator: %i unDenominator: %i", unNumerator, unDenominator);
346 hr = MFSetAttributeRatio(pNativeMediaType, MF_MT_FRAME_RATE, unNumerator, unDenominator);
351 hr = MFGetAttributeRatio(pNativeMediaType, MF_MT_PIXEL_ASPECT_RATIO, &unAspectX, &unAspectY);
356 hr = pNativeMediaType->GetUINT32(MF_MT_INTERLACE_MODE, &unInterlaceMode);
358 sprintf_s(msg, 99,
"Webcam::CreateTargetVideoMediaType Native GetUINT32 MF_MT_INTERLACE_MODE: %i", unInterlaceMode);
370 hr = pNativeMediaType->GetUINT32(MF_MT_AVG_BITRATE, &unBitrate);
372 sprintf_s(msg, 99,
"Webcam::CreateTargetVideoMediaType Native unBitrate: %i", unBitrate);
387 hr = MFSetAttributeSize(pTargetMediaType, MF_MT_FRAME_SIZE, unWidth, unHeight);
392 hr = MFSetAttributeRatio(pTargetMediaType, MF_MT_FRAME_RATE, unNumerator, unDenominator);
396 hr = MFSetAttributeRatio(pTargetMediaType, MF_MT_PIXEL_ASPECT_RATIO, unAspectX, unAspectY);
401 hr = pTargetMediaType->SetUINT32(MF_MT_INTERLACE_MODE, unInterlaceMode);
406 hr = pTargetMediaType->SetUINT32(MF_MT_AVG_BITRATE, unBitrate);
408 *ppTargetMediaType = pTargetMediaType;
409 pTargetMediaType =
nullptr;
411 SAFE_RELEASE(pTargetMediaType);
421 IMFMediaType* pTargetMediaType =
nullptr;
422 IMFCollection* pAvailableTypes =
nullptr;
423 IUnknown* punkObject =
nullptr;
424 IMFMediaType* pMediaType =
nullptr;
426 DWORD dwAvailableTypes = 0;
428 UINT32 unNumChannels;
431 BOOL fFoundMediaType = FALSE;
433 *ppTargetMediaType =
nullptr;
437 if (FAILED(hr = MFTranscodeGetAudioOutputAvailableTypes(MFAudioFormat_AAC, MFT_ENUM_FLAG_ALL,
nullptr, &pAvailableTypes)))
439 logger->
Log(
"Webcam::CreateTargetAudioMediaType MFTranscodeGetAudioOutputAvailableTypes failed!",
Logger::Error, hr);
443 if (FAILED(hr = pAvailableTypes->GetElementCount(&dwAvailableTypes)))
453 for (DWORD ii = 0; ii < dwAvailableTypes; ii++)
455 SAFE_RELEASE(punkObject);
456 SAFE_RELEASE(pMediaType);
458 if (FAILED(hr = pAvailableTypes->GetElement(ii, &punkObject)))
464 if (FAILED(hr = punkObject->QueryInterface(IID_PPV_ARGS(&pMediaType))))
470 if (FAILED(hr = pMediaType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &unNumChannels)))
476 if (FAILED(hr = pMediaType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &unSampleRate)))
478 logger->
Log(
"Webcam::CreateTargetAudioMediaType MF_MT_AUDIO_SAMPLES_PER_SECOND failed!",
Logger::Error, hr);
484 fFoundMediaType = TRUE;
489 if (!fFoundMediaType)
495 if (FAILED(hr = MFCreateMediaType(&pTargetMediaType)))
501 if (FAILED(hr = pMediaType->CopyAllItems(pTargetMediaType)))
507 *ppTargetMediaType = pTargetMediaType;
509 pTargetMediaType =
nullptr;
511 SAFE_RELEASE(pTargetMediaType);
512 SAFE_RELEASE(pAvailableTypes);
513 SAFE_RELEASE(punkObject);
514 SAFE_RELEASE(pMediaType);
519 HRESULT
Webcam::NegotiateStreamFormat(__in DWORD dwStreamIndex, __in REFGUID guidMajorType, __in DWORD cFormats, __in_ecount(cFormats)
const GUID** paFormats)
const 523 IMFMediaType* pPartialMediaType =
nullptr;
524 IMFMediaType* pFullMediaType =
nullptr;
526 BOOL fConfigured = FALSE;
528 if (FAILED(hr = MFCreateMediaType(&pPartialMediaType)))
534 if (FAILED(hr = pPartialMediaType->SetGUID(MF_MT_MAJOR_TYPE, guidMajorType)))
543 sprintf_s(msg, 99,
"Webcam::NegotiateStreamFormat sink_video_stream cFormats count: %i", cFormats);
547 for (DWORD ii = 0; ii < cFormats; ii++)
549 SAFE_RELEASE(pFullMediaType);
551 if (FAILED(hr = pPartialMediaType->SetGUID(MF_MT_SUBTYPE, *paFormats[ii])))
572 hr =
m_pReader->SetCurrentMediaType(static_cast<DWORD>(MF_SOURCE_READER_FIRST_VIDEO_STREAM),
nullptr, pPartialMediaType);
576 hr =
m_pReader->SetCurrentMediaType(static_cast<DWORD>(MF_SOURCE_READER_FIRST_AUDIO_STREAM),
nullptr, pPartialMediaType);
589 hr =
m_pReader->GetCurrentMediaType(static_cast<DWORD>(MF_SOURCE_READER_FIRST_VIDEO_STREAM), &pFullMediaType);
593 hr =
m_pReader->GetCurrentMediaType(static_cast<DWORD>(MF_SOURCE_READER_FIRST_AUDIO_STREAM), &pFullMediaType);
599 hr =
m_pWriter->SetInputMediaType(dwStreamIndex, pFullMediaType,
nullptr);
618 SAFE_RELEASE(pPartialMediaType);
619 SAFE_RELEASE(pFullMediaType);
634 static const GUID* aVideoFormats[] =
639 &MFVideoFormat_RGB32,
641 &MFVideoFormat_RGB24,
645 return NegotiateStreamFormat(dwStreamIndex, MFMediaType_Video, ARRAYSIZE(aVideoFormats), aVideoFormats);
650 static const GUID* aAudioFormats[] =
652 &MFAudioFormat_Float,
656 return NegotiateStreamFormat(dwStreamIndex, MFMediaType_Audio, ARRAYSIZE(aAudioFormats), aAudioFormats);
663 BOOL bIsCapturing = (
m_pWriter !=
nullptr);
672 if (!prmConfig->
enabled)
return;
681 CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
682 MFStartup(MF_VERSION);
690 logger->
Log(
"Webcam::StartRecord Entering...");
725 sprintf_s(msg, 199,
"Webcam::Initialize Searching for video device: %S",
config->
videoDevice.c_str());
733 sprintf_s(msg, 199,
"Webcam::Initialize Searching for audio device: %S",
config->
audioDevice.c_str());
803 if (FAILED(hr =
m_pReader->ReadSample(static_cast<DWORD>(MF_SOURCE_READER_ANY_STREAM), 0,
nullptr,
nullptr,
nullptr,
nullptr)))
816 logger->
Log(
"Webcam::StartRecord Successful!");
821 logger->
Log(
"Webcam::StopRecord Entering...");
834 if (hr == 0xc00d4a44)
835 logger->
Log(
"Webcam::StopRecord Finalize failed because no samples were processed by the sink!",
Logger::Error, hr);
860 sprintf_s(msg, 99,
"Webcam::StopRecord Success, returning: %s",
pathAndFileNameA.c_str());
895 IMFAttributes* pAttributes =
nullptr;
902 if (FAILED(hr = MFCreateAttributes(&pAttributes, 1)))
909 if (FAILED(hr = pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
m_guidDevice)))
911 logger->
Log(
"Webcam::DeviceList::EnumerateDevices SetGUID MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE failed!",
Logger::Error, hr);
922 SAFE_RELEASE(pAttributes);
929 WCHAR* szFriendlyName =
nullptr;
930 if (FAILED(hr =
m_ppDevices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &szFriendlyName, &cchName)))
932 logger->
Log(
"Webcam::DeviceList::EnumerateDevices GetAllocatedString MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME failed!",
Logger::Error, hr);
937 WCHAR* szFriendlyName2 =
nullptr;
938 if (
m_guidDevice == MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)
939 hr =
m_ppDevices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &szFriendlyName2, &cchName);
941 hr =
m_ppDevices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID, &szFriendlyName2, &cchName);
944 logger->
Log(
"Webcam::DeviceList::EnumerateDevices GetAllocatedString m_guidDevice failed!",
Logger::Error, hr);
949 if (
m_guidDevice == MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)
950 sprintf_s(msg, 199,
"WebCam::DeviceList::EnumerateDevices Available video capture device %S: %S", szFriendlyName, szFriendlyName2);
952 sprintf_s(msg, 199,
"WebCam::DeviceList::EnumerateDevices Available audio capture device %S: %S", szFriendlyName, szFriendlyName2);
955 if (
m_guidDevice == MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)
957 if (
config->videoDevice.empty())
959 config->videoDevice = szFriendlyName2;
960 sprintf_s(msg, 199,
"WebCam::DeviceList::EnumerateDevices Defaulted video capture device %S",
config->videoDevice.c_str());
965 if (
config->audioDevice.empty())
967 config->audioDevice = szFriendlyName2;
968 sprintf_s(msg, 199,
"WebCam::DeviceList::EnumerateDevices Defaulted audio capture device %S",
config->audioDevice.c_str());
972 CoTaskMemFree(szFriendlyName);
973 CoTaskMemFree(szFriendlyName2);
981 if (
m_guidDevice == MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)
983 for (UINT i = 0; i <
Count(); i++)
985 WCHAR* sympolicLink =
nullptr;
986 m_ppDevices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &sympolicLink,
nullptr);
987 if (
id == sympolicLink)
990 (*ppActivate)->AddRef();
995 else if (
m_guidDevice == MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID)
997 for (UINT i = 0; i <
Count(); i++)
999 WCHAR* emdPointID =
nullptr;
1000 m_ppDevices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID, &emdPointID,
nullptr);
1001 if (
id == emdPointID)
1004 (*ppActivate)->AddRef();
1017 if (command.
delay != 0.0f)
continue;
1019 if (command.
name ==
"StartRecord")
1025 else if (command.
name ==
"StopRecord")
STDMETHODIMP QueryInterface(REFIID iid, void **ppv)
IUnknown methods below can be moved where?
HRESULT NegotiateAudioStreamFormat(DWORD dwStreamIndex) const
std::vector< Command > commandStream
IMFMediaSource * pVideoSource
std::string pathAndFileNameA
IMFActivate * pAudioActivate
IMFActivate ** m_ppDevices
IMFActivate * pVideoActivate
HRESULT NegotiateStreamFormat(DWORD dwStreamIndex, REFGUID guidMajorType, DWORD cFormats, const GUID **paFormats) const
HRESULT CreateTargetAudioMediaType(IMFMediaType *pNativeMediaType, IMFMediaType **ppTargetMediaType) const
okay, the portable keyboard numbers don't work like the outside keypad because the outside keypad is ...
HRESULT CreateAggregatedSource(IMFMediaSource *pSource1, IMFMediaSource *pSource2, IMFMediaSource **ppAggSource) const
std::string name
command name
std::wstring pathAndFileName
HRESULT OpenMediaSource(IMFMediaSource *pSource)
IMFMediaSource * pAudioSource
DeviceList * videoDevices
HRESULT NegotiateVideoStreamFormat(DWORD dwStreamIndex) const
DeviceList(GUID guidDevice)
HRESULT ConfigureCapture()
IMFSourceReader * m_pReader
HRESULT GetDevicebyID(std::wstring id, IMFActivate **ppActivate) const
LONGLONG m_llVideoBaseTime
HRESULT CreateTargetVideoMediaType(IMFMediaType *pNativeMediaType, IMFMediaType **ppTargetMediaType) const
STDMETHODIMP OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample)
void Log(const char *msg, Level level=Info, int errorCode=0)
These have to be in this order.
HRESULT EnumerateDevices(Logger *logger, WebcamConfig *config)
std::string receiptNumber
LONGLONG m_llAudioBaseTime
IMFSinkWriter * m_pWriter
DeviceList * audioDevices
void Initialize(Logger *prmLogger, WebcamConfig *prmConfig, Bus *prmBus)
float delay
wait number of seconds before executing command
CRITICAL_SECTION m_critsec