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:
Jaime Rivera 2020-11-29 21:17:24 -08:00
parent aac30e772f
commit 2fa624aef0
3 changed files with 36 additions and 5 deletions

View File

@ -346,8 +346,6 @@ public:
STDMETHODIMP OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample) CV_OVERRIDE
{
CV_UNUSED(llTimestamp);
HRESULT hr = 0;
cv::AutoLock lock(m_mutex);
@ -360,6 +358,7 @@ public:
{
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop frame (not processed)");
}
m_lastSampleTimestamp = llTimestamp;
m_lastSample = pSample;
}
}
@ -439,6 +438,7 @@ public:
IMFSourceReader *m_reader;
DWORD m_dwStreamIndex;
LONGLONG m_lastSampleTimestamp;
_ComPtr<IMFSample> m_lastSample;
};
@ -912,6 +912,7 @@ bool CvCapture_MSMF::grabFrame()
CV_LOG_WARNING(NULL, "videoio(MSMF): EOS signal. Capture stream is lost");
return false;
}
sampleTime = reader->m_lastSampleTimestamp;
return true;
}
else if (isOpen)

View File

@ -11,21 +11,51 @@
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;
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++)
{
SCOPED_TRACE(cv::format("frame=%d", i));
capture >> frame;
const int64 sysTimeCurr = cv::getTickCount();
const double camTimeCurr = capture.get(cv::CAP_PROP_POS_MSEC);
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";
sysTimePrev = sysTimeCurr;
camTimePrev = camTimeCurr;
}
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();
}

View File

@ -237,7 +237,7 @@ public:
if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
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) +
cv::String(" does not support CAP_PROP_POS_MSEC option"));