mirror of
https://github.com/opencv/opencv.git
synced 2025-08-06 14:36:36 +08:00
Add Timestamps to MSMF Video Capture by index
Enable frame timestamp tests for MSMF Add functional test for camera live timestamps Remove trailing whitespace Add timestamp test to all functional tests. Protect div by 0 Add Timestamps to MSMF Video Capture by index
This commit is contained in:
parent
aac30e772f
commit
2fa624aef0
@ -346,8 +346,6 @@ public:
|
|||||||
|
|
||||||
STDMETHODIMP OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample) CV_OVERRIDE
|
STDMETHODIMP OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample) CV_OVERRIDE
|
||||||
{
|
{
|
||||||
CV_UNUSED(llTimestamp);
|
|
||||||
|
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
cv::AutoLock lock(m_mutex);
|
cv::AutoLock lock(m_mutex);
|
||||||
|
|
||||||
@ -360,6 +358,7 @@ public:
|
|||||||
{
|
{
|
||||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop frame (not processed)");
|
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop frame (not processed)");
|
||||||
}
|
}
|
||||||
|
m_lastSampleTimestamp = llTimestamp;
|
||||||
m_lastSample = pSample;
|
m_lastSample = pSample;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -439,6 +438,7 @@ public:
|
|||||||
|
|
||||||
IMFSourceReader *m_reader;
|
IMFSourceReader *m_reader;
|
||||||
DWORD m_dwStreamIndex;
|
DWORD m_dwStreamIndex;
|
||||||
|
LONGLONG m_lastSampleTimestamp;
|
||||||
_ComPtr<IMFSample> m_lastSample;
|
_ComPtr<IMFSample> m_lastSample;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -912,6 +912,7 @@ bool CvCapture_MSMF::grabFrame()
|
|||||||
CV_LOG_WARNING(NULL, "videoio(MSMF): EOS signal. Capture stream is lost");
|
CV_LOG_WARNING(NULL, "videoio(MSMF): EOS signal. Capture stream is lost");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
sampleTime = reader->m_lastSampleTimestamp;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (isOpen)
|
else if (isOpen)
|
||||||
|
@ -11,21 +11,51 @@
|
|||||||
|
|
||||||
namespace opencv_test { namespace {
|
namespace opencv_test { namespace {
|
||||||
|
|
||||||
static void test_readFrames(/*const*/ VideoCapture& capture, const int N = 100, Mat* lastFrame = NULL)
|
static void test_readFrames(/*const*/ VideoCapture& capture, const int N = 100, Mat* lastFrame = NULL, bool testTimestamps = true)
|
||||||
{
|
{
|
||||||
Mat frame;
|
Mat frame;
|
||||||
int64 time0 = cv::getTickCount();
|
int64 time0 = cv::getTickCount();
|
||||||
|
int64 sysTimePrev = time0;
|
||||||
|
const double cvTickFreq = cv::getTickFrequency();
|
||||||
|
|
||||||
|
double camTimePrev = 0.0;
|
||||||
|
const double fps = capture.get(cv::CAP_PROP_FPS);
|
||||||
|
const double framePeriod = fps == 0.0 ? 1. : 1.0 / fps;
|
||||||
|
|
||||||
|
const bool validTickAndFps = cvTickFreq != 0 && fps != 0.;
|
||||||
|
testTimestamps &= validTickAndFps;
|
||||||
|
|
||||||
for (int i = 0; i < N; i++)
|
for (int i = 0; i < N; i++)
|
||||||
{
|
{
|
||||||
SCOPED_TRACE(cv::format("frame=%d", i));
|
SCOPED_TRACE(cv::format("frame=%d", i));
|
||||||
|
|
||||||
capture >> frame;
|
capture >> frame;
|
||||||
|
const int64 sysTimeCurr = cv::getTickCount();
|
||||||
|
const double camTimeCurr = capture.get(cv::CAP_PROP_POS_MSEC);
|
||||||
ASSERT_FALSE(frame.empty());
|
ASSERT_FALSE(frame.empty());
|
||||||
|
|
||||||
|
// Do we have a previous frame?
|
||||||
|
if (i > 0 && testTimestamps)
|
||||||
|
{
|
||||||
|
const double sysTimeElapsedSecs = (sysTimeCurr - sysTimePrev) / cvTickFreq;
|
||||||
|
const double camTimeElapsedSecs = (camTimeCurr - camTimePrev) / 1000.;
|
||||||
|
|
||||||
|
// Check that the time between two camera frames and two system time calls
|
||||||
|
// are within 1.5 frame periods of one another.
|
||||||
|
//
|
||||||
|
// 1.5x is chosen to accomodate for a dropped frame, and an additional 50%
|
||||||
|
// to account for drift in the scale of the camera and system time domains.
|
||||||
|
EXPECT_NEAR(sysTimeElapsedSecs, camTimeElapsedSecs, framePeriod * 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
EXPECT_GT(cvtest::norm(frame, NORM_INF), 0) << "Complete black image has been received";
|
EXPECT_GT(cvtest::norm(frame, NORM_INF), 0) << "Complete black image has been received";
|
||||||
|
|
||||||
|
sysTimePrev = sysTimeCurr;
|
||||||
|
camTimePrev = camTimeCurr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 time1 = cv::getTickCount();
|
int64 time1 = cv::getTickCount();
|
||||||
printf("Processed %d frames on %.2f FPS\n", N, (N * cv::getTickFrequency()) / (time1 - time0 + 1));
|
printf("Processed %d frames on %.2f FPS\n", N, (N * cvTickFreq) / (time1 - time0 + 1));
|
||||||
if (lastFrame) *lastFrame = frame.clone();
|
if (lastFrame) *lastFrame = frame.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ public:
|
|||||||
if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
|
if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
|
||||||
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
|
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
|
||||||
|
|
||||||
if ((apiPref == CAP_MSMF) || ((apiPref == CAP_FFMPEG) && ((ext == "h264") || (ext == "h265"))))
|
if (((apiPref == CAP_FFMPEG) && ((ext == "h264") || (ext == "h265"))))
|
||||||
throw SkipTestException(cv::String("Backend ") + cv::videoio_registry::getBackendName(apiPref) +
|
throw SkipTestException(cv::String("Backend ") + cv::videoio_registry::getBackendName(apiPref) +
|
||||||
cv::String(" does not support CAP_PROP_POS_MSEC option"));
|
cv::String(" does not support CAP_PROP_POS_MSEC option"));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user