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); }