static inline bool MapPacketIDs(IBaseFilter *demuxer, ULONG video, ULONG audio) { CComPtr<IPin> videoPin, audioPin; HRESULT hr; if (!GetPinByName(demuxer, PINDIR_OUTPUT, DEMUX_VIDEO_PIN, &videoPin)) { Warning(L"Encoded Device: Could not get video pin from " L"demuxer"); return false; } if (!GetPinByName(demuxer, PINDIR_OUTPUT, DEMUX_AUDIO_PIN, &audioPin)) { Warning(L"Encoded Device: Could not get audio pin from " L"demuxer"); return false; } hr = MapPinToPacketID(videoPin, video); if (FAILED(hr)) { WarningHR(L"Encoded Device: Failed to map demuxer video pin " L"packet ID", hr); return false; } hr = MapPinToPacketID(audioPin, audio); if (FAILED(hr)) { WarningHR(L"Encoded Device: Failed to map demuxer audio pin " L"packet ID", hr); return false; } return true; }
bool HVideoEncoder::ConnectFilters() { ComPtr<IPin> deviceIn; ComPtr<IPin> deviceOut; ComPtr<IPin> encoderIn; ComPtr<IPin> encoderOut; bool success; HRESULT hr; success = GetPinByName(device, PINDIR_INPUT, L"YUV In", &deviceIn); if (!success) { Warning(L"Failed to get YUV In pin"); return false; } success = GetPinByName(device, PINDIR_OUTPUT, L"Virtual Video Out", &deviceOut); if (!success) { Warning(L"Failed to get Virtual Video Out pin"); return false; } success = GetPinByName(encoder, PINDIR_INPUT, L"Virtual Video In", &encoderIn); if (!success) { Warning(L"Failed to get encoder input pin"); return false; } success = GetPinByName(encoder, PINDIR_OUTPUT, nullptr, &encoderOut); if (!success) { Warning(L"Failed to get encoder output pin"); return false; } hr = graph->ConnectDirect(output->GetPin(), deviceIn, nullptr); if (FAILED(hr)) { WarningHR(L"Failed to connect output to device", hr); return false; } hr = graph->ConnectDirect(deviceOut, encoderIn, nullptr); if (FAILED(hr)) { WarningHR(L"Failed to connect device to encoder", hr); return false; } hr = graph->ConnectDirect(encoderOut, capture->GetPin(), nullptr); if (FAILED(hr)) { WarningHR(L"Failed to connect encoder to capture", hr); return false; } return true; }
bool HDevice::SetupExceptionVideoCapture(IBaseFilter *filter, VideoConfig &config) { ComPtr<IPin> pin; if (GetPinByName(filter, PINDIR_OUTPUT, L"656", &pin)) return SetupEncodedVideoCapture(filter, config, HD_PVR2); else if (GetPinByName(filter, PINDIR_OUTPUT, L"TS Out", &pin)) return SetupEncodedVideoCapture(filter, config, Roxio); return false; }
static void EnumExceptionVideoDevice(std::vector<VideoDevice> &devices, IBaseFilter *filter, const wchar_t *deviceName, const wchar_t *devicePath) { ComPtr<IPin> pin; if (GetPinByName(filter, PINDIR_OUTPUT, L"656", &pin)) EnumEncodedVideo(devices, deviceName, devicePath, HD_PVR2); else if (GetPinByName(filter, PINDIR_OUTPUT, L"TS Out", &pin)) EnumEncodedVideo(devices, deviceName, devicePath, Roxio); }
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 HDevice::ConnectPins(const GUID &category, const GUID &type, IBaseFilter *filter, IBaseFilter *capture) { HRESULT hr; ComPtr<IBaseFilter> crossbar; ComPtr<IPin> filterPin; ComPtr<IPin> capturePin; bool connectCrossbar = !encodedDevice && type == MEDIATYPE_Video; if (!EnsureInitialized(L"HDevice::ConnectPins") || !EnsureInactive(L"HDevice::ConnectPins")) return false; if (connectCrossbar && FindCrossbar(filter, &crossbar)) { if (!DirectConnectFilters(graph, crossbar, filter)) { Warning(L"HDevice::ConnectPins: Failed to connect " L"crossbar"); return false; } } if (!GetFilterPin(filter, type, category, PINDIR_OUTPUT, &filterPin)) { Error(L"HDevice::ConnectPins: Failed to find pin"); return false; } if (!GetPinByName(capture, PINDIR_INPUT, nullptr, &capturePin)) { Error(L"HDevice::ConnectPins: Failed to find capture pin"); return false; } hr = graph->ConnectDirect(filterPin, capturePin, nullptr); if (FAILED(hr)) { WarningHR(L"HDevice::ConnectPins: failed to connect pins", hr); return false; } 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; }