mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
MF Discovery extended
This commit is contained in:
parent
8d8ee8b3cd
commit
5f0ad931ba
@ -31,13 +31,12 @@ body{
|
|||||||
}
|
}
|
||||||
.navbar-brand{
|
.navbar-brand{
|
||||||
position:fixed;
|
position:fixed;
|
||||||
padding: 0px;
|
|
||||||
height: 80px;
|
height: 80px;
|
||||||
}
|
}
|
||||||
#main-nav{
|
#main-nav{
|
||||||
position:absolute !important;
|
position:absolute !important;
|
||||||
}
|
}
|
||||||
.navbar-top-links li a {
|
.navbar-top-links li a > .fa{
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +92,7 @@ table.input-group{width:100%}
|
|||||||
@media (max-width: 767px) {.ltd{white-space:normal;}}
|
@media (max-width: 767px) {.ltd{white-space:normal;}}
|
||||||
|
|
||||||
/*icon spacing*/
|
/*icon spacing*/
|
||||||
.fa-fw,.mdi-24px{margin-right:5px;}
|
.fa-fw, .mdi-24px{margin-right:5px;}
|
||||||
|
|
||||||
/*table*/
|
/*table*/
|
||||||
table.borderless td,table.borderless th{border: none !important;}
|
table.borderless td,table.borderless th{border: none !important;}
|
||||||
@ -104,7 +103,7 @@ table.first_cell_borderless td:first-child,table.first_cell_borderless th:first-
|
|||||||
table.first_cell_borderless td:first-child{width: 25px !important;}
|
table.first_cell_borderless td:first-child{width: 25px !important;}
|
||||||
|
|
||||||
/*Header*/
|
/*Header*/
|
||||||
.navbar-brand{padding-top:0px;padding-left:2;}
|
.navbar-brand{top:0px;left:17px;padding-top:0;}
|
||||||
.sidebar{margin-top:85px;}
|
.sidebar{margin-top:85px;}
|
||||||
.dropdown{font-size:18px;}
|
.dropdown{font-size:18px;}
|
||||||
@media (max-width: 767px) {.sidebar{margin-top:0px;padding-top:0px !important;}}
|
@media (max-width: 767px) {.sidebar{margin-top:0px;padding-top:0px !important;}}
|
||||||
@ -239,6 +238,7 @@ table.first_cell_borderless td:first-child{width: 25px !important;}
|
|||||||
.btn-transparent {
|
.btn-transparent {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border-style: none;
|
border-style: none;
|
||||||
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*general instance management button*/
|
/*general instance management button*/
|
||||||
|
@ -170,7 +170,7 @@
|
|||||||
<li id="btn_setlang">
|
<li id="btn_setlang">
|
||||||
<a>
|
<a>
|
||||||
<div>
|
<div>
|
||||||
<i class="fa fa-globe"></i>
|
<i class="fa fa-globe fa-fw"></i>
|
||||||
<select id="language-select" class="selectpicker" data-width="fit" data-style="btn-transparent"> </select>
|
<select id="language-select" class="selectpicker" data-width="fit" data-style="btn-transparent"> </select>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
@ -49,6 +49,16 @@ public:
|
|||||||
GUID guid = GUID_NULL;
|
GUID guid = GUID_NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DeviceControls
|
||||||
|
{
|
||||||
|
QString property = QString();
|
||||||
|
int minValue = 0;
|
||||||
|
int maxValue = 0;
|
||||||
|
int step = 0;
|
||||||
|
int default = 0;
|
||||||
|
int currentValue = 0;
|
||||||
|
};
|
||||||
|
|
||||||
MFGrabber();
|
MFGrabber();
|
||||||
~MFGrabber() override;
|
~MFGrabber() override;
|
||||||
|
|
||||||
@ -91,6 +101,7 @@ private:
|
|||||||
QString _currentDeviceName,
|
QString _currentDeviceName,
|
||||||
_newDeviceName;
|
_newDeviceName;
|
||||||
QMap<QString, QList<DeviceProperties>> _deviceProperties;
|
QMap<QString, QList<DeviceProperties>> _deviceProperties;
|
||||||
|
QMap<QString, QList<DeviceControls>> _deviceControls;
|
||||||
HRESULT _hr;
|
HRESULT _hr;
|
||||||
IMFSourceReader* _sourceReader;
|
IMFSourceReader* _sourceReader;
|
||||||
SourceReaderCB* _sourceReaderCB;
|
SourceReaderCB* _sourceReaderCB;
|
||||||
|
@ -2,7 +2,24 @@
|
|||||||
#include "grabber/MFGrabber.h"
|
#include "grabber/MFGrabber.h"
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
namespace { const bool verbose = false; }
|
namespace { const bool verbose = true; }
|
||||||
|
|
||||||
|
// Need more video properties? Visit https://docs.microsoft.com/en-us/windows/win32/api/strmif/ne-strmif-videoprocampproperty
|
||||||
|
using VideoProcAmpPropertyMap = QMap<VideoProcAmpProperty, QString>;
|
||||||
|
inline QMap<VideoProcAmpProperty, QString> initVideoProcAmpPropertyMap()
|
||||||
|
{
|
||||||
|
QMap<VideoProcAmpProperty, QString> _videoProcAmpPropertyMap
|
||||||
|
{
|
||||||
|
{VideoProcAmp_Brightness, "brightness" },
|
||||||
|
{VideoProcAmp_Contrast , "contrast" },
|
||||||
|
{VideoProcAmp_Saturation, "saturation" },
|
||||||
|
{VideoProcAmp_Hue , "hue" }
|
||||||
|
};
|
||||||
|
|
||||||
|
return _videoProcAmpPropertyMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_GLOBAL_STATIC_WITH_ARGS(VideoProcAmpPropertyMap, _videoProcAmpPropertyMap, (initVideoProcAmpPropertyMap()));
|
||||||
|
|
||||||
MFGrabber::MFGrabber()
|
MFGrabber::MFGrabber()
|
||||||
: Grabber("V4L2:MEDIA_FOUNDATION")
|
: Grabber("V4L2:MEDIA_FOUNDATION")
|
||||||
@ -102,9 +119,10 @@ void MFGrabber::stop()
|
|||||||
_threadManager->stop();
|
_threadManager->stop();
|
||||||
disconnect(_threadManager, nullptr, nullptr, nullptr);
|
disconnect(_threadManager, nullptr, nullptr, nullptr);
|
||||||
_sourceReader->Flush(MF_SOURCE_READER_FIRST_VIDEO_STREAM);
|
_sourceReader->Flush(MF_SOURCE_READER_FIRST_VIDEO_STREAM);
|
||||||
while (_sourceReaderCB->isBusy()) {}
|
_sourceReaderCB->Wait();
|
||||||
SAFE_RELEASE(_sourceReader);
|
SAFE_RELEASE(_sourceReader);
|
||||||
_deviceProperties.clear();
|
_deviceProperties.clear();
|
||||||
|
_deviceControls.clear();
|
||||||
Info(_log, "Stopped");
|
Info(_log, "Stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,7 +189,6 @@ HRESULT MFGrabber::init_device(QString deviceName, DeviceProperties props)
|
|||||||
QString error;
|
QString error;
|
||||||
IMFMediaSource* device = nullptr;
|
IMFMediaSource* device = nullptr;
|
||||||
IMFAttributes* deviceAttributes = nullptr, *sourceReaderAttributes = nullptr;
|
IMFAttributes* deviceAttributes = nullptr, *sourceReaderAttributes = nullptr;
|
||||||
IAMVideoProcAmp *pProcAmp = nullptr;
|
|
||||||
IMFMediaType* type = nullptr;
|
IMFMediaType* type = nullptr;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
@ -213,86 +230,43 @@ HRESULT MFGrabber::init_device(QString deviceName, DeviceProperties props)
|
|||||||
else
|
else
|
||||||
Debug(_log, "Device opened");
|
Debug(_log, "Device opened");
|
||||||
|
|
||||||
// Set Brightness/Contrast/Saturation/Hue
|
IAMVideoProcAmp *pProcAmp = nullptr;
|
||||||
if (_brightness != 0 || _contrast != 0 || _saturation != 0 || _hue != 0)
|
if (SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&pProcAmp))))
|
||||||
{
|
{
|
||||||
if (SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&pProcAmp))))
|
for (auto control : _deviceControls[deviceName])
|
||||||
{
|
{
|
||||||
long lMin, lMax, lStep, lDefault, lCaps, Val;
|
switch (_videoProcAmpPropertyMap->key(control.property))
|
||||||
if (_brightness != 0)
|
|
||||||
{
|
{
|
||||||
if (SUCCEEDED(pProcAmp->GetRange(VideoProcAmp_Brightness, &lMin, &lMax, &lStep, &lDefault, &lCaps)))
|
case VideoProcAmpProperty::VideoProcAmp_Brightness:
|
||||||
{
|
if (_brightness >= control.minValue && _brightness <= control.maxValue && _brightness != control.currentValue)
|
||||||
Debug(_log, "Brightness: min=%i, max=%i, default=%i", lMin, lMax, lDefault);
|
{
|
||||||
|
Debug(_log,"Set brightness to %i", _brightness);
|
||||||
if (SUCCEEDED(pProcAmp->Get(VideoProcAmp_Brightness, &Val, &lCaps)))
|
pProcAmp->Set(VideoProcAmp_Brightness, _brightness, VideoProcAmp_Flags_Manual);
|
||||||
Debug(_log, "Current brightness set to: %i",Val);
|
}
|
||||||
|
break;
|
||||||
if (SUCCEEDED(pProcAmp->Set(VideoProcAmp_Brightness, _brightness, VideoProcAmp_Flags_Manual)))
|
case VideoProcAmpProperty::VideoProcAmp_Contrast:
|
||||||
Debug(_log, "Brightness set to: %i",_brightness);
|
if (_contrast >= control.minValue && _contrast <= control.maxValue && _contrast != control.currentValue)
|
||||||
else
|
{
|
||||||
Error(_log, "Could not set brightness");
|
Debug(_log,"Set contrast to %i", _contrast);
|
||||||
}
|
pProcAmp->Set(VideoProcAmp_Contrast, _contrast, VideoProcAmp_Flags_Manual);
|
||||||
else
|
}
|
||||||
Error(_log, "Brightness is not supported by the grabber");
|
break;
|
||||||
}
|
case VideoProcAmpProperty::VideoProcAmp_Saturation:
|
||||||
|
if (_saturation >= control.minValue && _saturation <= control.maxValue && _saturation != control.currentValue)
|
||||||
if (_contrast != 0)
|
{
|
||||||
{
|
Debug(_log,"Set saturation to %i", _saturation);
|
||||||
if (SUCCEEDED(pProcAmp->GetRange(VideoProcAmp_Contrast, &lMin, &lMax, &lStep, &lDefault, &lCaps)))
|
pProcAmp->Set(VideoProcAmp_Saturation, _saturation, VideoProcAmp_Flags_Manual);
|
||||||
{
|
}
|
||||||
Debug(_log, "Contrast: min=%i, max=%i, default=%i", lMin, lMax, lDefault);
|
break;
|
||||||
|
case VideoProcAmpProperty::VideoProcAmp_Hue:
|
||||||
if (SUCCEEDED(pProcAmp->Get(VideoProcAmp_Contrast, &Val, &lCaps)))
|
if (_hue >= control.minValue && _hue <= control.maxValue && _hue != control.currentValue)
|
||||||
Debug(_log, "Current contrast set to: %i",Val);
|
{
|
||||||
|
Debug(_log,"Set hue to %i", _hue);
|
||||||
if (SUCCEEDED(pProcAmp->Set(VideoProcAmp_Contrast, _contrast, VideoProcAmp_Flags_Manual)))
|
pProcAmp->Set(VideoProcAmp_Hue, _hue, VideoProcAmp_Flags_Manual);
|
||||||
Debug(_log, "Contrast set to: %i",_contrast);
|
}
|
||||||
else
|
break;
|
||||||
Error(_log, "Could not set contrast");
|
default:
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
Error(_log, "Contrast is not supported by the grabber");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_saturation != 0)
|
|
||||||
{
|
|
||||||
if (SUCCEEDED(pProcAmp->GetRange(VideoProcAmp_Saturation, &lMin, &lMax, &lStep, &lDefault, &lCaps)))
|
|
||||||
{
|
|
||||||
Debug(_log, "Saturation: min=%i, max=%i, default=%i", lMin, lMax, lDefault);
|
|
||||||
|
|
||||||
if (SUCCEEDED(pProcAmp->Get(VideoProcAmp_Saturation, &Val, &lCaps)))
|
|
||||||
Debug(_log, "Current saturation set to: %i",Val);
|
|
||||||
|
|
||||||
if (SUCCEEDED(pProcAmp->Set(VideoProcAmp_Saturation, _saturation, VideoProcAmp_Flags_Manual)))
|
|
||||||
Debug(_log, "Saturation set to: %i",_saturation);
|
|
||||||
else
|
|
||||||
Error(_log, "Could not set saturation");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Error(_log, "Saturation is not supported by the grabber");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_hue != 0)
|
|
||||||
{
|
|
||||||
hr = pProcAmp->GetRange(VideoProcAmp_Hue, &lMin, &lMax, &lStep, &lDefault, &lCaps);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
Debug(_log, "Hue: min=%i, max=%i, default=%i", lMin, lMax, lDefault);
|
|
||||||
|
|
||||||
hr = pProcAmp->Get(VideoProcAmp_Hue, &Val, &lCaps);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
Debug(_log, "Current hue set to: %i",Val);
|
|
||||||
|
|
||||||
hr = pProcAmp->Set(VideoProcAmp_Hue, _hue, VideoProcAmp_Flags_Manual);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
Debug(_log, "Hue set to: %i",_hue);
|
|
||||||
else
|
|
||||||
Error(_log, "Could not set hue");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Error(_log, "Hue is not supported by the grabber");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,6 +376,7 @@ done:
|
|||||||
void MFGrabber::enumVideoCaptureDevices()
|
void MFGrabber::enumVideoCaptureDevices()
|
||||||
{
|
{
|
||||||
_deviceProperties.clear();
|
_deviceProperties.clear();
|
||||||
|
_deviceControls.clear();
|
||||||
|
|
||||||
IMFAttributes* attr;
|
IMFAttributes* attr;
|
||||||
if (SUCCEEDED(MFCreateAttributes(&attr, 1)))
|
if (SUCCEEDED(MFCreateAttributes(&attr, 1)))
|
||||||
@ -461,15 +436,55 @@ void MFGrabber::enumVideoCaptureDevices()
|
|||||||
properties.guid = format;
|
properties.guid = format;
|
||||||
devicePropertyList.append(properties);
|
devicePropertyList.append(properties);
|
||||||
|
|
||||||
DebugIf (verbose, _log, "%s %d x %d @ %d fps (%s)", QSTRING_CSTR(dev), properties.width, properties.height, properties.fps, QSTRING_CSTR(pixelFormatToString(properties.pf)));
|
DebugIf (verbose, _log, "%s %d x %d @ %d fps (%s)", QSTRING_CSTR(dev), properties.width, properties.height, properties.fps, QSTRING_CSTR(pixelFormatToString(properties.pf)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pType->Release();
|
SAFE_RELEASE(pType);
|
||||||
}
|
}
|
||||||
reader->Release();
|
|
||||||
|
IAMVideoProcAmp *videoProcAmp = nullptr;
|
||||||
|
if (SUCCEEDED(pSource->QueryInterface(IID_PPV_ARGS(&videoProcAmp))))
|
||||||
|
{
|
||||||
|
QList<DeviceControls> deviceControlList;
|
||||||
|
for (auto it = _videoProcAmpPropertyMap->begin(); it != _videoProcAmpPropertyMap->end(); it++)
|
||||||
|
{
|
||||||
|
long minVal, maxVal, stepVal, defaultVal, flag;
|
||||||
|
if (SUCCEEDED(videoProcAmp->GetRange(it.key(), &minVal, &maxVal, &stepVal, &defaultVal, &flag)))
|
||||||
|
{
|
||||||
|
if (flag & VideoProcAmp_Flags_Manual)
|
||||||
|
{
|
||||||
|
DeviceControls control;
|
||||||
|
control.property = it.value();
|
||||||
|
control.minValue = minVal;
|
||||||
|
control.maxValue = maxVal;
|
||||||
|
control.step = stepVal;
|
||||||
|
control.default = defaultVal;
|
||||||
|
|
||||||
|
long currentVal;
|
||||||
|
if (SUCCEEDED(videoProcAmp->Get(it.key(), ¤tVal, &flag)))
|
||||||
|
{
|
||||||
|
control.currentValue = currentVal;
|
||||||
|
DebugIf(verbose, _log, "%s: min=%i, max=%i, step=%i, default=%i, current=%i", QSTRING_CSTR(it.value()), minVal, maxVal, stepVal, defaultVal, currentVal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
deviceControlList.append(control);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deviceControlList.isEmpty())
|
||||||
|
_deviceControls.insert(dev, deviceControlList);
|
||||||
|
}
|
||||||
|
|
||||||
|
SAFE_RELEASE(videoProcAmp);
|
||||||
|
SAFE_RELEASE(reader);
|
||||||
}
|
}
|
||||||
pSource->Release();
|
|
||||||
|
SAFE_RELEASE(pSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!devicePropertyList.isEmpty())
|
if (!devicePropertyList.isEmpty())
|
||||||
@ -480,13 +495,13 @@ void MFGrabber::enumVideoCaptureDevices()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoTaskMemFree(name);
|
CoTaskMemFree(name);
|
||||||
devices[i]->Release();
|
SAFE_RELEASE(devices[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoTaskMemFree(devices);
|
CoTaskMemFree(devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
attr->Release();
|
SAFE_RELEASE(attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -628,9 +643,6 @@ void MFGrabber::setBrightnessContrastSaturationHue(int brightness, int contrast,
|
|||||||
{
|
{
|
||||||
if (_brightness != brightness || _contrast != contrast || _saturation != saturation || _hue != hue)
|
if (_brightness != brightness || _contrast != contrast || _saturation != saturation || _hue != hue)
|
||||||
{
|
{
|
||||||
if (_initialized)
|
|
||||||
Debug(_log,"Set brightness to %i, contrast to %i, saturation to %i, hue to %i", _brightness, _contrast, _saturation, _hue);
|
|
||||||
|
|
||||||
_brightness = brightness;
|
_brightness = brightness;
|
||||||
_contrast = contrast;
|
_contrast = contrast;
|
||||||
_saturation = saturation;
|
_saturation = saturation;
|
||||||
@ -677,14 +689,18 @@ void MFGrabber::setSignalDetectionEnable(bool enable)
|
|||||||
|
|
||||||
bool MFGrabber::reload(bool force)
|
bool MFGrabber::reload(bool force)
|
||||||
{
|
{
|
||||||
if (_sourceReader && (_reload || force))
|
if (_reload || force)
|
||||||
{
|
{
|
||||||
Info(_log,"Reloading Media Foundation Grabber");
|
if (_sourceReader)
|
||||||
uninit();
|
{
|
||||||
_pixelFormat = _pixelFormatConfig;
|
Info(_log,"Reloading Media Foundation Grabber");
|
||||||
_newDeviceName = _currentDeviceName;
|
uninit();
|
||||||
|
_pixelFormat = _pixelFormatConfig;
|
||||||
|
_newDeviceName = _currentDeviceName;
|
||||||
|
}
|
||||||
|
|
||||||
_reload = false;
|
_reload = false;
|
||||||
return start();
|
return prepare() && start();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -754,12 +770,39 @@ QJsonArray MFGrabber::discover(const QJsonObject& params)
|
|||||||
}
|
}
|
||||||
in["formats"] = formats;
|
in["formats"] = formats;
|
||||||
video_inputs.append(in);
|
video_inputs.append(in);
|
||||||
|
|
||||||
device["video_inputs"] = video_inputs;
|
device["video_inputs"] = video_inputs;
|
||||||
|
|
||||||
|
QJsonObject controls, controls_default;
|
||||||
|
for (auto control : _deviceControls[it.key()])
|
||||||
|
{
|
||||||
|
QJsonObject property;
|
||||||
|
property["minValue"] = control.minValue;
|
||||||
|
property["maxValue"] = control.maxValue;
|
||||||
|
property["step"] = control.step;
|
||||||
|
controls[control.property] = property;
|
||||||
|
controls_default[control.property] = control.default;
|
||||||
|
}
|
||||||
|
device["properties"] = controls;
|
||||||
|
|
||||||
|
QJsonObject default, video_inputs_default, format_default, resolution_default;
|
||||||
|
resolution_default["width"] = 640;
|
||||||
|
resolution_default["height"] = 480;
|
||||||
|
resolution_default["fps"] = 25;
|
||||||
|
format_default["format"] = "bgr24";
|
||||||
|
format_default["resolution"] = resolution_default;
|
||||||
|
video_inputs_default["inputIdx"] = 0;
|
||||||
|
video_inputs_default["standards"] = "PAL";
|
||||||
|
video_inputs_default["formats"] = format_default;
|
||||||
|
|
||||||
|
default["video_input"] = video_inputs_default;
|
||||||
|
default["properties"] = controls_default;
|
||||||
|
device["default"] = default;
|
||||||
|
|
||||||
inputsDiscovered.append(device);
|
inputsDiscovered.append(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
_deviceProperties.clear();
|
_deviceProperties.clear();
|
||||||
|
_deviceControls.clear();
|
||||||
DebugIf (verbose, _log, "device: [%s]", QString(QJsonDocument(inputsDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData());
|
DebugIf (verbose, _log, "device: [%s]", QString(QJsonDocument(inputsDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData());
|
||||||
|
|
||||||
return inputsDiscovered;
|
return inputsDiscovered;
|
||||||
|
@ -42,14 +42,15 @@ public:
|
|||||||
SourceReaderCB(MFGrabber* grabber)
|
SourceReaderCB(MFGrabber* grabber)
|
||||||
: _nRefCount(1)
|
: _nRefCount(1)
|
||||||
, _grabber(grabber)
|
, _grabber(grabber)
|
||||||
, _bEOS(FALSE)
|
|
||||||
, _hrStatus(S_OK)
|
, _hrStatus(S_OK)
|
||||||
, _isBusy(false)
|
|
||||||
, _transform(nullptr)
|
, _transform(nullptr)
|
||||||
, _pixelformat(PixelFormat::NO_CHANGE)
|
, _pixelformat(PixelFormat::NO_CHANGE)
|
||||||
{
|
{
|
||||||
// Initialize critical section.
|
// Initialize critical section.
|
||||||
InitializeCriticalSection(&_critsec);
|
InitializeCriticalSection(&_critsec);
|
||||||
|
|
||||||
|
// Create event handler
|
||||||
|
_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IUnknown methods
|
// IUnknown methods
|
||||||
@ -83,12 +84,11 @@ public:
|
|||||||
DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample* pSample)
|
DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample* pSample)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&_critsec);
|
EnterCriticalSection(&_critsec);
|
||||||
_isBusy = true;
|
|
||||||
|
|
||||||
if (_grabber->_sourceReader == nullptr)
|
if (_grabber->_sourceReader == nullptr)
|
||||||
{
|
{
|
||||||
_isBusy = false;
|
|
||||||
LeaveCriticalSection(&_critsec);
|
LeaveCriticalSection(&_critsec);
|
||||||
|
SetEvent(_event);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,14 +172,11 @@ public:
|
|||||||
done:
|
done:
|
||||||
SAFE_RELEASE(buffer);
|
SAFE_RELEASE(buffer);
|
||||||
|
|
||||||
if (MF_SOURCE_READERF_ENDOFSTREAM & dwStreamFlags)
|
|
||||||
_bEOS = TRUE; // Reached the end of the stream.
|
|
||||||
|
|
||||||
if (_pixelformat != PixelFormat::MJPEG && _pixelformat != PixelFormat::BGR24 && _pixelformat != PixelFormat::NO_CHANGE)
|
if (_pixelformat != PixelFormat::MJPEG && _pixelformat != PixelFormat::BGR24 && _pixelformat != PixelFormat::NO_CHANGE)
|
||||||
SAFE_RELEASE(pSample);
|
SAFE_RELEASE(pSample);
|
||||||
|
|
||||||
_isBusy = false;
|
|
||||||
LeaveCriticalSection(&_critsec);
|
LeaveCriticalSection(&_critsec);
|
||||||
|
SetEvent(_event);
|
||||||
return _hrStatus;
|
return _hrStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,15 +280,7 @@ public:
|
|||||||
return _hrStatus;
|
return _hrStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL SourceReaderCB::isBusy()
|
void Wait() { WaitForSingleObject(_event, INFINITE); }
|
||||||
{
|
|
||||||
EnterCriticalSection(&_critsec);
|
|
||||||
BOOL result = _isBusy;
|
|
||||||
LeaveCriticalSection(&_critsec);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP OnEvent(DWORD, IMFMediaEvent*) { return S_OK; }
|
STDMETHODIMP OnEvent(DWORD, IMFMediaEvent*) { return S_OK; }
|
||||||
STDMETHODIMP OnFlush(DWORD) { return S_OK; }
|
STDMETHODIMP OnFlush(DWORD) { return S_OK; }
|
||||||
|
|
||||||
@ -397,5 +386,5 @@ private:
|
|||||||
HRESULT _hrStatus;
|
HRESULT _hrStatus;
|
||||||
IMFTransform* _transform;
|
IMFTransform* _transform;
|
||||||
PixelFormat _pixelformat;
|
PixelFormat _pixelformat;
|
||||||
std::atomic<bool> _isBusy;
|
HANDLE _event;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user