コード例 #1
0
ファイル: device.cpp プロジェクト: Inner-room/libdshowcapture
Result HDevice::Start()
{
	HRESULT hr;

	if (!EnsureInitialized(L"Start") ||
	    !EnsureInactive(L"Start"))
		return Result::Error;

	if (!!rocketEncoder)
		Sleep(ROCKET_WAIT_TIME_MS);

	hr = control->Run();

	if (FAILED(hr)) {
		if (hr == (HRESULT)0x8007001F) {
			WarningHR(L"Run failed, device already in use", hr);
			return Result::InUse;
		} else {
			WarningHR(L"Run failed", hr);
			return Result::Error;
		}
	}

	active = true;
	return Result::Success;
}
コード例 #2
0
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;
}
コード例 #3
0
bool EnumDevices(const GUID &type, EnumDeviceCallback callback, void *param)
{
	CComPtr<ICreateDevEnum> deviceEnum;
	CComPtr<IEnumMoniker>   enumMoniker;
	CComPtr<IMoniker>       deviceInfo;
	HRESULT                 hr;
	DWORD                   count = 0;

	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
		CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&deviceEnum);
	if (FAILED(hr)) {
		WarningHR(L"EnumAudioDevices: Could not create "
		          L"ICreateDeviceEnum", hr);
		return false;
	}

	hr = deviceEnum->CreateClassEnumerator(type, &enumMoniker, 0);
	if (FAILED(hr)) {
		WarningHR(L"EnumAudioDevices: CreateClassEnumerator failed",
				hr);
		return false;
	}

	if (hr == S_FALSE)
		return true;

	while (enumMoniker->Next(1, &deviceInfo, &count) == S_OK) {
		if (!EnumDevice(deviceInfo, callback, param))
			return true;

		deviceInfo.Release();
	}

	return true;
}
コード例 #4
0
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;
}
コード例 #5
0
bool SetAvermediaEncoderConfig(IBaseFilter *encoder, VideoEncoderConfig &config)
{
	HRESULT hr;

	ComQIPtr<IKsPropertySet> propertySet(encoder);
	if (!propertySet) {
		Warning(L"Could not get IKsPropertySet for encoder");
		return false;
	}

	double fps = double(config.fpsNumerator) /
		double(config.fpsDenominator);

	hr = SetAVMEncoderSetting(propertySet,
			AVER_PARAMETER_ENCODE_FRAME_RATE,
			ULONG(fps), 0);
	if (FAILED(hr)) {
		WarningHR(L"Failed to set Avermedia encoder FPS", hr);
		return false;
	}

	hr = SetAVMEncoderSetting(propertySet,
			AVER_PARAMETER_ENCODE_BIT_RATE,
			ULONG(config.bitrate), 0);
	if (FAILED(hr)) {
		WarningHR(L"Failed to set Avermedia encoder bitrate", hr);
		return false;
	}

	hr = SetAVMEncoderSetting(propertySet,
			AVER_PARAMETER_CURRENT_RESOLUTION,
			ULONG(config.cx), ULONG(config.cy));
	if (FAILED(hr)) {
		WarningHR(L"Failed to set Avermedia encoder current res", hr);
		return false;
	}

	hr = SetAVMEncoderSetting(propertySet,
			AVER_PARAMETER_ENCODE_RESOLUTION,
			ULONG(config.cx), ULONG(config.cy));
	if (FAILED(hr)) {
		WarningHR(L"Failed to set Avermedia encoder res", hr);
		return false;
	}

	hr = SetAVMEncoderSetting(propertySet,
			AVER_PARAMETER_ENCODE_GOP,
			ULONG(config.keyframeInterval), 0);
	if (FAILED(hr)) {
		WarningHR(L"Failed to set Avermedia encoder GOP", hr);
		return false;
	}

	return true;
}
コード例 #6
0
void Device::OpenDialog(void *hwnd, DialogType type) const
{
	ComPtr<IUnknown>  ptr;
	HRESULT           hr;

	if (type == DialogType::ConfigVideo) {
		ptr = context->videoFilter;
	} else if (type == DialogType::ConfigCrossbar ||
	           type == DialogType::ConfigCrossbar2) {
		hr = context->builder->FindInterface(NULL, NULL,
				context->videoFilter, IID_IAMCrossbar,
				(void**)&ptr);
		if (FAILED(hr)) {
			WarningHR(L"Failed to find crossbar", hr);
			return;
		}

		if (ptr != NULL && type == DialogType::ConfigCrossbar2) {
			ComQIPtr<IAMCrossbar> xbar(ptr);
			ComQIPtr<IBaseFilter> filter(xbar);

			hr = context->builder->FindInterface(
					&LOOK_UPSTREAM_ONLY,
					NULL, filter, IID_IAMCrossbar,
					(void**)&ptr);
			if (FAILED(hr)) {
				WarningHR(L"Failed to find crossbar2", hr);
				return;
			}
		}
	} else if (type == DialogType::ConfigAudio) {
		ptr = context->audioFilter;
	}

	if (!ptr) {
		Warning(L"Could not find filter to open dialog type: %d with",
				(int)type);
		return;
	}

	OpenPropertyPages((HWND)hwnd, ptr);
}
コード例 #7
0
bool HVideoEncoder::SetConfig(VideoEncoderConfig &config)
{
	ComPtr<IBaseFilter> filter;
	ComPtr<IBaseFilter> crossbar;

	if (config.name.empty() && config.path.empty()) {
		Warning(L"No video encoder name or path specified");
		return false;
	}

	bool success = GetDeviceFilter(KSCATEGORY_ENCODER,
			config.name.c_str(), config.path.c_str(), &filter);
	if (!success) {
		Warning(L"Video encoder '%s': %s not found", config.name.c_str(),
				config.path.c_str());
		return false;
	}

	if (!filter) {
		Warning(L"Could not get encoder filter");
		return false;
	}

	this->config = config;

	if (!SetupEncoder(filter)) {
		Warning(L"Failed to set up encoder");
		return false;
	}
	if (!SetupCrossbar()) {
		Warning(L"Failed to set up crossbar");
		return false;
	}
	if (!SetAvermediaEncoderConfig(device, config)) {
		Warning(L"Failed to set Avermedia encoder settings");
		return false;
	}
	if (!ConnectFilters()) {
		Warning(L"Failed to connect encoder filters");
		return false;
	}

	LogFilters(graph);

	HRESULT hr = control->Run();
	if (FAILED(hr)) {
		WarningHR(L"Run failed", hr);
		return false;
	}

	active = true;
	return true;
}
コード例 #8
0
ファイル: device.cpp プロジェクト: Inner-room/libdshowcapture
bool HDevice::RenderFilters(const GUID &category, const GUID &type,
		IBaseFilter *filter, IBaseFilter *capture)
{
	HRESULT hr;

	if (!EnsureInitialized(L"HDevice::RenderFilters") ||
	    !EnsureInactive(L"HDevice::RenderFilters"))
		return false;

	hr = builder->RenderStream(&category, &type, filter, NULL, capture);
	if (FAILED(hr)) {
		WarningHR(L"HDevice::ConnectFilters: RenderStream failed", hr);
		return false;
	}

	return true;
}
コード例 #9
0
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;
}
コード例 #10
0
bool CreateDemuxVideoPin(IBaseFilter *demuxFilter, MediaType &mt,
		long width, long height, long long frameTime,
		VideoFormat format)
{
	CComQIPtr<IMpeg2Demultiplexer> demuxer(demuxFilter);
	if (!demuxer) {
		Warning(L"CreateDemuxVideoPin: Failed to get "
		        L"IMpeg2Demultiplexer from filter");
		return false;
	}

	CComPtr<IPin> pin;
	HRESULT       hr;

	VIDEOINFOHEADER *vih           = mt.AllocFormat<VIDEOINFOHEADER>();
	vih->bmiHeader.biSize          = sizeof(vih->bmiHeader);
	vih->bmiHeader.biWidth         = width;
	vih->bmiHeader.biHeight        = height;
	vih->bmiHeader.biCompression   = VideoFormatToFourCC(format);
	vih->rcSource.right            = height;
	vih->rcSource.bottom           = width;
	vih->AvgTimePerFrame           = frameTime;

	if (!vih->bmiHeader.biCompression) {
		Warning(L"CreateDemuxVideoPin: Invalid video format");
		return false;
	}

	mt->majortype            = MEDIATYPE_Video;
	mt->subtype              = VideoFormatToSubType(format);
	mt->formattype           = FORMAT_VideoInfo;
	mt->bTemporalCompression = true;

	hr = demuxer->CreateOutputPin(mt, DEMUX_VIDEO_PIN, &pin);
	if (FAILED(hr)) {
		WarningHR(L"CreateDemuxVideoPin: Failed to create video pin "
		          L"on demuxer", hr);
		return false;
	}

	return true;
}
コード例 #11
0
ファイル: device.cpp プロジェクト: Inner-room/libdshowcapture
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;
}
コード例 #12
0
bool CreateDemuxAudioPin(IBaseFilter *demuxFilter, MediaType &mt,
		DWORD samplesPerSec, WORD bitsPerSample, WORD channels,
		AudioFormat format)
{
	CComQIPtr<IMpeg2Demultiplexer> demuxer(demuxFilter);
	if (!demuxer) {
		Warning(L"CreateDemuxAudioPin: Failed to get "
		        L"IMpeg2Demultiplexer from filter");
		return false;
	}

	CComPtr<IPin> pin;
	HRESULT       hr;

	WAVEFORMATEX *wfex   = mt.AllocFormat<WAVEFORMATEX>();
	wfex->wFormatTag     = AudioFormatToFormatTag(format);
	wfex->nChannels      = channels;
	wfex->nSamplesPerSec = samplesPerSec;
	wfex->wBitsPerSample = bitsPerSample;

	if (!wfex->wFormatTag) {
		Warning(L"CreateDemuxAudioPin: Invalid audio format");
		return false;
	}

	mt->majortype            = MEDIATYPE_Audio;
	mt->subtype              = AudioFormatToSubType(format);
	mt->formattype           = FORMAT_WaveFormatEx;
	mt->bTemporalCompression = true;

	hr = demuxer->CreateOutputPin(mt, DEMUX_AUDIO_PIN, &pin);
	if (FAILED(hr)) {
		WarningHR(L"CreateDemuxAudioPin: Failed to create audio pin "
		          L"on demuxer", hr);
		return false;
	}

	return true;
}
コード例 #13
0
ファイル: device.cpp プロジェクト: Inner-room/libdshowcapture
void HDevice::SetAudioBuffering(int bufferingMs)
{
	ComPtr<IPin> pin;
	bool success = GetFilterPin(audioFilter, MEDIATYPE_Audio,
			PIN_CATEGORY_CAPTURE, PINDIR_OUTPUT, &pin);
	if (!success)
		return;

	ComQIPtr<IAMStreamConfig> config(pin);
	if (!config)
		return;

	ComQIPtr<IAMBufferNegotiation> neg(pin);
	if (!neg)
		return;

	MediaTypePtr mt;
	if (FAILED(config->GetFormat(&mt)))
		return;

	if (mt->formattype != FORMAT_WaveFormatEx)
		return;
	if (mt->cbFormat != sizeof(WAVEFORMATEX))
		return;

	WAVEFORMATEX *wfex = (WAVEFORMATEX*)mt->pbFormat;

	ALLOCATOR_PROPERTIES props;
	props.cBuffers = -1;
	props.cbBuffer = wfex->nAvgBytesPerSec * bufferingMs / 1000;
	props.cbAlign = -1;
	props.cbPrefix = -1;
	HRESULT hr = neg->SuggestAllocatorProperties(&props);
	if (FAILED(hr))
		WarningHR(L"Could not set allocator properties on audio "
		          L"capture pin", hr);
}
コード例 #14
0
ファイル: device.cpp プロジェクト: Inner-room/libdshowcapture
bool HDevice::SetupExceptionAudioCapture(IPin *pin)
{
	ComPtr<IEnumMediaTypes>  enumMediaTypes;
	ULONG                    count = 0;
	HRESULT                  hr;
	MediaTypePtr             mt;

	hr = pin->EnumMediaTypes(&enumMediaTypes);
	if (FAILED(hr)) {
		WarningHR(L"SetupExceptionAudioCapture: pin->EnumMediaTypes "
		          L"failed", hr);
		return false;
	}

	enumMediaTypes->Reset();

	if (enumMediaTypes->Next(1, &mt, &count) == S_OK &&
	    mt->formattype == FORMAT_WaveFormatEx) {
		audioMediaType = mt;
		return true;
	}

	return false;
}