Skip to content
Snippets Groups Projects
Commit e4fa8338 authored by Andreas Traczyk's avatar Andreas Traczyk Committed by Kateryna Kostiuk
Browse files

winvideo: only add relevant framerates to ratelist

- Ignores video formats with duplicate or zero bitrates.

- Adds only the average framerate to the list instead of the min
  and max.

Change-Id: I18b878a3235fe786281b10627232e046fc8f77d6
parent 1cf88276
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright (C) 2015-2019 Savoir-faire Linux Inc. * Copyright (C) 2015-2019 Savoir-faire Linux Inc.
* *
* Author: Edric Milaret <edric.ladent-milaret@savoirfairelinux.com> * Author: Edric Milaret <edric.ladent-milaret@savoirfairelinux.com>
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -45,7 +46,6 @@ class VideoDeviceImpl { ...@@ -45,7 +46,6 @@ class VideoDeviceImpl {
VideoDeviceImpl(const std::string& path); VideoDeviceImpl(const std::string& path);
std::string device; std::string device;
std::string name; std::string name;
unsigned int id;
std::vector<std::string> getChannelList() const; std::vector<std::string> getChannelList() const;
std::vector<VideoSize> getSizeList(const std::string& channel) const; std::vector<VideoSize> getSizeList(const std::string& channel) const;
...@@ -67,8 +67,8 @@ class VideoDeviceImpl { ...@@ -67,8 +67,8 @@ class VideoDeviceImpl {
void fail(const std::string& error); void fail(const std::string& error);
}; };
VideoDeviceImpl::VideoDeviceImpl(const std::string& id) VideoDeviceImpl::VideoDeviceImpl(const std::string& path)
: id(atoi(id.c_str())) : name(path)
, cInterface(new CaptureGraphInterfaces()) , cInterface(new CaptureGraphInterfaces())
{ {
setup(); setup();
...@@ -122,37 +122,22 @@ VideoDeviceImpl::setup() ...@@ -122,37 +122,22 @@ VideoDeviceImpl::setup()
IMoniker *pMoniker = nullptr; IMoniker *pMoniker = nullptr;
ULONG cFetched; ULONG cFetched;
unsigned int deviceCounter = 0; while ((pEnumCatGuard->Next(1, &pMoniker, &cFetched) == S_OK)) {
while ((pEnumCatGuard->Next(1, &pMoniker, &cFetched) == S_OK))
{
if (deviceCounter == this->id) {
IPropertyBag *pPropBag; IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage( hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
0, if (FAILED(hr)) {
0, continue;
IID_IPropertyBag, }
(void **)&pPropBag); VARIANT var;
if (SUCCEEDED(hr)) { VariantInit(&var);
VARIANT varName; hr = pPropBag->Read(L"FriendlyName", &var, 0);
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
int l = WideCharToMultiByte( // We want to get the capabilities of a device with the friendly name
CP_UTF8, // that corresponds to what was enumerated by the video device monitor,
0, // and passed in the ctor as the name of this device.
varName.bstrVal, if (this->name != bstrToStdString(var.bstrVal)) {
-1, continue;
0, 0, 0, 0); }
auto tmp = new char[l];
WideCharToMultiByte(
CP_UTF8,
0,
varName.bstrVal,
-1,
tmp,
l,
0, 0);
this->name = std::string(tmp);
this->device = std::string("video=") + this->name; this->device = std::string("video=") + this->name;
hr = pMoniker->BindToObject( hr = pMoniker->BindToObject(
nullptr, nullptr, nullptr, nullptr,
...@@ -161,7 +146,7 @@ VideoDeviceImpl::setup() ...@@ -161,7 +146,7 @@ VideoDeviceImpl::setup()
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
hr = cInterface->graph_->AddFilter( hr = cInterface->graph_->AddFilter(
cInterface->videoInputFilter_, cInterface->videoInputFilter_,
varName.bstrVal); var.bstrVal);
else { else {
fail("Could not add filter to video device."); fail("Could not add filter to video device.");
} }
...@@ -182,33 +167,59 @@ VideoDeviceImpl::setup() ...@@ -182,33 +167,59 @@ VideoDeviceImpl::setup()
fail("Couldn't config the stream!"); fail("Couldn't config the stream!");
} }
} }
break; // Device found // Device found.
break;
} }
VariantClear(&varName); VariantClear(&var);
pPropBag->Release(); pPropBag->Release();
pPropBag = nullptr; pPropBag = nullptr;
pMoniker->Release(); pMoniker->Release();
pMoniker = nullptr; pMoniker = nullptr;
} }
}
deviceCounter++;
}
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
int piCount; int piCount;
int piSize; int piSize;
cInterface->streamConf_->GetNumberOfCapabilities(&piCount, &piSize); cInterface->streamConf_->GetNumberOfCapabilities(&piCount, &piSize);
AM_MEDIA_TYPE *pmt; AM_MEDIA_TYPE *pmt;
VIDEO_STREAM_CONFIG_CAPS pSCC; VIDEO_STREAM_CONFIG_CAPS pSCC;
std::map<std::pair<ring::video::VideoSize, ring::video::FrameRate>, LONG> bitrateList;
for (int i = 0; i < piCount; i++) { for (int i = 0; i < piCount; i++) {
cInterface->streamConf_->GetStreamCaps(i, &pmt, (BYTE*)&pSCC); cInterface->streamConf_->GetStreamCaps(i, &pmt, (BYTE*)&pSCC);
if (pmt->formattype == FORMAT_VideoInfo) { if (pmt->formattype != FORMAT_VideoInfo) {
continue;
}
auto videoInfo = (VIDEOINFOHEADER*) pmt->pbFormat; auto videoInfo = (VIDEOINFOHEADER*) pmt->pbFormat;
sizeList_.emplace_back(videoInfo->bmiHeader.biWidth, videoInfo->bmiHeader.biHeight); auto size = ring::video::VideoSize(videoInfo->bmiHeader.biWidth, videoInfo->bmiHeader.biHeight);
rateList_[sizeList_.back()].emplace_back(1e7, pSCC.MinFrameInterval); auto rate = ring::video::FrameRate(1e7, videoInfo->AvgTimePerFrame);
rateList_[sizeList_.back()].emplace_back(1e7, pSCC.MaxFrameInterval); auto bitrate = videoInfo->dwBitRate;
capMap_[sizeList_.back()] = pmt; // Only add configurations with positive bitrates.
if (bitrate == 0)
continue;
// Avoid adding multiple rates with different bitrates.
auto ratesIt = rateList_.find(size);
if (ratesIt != rateList_.end() &&
std::find(ratesIt->second.begin(), ratesIt->second.end(), rate) != ratesIt->second.end()) {
// Update bitrate and cap map if the bitrate is greater.
auto key = std::make_pair(size, rate);
if (bitrate > bitrateList[key]) {
bitrateList[key] = bitrate;
capMap_[size] = pmt;
}
continue;
}
// Add new size, rate, bitrate, and cap map.
sizeList_.emplace_back(size);
rateList_[size].emplace_back(rate);
bitrateList[std::make_pair(size, rate)] = bitrate;
capMap_[size] = pmt;
} }
} }
// Sort rates descending.
for (auto& rateList : rateList_) {
std::sort(rateList.second.begin(), rateList.second.end(),
[](const ring::video::FrameRate& lhs, const ring::video::FrameRate& rhs) {
return lhs.denominator() < rhs.denominator();
});
} }
} }
pSysDevEnum->Release(); pSysDevEnum->Release();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment