Commit e4fa8338 authored by Andreas Traczyk's avatar Andreas Traczyk Committed by Kateryna Kostiuk

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
...@@ -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,76 +122,59 @@ VideoDeviceImpl::setup() ...@@ -122,76 +122,59 @@ 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)) IPropertyBag *pPropBag;
{ hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
if (deviceCounter == this->id) { if (FAILED(hr)) {
IPropertyBag *pPropBag; continue;
hr = pMoniker->BindToStorage( }
0, VARIANT var;
0, VariantInit(&var);
IID_IPropertyBag, hr = pPropBag->Read(L"FriendlyName", &var, 0);
(void **)&pPropBag); if (SUCCEEDED(hr)) {
if (SUCCEEDED(hr)) { // We want to get the capabilities of a device with the friendly name
VARIANT varName; // that corresponds to what was enumerated by the video device monitor,
VariantInit(&varName); // and passed in the ctor as the name of this device.
hr = pPropBag->Read(L"FriendlyName", &varName, 0); if (this->name != bstrToStdString(var.bstrVal)) {
if (SUCCEEDED(hr)) { continue;
int l = WideCharToMultiByte( }
CP_UTF8, this->device = std::string("video=") + this->name;
0, hr = pMoniker->BindToObject(
varName.bstrVal, nullptr, nullptr,
-1, IID_IBaseFilter,
0, 0, 0, 0); (void**)&cInterface->videoInputFilter_);
auto tmp = new char[l]; if (SUCCEEDED(hr))
WideCharToMultiByte( hr = cInterface->graph_->AddFilter(
CP_UTF8, cInterface->videoInputFilter_,
0, var.bstrVal);
varName.bstrVal, else {
-1, fail("Could not add filter to video device.");
tmp, }
l, hr = cInterface->captureGraph_->FindInterface(
0, 0); &PIN_CATEGORY_PREVIEW,
this->name = std::string(tmp); &MEDIATYPE_Video,
this->device = std::string("video=") + this->name; cInterface->videoInputFilter_,
hr = pMoniker->BindToObject( IID_IAMStreamConfig,
nullptr, nullptr, (void **)&cInterface->streamConf_);
IID_IBaseFilter, if (FAILED(hr)) {
(void**)&cInterface->videoInputFilter_); hr = cInterface->captureGraph_->FindInterface(
if (SUCCEEDED(hr)) &PIN_CATEGORY_CAPTURE,
hr = cInterface->graph_->AddFilter( &MEDIATYPE_Video,
cInterface->videoInputFilter_, cInterface->videoInputFilter_,
varName.bstrVal); IID_IAMStreamConfig,
else { (void **)&cInterface->streamConf_);
fail("Could not add filter to video device."); if (FAILED(hr)) {
} fail("Couldn't config the stream!");
hr = cInterface->captureGraph_->FindInterface(
&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video,
cInterface->videoInputFilter_,
IID_IAMStreamConfig,
(void **)&cInterface->streamConf_);
if(FAILED(hr)) {
hr = cInterface->captureGraph_->FindInterface(
&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video,
cInterface->videoInputFilter_,
IID_IAMStreamConfig,
(void **)&cInterface->streamConf_);
if (FAILED(hr)) {
fail("Couldn't config the stream!");
}
}
break; // Device found
} }
VariantClear(&varName);
pPropBag->Release();
pPropBag = nullptr;
pMoniker->Release();
pMoniker = nullptr;
} }
// Device found.
break;
} }
deviceCounter++; VariantClear(&var);
pPropBag->Release();
pPropBag = nullptr;
pMoniker->Release();
pMoniker = nullptr;
} }
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
int piCount; int piCount;
...@@ -199,17 +182,45 @@ VideoDeviceImpl::setup() ...@@ -199,17 +182,45 @@ VideoDeviceImpl::setup()
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) {
auto videoInfo = (VIDEOINFOHEADER*) pmt->pbFormat; continue;
sizeList_.emplace_back(videoInfo->bmiHeader.biWidth, videoInfo->bmiHeader.biHeight);
rateList_[sizeList_.back()].emplace_back(1e7, pSCC.MinFrameInterval);
rateList_[sizeList_.back()].emplace_back(1e7, pSCC.MaxFrameInterval);
capMap_[sizeList_.back()] = pmt;
} }
auto videoInfo = (VIDEOINFOHEADER*) pmt->pbFormat;
auto size = ring::video::VideoSize(videoInfo->bmiHeader.biWidth, videoInfo->bmiHeader.biHeight);
auto rate = ring::video::FrameRate(1e7, videoInfo->AvgTimePerFrame);
auto bitrate = videoInfo->dwBitRate;
// 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();
pSysDevEnum = NULL; pSysDevEnum = NULL;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment