mirror of
https://github.com/opencv/opencv.git
synced 2025-06-17 07:10:51 +08:00
Merge pull request #11727 from alalek:videoio_msmf_use_Lock2D
This commit is contained in:
commit
f72633b9f5
@ -1047,24 +1047,31 @@ bool CvCapture_MSMF::open(const cv::String& _filename)
|
|||||||
|
|
||||||
bool CvCapture_MSMF::grabFrame()
|
bool CvCapture_MSMF::grabFrame()
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
if (isOpen)
|
if (isOpen)
|
||||||
{
|
{
|
||||||
DWORD streamIndex, flags;
|
DWORD streamIndex, flags;
|
||||||
if (videoSample)
|
if (videoSample)
|
||||||
videoSample.Reset();
|
videoSample.Reset();
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
while(SUCCEEDED(hr = videoFileSource->ReadSample(
|
for(;;)
|
||||||
|
{
|
||||||
|
CV_TRACE_REGION("ReadSample");
|
||||||
|
if (!SUCCEEDED(hr = videoFileSource->ReadSample(
|
||||||
dwStreamIndex, // Stream index.
|
dwStreamIndex, // Stream index.
|
||||||
0, // Flags.
|
0, // Flags.
|
||||||
&streamIndex, // Receives the actual stream index.
|
&streamIndex, // Receives the actual stream index.
|
||||||
&flags, // Receives status flags.
|
&flags, // Receives status flags.
|
||||||
&sampleTime, // Receives the time stamp.
|
&sampleTime, // Receives the time stamp.
|
||||||
&videoSample // Receives the sample or NULL.
|
&videoSample // Receives the sample or NULL.
|
||||||
)) &&
|
)))
|
||||||
streamIndex == dwStreamIndex && !(flags & (MF_SOURCE_READERF_ERROR|MF_SOURCE_READERF_ALLEFFECTSREMOVED|MF_SOURCE_READERF_ENDOFSTREAM)) &&
|
break;
|
||||||
!videoSample
|
if (streamIndex != dwStreamIndex)
|
||||||
)
|
break;
|
||||||
{
|
if (flags & (MF_SOURCE_READERF_ERROR | MF_SOURCE_READERF_ALLEFFECTSREMOVED | MF_SOURCE_READERF_ENDOFSTREAM))
|
||||||
|
break;
|
||||||
|
if (videoSample)
|
||||||
|
break;
|
||||||
if (flags & MF_SOURCE_READERF_STREAMTICK)
|
if (flags & MF_SOURCE_READERF_STREAMTICK)
|
||||||
{
|
{
|
||||||
DebugPrintOut(L"\tStream tick detected. Retrying to grab the frame\n");
|
DebugPrintOut(L"\tStream tick detected. Retrying to grab the frame\n");
|
||||||
@ -1117,39 +1124,80 @@ bool CvCapture_MSMF::grabFrame()
|
|||||||
|
|
||||||
bool CvCapture_MSMF::retrieveFrame(int, cv::OutputArray frame)
|
bool CvCapture_MSMF::retrieveFrame(int, cv::OutputArray frame)
|
||||||
{
|
{
|
||||||
DWORD bcnt;
|
CV_TRACE_FUNCTION();
|
||||||
if (videoSample && SUCCEEDED(videoSample->GetBufferCount(&bcnt)) && bcnt > 0)
|
do
|
||||||
{
|
{
|
||||||
|
if (!videoSample)
|
||||||
|
break;
|
||||||
|
|
||||||
_ComPtr<IMFMediaBuffer> buf = NULL;
|
_ComPtr<IMFMediaBuffer> buf = NULL;
|
||||||
if (SUCCEEDED(videoSample->GetBufferByIndex(0, &buf)))
|
|
||||||
|
CV_TRACE_REGION("get_contiguous_buffer");
|
||||||
|
if (!SUCCEEDED(videoSample->ConvertToContiguousBuffer(&buf)))
|
||||||
{
|
{
|
||||||
DWORD maxsize, cursize;
|
CV_TRACE_REGION("get_buffer");
|
||||||
|
DWORD bcnt = 0;
|
||||||
|
if (!SUCCEEDED(videoSample->GetBufferCount(&bcnt)))
|
||||||
|
break;
|
||||||
|
if (bcnt == 0)
|
||||||
|
break;
|
||||||
|
if (!SUCCEEDED(videoSample->GetBufferByIndex(0, &buf)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lock2d = false;
|
||||||
BYTE* ptr = NULL;
|
BYTE* ptr = NULL;
|
||||||
if (SUCCEEDED(buf->Lock(&ptr, &maxsize, &cursize)))
|
LONG pitch = 0;
|
||||||
{
|
DWORD maxsize = 0, cursize = 0;
|
||||||
|
|
||||||
|
// "For 2-D buffers, the Lock2D method is more efficient than the Lock method"
|
||||||
|
// see IMFMediaBuffer::Lock method documentation: https://msdn.microsoft.com/en-us/library/windows/desktop/bb970366(v=vs.85).aspx
|
||||||
|
_ComPtr<IMF2DBuffer> buffer2d;
|
||||||
if (convertFormat)
|
if (convertFormat)
|
||||||
{
|
{
|
||||||
if ((unsigned int)cursize == captureFormat.MF_MT_SAMPLE_SIZE)
|
if (SUCCEEDED(buf.As<IMF2DBuffer>(&buffer2d)))
|
||||||
|
{
|
||||||
|
CV_TRACE_REGION_NEXT("lock2d");
|
||||||
|
if (SUCCEEDED(buffer2d->Lock2D(&ptr, &pitch)))
|
||||||
|
{
|
||||||
|
lock2d = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
CV_Assert(lock2d == false);
|
||||||
|
CV_TRACE_REGION_NEXT("lock");
|
||||||
|
if (!SUCCEEDED(buf->Lock(&ptr, &maxsize, &cursize)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ptr)
|
||||||
|
break;
|
||||||
|
if (convertFormat)
|
||||||
|
{
|
||||||
|
if (lock2d || (unsigned int)cursize == captureFormat.MF_MT_SAMPLE_SIZE)
|
||||||
{
|
{
|
||||||
switch (outputFormat)
|
switch (outputFormat)
|
||||||
{
|
{
|
||||||
case CV_CAP_MODE_YUYV:
|
case CV_CAP_MODE_YUYV:
|
||||||
cv::Mat(captureFormat.height, captureFormat.width, CV_8UC2, ptr).copyTo(frame);
|
cv::Mat(captureFormat.height, captureFormat.width, CV_8UC2, ptr, pitch).copyTo(frame);
|
||||||
break;
|
break;
|
||||||
case CV_CAP_MODE_BGR:
|
case CV_CAP_MODE_BGR:
|
||||||
if (captureMode == MODE_HW)
|
if (captureMode == MODE_HW)
|
||||||
cv::cvtColor(cv::Mat(captureFormat.height, captureFormat.width, CV_8UC4, ptr), frame, cv::COLOR_BGRA2BGR);
|
cv::cvtColor(cv::Mat(captureFormat.height, captureFormat.width, CV_8UC4, ptr, pitch), frame, cv::COLOR_BGRA2BGR);
|
||||||
else
|
else
|
||||||
cv::Mat(captureFormat.height, captureFormat.width, CV_8UC3, ptr).copyTo(frame);
|
cv::Mat(captureFormat.height, captureFormat.width, CV_8UC3, ptr, pitch).copyTo(frame);
|
||||||
break;
|
break;
|
||||||
case CV_CAP_MODE_RGB:
|
case CV_CAP_MODE_RGB:
|
||||||
if (captureMode == MODE_HW)
|
if (captureMode == MODE_HW)
|
||||||
cv::cvtColor(cv::Mat(captureFormat.height, captureFormat.width, CV_8UC4, ptr), frame, cv::COLOR_BGRA2BGR);
|
cv::cvtColor(cv::Mat(captureFormat.height, captureFormat.width, CV_8UC4, ptr, pitch), frame, cv::COLOR_BGRA2BGR);
|
||||||
else
|
else
|
||||||
cv::cvtColor(cv::Mat(captureFormat.height, captureFormat.width, CV_8UC3, ptr), frame, cv::COLOR_BGR2RGB);
|
cv::cvtColor(cv::Mat(captureFormat.height, captureFormat.width, CV_8UC3, ptr, pitch), frame, cv::COLOR_BGR2RGB);
|
||||||
break;
|
break;
|
||||||
case CV_CAP_MODE_GRAY:
|
case CV_CAP_MODE_GRAY:
|
||||||
cv::Mat(captureFormat.height, captureFormat.width, CV_8UC1, ptr).copyTo(frame);
|
cv::Mat(captureFormat.height, captureFormat.width, CV_8UC1, ptr, pitch).copyTo(frame);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
frame.release();
|
frame.release();
|
||||||
@ -1161,13 +1209,15 @@ bool CvCapture_MSMF::retrieveFrame(int, cv::OutputArray frame)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cv::Mat(1, cursize, CV_8UC1, ptr).copyTo(frame);
|
cv::Mat(1, cursize, CV_8UC1, ptr, pitch).copyTo(frame);
|
||||||
}
|
}
|
||||||
|
CV_TRACE_REGION_NEXT("unlock");
|
||||||
|
if (lock2d)
|
||||||
|
buffer2d->Unlock2D();
|
||||||
|
else
|
||||||
buf->Unlock();
|
buf->Unlock();
|
||||||
return !frame.empty();
|
return !frame.empty();
|
||||||
}
|
} while (0);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
frame.release();
|
frame.release();
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user