示例#1
0
void VideoDevice::configure(const Misc::ConfigurationFileSection& cfg)
	{
	/* Check which components of the video format are stored in the configuration file section: */
	unsigned int frameSize[2]={0,0};
	bool haveFrameSize=false;
	if(cfg.hasTag("./width")&&cfg.hasTag("./height"))
		{
		/* Read the requested frame size as width and height: */
		frameSize[0]=cfg.retrieveValue<unsigned int>("./width");
		frameSize[1]=cfg.retrieveValue<unsigned int>("./height");
		
		haveFrameSize=true;
		}
	if(cfg.hasTag("./frameSize"))
		{
		/* Read the requested frame size as a two-element array: */
		Misc::CFixedArrayValueCoder<unsigned int,2> valueCoder(frameSize);
		cfg.retrieveValueWC<unsigned int*>("./frameSize",valueCoder);
		
		haveFrameSize=true;
		}
	
	double frameRate=0.0;
	bool haveFrameRate=false;
	if(cfg.hasTag("./frameRate"))
		{
		/* Read the requested frame rate as a double: */
		frameRate=cfg.retrieveValue<double>("./frameRate");
		
		haveFrameRate=true;
		}
	
	unsigned int pixelFormat=0;
	bool havePixelFormat=false;
	if(cfg.hasTag("./pixelFormat"))
		{
		/* Read a pixel format as a FourCC code: */
		std::string fourCC=cfg.retrieveValue<std::string>("./pixelFormat");
		if(fourCC.size()!=4)
			Misc::throwStdErr("Video::VideoDevice::configure: Invalid pixel format code \"%s\"",fourCC.c_str());
		
		/* Convert the FourCC code to a pixel format: */
		VideoDataFormat temp;
		temp.setPixelFormat(fourCC.c_str());
		pixelFormat=temp.pixelFormat;
		
		havePixelFormat=true;
		}
	if(cfg.hasTag("./pixelFormatHex"))
		{
		/* Read a pixel format as a hexadecimal number: */
		std::string hex=cfg.retrieveString("./pixelFormatHex");
		if(hex.size()!=8)
			Misc::throwStdErr("Video::VideoDevice::configure: Invalid hexadecimal pixel format code \"%s\"",hex.c_str());
		for(int i=0;i<8;++i)
			{
			if(hex[i]>='0'&&hex[i]<='9')
				pixelFormat=(pixelFormat<<4)|(hex[i]-'0');
			else if(hex[i]>='A'&&hex[i]<='F')
				pixelFormat=(pixelFormat<<4)|(hex[i]-'A'+10);
			else if(hex[i]>='a'&&hex[i]<='f')
				pixelFormat=(pixelFormat<<4)|(hex[i]-'a'+10);
			else
				Misc::throwStdErr("Video::VideoDevice::configure: Invalid hexadecimal pixel format code \"%s\"",hex.c_str());
			}
		
		havePixelFormat=true;
		}
	
	/* Get the list of the device's supported video formats: */
	std::vector<VideoDataFormat> deviceFormats=getVideoFormatList();
	
	/* Find the best-matching video format among the device's advertised formats: */
	std::vector<VideoDataFormat>::iterator bestFormat=deviceFormats.end();
	double bestMatch=0.0;
	for(std::vector<VideoDataFormat>::iterator dfIt=deviceFormats.begin();dfIt!=deviceFormats.end();++dfIt)
		{
		double match=1.0;
		if(haveFrameSize)
			for(int i=0;i<2;++i)
				match*=dfIt->size[i]>=frameSize[i]?double(frameSize[i])/double(dfIt->size[i]):double(dfIt->size[i])/double(frameSize[i]);
		if(haveFrameRate)
			{
			double dfRate=double(dfIt->frameIntervalDenominator)/double(dfIt->frameIntervalCounter);
			match*=dfRate>=frameRate?frameRate/dfRate:dfRate/frameRate;
			}
		if(havePixelFormat&&dfIt->pixelFormat!=pixelFormat)
			match*=0.75;
		
		if(bestMatch<match)
			{
			bestFormat=dfIt;
			bestMatch=match;
			}
		}
	if(bestFormat==deviceFormats.end()) // Can only happen if there are no device formats
		throw std::runtime_error("Video::VideoDevice::configure: No matching video formats found");
	
	/* Set the selected video format: */
	setVideoFormat(*bestFormat);
	}
void VideoDevice::configure(const Misc::ConfigurationFileSection& cfg)
	{
	/* Get the device's current video format to use as default: */
	VideoDataFormat currentFormat=getVideoFormat();
	
	/* Get the list of the device's supported video formats: */
	std::vector<VideoDataFormat> deviceFormats=getVideoFormatList();
	
	/* Read the requested frame size: */
	currentFormat.size[0]=cfg.retrieveValue<unsigned int>("./width",currentFormat.size[0]);
	currentFormat.size[1]=cfg.retrieveValue<unsigned int>("./height",currentFormat.size[1]);
	
	/* Find the best-matching frame size among the supported video formats: */
	std::vector<VideoDataFormat>::iterator bestSizeMatch=deviceFormats.end();
	double bestSizeMatchRatio=1.0e10;
	for(std::vector<VideoDataFormat>::iterator dfIt=deviceFormats.begin();dfIt!=deviceFormats.end();++dfIt)
		{
		/* Calculate the format's size mismatch: */
		double sizeMatchRatio=0.0;
		for(int i=0;i<2;++i)
			{
			if(dfIt->size[i]<currentFormat.size[i])
				sizeMatchRatio+=double(currentFormat.size[i])/double(dfIt->size[i]);
			else
				sizeMatchRatio+=double(dfIt->size[i])/double(currentFormat.size[i]);
			}
		if(bestSizeMatchRatio>sizeMatchRatio)
			{
			bestSizeMatch=dfIt;
			bestSizeMatchRatio=sizeMatchRatio;
			}
		}
	currentFormat.size[0]=bestSizeMatch->size[0];
	currentFormat.size[1]=bestSizeMatch->size[1];
	
	/* Read the requested frame rate: */
	double frameRate=cfg.retrieveValue<double>("./frameRate",double(currentFormat.frameIntervalDenominator)/double(currentFormat.frameIntervalCounter));
	
	/* Find the best-matching frame rate among the supporting video formats: */
	std::vector<VideoDataFormat>::iterator bestRateMatch=deviceFormats.end();
	double bestRateMatchRatio=1.0e10;
	for(std::vector<VideoDataFormat>::iterator dfIt=deviceFormats.begin();dfIt!=deviceFormats.end();++dfIt)
		if(dfIt->size[0]==currentFormat.size[0]&&dfIt->size[1]==currentFormat.size[1])
			{
			/* Calculate the format's frame rate mismatch: */
			double rate=double(dfIt->frameIntervalDenominator)/double(dfIt->frameIntervalCounter);
			double rateMatchRatio;
			if(rate<frameRate)
				rateMatchRatio=frameRate/rate;
			else
				rateMatchRatio=rate/frameRate;
			if(bestRateMatchRatio>rateMatchRatio)
				{
				bestRateMatch=dfIt;
				bestRateMatchRatio=rateMatchRatio;
				}
			}
	currentFormat.pixelFormat=bestRateMatch->pixelFormat;
	currentFormat.frameIntervalCounter=bestRateMatch->frameIntervalCounter;
	currentFormat.frameIntervalDenominator=bestRateMatch->frameIntervalDenominator;
	
	/* Set the selected video format: */
	setVideoFormat(currentFormat);
	}