void AVForm::updateVideoModes(int curIndex) { if (curIndex<0 || curIndex>=videoDeviceList.size()) { qWarning() << "Invalid index"; return; } QString devName = videoDeviceList[curIndex].first; QVector<VideoMode> allVideoModes = CameraDevice::getVideoModes(devName); std::sort(allVideoModes.begin(), allVideoModes.end(), [](const VideoMode& a, const VideoMode& b) {return a.width!=b.width ? a.width>b.width : a.height!=b.height ? a.height>b.height : a.FPS>b.FPS;}); bool previouslyBlocked = bodyUI->videoModescomboBox->blockSignals(true); bodyUI->videoModescomboBox->clear(); // Identify the best resolutions available for the supposed XXXXp resolutions. std::map<int, VideoMode> idealModes; idealModes[120] = {160,120,0,0}; idealModes[240] = {460,240,0,0}; idealModes[360] = {640,360,0,0}; idealModes[480] = {854,480,0,0}; idealModes[720] = {1280,720,0,0}; idealModes[1080] = {1920,1080,0,0}; std::map<int, int> bestModeInds; qDebug("available Modes:"); for (int i=0; i<allVideoModes.size(); ++i) { VideoMode mode = allVideoModes[i]; qDebug("width: %d, height: %d, FPS: %f, pixel format: %s", mode.width, mode.height, mode.FPS, CameraDevice::getPixelFormatString(mode.pixel_format).toStdString().c_str()); // PS3-Cam protection, everything above 60fps makes no sense if(mode.FPS > 60) continue; for(auto iter = idealModes.begin(); iter != idealModes.end(); ++iter) { int res = iter->first; VideoMode idealMode = iter->second; // don't take approximately correct resolutions unless they really // are close if (mode.norm(idealMode) > 300) continue; if (bestModeInds.find(res) == bestModeInds.end()) { bestModeInds[res] = i; continue; } int ind = bestModeInds[res]; if (mode.norm(idealMode) < allVideoModes[ind].norm(idealMode)) { bestModeInds[res] = i; } else if (mode.norm(idealMode) == allVideoModes[ind].norm(idealMode)) { // prefer higher FPS and "better" pixel formats if (mode.FPS > allVideoModes[ind].FPS) { bestModeInds[res] = i; } else if (mode.FPS == allVideoModes[ind].FPS && CameraDevice::betterPixelFormat(mode.pixel_format, allVideoModes[ind].pixel_format)) { bestModeInds[res] = i; } } } } qDebug("selected Modes:"); int prefResIndex = -1; QSize prefRes = Settings::getInstance().getCamVideoRes(); unsigned short prefFPS = Settings::getInstance().getCamVideoFPS(); // Iterate backwards to show higest resolution first. videoModes.clear(); for(auto iter = bestModeInds.rbegin(); iter != bestModeInds.rend(); ++iter) { int i = iter->second; VideoMode mode = allVideoModes[i]; if (videoModes.contains(mode)) continue; videoModes.append(mode); if (mode.width==prefRes.width() && mode.height==prefRes.height() && mode.FPS == prefFPS && prefResIndex==-1) prefResIndex = videoModes.size() - 1; QString str; qDebug("width: %d, height: %d, FPS: %f, pixel format: %s\n", mode.width, mode.height, mode.FPS, CameraDevice::getPixelFormatString(mode.pixel_format).toStdString().c_str()); if (mode.height && mode.width) str += tr("%1p").arg(iter->first); else str += tr("Default resolution"); bodyUI->videoModescomboBox->addItem(str); } if (videoModes.isEmpty()) bodyUI->videoModescomboBox->addItem(tr("Default resolution")); bodyUI->videoModescomboBox->blockSignals(previouslyBlocked); if (prefResIndex != -1) { bodyUI->videoModescomboBox->setCurrentIndex(prefResIndex); } else { // If the user hasn't set a preffered resolution yet, // we'll pick the resolution in the middle of the list, // and the best FPS for that resolution. // If we picked the lowest resolution, the quality would be awful // but if we picked the largest, FPS would be bad and thus quality bad too. int numRes=0; QSize lastSize; for (int i=0; i<videoModes.size(); i++) { if (lastSize != QSize{videoModes[i].width, videoModes[i].height}) { numRes++; lastSize = {videoModes[i].width, videoModes[i].height}; } } int target = numRes/2; numRes=0; for (int i=0; i<videoModes.size(); i++) { if (lastSize != QSize{videoModes[i].width, videoModes[i].height}) { numRes++; lastSize = {videoModes[i].width, videoModes[i].height}; } if (numRes==target) { bodyUI->videoModescomboBox->setCurrentIndex(i); break; } } if (videoModes.size()) { bodyUI->videoModescomboBox->setUpdatesEnabled(false); bodyUI->videoModescomboBox->setCurrentIndex(-1); bodyUI->videoModescomboBox->setUpdatesEnabled(true); bodyUI->videoModescomboBox->setCurrentIndex(0); } else { // We don't have any video modes, open it with the default mode camera.open(devName); } } }
void AVForm::selectBestModes(QVector<VideoMode> &allVideoModes) { // Identify the best resolutions available for the supposed XXXXp resolutions. std::map<int, VideoMode> idealModes; idealModes[120] = VideoMode(160, 120); idealModes[240] = VideoMode(430, 240); idealModes[360] = VideoMode(640, 360); idealModes[480] = VideoMode(854, 480); idealModes[720] = VideoMode(1280, 720); idealModes[1080] = VideoMode(1920, 1080); std::map<int, int> bestModeInds; for (int i = 0; i < allVideoModes.size(); ++i) { VideoMode mode = allVideoModes[i]; // PS3-Cam protection, everything above 60fps makes no sense if (mode.FPS > 60) continue; for (auto iter = idealModes.begin(); iter != idealModes.end(); ++iter) { int res = iter->first; VideoMode idealMode = iter->second; // don't take approximately correct resolutions unless they really // are close if (mode.norm(idealMode) > 300) continue; if (bestModeInds.find(res) == bestModeInds.end()) { bestModeInds[res] = i; continue; } int index = bestModeInds[res]; VideoMode best = allVideoModes[index]; if (mode.norm(idealMode) < best.norm(idealMode)) { bestModeInds[res] = i; continue; } if (mode.norm(idealMode) == best.norm(idealMode)) { // prefer higher FPS and "better" pixel formats if (mode.FPS > best.FPS) { bestModeInds[res] = i; continue; } bool better = CameraDevice::betterPixelFormat(mode.pixel_format, best.pixel_format); if (mode.FPS >= best.FPS && better) bestModeInds[res] = i; } } } QVector<VideoMode> newVideoModes; for (auto it = bestModeInds.rbegin(); it != bestModeInds.rend(); ++it) { VideoMode mode = allVideoModes[it->second]; if (newVideoModes.empty()) { newVideoModes.push_back(mode); } else { int size = getModeSize(mode); auto result = std::find_if(newVideoModes.cbegin(), newVideoModes.cend(), [size](VideoMode mode) { return getModeSize(mode) == size; }); if (result == newVideoModes.end()) newVideoModes.push_back(mode); } } allVideoModes = newVideoModes; }