1
0
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:
Alexander Smorkalov
2025-12-02 15:22:25 +03:00
56 changed files with 1639 additions and 876 deletions
+37 -4
View File
@@ -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();
}
}
+4 -4
View File
@@ -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:
+142 -98
View File
@@ -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;
}