mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 08:13:04 +04:00
Merge branch 4.x
This commit is contained in:
@@ -127,6 +127,8 @@ protected:
|
||||
|
||||
void autoExposureControl(const Mat &);
|
||||
|
||||
double getExpectedMidGrey(ArvPixelFormat fmt) const;
|
||||
|
||||
ArvCamera *camera; // Camera to control.
|
||||
ArvStream *stream; // Object for video stream reception.
|
||||
void *framebuffer; //
|
||||
@@ -269,6 +271,19 @@ bool CvCaptureCAM_Aravis::open( int index )
|
||||
|
||||
// get initial values
|
||||
pixelFormat = arv_camera_get_pixel_format(camera, NULL);
|
||||
|
||||
// If camera's pixel format is not one of the supported formats, set a default
|
||||
if (pixelFormat != ARV_PIXEL_FORMAT_MONO_8 &&
|
||||
pixelFormat != ARV_PIXEL_FORMAT_BAYER_GR_8 &&
|
||||
pixelFormat != ARV_PIXEL_FORMAT_MONO_12 &&
|
||||
pixelFormat != ARV_PIXEL_FORMAT_MONO_16) {
|
||||
pixelFormat = ARV_PIXEL_FORMAT_MONO_8;
|
||||
arv_camera_set_pixel_format(camera, pixelFormat, NULL);
|
||||
CV_LOG_WARNING(NULL, "Current camera pixel format is not supported. Failed back to MONO_8.");
|
||||
}
|
||||
|
||||
midGrey = getExpectedMidGrey(pixelFormat);
|
||||
|
||||
exposure = exposureAvailable ? arv_camera_get_exposure_time(camera, NULL) : 0;
|
||||
gain = gainAvailable ? arv_camera_get_gain(camera, NULL) : 0;
|
||||
fps = arv_camera_get_frame_rate(camera, NULL);
|
||||
@@ -489,6 +504,26 @@ double CvCaptureCAM_Aravis::getProperty( int property_id ) const
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
double CvCaptureCAM_Aravis::getExpectedMidGrey(ArvPixelFormat fmt) const
|
||||
{
|
||||
double grey = 0.;
|
||||
switch(fmt)
|
||||
{
|
||||
case ARV_PIXEL_FORMAT_MONO_8:
|
||||
case ARV_PIXEL_FORMAT_BAYER_GR_8:
|
||||
grey = 128.;
|
||||
break;
|
||||
case ARV_PIXEL_FORMAT_MONO_12:
|
||||
grey = 2048.;
|
||||
break;
|
||||
case ARV_PIXEL_FORMAT_MONO_16:
|
||||
grey = 32768.;
|
||||
break;
|
||||
}
|
||||
|
||||
return grey;
|
||||
}
|
||||
|
||||
bool CvCaptureCAM_Aravis::setProperty( int property_id, double value )
|
||||
{
|
||||
switch(property_id) {
|
||||
@@ -535,24 +570,22 @@ bool CvCaptureCAM_Aravis::setProperty( int property_id, double value )
|
||||
case MODE_GREY:
|
||||
case MODE_Y800:
|
||||
newFormat = ARV_PIXEL_FORMAT_MONO_8;
|
||||
targetGrey = 128;
|
||||
break;
|
||||
case MODE_Y12:
|
||||
newFormat = ARV_PIXEL_FORMAT_MONO_12;
|
||||
targetGrey = 2048;
|
||||
break;
|
||||
case MODE_Y16:
|
||||
newFormat = ARV_PIXEL_FORMAT_MONO_16;
|
||||
targetGrey = 32768;
|
||||
break;
|
||||
case MODE_GRBG:
|
||||
newFormat = ARV_PIXEL_FORMAT_BAYER_GR_8;
|
||||
targetGrey = 128;
|
||||
break;
|
||||
}
|
||||
|
||||
if(newFormat != pixelFormat) {
|
||||
stopCapture();
|
||||
arv_camera_set_pixel_format(camera, pixelFormat = newFormat, NULL);
|
||||
midGrey = getExpectedMidGrey(newFormat);
|
||||
startCapture();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
|
||||
protected:
|
||||
// Known widget names
|
||||
static const char * PROP_EXPOSURE_COMPENSACTION;
|
||||
static const char * PROP_EXPOSURE_COMPENSATION;
|
||||
static const char * PROP_SELF_TIMER_DELAY;
|
||||
static const char * PROP_MANUALFOCUS;
|
||||
static const char * PROP_AUTOFOCUS;
|
||||
@@ -294,7 +294,7 @@ const char * DigitalCameraCapture::lineDelimiter = "\n";
|
||||
* Those are actually substrings of widget name.
|
||||
* ie. for VIEWFINDER, Nikon uses "viewfinder", while Canon can use "eosviewfinder".
|
||||
*/
|
||||
const char * DigitalCameraCapture::PROP_EXPOSURE_COMPENSACTION =
|
||||
const char * DigitalCameraCapture::PROP_EXPOSURE_COMPENSATION =
|
||||
"exposurecompensation";
|
||||
const char * DigitalCameraCapture::PROP_SELF_TIMER_DELAY = "selftimerdelay";
|
||||
const char * DigitalCameraCapture::PROP_MANUALFOCUS = "manualfocusdrive";
|
||||
@@ -555,7 +555,7 @@ CameraWidget * DigitalCameraCapture::getGenericProperty(int propertyId,
|
||||
return NULL;
|
||||
}
|
||||
case CAP_PROP_EXPOSURE:
|
||||
return findWidgetByName(PROP_EXPOSURE_COMPENSACTION);
|
||||
return findWidgetByName(PROP_EXPOSURE_COMPENSATION);
|
||||
case CAP_PROP_TRIGGER_DELAY:
|
||||
return findWidgetByName(PROP_SELF_TIMER_DELAY);
|
||||
case CAP_PROP_ZOOM:
|
||||
@@ -692,7 +692,7 @@ CameraWidget * DigitalCameraCapture::setGenericProperty(int propertyId,
|
||||
output = false;
|
||||
return NULL;
|
||||
case CAP_PROP_EXPOSURE:
|
||||
return findWidgetByName(PROP_EXPOSURE_COMPENSACTION);
|
||||
return findWidgetByName(PROP_EXPOSURE_COMPENSATION);
|
||||
case CAP_PROP_TRIGGER_DELAY:
|
||||
return findWidgetByName(PROP_SELF_TIMER_DELAY);
|
||||
case CAP_PROP_ZOOM:
|
||||
|
||||
@@ -448,50 +448,68 @@ public:
|
||||
|
||||
STDMETHODIMP OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample) CV_OVERRIDE
|
||||
{
|
||||
HRESULT hr = 0;
|
||||
cv::AutoLock lock(m_mutex);
|
||||
|
||||
if (SUCCEEDED(hrStatus))
|
||||
HRESULT hr = S_OK;
|
||||
try
|
||||
{
|
||||
if (pSample)
|
||||
cv::AutoLock lock(m_mutex);
|
||||
|
||||
if (SUCCEEDED(hrStatus))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): got frame at " << llTimestamp);
|
||||
if (m_capturedFrames.size() >= MSMF_READER_MAX_QUEUE_SIZE)
|
||||
if (pSample)
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): got frame at " << llTimestamp);
|
||||
if (m_capturedFrames.size() >= MSMF_READER_MAX_QUEUE_SIZE)
|
||||
{
|
||||
#if 0
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop frame (not processed). Timestamp=" << m_capturedFrames.front().timestamp);
|
||||
m_capturedFrames.pop();
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop frame (not processed). Timestamp=" << m_capturedFrames.front().timestamp);
|
||||
m_capturedFrames.pop();
|
||||
#else
|
||||
// this branch reduces latency if we drop frames due to slow processing.
|
||||
// avoid fetching of already outdated frames from the queue's front.
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop previous frames (not processed): " << m_capturedFrames.size());
|
||||
std::queue<CapturedFrameInfo>().swap(m_capturedFrames); // similar to missing m_capturedFrames.clean();
|
||||
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop previous frames (not processed): " << m_capturedFrames.size());
|
||||
std::queue<CapturedFrameInfo>().swap(m_capturedFrames); // similar to missing m_capturedFrames.clean();
|
||||
#endif
|
||||
}
|
||||
m_capturedFrames.emplace(CapturedFrameInfo{ llTimestamp, _ComPtr<IMFSample>(pSample), hrStatus });
|
||||
}
|
||||
m_capturedFrames.emplace(CapturedFrameInfo{ llTimestamp, _ComPtr<IMFSample>(pSample), hrStatus });
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): OnReadSample() is called with error status: " << hrStatus);
|
||||
}
|
||||
if (MF_SOURCE_READERF_ENDOFSTREAM & dwStreamFlags)
|
||||
{
|
||||
// Reached the end of the stream.
|
||||
m_bEOS = true;
|
||||
}
|
||||
m_hrStatus = hrStatus;
|
||||
|
||||
if (FAILED(hr = m_reader->ReadSample(dwStreamIndex, 0, NULL, NULL, NULL, NULL)))
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): async ReadSample() call is failed with error status: " << hr);
|
||||
m_bEOS = true;
|
||||
}
|
||||
|
||||
if (pSample || m_bEOS)
|
||||
{
|
||||
SetEvent(m_hEvent);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (const _com_error& e)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): OnReadSample() is called with error status: " << hrStatus);
|
||||
std::string msg;
|
||||
#ifdef _UNICODE
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv;
|
||||
msg = conv.to_bytes(e.ErrorMessage());
|
||||
#else
|
||||
msg = std::string(e.ErrorMessage());
|
||||
#endif
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): _com_error in OnReadSample: " << msg);
|
||||
return S_OK; // Keep callback alive
|
||||
}
|
||||
|
||||
if (MF_SOURCE_READERF_ENDOFSTREAM & dwStreamFlags)
|
||||
catch (...)
|
||||
{
|
||||
// Reached the end of the stream.
|
||||
m_bEOS = true;
|
||||
}
|
||||
m_hrStatus = hrStatus;
|
||||
|
||||
if (FAILED(hr = m_reader->ReadSample(dwStreamIndex, 0, NULL, NULL, NULL, NULL)))
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): async ReadSample() call is failed with error status: " << hr);
|
||||
m_bEOS = true;
|
||||
}
|
||||
|
||||
if (pSample || m_bEOS)
|
||||
{
|
||||
SetEvent(m_hEvent);
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): Unknown exception in OnReadSample");
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1758,82 +1776,108 @@ bool CvCapture_MSMF::grabFrame()
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
if (grabIsDone)
|
||||
try
|
||||
{
|
||||
grabIsDone = false;
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): return pre-grabbed frame " << usedVideoSampleTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
audioFrame = Mat();
|
||||
if (readCallback) // async "live" capture mode
|
||||
{
|
||||
audioSamples.push_back(NULL);
|
||||
HRESULT hr = 0;
|
||||
SourceReaderCB* reader = ((SourceReaderCB*)readCallback.Get());
|
||||
DWORD dwStreamIndex = 0;
|
||||
if (videoStream != -1)
|
||||
dwStreamIndex = dwVideoStreamIndex;
|
||||
if (audioStream != -1)
|
||||
dwStreamIndex = dwAudioStreamIndex;
|
||||
if (!reader->m_reader)
|
||||
if (grabIsDone)
|
||||
{
|
||||
// Initiate capturing with async callback
|
||||
reader->m_reader = videoFileSource.Get();
|
||||
reader->m_dwStreamIndex = dwStreamIndex;
|
||||
if (FAILED(hr = videoFileSource->ReadSample(dwStreamIndex, 0, NULL, NULL, NULL, NULL)))
|
||||
grabIsDone = false;
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): return pre-grabbed frame " << usedVideoSampleTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
audioFrame = Mat();
|
||||
if (readCallback) // async "live" capture mode
|
||||
{
|
||||
audioSamples.push_back(NULL);
|
||||
HRESULT hr = 0;
|
||||
SourceReaderCB* reader = ((SourceReaderCB*)readCallback.Get());
|
||||
DWORD dwStreamIndex = 0;
|
||||
if (videoStream != -1)
|
||||
dwStreamIndex = dwVideoStreamIndex;
|
||||
if (audioStream != -1)
|
||||
dwStreamIndex = dwAudioStreamIndex;
|
||||
if (!reader->m_reader)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "videoio(MSMF): can't grab frame - initial async ReadSample() call failed: " << hr);
|
||||
reader->m_reader = NULL;
|
||||
// Initiate capturing with async callback
|
||||
reader->m_reader = videoFileSource.Get();
|
||||
reader->m_dwStreamIndex = dwStreamIndex;
|
||||
if (FAILED(hr = videoFileSource->ReadSample(dwStreamIndex, 0, NULL, NULL, NULL, NULL)))
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "videoio(MSMF): can't grab frame - initial async ReadSample() call failed: " << hr);
|
||||
reader->m_reader = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BOOL bEOS = false;
|
||||
LONGLONG timestamp = 0;
|
||||
if (FAILED(hr = reader->Wait( videoStream == -1 ? INFINITE : 10000, (videoStream != -1) ? usedVideoSample : audioSamples[0], timestamp, bEOS))) // 10 sec
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): can't grab frame. Error: " << hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BOOL bEOS = false;
|
||||
LONGLONG timestamp = 0;
|
||||
if (FAILED(hr = reader->Wait( videoStream == -1 ? INFINITE : 10000, (videoStream != -1) ? usedVideoSample : audioSamples[0], timestamp, bEOS))) // 10 sec
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): can't grab frame. Error: " << hr);
|
||||
return false;
|
||||
}
|
||||
if (bEOS)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): EOS signal. Capture stream is lost");
|
||||
return false;
|
||||
}
|
||||
if (videoStream != -1)
|
||||
usedVideoSampleTime = timestamp;
|
||||
if (audioStream != -1)
|
||||
return configureAudioFrame();
|
||||
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): grabbed frame " << usedVideoSampleTime);
|
||||
return true;
|
||||
}
|
||||
else if (isOpen)
|
||||
{
|
||||
if (vEOS)
|
||||
return false;
|
||||
|
||||
bool returnFlag = true;
|
||||
|
||||
if (videoStream != -1)
|
||||
{
|
||||
if (!vEOS)
|
||||
returnFlag &= grabVideoFrame();
|
||||
if (!returnFlag)
|
||||
if (bEOS)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): EOS signal. Capture stream is lost");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (videoStream != -1)
|
||||
usedVideoSampleTime = timestamp;
|
||||
if (audioStream != -1)
|
||||
return configureAudioFrame();
|
||||
|
||||
if (audioStream != -1)
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): grabbed frame " << usedVideoSampleTime);
|
||||
return true;
|
||||
}
|
||||
else if (isOpen)
|
||||
{
|
||||
const int bytesPerSample = (captureAudioFormat.bit_per_sample/8) * captureAudioFormat.nChannels;
|
||||
bufferedAudioDuration = (double)(bufferAudioData.size()/bytesPerSample)/captureAudioFormat.nSamplesPerSec;
|
||||
audioFrame.release();
|
||||
if (!aEOS)
|
||||
returnFlag &= grabAudioFrame();
|
||||
}
|
||||
if (vEOS)
|
||||
return false;
|
||||
|
||||
return returnFlag;
|
||||
bool returnFlag = true;
|
||||
|
||||
if (videoStream != -1)
|
||||
{
|
||||
if (!vEOS)
|
||||
returnFlag &= grabVideoFrame();
|
||||
if (!returnFlag)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (audioStream != -1)
|
||||
{
|
||||
const int bytesPerSample = (captureAudioFormat.bit_per_sample/8) * captureAudioFormat.nChannels;
|
||||
bufferedAudioDuration = (double)(bufferAudioData.size()/bytesPerSample)/captureAudioFormat.nSamplesPerSec;
|
||||
audioFrame.release();
|
||||
if (!aEOS)
|
||||
returnFlag &= grabAudioFrame();
|
||||
}
|
||||
|
||||
return returnFlag;
|
||||
}
|
||||
}
|
||||
catch (const _com_error& e)
|
||||
{
|
||||
std::string msg;
|
||||
#ifdef _UNICODE
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv;
|
||||
msg = conv.to_bytes(e.ErrorMessage());
|
||||
#else
|
||||
msg = std::string(e.ErrorMessage());
|
||||
#endif
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): _com_error caught in grabFrame: " << msg);
|
||||
return false;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): std::exception caught in grabFrame: " << e.what());
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "videoio(MSMF): Unknown exception caught in grabFrame");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user