bool HVideoEncoder::SetupCrossbar() { ComPtr<IBaseFilter> crossbar; ComPtr<IPin> pin; REGPINMEDIUM medium; /* C353 has no crossbar */ if (config.name.find(L"C353") != std::string::npos) return true; if (!GetPinByName(device, PINDIR_INPUT, L"Analog Video In", &pin)) { Warning(L"Failed to get Analog Video In pin"); return false; } if (!GetPinMedium(pin, medium)) { Warning(L"Failed to get Analog Video In pin medium"); return false; } if (!GetFilterByMedium(AM_KSCATEGORY_CROSSBAR, medium, &crossbar)) { Warning(L"Failed to get crossbar filter"); return false; } graph->AddFilter(crossbar, L"Crossbar Filter"); if (!DirectConnectFilters(graph, crossbar, device)) { Warning(L"Failed to connect crossbar to device"); return false; } return true; }
static inline bool CreateFilters(IBaseFilter *filter, IBaseFilter **crossbar, IBaseFilter **encoder, IBaseFilter **demuxer) { CComPtr<IPin> inputPin; CComPtr<IPin> outputPin; REGPINMEDIUM inMedium; REGPINMEDIUM outMedium; bool hasOutMedium; HRESULT hr; if (!GetPinByName(filter, PINDIR_INPUT, nullptr, &inputPin)) { Warning(L"Encoded Device: Failed to get input pin"); return false; } if (!GetPinByName(filter, PINDIR_OUTPUT, nullptr, &outputPin)) { Warning(L"Encoded Device: Failed to get output pin"); return false; } if (!GetPinMedium(inputPin, inMedium)) { Warning(L"Encoded Device: Failed to get input pin medium"); return false; } hasOutMedium = GetPinMedium(outputPin, outMedium); if (!GetFilterByMedium(AM_KSCATEGORY_CROSSBAR, inMedium, crossbar)) { Warning(L"Encoded Device: Failed to get crossbar filter"); return false; } /* perfectly okay if there's no encoder filter, some don't have them */ if (hasOutMedium) GetFilterByMedium(KSCATEGORY_ENCODER, outMedium, encoder); hr = CoCreateInstance(CLSID_MPEG2Demultiplexer, nullptr, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)demuxer); if (FAILED(hr)) { WarningHR(L"Encoded Device: Failed to create demuxer", hr); return false; } return true; }
bool HDevice::FindCrossbar(IBaseFilter *filter, IBaseFilter **crossbar) { ComPtr<IPin> pin; REGPINMEDIUM medium; HRESULT hr; hr = builder->FindInterface(NULL, NULL, filter, IID_IAMCrossbar, (void**)crossbar); if (SUCCEEDED(hr)) return true; if (!GetPinByName(filter, PINDIR_INPUT, nullptr, &pin)) return false; if (!GetPinMedium(pin, medium)) return false; if (!GetFilterByMedium(AM_KSCATEGORY_CROSSBAR, medium, crossbar)) return false; graph->AddFilter(*crossbar, L"Crossbar Filter"); return true; }
bool HVideoEncoder::SetupEncoder(IBaseFilter *filter) { ComPtr<IBaseFilter> deviceFilter; ComPtr<IPin> inputPin; ComPtr<IPin> outputPin; REGPINMEDIUM medium; MediaTypePtr mtRaw; MediaTypePtr mtEncoded; if (!GetPinByName(filter, PINDIR_INPUT, nullptr, &inputPin)) { Warning(L"Could not get encoder input pin"); return false; } if (!GetPinByName(filter, PINDIR_OUTPUT, nullptr, &outputPin)) { Warning(L"Could not get encoder output pin"); return false; } if (!GetPinMedium(inputPin, medium)) { Warning(L"Could not get input pin medium"); return false; } inputPin.Release(); if (!GetFilterByMedium(CLSID_VideoInputDeviceCategory, medium, &deviceFilter)) { Warning(L"Could not get device filter from medium"); return false; } if (!GetPinByName(deviceFilter, PINDIR_INPUT, L"YUV In", &inputPin)) { Warning(L"Could not device YUV pin"); return false; } if (!GetPinFirstMediaType(inputPin, &mtRaw)) { Warning(L"Could not get YUV pin media type"); return false; } if (!GetPinFirstMediaType(outputPin, &mtEncoded)) { Warning(L"Could not get encoder output pin media type"); return false; } PinCaptureInfo captureInfo; captureInfo.callback = [this] (IMediaSample *s) {Receive(s);}; captureInfo.expectedMajorType = mtEncoded->majortype; captureInfo.expectedSubType = mtEncoded->subtype; PinOutputInfo outputInfo; outputInfo.expectedMajorType = mtRaw->majortype; outputInfo.expectedSubType = mtRaw->subtype; outputInfo.cx = config.cx; outputInfo.cy = config.cy; InitializeVideoFormat(outputInfo.mt); encoder = filter; device = deviceFilter; capture = new CaptureFilter(captureInfo); output = new OutputFilter(outputInfo); graph->AddFilter(output, nullptr); graph->AddFilter(device, L"Device Filter"); graph->AddFilter(encoder, L"Encoder Filter"); graph->AddFilter(capture, nullptr); return true; }