mirror of
https://github.com/opencv/opencv.git
synced 2026-09-25 04:09:57 +03:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -25,6 +25,16 @@ if(WITH_IPP)
|
||||
elseif(ANDROID AND NOT OPENCV_SKIP_ANDROID_IPP_FIX_2)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-Bsymbolic ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
endif()
|
||||
|
||||
if(OPENCV_FORCE_IPP_EXCLUDE_LIBS
|
||||
OR (HAVE_IPP_ICV
|
||||
AND UNIX AND NOT ANDROID AND NOT APPLE
|
||||
AND (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
)
|
||||
AND NOT OPENCV_SKIP_IPP_EXCLUDE_LIBS
|
||||
)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a ${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
+160
-100
@@ -48,8 +48,10 @@
|
||||
#include "precomp.hpp"
|
||||
#include <stdio.h>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include "opencl_kernels_calib3d.hpp"
|
||||
#include "opencv2/core/hal/intrin.hpp"
|
||||
#include "opencv2/core/utils/buffer_area.private.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -85,6 +87,19 @@ struct StereoBMParams
|
||||
Rect roi1, roi2;
|
||||
int disp12MaxDiff;
|
||||
int dispType;
|
||||
|
||||
inline bool useShorts() const
|
||||
{
|
||||
return preFilterCap <= 31 && SADWindowSize <= 21;
|
||||
}
|
||||
inline bool useFilterSpeckles() const
|
||||
{
|
||||
return speckleRange >= 0 && speckleWindowSize > 0;
|
||||
}
|
||||
inline bool useNormPrefilter() const
|
||||
{
|
||||
return preFilterType == StereoBM::PREFILTER_NORMALIZED_RESPONSE;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
@@ -110,10 +125,10 @@ static bool ocl_prefilter_norm(InputArray _input, OutputArray _output, int winsi
|
||||
}
|
||||
#endif
|
||||
|
||||
static void prefilterNorm( const Mat& src, Mat& dst, int winsize, int ftzero, uchar* buf )
|
||||
static void prefilterNorm( const Mat& src, Mat& dst, int winsize, int ftzero, int *buf )
|
||||
{
|
||||
int x, y, wsz2 = winsize/2;
|
||||
int* vsum = (int*)alignPtr(buf + (wsz2 + 1)*sizeof(vsum[0]), 32);
|
||||
int* vsum = buf + (wsz2 + 1);
|
||||
int scale_g = winsize*winsize/8, scale_s = (1024 + scale_g)/(scale_g*2);
|
||||
const int OFS = 256*5, TABSZ = OFS*2 + 256;
|
||||
uchar tab[TABSZ];
|
||||
@@ -309,13 +324,77 @@ inline int dispDescale(int v1, int v2, int d)
|
||||
return (int)(v1*256 + (d != 0 ? v2*256/d : 0)); // no need to add 127, this will be converted to float
|
||||
}
|
||||
|
||||
|
||||
class BufferBM
|
||||
{
|
||||
static const int TABSZ = 256;
|
||||
public:
|
||||
std::vector<int*> sad;
|
||||
std::vector<int*> hsad;
|
||||
std::vector<int*> htext;
|
||||
std::vector<uchar*> cbuf0;
|
||||
std::vector<ushort*> sad_short;
|
||||
std::vector<ushort*> hsad_short;
|
||||
int *prefilter[2];
|
||||
uchar tab[TABSZ];
|
||||
private:
|
||||
utils::BufferArea area;
|
||||
|
||||
public:
|
||||
BufferBM(size_t nstripes, size_t width, size_t height, const StereoBMParams& params)
|
||||
: sad(nstripes, NULL),
|
||||
hsad(nstripes, NULL),
|
||||
htext(nstripes, NULL),
|
||||
cbuf0(nstripes, NULL),
|
||||
sad_short(nstripes, NULL),
|
||||
hsad_short(nstripes, NULL)
|
||||
{
|
||||
const int wsz = params.SADWindowSize;
|
||||
const int ndisp = params.numDisparities;
|
||||
const int ftzero = params.preFilterCap;
|
||||
for (size_t i = 0; i < nstripes; ++i)
|
||||
{
|
||||
// 1D: [1][ ndisp ][1]
|
||||
#if CV_SIMD
|
||||
if (params.useShorts())
|
||||
area.allocate(sad_short[i], ndisp + 2);
|
||||
else
|
||||
#endif
|
||||
area.allocate(sad[i], ndisp + 2);
|
||||
|
||||
// 2D: [ wsz/2 + 1 ][ height ][ wsz/2 + 1 ] * [ ndisp ]
|
||||
#if CV_SIMD
|
||||
if (params.useShorts())
|
||||
area.allocate(hsad_short[i], (height + wsz + 2) * ndisp);
|
||||
else
|
||||
#endif
|
||||
area.allocate(hsad[i], (height + wsz + 2) * ndisp);
|
||||
|
||||
// 1D: [ wsz/2 + 1 ][ height ][ wsz/2 + 1 ]
|
||||
area.allocate(htext[i], (height + wsz + 2));
|
||||
|
||||
// 3D: [ wsz/2 + 1 ][ height ][ wsz/2 + 1 ] * [ ndisp ] * [ wsz/2 + 1 ][ wsz/2 + 1 ]
|
||||
area.allocate(cbuf0[i], ((height + wsz + 2) * ndisp * (wsz + 2) + 256));
|
||||
}
|
||||
if (params.useNormPrefilter())
|
||||
{
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
area.allocate(prefilter[0], width + params.preFilterSize + 2);
|
||||
}
|
||||
area.commit();
|
||||
|
||||
// static table
|
||||
for (int x = 0; x < TABSZ; x++)
|
||||
tab[x] = (uchar)std::abs(x - ftzero);
|
||||
}
|
||||
};
|
||||
|
||||
#if CV_SIMD
|
||||
template <typename dType>
|
||||
static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
|
||||
Mat& disp, Mat& cost, StereoBMParams& state,
|
||||
uchar* buf, int _dy0, int _dy1 )
|
||||
Mat& disp, Mat& cost, const StereoBMParams& state,
|
||||
int _dy0, int _dy1, const BufferBM & bufX, size_t bufNum )
|
||||
{
|
||||
const int ALIGN = CV_SIMD_WIDTH;
|
||||
int x, y, d;
|
||||
int wsz = state.SADWindowSize, wsz2 = wsz/2;
|
||||
int dy0 = MIN(_dy0, wsz2+1), dy1 = MIN(_dy1, wsz2+1);
|
||||
@@ -325,15 +404,13 @@ static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
|
||||
int rofs = -MIN(ndisp - 1 + mindisp, 0);
|
||||
int width = left.cols, height = left.rows;
|
||||
int width1 = width - rofs - ndisp + 1;
|
||||
int ftzero = state.preFilterCap;
|
||||
int textureThreshold = state.textureThreshold;
|
||||
int uniquenessRatio = state.uniquenessRatio;
|
||||
const int disp_shift = dispShiftTemplate<dType>::value;
|
||||
dType FILTERED = (dType)((mindisp - 1) << disp_shift);
|
||||
|
||||
ushort *sad, *hsad0, *hsad, *hsad_sub;
|
||||
int *htext;
|
||||
uchar *cbuf0, *cbuf;
|
||||
ushort *hsad, *hsad_sub;
|
||||
uchar *cbuf;
|
||||
const uchar* lptr0 = left.ptr() + lofs;
|
||||
const uchar* rptr0 = right.ptr() + rofs;
|
||||
const uchar *lptr, *lptr_sub, *rptr;
|
||||
@@ -343,23 +420,20 @@ static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
|
||||
int cstep = (height + dy0 + dy1)*ndisp;
|
||||
short costbuf = 0;
|
||||
int coststep = cost.data ? (int)(cost.step/sizeof(costbuf)) : 0;
|
||||
const int TABSZ = 256;
|
||||
uchar tab[TABSZ];
|
||||
const uchar * tab = bufX.tab;
|
||||
short v_seq[v_int16::nlanes];
|
||||
for (short i = 0; i < v_int16::nlanes; ++i)
|
||||
v_seq[i] = i;
|
||||
|
||||
sad = (ushort*)alignPtr(buf + sizeof(sad[0]), ALIGN);
|
||||
hsad0 = (ushort*)alignPtr(sad + ndisp + 1 + dy0*ndisp, ALIGN);
|
||||
htext = (int*)alignPtr((int*)(hsad0 + (height+dy1)*ndisp) + wsz2 + 2, ALIGN);
|
||||
cbuf0 = (uchar*)alignPtr((uchar*)(htext + height + wsz2 + 2) + dy0*ndisp, ALIGN);
|
||||
|
||||
for( x = 0; x < TABSZ; x++ )
|
||||
tab[x] = (uchar)std::abs(x - ftzero);
|
||||
ushort *sad = bufX.sad_short[bufNum] + 1;
|
||||
ushort *hsad0 = bufX.hsad_short[bufNum] + (wsz2 + 1) * ndisp;
|
||||
int *htext = bufX.htext[bufNum] + (wsz2 + 1);
|
||||
uchar *cbuf0 = bufX.cbuf0[bufNum] + (wsz2 + 1) * ndisp;
|
||||
|
||||
// initialize buffers
|
||||
memset( hsad0 - dy0*ndisp, 0, (height + dy0 + dy1)*ndisp*sizeof(hsad0[0]) );
|
||||
memset( htext - wsz2 - 1, 0, (height + wsz + 1)*sizeof(htext[0]) );
|
||||
memset(sad - 1, 0, (ndisp + 2) * sizeof(sad[0]));
|
||||
memset(hsad0 - dy0 * ndisp, 0, (height + wsz + 2) * ndisp * sizeof(hsad[0]));
|
||||
memset(htext - dy0, 0, (height + wsz + 2) * sizeof(htext[0]));
|
||||
|
||||
for( x = -wsz2-1; x < wsz2; x++ )
|
||||
{
|
||||
@@ -594,10 +668,9 @@ template <typename mType>
|
||||
static void
|
||||
findStereoCorrespondenceBM( const Mat& left, const Mat& right,
|
||||
Mat& disp, Mat& cost, const StereoBMParams& state,
|
||||
uchar* buf, int _dy0, int _dy1 )
|
||||
int _dy0, int _dy1, const BufferBM & bufX, size_t bufNum )
|
||||
{
|
||||
|
||||
const int ALIGN = CV_SIMD_WIDTH;
|
||||
int x, y, d;
|
||||
int wsz = state.SADWindowSize, wsz2 = wsz/2;
|
||||
int dy0 = MIN(_dy0, wsz2+1), dy1 = MIN(_dy1, wsz2+1);
|
||||
@@ -607,14 +680,13 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
|
||||
int rofs = -MIN(ndisp - 1 + mindisp, 0);
|
||||
int width = left.cols, height = left.rows;
|
||||
int width1 = width - rofs - ndisp + 1;
|
||||
int ftzero = state.preFilterCap;
|
||||
int textureThreshold = state.textureThreshold;
|
||||
int uniquenessRatio = state.uniquenessRatio;
|
||||
const int disp_shift = dispShiftTemplate<mType>::value;
|
||||
mType FILTERED = (mType)((mindisp - 1) << disp_shift);
|
||||
|
||||
int *sad, *hsad0, *hsad, *hsad_sub, *htext;
|
||||
uchar *cbuf0, *cbuf;
|
||||
int *hsad, *hsad_sub;
|
||||
uchar *cbuf;
|
||||
const uchar* lptr0 = left.ptr() + lofs;
|
||||
const uchar* rptr0 = right.ptr() + rofs;
|
||||
const uchar *lptr, *lptr_sub, *rptr;
|
||||
@@ -624,8 +696,7 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
|
||||
int cstep = (height+dy0+dy1)*ndisp;
|
||||
int costbuf = 0;
|
||||
int coststep = cost.data ? (int)(cost.step/sizeof(costbuf)) : 0;
|
||||
const int TABSZ = 256;
|
||||
uchar tab[TABSZ];
|
||||
const uchar * tab = bufX.tab;
|
||||
|
||||
#if CV_SIMD
|
||||
int v_seq[v_int32::nlanes];
|
||||
@@ -634,17 +705,15 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
|
||||
v_int32 d0_4 = vx_load(v_seq), dd_4 = vx_setall_s32(v_int32::nlanes);
|
||||
#endif
|
||||
|
||||
sad = (int*)alignPtr(buf + sizeof(sad[0]), ALIGN);
|
||||
hsad0 = (int*)alignPtr(sad + ndisp + 1 + dy0*ndisp, ALIGN);
|
||||
htext = (int*)alignPtr((int*)(hsad0 + (height+dy1)*ndisp) + wsz2 + 2, ALIGN);
|
||||
cbuf0 = (uchar*)alignPtr((uchar*)(htext + height + wsz2 + 2) + dy0*ndisp, ALIGN);
|
||||
|
||||
for( x = 0; x < TABSZ; x++ )
|
||||
tab[x] = (uchar)std::abs(x - ftzero);
|
||||
int *sad = bufX.sad[bufNum] + 1;
|
||||
int *hsad0 = bufX.hsad[bufNum] + (wsz2 + 1) * ndisp;
|
||||
int *htext = bufX.htext[bufNum] + (wsz2 + 1);
|
||||
uchar *cbuf0 = bufX.cbuf0[bufNum] + (wsz2 + 1) * ndisp;
|
||||
|
||||
// initialize buffers
|
||||
memset( hsad0 - dy0*ndisp, 0, (height + dy0 + dy1)*ndisp*sizeof(hsad0[0]) );
|
||||
memset( htext - wsz2 - 1, 0, (height + wsz + 1)*sizeof(htext[0]) );
|
||||
memset(sad - 1, 0, (ndisp + 2) * sizeof(sad[0]));
|
||||
memset(hsad0 - dy0 * ndisp, 0, (height + wsz + 2) * ndisp * sizeof(hsad[0]));
|
||||
memset(htext - dy0, 0, (height + wsz + 2) * sizeof(htext[0]));
|
||||
|
||||
for( x = -wsz2-1; x < wsz2; x++ )
|
||||
{
|
||||
@@ -890,7 +959,7 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
|
||||
#ifdef HAVE_OPENCL
|
||||
static bool ocl_prefiltering(InputArray left0, InputArray right0, OutputArray left, OutputArray right, StereoBMParams* state)
|
||||
{
|
||||
if( state->preFilterType == StereoBM::PREFILTER_NORMALIZED_RESPONSE )
|
||||
if (state->useNormPrefilter())
|
||||
{
|
||||
if(!ocl_prefilter_norm( left0, left, state->preFilterSize, state->preFilterCap))
|
||||
return false;
|
||||
@@ -911,29 +980,28 @@ static bool ocl_prefiltering(InputArray left0, InputArray right0, OutputArray le
|
||||
struct PrefilterInvoker : public ParallelLoopBody
|
||||
{
|
||||
PrefilterInvoker(const Mat& left0, const Mat& right0, Mat& left, Mat& right,
|
||||
uchar* buf0, uchar* buf1, StereoBMParams* _state)
|
||||
const BufferBM &bufX_, const StereoBMParams &state_)
|
||||
: bufX(bufX_), state(state_)
|
||||
{
|
||||
imgs0[0] = &left0; imgs0[1] = &right0;
|
||||
imgs[0] = &left; imgs[1] = &right;
|
||||
buf[0] = buf0; buf[1] = buf1;
|
||||
state = _state;
|
||||
}
|
||||
|
||||
void operator()(const Range& range) const CV_OVERRIDE
|
||||
{
|
||||
for( int i = range.start; i < range.end; i++ )
|
||||
{
|
||||
if( state->preFilterType == StereoBM::PREFILTER_NORMALIZED_RESPONSE )
|
||||
prefilterNorm( *imgs0[i], *imgs[i], state->preFilterSize, state->preFilterCap, buf[i] );
|
||||
if (state.useNormPrefilter())
|
||||
prefilterNorm( *imgs0[i], *imgs[i], state.preFilterSize, state.preFilterCap, bufX.prefilter[i] );
|
||||
else
|
||||
prefilterXSobel( *imgs0[i], *imgs[i], state->preFilterCap );
|
||||
prefilterXSobel( *imgs0[i], *imgs[i], state.preFilterCap );
|
||||
}
|
||||
}
|
||||
|
||||
const Mat* imgs0[2];
|
||||
Mat* imgs[2];
|
||||
uchar* buf[2];
|
||||
StereoBMParams* state;
|
||||
const BufferBM &bufX;
|
||||
const StereoBMParams &state;
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
@@ -986,18 +1054,17 @@ static bool ocl_stereobm( InputArray _left, InputArray _right,
|
||||
struct FindStereoCorrespInvoker : public ParallelLoopBody
|
||||
{
|
||||
FindStereoCorrespInvoker( const Mat& _left, const Mat& _right,
|
||||
Mat& _disp, StereoBMParams* _state,
|
||||
int _nstripes, size_t _stripeBufSize,
|
||||
bool _useShorts, Rect _validDisparityRect,
|
||||
Mat& _slidingSumBuf, Mat& _cost )
|
||||
Mat& _disp, const StereoBMParams &_state,
|
||||
int _nstripes,
|
||||
Rect _validDisparityRect,
|
||||
Mat& _cost, const BufferBM & buf_ )
|
||||
: state(_state), buf(buf_)
|
||||
{
|
||||
CV_Assert( _disp.type() == CV_16S || _disp.type() == CV_32S );
|
||||
left = &_left; right = &_right;
|
||||
disp = &_disp; state = _state;
|
||||
nstripes = _nstripes; stripeBufSize = _stripeBufSize;
|
||||
useShorts = _useShorts;
|
||||
disp = &_disp;
|
||||
nstripes = _nstripes;
|
||||
validDisparityRect = _validDisparityRect;
|
||||
slidingSumBuf = &_slidingSumBuf;
|
||||
cost = &_cost;
|
||||
}
|
||||
|
||||
@@ -1006,11 +1073,10 @@ struct FindStereoCorrespInvoker : public ParallelLoopBody
|
||||
int cols = left->cols, rows = left->rows;
|
||||
int _row0 = std::min(cvRound(range.start * rows / nstripes), rows);
|
||||
int _row1 = std::min(cvRound(range.end * rows / nstripes), rows);
|
||||
uchar *ptr = slidingSumBuf->ptr() + range.start * stripeBufSize;
|
||||
|
||||
int dispShift = disp->type() == CV_16S ? DISPARITY_SHIFT_16S :
|
||||
DISPARITY_SHIFT_32S;
|
||||
int FILTERED = (state->minDisparity - 1) << dispShift;
|
||||
int FILTERED = (state.minDisparity - 1) << dispShift;
|
||||
|
||||
Rect roi = validDisparityRect & Rect(0, _row0, cols, _row1 - _row0);
|
||||
if( roi.height == 0 )
|
||||
@@ -1033,27 +1099,27 @@ struct FindStereoCorrespInvoker : public ParallelLoopBody
|
||||
Mat left_i = left->rowRange(row0, row1);
|
||||
Mat right_i = right->rowRange(row0, row1);
|
||||
Mat disp_i = disp->rowRange(row0, row1);
|
||||
Mat cost_i = state->disp12MaxDiff >= 0 ? cost->rowRange(row0, row1) : Mat();
|
||||
Mat cost_i = state.disp12MaxDiff >= 0 ? cost->rowRange(row0, row1) : Mat();
|
||||
|
||||
#if CV_SIMD
|
||||
if (useShorts)
|
||||
if (state.useShorts())
|
||||
{
|
||||
if( disp_i.type() == CV_16S)
|
||||
findStereoCorrespondenceBM_SIMD<short>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
|
||||
findStereoCorrespondenceBM_SIMD<short>( left_i, right_i, disp_i, cost_i, state, row0, rows - row1, buf, range.start );
|
||||
else
|
||||
findStereoCorrespondenceBM_SIMD<int>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1);
|
||||
findStereoCorrespondenceBM_SIMD<int>( left_i, right_i, disp_i, cost_i, state, row0, rows - row1, buf, range.start);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if( disp_i.type() == CV_16S )
|
||||
findStereoCorrespondenceBM<short>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
|
||||
findStereoCorrespondenceBM<short>( left_i, right_i, disp_i, cost_i, state, row0, rows - row1, buf, range.start );
|
||||
else
|
||||
findStereoCorrespondenceBM<int>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
|
||||
findStereoCorrespondenceBM<int>( left_i, right_i, disp_i, cost_i, state, row0, rows - row1, buf, range.start );
|
||||
}
|
||||
|
||||
if( state->disp12MaxDiff >= 0 )
|
||||
validateDisparity( disp_i, cost_i, state->minDisparity, state->numDisparities, state->disp12MaxDiff );
|
||||
if( state.disp12MaxDiff >= 0 )
|
||||
validateDisparity( disp_i, cost_i, state.minDisparity, state.numDisparities, state.disp12MaxDiff );
|
||||
|
||||
if( roi.x > 0 )
|
||||
{
|
||||
@@ -1069,13 +1135,12 @@ struct FindStereoCorrespInvoker : public ParallelLoopBody
|
||||
|
||||
protected:
|
||||
const Mat *left, *right;
|
||||
Mat* disp, *slidingSumBuf, *cost;
|
||||
StereoBMParams *state;
|
||||
Mat* disp, *cost;
|
||||
const StereoBMParams &state;
|
||||
|
||||
int nstripes;
|
||||
size_t stripeBufSize;
|
||||
bool useShorts;
|
||||
Rect validDisparityRect;
|
||||
const BufferBM & buf;
|
||||
};
|
||||
|
||||
class StereoBMImpl CV_FINAL : public StereoBM
|
||||
@@ -1149,7 +1214,7 @@ public:
|
||||
disp_shift = DISPARITY_SHIFT_16S;
|
||||
FILTERED = (params.minDisparity - 1) << disp_shift;
|
||||
|
||||
if( params.speckleRange >= 0 && params.speckleWindowSize > 0 )
|
||||
if (params.useFilterSpeckles())
|
||||
filterSpeckles(disparr.getMat(), FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf);
|
||||
if (dtype == CV_32F)
|
||||
disparr.getUMat().convertTo(disparr, CV_32FC1, 1./(1 << disp_shift), 0);
|
||||
@@ -1192,44 +1257,39 @@ public:
|
||||
disp = dispbuf;
|
||||
}
|
||||
|
||||
int wsz = params.SADWindowSize;
|
||||
int bufSize0 = (int)((ndisp + 2)*sizeof(int));
|
||||
bufSize0 += (int)((height+wsz+2)*ndisp*sizeof(int));
|
||||
bufSize0 += (int)((height + wsz + 2)*sizeof(int));
|
||||
bufSize0 += (int)((height+wsz+2)*ndisp*(wsz+2)*sizeof(uchar) + 256);
|
||||
{
|
||||
const double SAD_overhead_coeff = 10.0;
|
||||
const double N0 = 8000000 / (params.useShorts() ? 1 : 4); // approx tbb's min number instructions reasonable for one thread
|
||||
const double maxStripeSize = std::min(
|
||||
std::max(
|
||||
N0 / (width * ndisp),
|
||||
(params.SADWindowSize-1) * SAD_overhead_coeff
|
||||
),
|
||||
(double)height
|
||||
);
|
||||
const int nstripes = cvCeil(height / maxStripeSize);
|
||||
BufferBM localBuf(nstripes, width, height, params);
|
||||
|
||||
int bufSize1 = (int)((width + params.preFilterSize + 2) * sizeof(int) + 256);
|
||||
int bufSize2 = 0;
|
||||
if( params.speckleRange >= 0 && params.speckleWindowSize > 0 )
|
||||
bufSize2 = width*height*(sizeof(Point_<short>) + sizeof(int) + sizeof(uchar));
|
||||
// Prefiltering
|
||||
parallel_for_(Range(0, 2), PrefilterInvoker(left0, right0, left, right, localBuf, params), 1);
|
||||
|
||||
bool useShorts = params.preFilterCap <= 31 && params.SADWindowSize <= 21;
|
||||
const double SAD_overhead_coeff = 10.0;
|
||||
double N0 = 8000000 / (useShorts ? 1 : 4); // approx tbb's min number instructions reasonable for one thread
|
||||
double maxStripeSize = std::min(std::max(N0 / (width * ndisp), (wsz-1) * SAD_overhead_coeff), (double)height);
|
||||
int nstripes = cvCeil(height / maxStripeSize);
|
||||
int bufSize = std::max(bufSize0 * nstripes, std::max(bufSize1 * 2, bufSize2));
|
||||
|
||||
if( slidingSumBuf.cols < bufSize )
|
||||
slidingSumBuf.create( 1, bufSize, CV_8U );
|
||||
Rect validDisparityRect(0, 0, width, height), R1 = params.roi1, R2 = params.roi2;
|
||||
validDisparityRect = getValidDisparityROI(!R1.empty() ? R1 : validDisparityRect,
|
||||
!R2.empty() ? R2 : validDisparityRect,
|
||||
params.minDisparity, params.numDisparities,
|
||||
params.SADWindowSize);
|
||||
|
||||
uchar *_buf = slidingSumBuf.ptr();
|
||||
FindStereoCorrespInvoker invoker(left, right, disp, params, nstripes, validDisparityRect, cost, localBuf);
|
||||
parallel_for_(Range(0, nstripes), invoker);
|
||||
|
||||
parallel_for_(Range(0, 2), PrefilterInvoker(left0, right0, left, right, _buf, _buf + bufSize1, ¶ms), 1);
|
||||
if (params.useFilterSpeckles())
|
||||
{
|
||||
slidingSumBuf.create( 1, width * height * (sizeof(Point_<short>) + sizeof(int) + sizeof(uchar)), CV_8U );
|
||||
filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf);
|
||||
}
|
||||
|
||||
Rect validDisparityRect(0, 0, width, height), R1 = params.roi1, R2 = params.roi2;
|
||||
validDisparityRect = getValidDisparityROI(!R1.empty() ? R1 : validDisparityRect,
|
||||
!R2.empty() ? R2 : validDisparityRect,
|
||||
params.minDisparity, params.numDisparities,
|
||||
params.SADWindowSize);
|
||||
|
||||
parallel_for_(Range(0, nstripes),
|
||||
FindStereoCorrespInvoker(left, right, disp, ¶ms, nstripes,
|
||||
bufSize0, useShorts, validDisparityRect,
|
||||
slidingSumBuf, cost));
|
||||
|
||||
if( params.speckleRange >= 0 && params.speckleWindowSize > 0 )
|
||||
filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf);
|
||||
}
|
||||
|
||||
if (disp0.data != disp.data)
|
||||
disp.convertTo(disp0, disp0.type(), 1./(1 << disp_shift), 0);
|
||||
|
||||
@@ -326,6 +326,13 @@ enum CpuFeatures {
|
||||
|
||||
#include "cv_cpu_dispatch.h"
|
||||
|
||||
#if !defined(CV_STRONG_ALIGNMENT) && defined(__arm__) && !(defined(__aarch64__) || defined(_M_ARM64))
|
||||
// int*, int64* should be propertly aligned pointers on ARMv7
|
||||
#define CV_STRONG_ALIGNMENT 1
|
||||
#endif
|
||||
#if !defined(CV_STRONG_ALIGNMENT)
|
||||
#define CV_STRONG_ALIGNMENT 0
|
||||
#endif
|
||||
|
||||
/* fundamental constants */
|
||||
#define CV_PI 3.1415926535897932384626433832795
|
||||
|
||||
@@ -1458,16 +1458,23 @@ template<typename _Tp, int n> inline void v_zip( const v_reg<_Tp, n>& a0, const
|
||||
@return register object
|
||||
|
||||
@note Returned type will be detected from passed pointer type, for example uchar ==> cv::v_uint8x16, int ==> cv::v_int32x4, etc.
|
||||
|
||||
@note Alignment requirement:
|
||||
if CV_STRONG_ALIGNMENT=1 then passed pointer must be aligned (`sizeof(lane type)` should be enough).
|
||||
Do not cast pointer types without runtime check for pointer alignment (like `uchar*` => `int*`).
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load(const _Tp* ptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
return v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128>(ptr);
|
||||
}
|
||||
|
||||
/** @brief Load register contents from memory (aligned)
|
||||
|
||||
similar to cv::v_load, but source memory block should be aligned (to 16-byte boundary)
|
||||
similar to cv::v_load, but source memory block should be aligned (to 16-byte boundary in case of SIMD128, 32-byte - SIMD256, etc)
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_aligned(const _Tp* ptr)
|
||||
@@ -1488,6 +1495,9 @@ v_int32x4 r = v_load_low(lo);
|
||||
template<typename _Tp>
|
||||
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_low(const _Tp* ptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
|
||||
for( int i = 0; i < c.nlanes/2; i++ )
|
||||
{
|
||||
@@ -1509,6 +1519,10 @@ v_int32x4 r = v_load_halves(lo, hi);
|
||||
template<typename _Tp>
|
||||
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_halves(const _Tp* loptr, const _Tp* hiptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(loptr));
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(hiptr));
|
||||
#endif
|
||||
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
|
||||
for( int i = 0; i < c.nlanes/2; i++ )
|
||||
{
|
||||
@@ -1531,6 +1545,9 @@ template<typename _Tp>
|
||||
inline v_reg<typename V_TypeTraits<_Tp>::w_type, V_TypeTraits<_Tp>::nlanes128 / 2>
|
||||
v_load_expand(const _Tp* ptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
typedef typename V_TypeTraits<_Tp>::w_type w_type;
|
||||
v_reg<w_type, V_TypeTraits<w_type>::nlanes128> c;
|
||||
for( int i = 0; i < c.nlanes; i++ )
|
||||
@@ -1552,6 +1569,9 @@ template<typename _Tp>
|
||||
inline v_reg<typename V_TypeTraits<_Tp>::q_type, V_TypeTraits<_Tp>::nlanes128 / 4>
|
||||
v_load_expand_q(const _Tp* ptr)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
typedef typename V_TypeTraits<_Tp>::q_type q_type;
|
||||
v_reg<q_type, V_TypeTraits<q_type>::nlanes128> c;
|
||||
for( int i = 0; i < c.nlanes; i++ )
|
||||
@@ -1572,6 +1592,9 @@ For all types except 64-bit. */
|
||||
template<typename _Tp, int n> inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a,
|
||||
v_reg<_Tp, n>& b)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i2;
|
||||
for( i = i2 = 0; i < n; i++, i2 += 2 )
|
||||
{
|
||||
@@ -1591,6 +1614,9 @@ For all types except 64-bit. */
|
||||
template<typename _Tp, int n> inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a,
|
||||
v_reg<_Tp, n>& b, v_reg<_Tp, n>& c)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i3;
|
||||
for( i = i3 = 0; i < n; i++, i3 += 3 )
|
||||
{
|
||||
@@ -1613,6 +1639,9 @@ inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a,
|
||||
v_reg<_Tp, n>& b, v_reg<_Tp, n>& c,
|
||||
v_reg<_Tp, n>& d)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i4;
|
||||
for( i = i4 = 0; i < n; i++, i4 += 4 )
|
||||
{
|
||||
@@ -1636,6 +1665,9 @@ inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a,
|
||||
const v_reg<_Tp, n>& b,
|
||||
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i2;
|
||||
for( i = i2 = 0; i < n; i++, i2 += 2 )
|
||||
{
|
||||
@@ -1657,6 +1689,9 @@ inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a,
|
||||
const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c,
|
||||
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i3;
|
||||
for( i = i3 = 0; i < n; i++, i3 += 3 )
|
||||
{
|
||||
@@ -1679,6 +1714,9 @@ template<typename _Tp, int n> inline void v_store_interleave( _Tp* ptr, const v_
|
||||
const v_reg<_Tp, n>& d,
|
||||
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
int i, i4;
|
||||
for( i = i4 = 0; i < n; i++, i4 += 4 )
|
||||
{
|
||||
@@ -1700,6 +1738,9 @@ Pointer can be unaligned. */
|
||||
template<typename _Tp, int n>
|
||||
inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
for( int i = 0; i < n; i++ )
|
||||
ptr[i] = a.s[i];
|
||||
}
|
||||
@@ -1707,6 +1748,9 @@ inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a)
|
||||
template<typename _Tp, int n>
|
||||
inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a, hal::StoreMode /*mode*/)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
v_store(ptr, a);
|
||||
}
|
||||
|
||||
@@ -1720,6 +1764,9 @@ Scheme:
|
||||
template<typename _Tp, int n>
|
||||
inline void v_store_low(_Tp* ptr, const v_reg<_Tp, n>& a)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
for( int i = 0; i < (n/2); i++ )
|
||||
ptr[i] = a.s[i];
|
||||
}
|
||||
@@ -1734,6 +1781,9 @@ Scheme:
|
||||
template<typename _Tp, int n>
|
||||
inline void v_store_high(_Tp* ptr, const v_reg<_Tp, n>& a)
|
||||
{
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
|
||||
#endif
|
||||
for( int i = 0; i < (n/2); i++ )
|
||||
ptr[i] = a.s[i+(n/2)];
|
||||
}
|
||||
|
||||
@@ -449,7 +449,7 @@ Returned value is a string containing space separated list of CPU features with
|
||||
|
||||
Example: `SSE SSE2 SSE3 *SSE4.1 *SSE4.2 *FP16 *AVX *AVX2 *AVX512-SKX?`
|
||||
*/
|
||||
CV_EXPORTS std::string getCPUFeaturesLine();
|
||||
CV_EXPORTS_W std::string getCPUFeaturesLine();
|
||||
|
||||
/** @brief Returns the number of logical CPUs available for the process.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#ifndef OPENCV_UTILS_BUFFER_AREA_HPP
|
||||
#define OPENCV_UTILS_BUFFER_AREA_HPP
|
||||
|
||||
#include <opencv2/core/base.hpp>
|
||||
#include <opencv2/core/private.hpp>
|
||||
#include <opencv2/core/utility.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace cv { namespace utils {
|
||||
|
||||
//! @addtogroup core_utils
|
||||
//! @{
|
||||
|
||||
/** @brief Manages memory block shared by muliple buffers.
|
||||
|
||||
This class allows to allocate one large memory block and split it into several smaller
|
||||
non-overlapping buffers. In safe mode each buffer allocation will be performed independently,
|
||||
this mode allows dynamic memory access instrumentation using valgrind or memory sanitizer.
|
||||
|
||||
Safe mode can be explicitly switched ON in constructor. It will also be enabled when compiling with
|
||||
memory sanitizer support or in runtime with the environment variable `OPENCV_BUFFER_AREA_ALWAYS_SAFE`.
|
||||
|
||||
Example of usage:
|
||||
@code
|
||||
int * buf1 = 0;
|
||||
double * buf2 = 0;
|
||||
cv::util::BufferArea area;
|
||||
area.allocate(buf1, 200); // buf1 = new int[200];
|
||||
area.allocate(buf2, 1000, 64); // buf2 = new double[1000]; - aligned by 64
|
||||
area.commit();
|
||||
@endcode
|
||||
|
||||
@note This class is considered private and should be used only in OpenCV itself. API can be changed.
|
||||
*/
|
||||
class CV_EXPORTS BufferArea
|
||||
{
|
||||
public:
|
||||
/** @brief Class constructor.
|
||||
|
||||
@param safe Enable _safe_ operation mode, each allocation will be performed independently.
|
||||
*/
|
||||
BufferArea(bool safe = false);
|
||||
|
||||
/** @brief Class destructor
|
||||
|
||||
All allocated memory well be freed. Each bound pointer will be reset to NULL.
|
||||
*/
|
||||
~BufferArea();
|
||||
|
||||
/** @brief Bind a pointer to local area.
|
||||
|
||||
BufferArea will store reference to the pointer and allocation parameters effectively owning the
|
||||
pointer and allocated memory. This operation has the same parameters and does the same job
|
||||
as the operator `new`, except allocation can be performed later during the BufferArea::commit call.
|
||||
|
||||
@param ptr Reference to a pointer of type T. Must be NULL
|
||||
@param count Count of objects to be allocated, it has the same meaning as in the operator `new`.
|
||||
@param alignment Alignment of allocated memory. same meaning as in the operator `new` (C++17).
|
||||
Must be divisible by sizeof(T). Must be power of two.
|
||||
|
||||
@note In safe mode allocation will be performed immediatly.
|
||||
*/
|
||||
template <typename T>
|
||||
void allocate(T*&ptr, size_t count, ushort alignment = sizeof(T))
|
||||
{
|
||||
CV_Assert(ptr == NULL);
|
||||
CV_Assert(count > 0);
|
||||
CV_Assert(alignment > 0);
|
||||
CV_Assert(alignment % sizeof(T) == 0);
|
||||
CV_Assert((alignment & (alignment - 1)) == 0);
|
||||
allocate_((void**)(&ptr), static_cast<ushort>(sizeof(T)), count, alignment);
|
||||
}
|
||||
|
||||
/** @brief Allocate memory and initialize all bound pointers
|
||||
|
||||
Each pointer bound to the area with the BufferArea::allocate will be initialized and will be set
|
||||
to point to a memory block with requested size and alignment.
|
||||
|
||||
@note Does nothing in safe mode as all allocations will be performed by BufferArea::allocate
|
||||
*/
|
||||
void commit();
|
||||
|
||||
private:
|
||||
BufferArea(const BufferArea &); // = delete
|
||||
BufferArea &operator=(const BufferArea &); // = delete
|
||||
void allocate_(void **ptr, ushort type_size, size_t count, ushort alignment);
|
||||
|
||||
private:
|
||||
class Block;
|
||||
std::vector<Block> blocks;
|
||||
void * oneBuf;
|
||||
size_t totalSize;
|
||||
const bool safe;
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
}} // cv::utils::
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "opencv2/core/utils/buffer_area.private.hpp"
|
||||
#include "opencv2/core/utils/configuration.private.hpp"
|
||||
|
||||
#ifdef OPENCV_ENABLE_MEMORY_SANITIZER
|
||||
#define BUFFER_AREA_DEFAULT_MODE true
|
||||
#else
|
||||
#define BUFFER_AREA_DEFAULT_MODE false
|
||||
#endif
|
||||
|
||||
static bool CV_BUFFER_AREA_OVERRIDE_SAFE_MODE =
|
||||
cv::utils::getConfigurationParameterBool("OPENCV_BUFFER_AREA_ALWAYS_SAFE", BUFFER_AREA_DEFAULT_MODE);
|
||||
|
||||
namespace cv { namespace utils {
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
class BufferArea::Block
|
||||
{
|
||||
private:
|
||||
inline size_t reserve_count() const
|
||||
{
|
||||
return alignment / type_size - 1;
|
||||
}
|
||||
public:
|
||||
Block(void **ptr_, ushort type_size_, size_t count_, ushort alignment_)
|
||||
: ptr(ptr_), raw_mem(0), count(count_), type_size(type_size_), alignment(alignment_)
|
||||
{
|
||||
CV_Assert(ptr && *ptr == NULL);
|
||||
}
|
||||
void cleanup() const
|
||||
{
|
||||
CV_Assert(ptr && *ptr);
|
||||
*ptr = 0;
|
||||
if (raw_mem)
|
||||
fastFree(raw_mem);
|
||||
}
|
||||
size_t getByteCount() const
|
||||
{
|
||||
return type_size * (count + reserve_count());
|
||||
}
|
||||
void real_allocate()
|
||||
{
|
||||
CV_Assert(ptr && *ptr == NULL);
|
||||
const size_t allocated_count = count + reserve_count();
|
||||
raw_mem = fastMalloc(type_size * allocated_count);
|
||||
if (alignment != type_size)
|
||||
{
|
||||
*ptr = alignPtr(raw_mem, alignment);
|
||||
CV_Assert(reinterpret_cast<size_t>(*ptr) % alignment == 0);
|
||||
CV_Assert(static_cast<uchar*>(*ptr) + type_size * count <= static_cast<uchar*>(raw_mem) + type_size * allocated_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr = raw_mem;
|
||||
}
|
||||
}
|
||||
void * fast_allocate(void * buf) const
|
||||
{
|
||||
CV_Assert(ptr && *ptr == NULL);
|
||||
buf = alignPtr(buf, alignment);
|
||||
CV_Assert(reinterpret_cast<size_t>(buf) % alignment == 0);
|
||||
*ptr = buf;
|
||||
return static_cast<void*>(static_cast<uchar*>(*ptr) + type_size * count);
|
||||
}
|
||||
private:
|
||||
void **ptr;
|
||||
void * raw_mem;
|
||||
size_t count;
|
||||
ushort type_size;
|
||||
ushort alignment;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
BufferArea::BufferArea(bool safe_) :
|
||||
oneBuf(0),
|
||||
totalSize(0),
|
||||
safe(safe_ || CV_BUFFER_AREA_OVERRIDE_SAFE_MODE)
|
||||
{
|
||||
}
|
||||
|
||||
BufferArea::~BufferArea()
|
||||
{
|
||||
for(std::vector<Block>::const_iterator i = blocks.begin(); i != blocks.end(); ++i)
|
||||
i->cleanup();
|
||||
if (oneBuf)
|
||||
fastFree(oneBuf);
|
||||
}
|
||||
|
||||
void BufferArea::allocate_(void **ptr, ushort type_size, size_t count, ushort alignment)
|
||||
{
|
||||
blocks.push_back(Block(ptr, type_size, count, alignment));
|
||||
if (safe)
|
||||
blocks.back().real_allocate();
|
||||
else
|
||||
totalSize += blocks.back().getByteCount();
|
||||
}
|
||||
|
||||
void BufferArea::commit()
|
||||
{
|
||||
if (!safe)
|
||||
{
|
||||
CV_Assert(totalSize > 0);
|
||||
CV_Assert(oneBuf == NULL);
|
||||
CV_Assert(!blocks.empty());
|
||||
oneBuf = fastMalloc(totalSize);
|
||||
void * ptr = oneBuf;
|
||||
for(std::vector<Block>::const_iterator i = blocks.begin(); i != blocks.end(); ++i)
|
||||
{
|
||||
ptr = i->fast_allocate(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
}} // cv::utils::
|
||||
+10
-16
@@ -563,12 +563,6 @@ Mat& Mat::setTo(InputArray _value, InputArray _mask)
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if CV_NEON && !defined(__aarch64__)
|
||||
#define CV_CHECK_ALIGNMENT 1
|
||||
#else
|
||||
#define CV_CHECK_ALIGNMENT 0
|
||||
#endif
|
||||
|
||||
#if CV_SIMD128
|
||||
template<typename V> CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
@@ -578,7 +572,7 @@ template<typename V> CV_ALWAYS_INLINE void flipHoriz_single( const uchar* src, s
|
||||
int width_1 = width & -v_uint8x16::nlanes;
|
||||
int i, j;
|
||||
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(T)>(src, dst));
|
||||
#endif
|
||||
|
||||
@@ -630,7 +624,7 @@ template<typename T1, typename T2> CV_ALWAYS_INLINE void flipHoriz_double( const
|
||||
int end = (int)(size.width*esz);
|
||||
int width = (end + 1)/2;
|
||||
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
CV_Assert(isAligned<sizeof(T1)>(src, dst));
|
||||
CV_Assert(isAligned<sizeof(T2)>(src, dst));
|
||||
#endif
|
||||
@@ -659,7 +653,7 @@ static void
|
||||
flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz )
|
||||
{
|
||||
#if CV_SIMD
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
size_t alignmentMark = ((size_t)src)|((size_t)dst)|sstep|dstep;
|
||||
#endif
|
||||
if (esz == 2 * v_uint8x16::nlanes)
|
||||
@@ -712,7 +706,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
}
|
||||
}
|
||||
else if (esz == 8
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(uint64)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
@@ -720,7 +714,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
flipHoriz_single<v_uint64x2>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 4
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(unsigned)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
@@ -728,7 +722,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
flipHoriz_single<v_uint32x4>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 2
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(ushort)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
@@ -740,7 +734,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
flipHoriz_single<v_uint8x16>(src, sstep, dst, dstep, size, esz);
|
||||
}
|
||||
else if (esz == 24
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
&& isAligned<sizeof(uint64_t)>(alignmentMark)
|
||||
#endif
|
||||
)
|
||||
@@ -766,7 +760,7 @@ flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size,
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !CV_CHECK_ALIGNMENT
|
||||
#if !CV_STRONG_ALIGNMENT
|
||||
else if (esz == 12)
|
||||
{
|
||||
flipHoriz_double<uint64_t,uint>(src, sstep, dst, dstep, size, esz);
|
||||
@@ -815,7 +809,7 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size,
|
||||
{
|
||||
int i = 0;
|
||||
#if CV_SIMD
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
if (isAligned<sizeof(int)>(src0, src1, dst0, dst1))
|
||||
#endif
|
||||
{
|
||||
@@ -827,7 +821,7 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size,
|
||||
vx_store((int*)(dst1 + i), t0);
|
||||
}
|
||||
}
|
||||
#if CV_CHECK_ALIGNMENT
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
else
|
||||
{
|
||||
for (; i <= size.width - CV_SIMD_WIDTH; i += CV_SIMD_WIDTH)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/core/utils/logger.hpp"
|
||||
#include "opencv2/core/utils/buffer_area.private.hpp"
|
||||
|
||||
#include "test_utils_tls.impl.hpp"
|
||||
|
||||
@@ -303,4 +304,132 @@ TEST(Samples, findFile_missing)
|
||||
cv::utils::logging::setLogLevel(prev);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool buffers_overlap(T * first, size_t first_num, T * second, size_t second_num)
|
||||
{
|
||||
// cerr << "[" << (void*)first << " : " << (void*)(first + first_num) << ")";
|
||||
// cerr << " X ";
|
||||
// cerr << "[" << (void*)second << " : " << (void*)(second + second_num) << ")";
|
||||
// cerr << endl;
|
||||
bool res = false;
|
||||
res |= (second <= first) && (first < second + second_num);
|
||||
res |= (second < first + first_num) && (first + first_num < second + second_num);
|
||||
return res;
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<bool> BufferArea;
|
||||
|
||||
TEST_P(BufferArea, basic)
|
||||
{
|
||||
const bool safe = GetParam();
|
||||
const size_t SZ = 3;
|
||||
int * int_ptr = NULL;
|
||||
uchar * uchar_ptr = NULL;
|
||||
double * dbl_ptr = NULL;
|
||||
{
|
||||
cv::utils::BufferArea area(safe);
|
||||
area.allocate(int_ptr, SZ);
|
||||
area.allocate(uchar_ptr, SZ);
|
||||
area.allocate(dbl_ptr, SZ);
|
||||
area.commit();
|
||||
ASSERT_TRUE(int_ptr != NULL);
|
||||
ASSERT_TRUE(uchar_ptr != NULL);
|
||||
ASSERT_TRUE(dbl_ptr != NULL);
|
||||
EXPECT_EQ((size_t)0, (size_t)int_ptr % sizeof(int));
|
||||
EXPECT_EQ((size_t)0, (size_t)dbl_ptr % sizeof(double));
|
||||
}
|
||||
EXPECT_TRUE(int_ptr == NULL);
|
||||
EXPECT_TRUE(uchar_ptr == NULL);
|
||||
EXPECT_TRUE(dbl_ptr == NULL);
|
||||
}
|
||||
|
||||
TEST_P(BufferArea, align)
|
||||
{
|
||||
const bool safe = GetParam();
|
||||
const size_t SZ = 3;
|
||||
const size_t CNT = 5;
|
||||
typedef int T;
|
||||
T * buffers[CNT] = {0};
|
||||
{
|
||||
cv::utils::BufferArea area(safe);
|
||||
// allocate buffers with 3 elements with growing alignment (power of two)
|
||||
for (size_t i = 0; i < CNT; ++i)
|
||||
{
|
||||
const ushort ALIGN = static_cast<ushort>(sizeof(T) << i);
|
||||
EXPECT_TRUE(buffers[i] == NULL);
|
||||
area.allocate(buffers[i], SZ, ALIGN);
|
||||
}
|
||||
area.commit();
|
||||
for (size_t i = 0; i < CNT; ++i)
|
||||
{
|
||||
const ushort ALIGN = static_cast<ushort>(sizeof(T) << i);
|
||||
EXPECT_TRUE(buffers[i] != NULL);
|
||||
EXPECT_EQ((size_t)0, reinterpret_cast<size_t>(buffers[i]) % ALIGN);
|
||||
if (i < CNT - 1)
|
||||
{
|
||||
SCOPED_TRACE(i);
|
||||
EXPECT_FALSE(buffers_overlap(buffers[i], SZ, buffers[i + 1], SZ))
|
||||
<< "Buffers overlap: "
|
||||
<< buffers[i] << " (" << SZ << " elems)"
|
||||
<< " and "
|
||||
<< buffers[i + 1] << " (" << SZ << " elems)"
|
||||
<< " (element size: " << sizeof(T) << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < CNT; ++i)
|
||||
{
|
||||
EXPECT_TRUE(buffers[i] == NULL);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(BufferArea, default_align)
|
||||
{
|
||||
const bool safe = GetParam();
|
||||
const size_t CNT = 100;
|
||||
const ushort ALIGN = 64;
|
||||
typedef int T;
|
||||
T * buffers[CNT] = {0};
|
||||
{
|
||||
cv::utils::BufferArea area(safe);
|
||||
// allocate buffers with 1-99 elements with default alignment
|
||||
for (size_t i = 0; i < CNT; ++ i)
|
||||
{
|
||||
EXPECT_TRUE(buffers[i] == NULL);
|
||||
area.allocate(buffers[i], i + 1, ALIGN);
|
||||
}
|
||||
area.commit();
|
||||
for (size_t i = 0; i < CNT; ++i)
|
||||
{
|
||||
EXPECT_TRUE(buffers[i] != NULL);
|
||||
EXPECT_EQ((size_t)0, reinterpret_cast<size_t>(buffers[i]) % ALIGN);
|
||||
if (i < CNT - 1)
|
||||
{
|
||||
SCOPED_TRACE(i);
|
||||
EXPECT_FALSE(buffers_overlap(buffers[i], i + 1, buffers[i + 1], i + 2))
|
||||
<< "Buffers overlap: "
|
||||
<< buffers[i] << " (" << i + 1 << " elems)"
|
||||
<< " and "
|
||||
<< buffers[i + 1] << " (" << i + 2 << " elems)"
|
||||
<< " (element size: " << sizeof(T) << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(BufferArea, bad)
|
||||
{
|
||||
const bool safe = GetParam();
|
||||
int * ptr = 0;
|
||||
cv::utils::BufferArea area(safe);
|
||||
EXPECT_ANY_THROW(area.allocate(ptr, 0)); // bad size
|
||||
EXPECT_ANY_THROW(area.allocate(ptr, 1, 0)); // bad alignment
|
||||
EXPECT_ANY_THROW(area.allocate(ptr, 1, 3)); // bad alignment
|
||||
ptr = (int*)1;
|
||||
EXPECT_ANY_THROW(area.allocate(ptr, 1)); // non-zero pointer
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, BufferArea, testing::Values(true, false));
|
||||
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
//M*/
|
||||
|
||||
#include "../precomp.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
@@ -109,6 +110,26 @@ namespace cv {
|
||||
params.blobs = blobs;
|
||||
}
|
||||
|
||||
void setBatchNorm()
|
||||
{
|
||||
cv::dnn::LayerParams bn_param;
|
||||
|
||||
bn_param.name = "BatchNorm-name";
|
||||
bn_param.type = "BatchNorm";
|
||||
bn_param.set<bool>("has_weight", true);
|
||||
bn_param.set<bool>("has_bias", true);
|
||||
bn_param.set<float>("eps", 1E-6); // .000001f in Darknet Yolo
|
||||
|
||||
darknet::LayerParameter lp;
|
||||
std::string layer_name = cv::format("bn_%d", layer_id);
|
||||
lp.layer_name = layer_name;
|
||||
lp.layer_type = bn_param.type;
|
||||
lp.layerParams = bn_param;
|
||||
lp.bottom_indexes.push_back(last_layer);
|
||||
last_layer = layer_name;
|
||||
net->layers.push_back(lp);
|
||||
}
|
||||
|
||||
cv::dnn::LayerParams getParamConvolution(int kernel, int pad,
|
||||
int stride, int filters_num)
|
||||
{
|
||||
@@ -149,25 +170,47 @@ namespace cv {
|
||||
net->layers.push_back(lp);
|
||||
|
||||
if (use_batch_normalize)
|
||||
{
|
||||
cv::dnn::LayerParams bn_param;
|
||||
setBatchNorm();
|
||||
|
||||
bn_param.name = "BatchNorm-name";
|
||||
bn_param.type = "BatchNorm";
|
||||
bn_param.set<bool>("has_weight", true);
|
||||
bn_param.set<bool>("has_bias", true);
|
||||
bn_param.set<float>("eps", 1E-6); // .000001f in Darknet Yolo
|
||||
layer_id++;
|
||||
fused_layer_names.push_back(last_layer);
|
||||
}
|
||||
|
||||
darknet::LayerParameter lp;
|
||||
std::string layer_name = cv::format("bn_%d", layer_id);
|
||||
lp.layer_name = layer_name;
|
||||
lp.layer_type = bn_param.type;
|
||||
lp.layerParams = bn_param;
|
||||
lp.bottom_indexes.push_back(last_layer);
|
||||
last_layer = layer_name;
|
||||
net->layers.push_back(lp);
|
||||
cv::dnn::LayerParams getParamFullyConnected(int output)
|
||||
{
|
||||
cv::dnn::LayerParams params;
|
||||
params.name = "FullyConnected-name";
|
||||
params.type = "InnerProduct";
|
||||
|
||||
params.set<bool>("bias_term", false); // true only if(BatchNorm == false)
|
||||
params.set<int>("num_output", output);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
void setFullyConnected(int output, int use_batch_normalize)
|
||||
{
|
||||
cv::dnn::LayerParams fullyconnected_param =
|
||||
getParamFullyConnected(output);
|
||||
|
||||
darknet::LayerParameter lp;
|
||||
std::string layer_name = cv::format("fullyConnected_%d", layer_id);
|
||||
|
||||
// use BIAS in any case
|
||||
if (!use_batch_normalize) {
|
||||
fullyconnected_param.set<bool>("bias_term", true);
|
||||
}
|
||||
|
||||
lp.layer_name = layer_name;
|
||||
lp.layer_type = fullyconnected_param.type;
|
||||
lp.layerParams = fullyconnected_param;
|
||||
lp.bottom_indexes.push_back(last_layer);
|
||||
last_layer = layer_name;
|
||||
net->layers.push_back(lp);
|
||||
|
||||
if (use_batch_normalize)
|
||||
setBatchNorm();
|
||||
|
||||
layer_id++;
|
||||
fused_layer_names.push_back(last_layer);
|
||||
}
|
||||
@@ -191,18 +234,21 @@ namespace cv {
|
||||
fused_layer_names.back() = last_layer;
|
||||
}
|
||||
|
||||
void setMaxpool(size_t kernel, size_t pad, size_t stride)
|
||||
void setMaxpool(int kernel, int pad, int stride)
|
||||
{
|
||||
cv::dnn::LayerParams maxpool_param;
|
||||
maxpool_param.set<cv::String>("pool", "max");
|
||||
maxpool_param.set<int>("kernel_size", kernel);
|
||||
maxpool_param.set<int>("pad", pad);
|
||||
maxpool_param.set<int>("pad_l", floor((float)pad / 2));
|
||||
maxpool_param.set<int>("pad_r", ceil((float)pad / 2));
|
||||
maxpool_param.set<int>("pad_t", floor((float)pad / 2));
|
||||
maxpool_param.set<int>("pad_b", ceil((float)pad / 2));
|
||||
maxpool_param.set<bool>("ceil_mode", false);
|
||||
maxpool_param.set<int>("stride", stride);
|
||||
maxpool_param.set<cv::String>("pad_mode", "SAME");
|
||||
maxpool_param.name = "Pooling-name";
|
||||
maxpool_param.type = "Pooling";
|
||||
darknet::LayerParameter lp;
|
||||
|
||||
darknet::LayerParameter lp;
|
||||
std::string layer_name = cv::format("pool_%d", layer_id);
|
||||
lp.layer_name = layer_name;
|
||||
lp.layer_type = maxpool_param.type;
|
||||
@@ -539,7 +585,10 @@ namespace cv {
|
||||
net->channels = getParam(net_params, "channels", 3);
|
||||
CV_Assert(net->width > 0 && net->height > 0 && net->channels > 0);
|
||||
|
||||
int current_channels = net->channels;
|
||||
MatShape tensor_shape(3);
|
||||
tensor_shape[0] = net->channels;
|
||||
tensor_shape[1] = net->width;
|
||||
tensor_shape[2] = net->height;
|
||||
net->out_channels_vec.resize(net->layers_cfg.size());
|
||||
|
||||
layers_counter = -1;
|
||||
@@ -568,23 +617,46 @@ namespace cv {
|
||||
padding = kernel_size / 2;
|
||||
|
||||
CV_Assert(kernel_size > 0 && filters > 0);
|
||||
CV_Assert(current_channels > 0);
|
||||
CV_Assert(tensor_shape[0] > 0);
|
||||
|
||||
setParams.setConvolution(kernel_size, padding, stride, filters, current_channels,
|
||||
setParams.setConvolution(kernel_size, padding, stride, filters, tensor_shape[0],
|
||||
batch_normalize);
|
||||
|
||||
current_channels = filters;
|
||||
tensor_shape[0] = filters;
|
||||
tensor_shape[1] = (tensor_shape[1] - kernel_size + 2 * padding) / stride + 1;
|
||||
tensor_shape[2] = (tensor_shape[2] - kernel_size + 2 * padding) / stride + 1;
|
||||
}
|
||||
else if (layer_type == "connected")
|
||||
{
|
||||
int output = getParam<int>(layer_params, "output", 1);
|
||||
bool batch_normalize = getParam<int>(layer_params, "batch_normalize", 0) == 1;
|
||||
|
||||
CV_Assert(output > 0);
|
||||
|
||||
setParams.setFullyConnected(output, batch_normalize);
|
||||
|
||||
if(layers_counter && tensor_shape[1] > 1)
|
||||
net->out_channels_vec[layers_counter-1] = total(tensor_shape);
|
||||
|
||||
tensor_shape[0] = output;
|
||||
tensor_shape[1] = 1;
|
||||
tensor_shape[2] = 1;
|
||||
}
|
||||
else if (layer_type == "maxpool")
|
||||
{
|
||||
int kernel_size = getParam<int>(layer_params, "size", 2);
|
||||
int stride = getParam<int>(layer_params, "stride", 2);
|
||||
int pad = getParam<int>(layer_params, "pad", 0);
|
||||
setParams.setMaxpool(kernel_size, pad, stride);
|
||||
int padding = getParam<int>(layer_params, "padding", kernel_size - 1);
|
||||
setParams.setMaxpool(kernel_size, padding, stride);
|
||||
|
||||
tensor_shape[1] = (tensor_shape[1] - kernel_size + padding) / stride + 1;
|
||||
tensor_shape[2] = (tensor_shape[2] - kernel_size + padding) / stride + 1;
|
||||
}
|
||||
else if (layer_type == "avgpool")
|
||||
{
|
||||
setParams.setAvgpool();
|
||||
tensor_shape[1] = 1;
|
||||
tensor_shape[2] = 1;
|
||||
}
|
||||
else if (layer_type == "softmax")
|
||||
{
|
||||
@@ -599,10 +671,10 @@ namespace cv {
|
||||
CV_Assert(!bottom_layers.empty());
|
||||
std::vector<int> layers_vec = getNumbers<int>(bottom_layers);
|
||||
|
||||
current_channels = 0;
|
||||
tensor_shape[0] = 0;
|
||||
for (size_t k = 0; k < layers_vec.size(); ++k) {
|
||||
layers_vec[k] = layers_vec[k] >= 0 ? layers_vec[k] : (layers_vec[k] + layers_counter);
|
||||
current_channels += net->out_channels_vec[layers_vec[k]];
|
||||
tensor_shape[0] += net->out_channels_vec[layers_vec[k]];
|
||||
}
|
||||
|
||||
if (layers_vec.size() == 1)
|
||||
@@ -610,10 +682,16 @@ namespace cv {
|
||||
else
|
||||
setParams.setConcat(layers_vec.size(), layers_vec.data());
|
||||
}
|
||||
else if (layer_type == "dropout")
|
||||
{
|
||||
setParams.setIdentity(layers_counter-1);
|
||||
}
|
||||
else if (layer_type == "reorg")
|
||||
{
|
||||
int stride = getParam<int>(layer_params, "stride", 2);
|
||||
current_channels = current_channels * (stride*stride);
|
||||
tensor_shape[0] = tensor_shape[0] * (stride * stride);
|
||||
tensor_shape[1] = tensor_shape[1] / stride;
|
||||
tensor_shape[2] = tensor_shape[2] / stride;
|
||||
|
||||
setParams.setReorg(stride);
|
||||
}
|
||||
@@ -653,6 +731,8 @@ namespace cv {
|
||||
{
|
||||
int scaleFactor = getParam<int>(layer_params, "stride", 1);
|
||||
setParams.setUpsample(scaleFactor);
|
||||
tensor_shape[1] = tensor_shape[1] * scaleFactor;
|
||||
tensor_shape[2] = tensor_shape[2] * scaleFactor;
|
||||
}
|
||||
else if (layer_type == "yolo")
|
||||
{
|
||||
@@ -686,7 +766,7 @@ namespace cv {
|
||||
else if (activation != "linear")
|
||||
CV_Error(cv::Error::StsParseError, "Unsupported activation: " + activation);
|
||||
|
||||
net->out_channels_vec[layers_counter] = current_channels;
|
||||
net->out_channels_vec[layers_counter] = tensor_shape[0];
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -712,7 +792,10 @@ namespace cv {
|
||||
if(transpose)
|
||||
CV_Error(cv::Error::StsNotImplemented, "Transpose the weights (except for convolutional) is not implemented");
|
||||
|
||||
int current_channels = net->channels;
|
||||
MatShape tensor_shape(3);
|
||||
tensor_shape[0] = net->channels;
|
||||
tensor_shape[1] = net->width;
|
||||
tensor_shape[2] = net->height;
|
||||
int cv_layers_counter = -1;
|
||||
int darknet_layers_counter = -1;
|
||||
|
||||
@@ -725,19 +808,36 @@ namespace cv {
|
||||
std::map<std::string, std::string> &layer_params = i->second;
|
||||
std::string layer_type = layer_params["type"];
|
||||
|
||||
if (layer_type == "convolutional")
|
||||
if (layer_type == "convolutional" || layer_type == "connected")
|
||||
{
|
||||
int kernel_size = getParam<int>(layer_params, "size", -1);
|
||||
int filters = getParam<int>(layer_params, "filters", -1);
|
||||
bool use_batch_normalize = getParam<int>(layer_params, "batch_normalize", 0) == 1;
|
||||
|
||||
CV_Assert(kernel_size > 0 && filters > 0);
|
||||
CV_Assert(current_channels > 0);
|
||||
|
||||
size_t const weights_size = filters * current_channels * kernel_size * kernel_size;
|
||||
int sizes_weights[] = { filters, current_channels, kernel_size, kernel_size };
|
||||
size_t weights_size;
|
||||
int filters;
|
||||
bool use_batch_normalize;
|
||||
cv::Mat weightsBlob;
|
||||
weightsBlob.create(4, sizes_weights, CV_32F);
|
||||
if(layer_type == "convolutional")
|
||||
{
|
||||
int kernel_size = getParam<int>(layer_params, "size", -1);
|
||||
filters = getParam<int>(layer_params, "filters", -1);
|
||||
use_batch_normalize = getParam<int>(layer_params, "batch_normalize", 0) == 1;
|
||||
|
||||
CV_Assert(kernel_size > 0 && filters > 0);
|
||||
CV_Assert(tensor_shape[0] > 0);
|
||||
|
||||
weights_size = filters * tensor_shape[0] * kernel_size * kernel_size;
|
||||
int sizes_weights[] = { filters, tensor_shape[0], kernel_size, kernel_size };
|
||||
weightsBlob.create(4, sizes_weights, CV_32F);
|
||||
}
|
||||
else
|
||||
{
|
||||
filters = getParam<int>(layer_params, "output", 1);
|
||||
use_batch_normalize = getParam<int>(layer_params, "batch_normalize", 0) == 1;
|
||||
|
||||
CV_Assert(filters>0);
|
||||
|
||||
weights_size = total(tensor_shape) * filters;
|
||||
int sizes_weights[] = { filters, total(tensor_shape) };
|
||||
weightsBlob.create(2, sizes_weights, CV_32F);
|
||||
}
|
||||
CV_Assert(weightsBlob.isContinuous());
|
||||
|
||||
cv::Mat meanData_mat(1, filters, CV_32F); // mean
|
||||
@@ -753,14 +853,14 @@ namespace cv {
|
||||
}
|
||||
ifile.read(reinterpret_cast<char *>(weightsBlob.ptr<float>()), sizeof(float)*weights_size);
|
||||
|
||||
// set convolutional weights
|
||||
std::vector<cv::Mat> conv_blobs;
|
||||
conv_blobs.push_back(weightsBlob);
|
||||
// set conv/connected weights
|
||||
std::vector<cv::Mat> layer_blobs;
|
||||
layer_blobs.push_back(weightsBlob);
|
||||
if (!use_batch_normalize) {
|
||||
// use BIAS in any case
|
||||
conv_blobs.push_back(biasData_mat);
|
||||
layer_blobs.push_back(biasData_mat);
|
||||
}
|
||||
setParams.setLayerBlobs(cv_layers_counter, conv_blobs);
|
||||
setParams.setLayerBlobs(cv_layers_counter, layer_blobs);
|
||||
|
||||
// set batch normalize (mean, variance, scale, bias)
|
||||
if (use_batch_normalize) {
|
||||
@@ -782,7 +882,10 @@ namespace cv {
|
||||
if(activation == "leaky")
|
||||
++cv_layers_counter; // For ReLU
|
||||
|
||||
current_channels = net->out_channels_vec[darknet_layers_counter];
|
||||
if(!darknet_layers_counter)
|
||||
tensor_shape.resize(1);
|
||||
|
||||
tensor_shape[0] = net->out_channels_vec[darknet_layers_counter];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,15 @@
|
||||
|
||||
#ifdef HAVE_DNN_NGRAPH
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4245)
|
||||
#pragma warning(disable : 4268)
|
||||
#endif
|
||||
#include <ngraph/ngraph.hpp>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // HAVE_DNN_NGRAPH
|
||||
|
||||
|
||||
@@ -148,6 +148,7 @@ Mat getMatFromTensor(opencv_onnx::TensorProto& tensor_proto)
|
||||
else
|
||||
{
|
||||
const char* val = tensor_proto.raw_data().c_str();
|
||||
#if CV_STRONG_ALIGNMENT
|
||||
// Aligned pointer is required: https://github.com/opencv/opencv/issues/16373
|
||||
// this doesn't work: typedef int64_t CV_DECL_ALIGNED(1) unaligned_int64_t;
|
||||
AutoBuffer<int64_t, 16> aligned_val;
|
||||
@@ -158,6 +159,7 @@ Mat getMatFromTensor(opencv_onnx::TensorProto& tensor_proto)
|
||||
memcpy(aligned_val.data(), val, sz);
|
||||
val = (const char*)aligned_val.data();
|
||||
}
|
||||
#endif
|
||||
const int64_t* src = reinterpret_cast<const int64_t*>(val);
|
||||
convertInt64ToInt32(src, dst, blob.total());
|
||||
}
|
||||
|
||||
@@ -1468,6 +1468,8 @@ void TFImporter::populateNet(Net dstNet)
|
||||
int end_mask = getLayerAttr(layer, "end_mask").i();
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
if (ends.at<int>(i) < 0)
|
||||
ends.at<int>(i) -= 1;
|
||||
if (end_mask & (1 << i))
|
||||
ends.at<int>(i) = -1;
|
||||
if (strides.at<int>(i) != 1)
|
||||
|
||||
@@ -486,7 +486,9 @@ TEST_P(DNNTestNetwork, FastNeuralStyle_eccv16)
|
||||
if (backend == DNN_BACKEND_HALIDE)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_HALIDE);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
#if defined(INF_ENGINE_RELEASE)
|
||||
#if INF_ENGINE_VER_MAJOR_LE(2018050000)
|
||||
|
||||
@@ -330,7 +330,9 @@ TEST_P(Reproducibility_MobileNet_SSD, Accuracy)
|
||||
}
|
||||
|
||||
// There is something wrong with Reshape layer in Myriad plugin.
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019
|
||||
|| backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH
|
||||
)
|
||||
{
|
||||
if (targetId == DNN_TARGET_MYRIAD || targetId == DNN_TARGET_OPENCL_FP16)
|
||||
return;
|
||||
@@ -675,7 +677,10 @@ TEST_P(Test_Caffe_nets, FasterRCNN_vgg16)
|
||||
if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16);
|
||||
|
||||
if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && target == DNN_TARGET_MYRIAD)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -460,6 +460,9 @@ TEST_P(Test_Darknet_nets, YOLOv3)
|
||||
{
|
||||
applyTestTag(CV_TEST_TAG_LONG, (target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_1GB : CV_TEST_TAG_MEMORY_2GB));
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
// batchId, classId, confidence, left, top, right, bottom
|
||||
Mat ref = (Mat_<float>(9, 7) << 0, 7, 0.952983f, 0.614622f, 0.150257f, 0.901369f, 0.289251f, // a truck
|
||||
0, 1, 0.987908f, 0.150913f, 0.221933f, 0.742255f, 0.74626f, // a bicycle
|
||||
@@ -554,6 +557,11 @@ TEST_P(Test_Darknet_layers, reorg)
|
||||
testDarknetLayer("reorg");
|
||||
}
|
||||
|
||||
TEST_P(Test_Darknet_layers, maxpool)
|
||||
{
|
||||
testDarknetLayer("maxpool");
|
||||
}
|
||||
|
||||
TEST_P(Test_Darknet_layers, convolutional)
|
||||
{
|
||||
if (target == DNN_TARGET_MYRIAD)
|
||||
@@ -563,6 +571,13 @@ TEST_P(Test_Darknet_layers, convolutional)
|
||||
testDarknetLayer("convolutional", true);
|
||||
}
|
||||
|
||||
TEST_P(Test_Darknet_layers, connected)
|
||||
{
|
||||
if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
|
||||
testDarknetLayer("connected", true);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_layers, dnnBackendsAndTargets());
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -503,6 +503,9 @@ TEST_P(Async, create_layer_pipeline_set_and_forward_all)
|
||||
if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
throw SkipTestException("No support for async forward");
|
||||
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
setInferenceEngineBackendType(CV_DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_API);
|
||||
else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
|
||||
@@ -196,20 +196,58 @@ TEST_P(Test_TensorFlow_layers, concat_axis_1)
|
||||
runTensorFlowNet("concat_axis_1");
|
||||
}
|
||||
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm)
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_1)
|
||||
{
|
||||
runTensorFlowNet("batch_norm");
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_2)
|
||||
{
|
||||
runTensorFlowNet("batch_norm", false, 0.0, 0.0, true);
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_3)
|
||||
{
|
||||
runTensorFlowNet("fused_batch_norm");
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_4)
|
||||
{
|
||||
runTensorFlowNet("fused_batch_norm", false, 0.0, 0.0, true);
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_5)
|
||||
{
|
||||
runTensorFlowNet("batch_norm_text", true);
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_6)
|
||||
{
|
||||
runTensorFlowNet("batch_norm_text", true, 0.0, 0.0, true);
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_7)
|
||||
{
|
||||
runTensorFlowNet("unfused_batch_norm");
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_8)
|
||||
{
|
||||
runTensorFlowNet("fused_batch_norm_no_gamma");
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_9)
|
||||
{
|
||||
runTensorFlowNet("unfused_batch_norm_no_gamma");
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_10)
|
||||
{
|
||||
runTensorFlowNet("mvn_batch_norm");
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_11)
|
||||
{
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
runTensorFlowNet("mvn_batch_norm_1x1");
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_12)
|
||||
{
|
||||
runTensorFlowNet("switch_identity");
|
||||
}
|
||||
TEST_P(Test_TensorFlow_layers, batch_norm_13)
|
||||
{
|
||||
runTensorFlowNet("keras_batch_norm_training");
|
||||
}
|
||||
|
||||
@@ -431,6 +469,8 @@ TEST_P(Test_TensorFlow_nets, MobileNet_SSD)
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NGRAPH,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -703,10 +743,15 @@ TEST_P(Test_TensorFlow_nets, EAST_text_detection)
|
||||
#if defined(INF_ENGINE_RELEASE)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL_FP16 &&
|
||||
INF_ENGINE_VER_MAJOR_EQ(2019020000))
|
||||
(INF_ENGINE_VER_MAJOR_EQ(2019020000) || INF_ENGINE_VER_MAJOR_GE(2020010000))
|
||||
)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
checkBackend();
|
||||
@@ -843,6 +888,8 @@ TEST_P(Test_TensorFlow_layers, slice)
|
||||
(target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
|
||||
applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
|
||||
CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
double l1 = target == DNN_TARGET_MYRIAD ? 4.9e-3 : default_l1;
|
||||
runTensorFlowNet("crop2d", false, l1);
|
||||
runTensorFlowNet("slice_4d");
|
||||
runTensorFlowNet("strided_slice");
|
||||
}
|
||||
|
||||
@@ -229,9 +229,14 @@ TEST_P(Test_Torch_layers, net_logsoftmax)
|
||||
runTorchNet("net_logsoftmax_spatial");
|
||||
}
|
||||
|
||||
TEST_P(Test_Torch_layers, net_lp_pooling)
|
||||
TEST_P(Test_Torch_layers, net_lp_pooling_square)
|
||||
{
|
||||
runTorchNet("net_lp_pooling_square", "", false, true);
|
||||
}
|
||||
TEST_P(Test_Torch_layers, net_lp_pooling_power)
|
||||
{
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
runTorchNet("net_lp_pooling_power", "", false, true);
|
||||
}
|
||||
|
||||
@@ -393,6 +398,10 @@ TEST_P(Test_Torch_nets, ENet_accuracy)
|
||||
throw SkipTestException("");
|
||||
if (backend == DNN_BACKEND_CUDA && target == DNN_TARGET_CUDA_FP16)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16);
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2020010000)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#else
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
|
||||
{
|
||||
if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
@@ -400,12 +409,10 @@ TEST_P(Test_Torch_nets, ENet_accuracy)
|
||||
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
throw SkipTestException("");
|
||||
}
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
|
||||
#endif
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
|
||||
{
|
||||
if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
throw SkipTestException("");
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
}
|
||||
|
||||
Net net;
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace cv
|
||||
|
||||
//! Imread flags
|
||||
enum ImreadModes {
|
||||
IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).
|
||||
IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). Ignore EXIF orientation.
|
||||
IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image (codec internal conversion).
|
||||
IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image.
|
||||
IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
|
||||
@@ -172,8 +172,9 @@ Currently, the following file formats are supported:
|
||||
then the [GDAL](http://www.gdal.org) driver will be used in order to decode the image, supporting
|
||||
the following formats: [Raster](http://www.gdal.org/formats_list.html),
|
||||
[Vector](http://www.gdal.org/ogr_formats.html).
|
||||
- If EXIF information are embedded in the image file, the EXIF orientation will be taken into account
|
||||
and thus the image will be rotated accordingly except if the flag @ref IMREAD_IGNORE_ORIENTATION is passed.
|
||||
- If EXIF information is embedded in the image file, the EXIF orientation will be taken into account
|
||||
and thus the image will be rotated accordingly except if the flags @ref IMREAD_IGNORE_ORIENTATION
|
||||
or @ref IMREAD_UNCHANGED are passed.
|
||||
- Use the IMREAD_UNCHANGED flag to keep the floating point values from PFM image.
|
||||
- By default number of pixels must be less than 2^30. Limit can be set using system
|
||||
variable OPENCV_IO_MAX_IMAGE_PIXELS
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
#undef max
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cerrno>
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
|
||||
|
||||
@@ -693,6 +695,23 @@ static bool imwrite_( const String& filename, const std::vector<Mat>& img_vec,
|
||||
code = encoder->write( write_vec[0], params );
|
||||
else
|
||||
code = encoder->writemulti( write_vec, params ); //to be implemented
|
||||
|
||||
if (!code)
|
||||
{
|
||||
FILE* f = fopen( filename.c_str(), "wb" );
|
||||
if ( !f )
|
||||
{
|
||||
if (errno == EACCES)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "imwrite_('" << filename << "'): can't open file for writing: permission denied");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(f);
|
||||
remove(filename.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
{
|
||||
|
||||
@@ -982,6 +982,14 @@ PyObject* pyopencv_from(const String& value)
|
||||
return PyString_FromString(value.empty() ? "" : value.c_str());
|
||||
}
|
||||
|
||||
#if CV_VERSION_MAJOR == 3
|
||||
template<>
|
||||
PyObject* pyopencv_from(const std::string& value)
|
||||
{
|
||||
return PyString_FromString(value.empty() ? "" : value.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject* obj, String &value, const ArgInfo& info)
|
||||
{
|
||||
|
||||
@@ -146,7 +146,8 @@ enum VideoCaptureProperties {
|
||||
CAP_PROP_HUE =13, //!< Hue of the image (only for cameras).
|
||||
CAP_PROP_GAIN =14, //!< Gain of the image (only for those cameras that support).
|
||||
CAP_PROP_EXPOSURE =15, //!< Exposure (only for those cameras that support).
|
||||
CAP_PROP_CONVERT_RGB =16, //!< Boolean flags indicating whether images should be converted to RGB.
|
||||
CAP_PROP_CONVERT_RGB =16, //!< Boolean flags indicating whether images should be converted to RGB. <br/>
|
||||
//!< *GStreamer note*: The flag is ignored in case if custom pipeline is used. It's user responsibility to interpret pipeline output.
|
||||
CAP_PROP_WHITE_BALANCE_BLUE_U =17, //!< Currently unsupported.
|
||||
CAP_PROP_RECTIFICATION =18, //!< Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently).
|
||||
CAP_PROP_MONOCHROME =19,
|
||||
@@ -631,7 +632,8 @@ public:
|
||||
@param filename it can be:
|
||||
- name of video file (eg. `video.avi`)
|
||||
- or image sequence (eg. `img_%02d.jpg`, which will read samples like `img_00.jpg, img_01.jpg, img_02.jpg, ...`)
|
||||
- or URL of video stream (eg. `protocol://host:port/script_name?script_params|auth`).
|
||||
- or URL of video stream (eg. `protocol://host:port/script_name?script_params|auth`)
|
||||
- or GStreamer pipeline string in gst-launch tool format in case if GStreamer is used as backend
|
||||
Note that each video stream or IP camera feed has its own URL scheme. Please refer to the
|
||||
documentation of source stream to know the right URL.
|
||||
@param apiPreference preferred Capture API backends to use. Can be used to enforce a specific reader
|
||||
|
||||
+627
-1131
@@ -1,43 +1,7 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
|
||||
#include "precomp.hpp"
|
||||
#if defined _WIN32 && defined HAVE_MSMF
|
||||
/*
|
||||
@@ -181,41 +145,156 @@ private:
|
||||
|
||||
#define _ComPtr ComPtr
|
||||
|
||||
// Structure for collecting info about types of video, which are supported by current video device
|
||||
template <typename T> inline T absDiff(T a, T b) { return a >= b ? a - b : b - a; }
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
// Structure for collecting info about types of video which are supported by current video device
|
||||
struct MediaType
|
||||
{
|
||||
unsigned int MF_MT_FRAME_SIZE;
|
||||
UINT32 height;
|
||||
UINT32 width;
|
||||
unsigned int MF_MT_YUV_MATRIX;
|
||||
unsigned int MF_MT_VIDEO_LIGHTING;
|
||||
int MF_MT_DEFAULT_STRIDE; // stride is negative if image is bottom-up
|
||||
unsigned int MF_MT_VIDEO_CHROMA_SITING;
|
||||
GUID MF_MT_AM_FORMAT_TYPE;
|
||||
unsigned int MF_MT_FIXED_SIZE_SAMPLES;
|
||||
unsigned int MF_MT_VIDEO_NOMINAL_RANGE;
|
||||
UINT32 MF_MT_FRAME_RATE_NUMERATOR;
|
||||
UINT32 MF_MT_FRAME_RATE_DENOMINATOR;
|
||||
UINT32 MF_MT_PIXEL_ASPECT_RATIO_NUMERATOR;
|
||||
UINT32 MF_MT_PIXEL_ASPECT_RATIO_DENOMINATOR;
|
||||
unsigned int MF_MT_ALL_SAMPLES_INDEPENDENT;
|
||||
UINT32 MF_MT_FRAME_RATE_RANGE_MIN_NUMERATOR;
|
||||
UINT32 MF_MT_FRAME_RATE_RANGE_MIN_DENOMINATOR;
|
||||
unsigned int MF_MT_SAMPLE_SIZE;
|
||||
unsigned int MF_MT_VIDEO_PRIMARIES;
|
||||
unsigned int MF_MT_INTERLACE_MODE;
|
||||
UINT32 MF_MT_FRAME_RATE_RANGE_MAX_NUMERATOR;
|
||||
UINT32 MF_MT_FRAME_RATE_RANGE_MAX_DENOMINATOR;
|
||||
GUID MF_MT_MAJOR_TYPE;
|
||||
GUID MF_MT_SUBTYPE;
|
||||
LPCWSTR pMF_MT_MAJOR_TYPEName;
|
||||
LPCWSTR pMF_MT_SUBTYPEName;
|
||||
MediaType();
|
||||
MediaType(IMFMediaType *pType);
|
||||
~MediaType();
|
||||
void Clear();
|
||||
UINT32 height;
|
||||
INT32 stride; // stride is negative if image is bottom-up
|
||||
UINT32 isFixedSize;
|
||||
UINT32 frameRateNum;
|
||||
UINT32 frameRateDenom;
|
||||
UINT32 aspectRatioNum;
|
||||
UINT32 aspectRatioDenom;
|
||||
UINT32 sampleSize;
|
||||
UINT32 interlaceMode;
|
||||
GUID majorType; // video or audio
|
||||
GUID subType; // fourCC
|
||||
MediaType(IMFMediaType *pType = 0) :
|
||||
width(0), height(0),
|
||||
stride(0),
|
||||
isFixedSize(true),
|
||||
frameRateNum(1), frameRateDenom(1),
|
||||
aspectRatioNum(1), aspectRatioDenom(1),
|
||||
sampleSize(0),
|
||||
interlaceMode(0),
|
||||
majorType(MFMediaType_Video),
|
||||
subType({ 0 })
|
||||
{
|
||||
if (pType)
|
||||
{
|
||||
MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &width, &height);
|
||||
pType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&stride); // value is stored as UINT32 but should be casted to INT3)
|
||||
pType->GetUINT32(MF_MT_FIXED_SIZE_SAMPLES, &isFixedSize);
|
||||
MFGetAttributeRatio(pType, MF_MT_FRAME_RATE, &frameRateNum, &frameRateDenom);
|
||||
MFGetAttributeRatio(pType, MF_MT_PIXEL_ASPECT_RATIO, &aspectRatioNum, &aspectRatioDenom);
|
||||
pType->GetUINT32(MF_MT_SAMPLE_SIZE, &sampleSize);
|
||||
pType->GetUINT32(MF_MT_INTERLACE_MODE, &interlaceMode);
|
||||
pType->GetGUID(MF_MT_MAJOR_TYPE, &majorType);
|
||||
pType->GetGUID(MF_MT_SUBTYPE, &subType);
|
||||
}
|
||||
}
|
||||
static MediaType createDefault()
|
||||
{
|
||||
MediaType res;
|
||||
res.width = 640;
|
||||
res.height = 480;
|
||||
res.setFramerate(30.0);
|
||||
return res;
|
||||
}
|
||||
inline bool isEmpty() const
|
||||
{
|
||||
return width == 0 && height == 0;
|
||||
}
|
||||
_ComPtr<IMFMediaType> createMediaType() const
|
||||
{
|
||||
_ComPtr<IMFMediaType> res;
|
||||
MFCreateMediaType(&res);
|
||||
if (width != 0 || height != 0)
|
||||
MFSetAttributeSize(res.Get(), MF_MT_FRAME_SIZE, width, height);
|
||||
if (stride != 0)
|
||||
res->SetUINT32(MF_MT_DEFAULT_STRIDE, stride);
|
||||
res->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, isFixedSize);
|
||||
if (frameRateNum != 0 || frameRateDenom != 0)
|
||||
MFSetAttributeRatio(res.Get(), MF_MT_FRAME_RATE, frameRateNum, frameRateDenom);
|
||||
if (aspectRatioNum != 0 || aspectRatioDenom != 0)
|
||||
MFSetAttributeRatio(res.Get(), MF_MT_PIXEL_ASPECT_RATIO, aspectRatioNum, aspectRatioDenom);
|
||||
if (sampleSize > 0)
|
||||
res->SetUINT32(MF_MT_SAMPLE_SIZE, sampleSize);
|
||||
res->SetUINT32(MF_MT_INTERLACE_MODE, interlaceMode);
|
||||
if (majorType != GUID())
|
||||
res->SetGUID(MF_MT_MAJOR_TYPE, majorType);
|
||||
if (subType != GUID())
|
||||
res->SetGUID(MF_MT_SUBTYPE, subType);
|
||||
return res;
|
||||
}
|
||||
void setFramerate(double fps)
|
||||
{
|
||||
frameRateNum = (UINT32)cvRound(fps * 1000.0);
|
||||
frameRateDenom = 1000;
|
||||
}
|
||||
double getFramerate() const
|
||||
{
|
||||
return frameRateDenom != 0 ? ((double)frameRateNum) / ((double)frameRateDenom) : 0;
|
||||
}
|
||||
LONGLONG getFrameStep() const
|
||||
{
|
||||
const double fps = getFramerate();
|
||||
return (LONGLONG)(fps > 0 ? 1e7 / fps : 0);
|
||||
}
|
||||
inline unsigned long resolutionDiff(const MediaType& other) const
|
||||
{
|
||||
const unsigned long wdiff = absDiff(width, other.width);
|
||||
const unsigned long hdiff = absDiff(height, other.height);
|
||||
return wdiff + hdiff;
|
||||
}
|
||||
// check if 'this' is better than 'other' comparing to reference
|
||||
bool isBetterThan(const MediaType& other, const MediaType& ref) const
|
||||
{
|
||||
const unsigned long thisDiff = resolutionDiff(ref);
|
||||
const unsigned long otherDiff = other.resolutionDiff(ref);
|
||||
if (thisDiff < otherDiff)
|
||||
return true;
|
||||
if (thisDiff == otherDiff)
|
||||
{
|
||||
if (width > other.width)
|
||||
return true;
|
||||
if (width == other.width && height > other.height)
|
||||
return true;
|
||||
if (width == other.width && height == other.height)
|
||||
{
|
||||
const double thisRateDiff = absDiff(getFramerate(), ref.getFramerate());
|
||||
const double otherRateDiff = absDiff(other.getFramerate(), ref.getFramerate());
|
||||
if (thisRateDiff < otherRateDiff)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void printFormat(std::ostream& out, const GUID& fmt)
|
||||
{
|
||||
#define PRNT(FMT) else if (fmt == FMT) out << #FMT;
|
||||
if (fmt == MFVideoFormat_Base) out << "Base";
|
||||
PRNT(MFVideoFormat_RGB32)
|
||||
PRNT(MFVideoFormat_ARGB32)
|
||||
PRNT(MFVideoFormat_RGB24)
|
||||
PRNT(MFVideoFormat_RGB555)
|
||||
PRNT(MFVideoFormat_RGB565)
|
||||
PRNT(MFVideoFormat_RGB8)
|
||||
else
|
||||
{
|
||||
char fourcc[5] = { 0 };
|
||||
memcpy(fourcc, &fmt.Data1, 4);
|
||||
out << fourcc;
|
||||
}
|
||||
#undef PRNT
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const MediaType& mt)
|
||||
{
|
||||
out << "(" << mt.width << "x" << mt.height << " @ " << mt.getFramerate() << ") ";
|
||||
printFormat(out, mt.subType);
|
||||
return out;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
// Class for creating of Media Foundation context
|
||||
class Media_Foundation
|
||||
{
|
||||
@@ -230,391 +309,7 @@ private:
|
||||
Media_Foundation(void) { CoInitialize(0); CV_Assert(SUCCEEDED(MFStartup(MF_VERSION))); }
|
||||
};
|
||||
|
||||
#ifndef IF_GUID_EQUAL_RETURN
|
||||
#define IF_GUID_EQUAL_RETURN(val) if(val == guid) return L#val
|
||||
#endif
|
||||
LPCWSTR GetGUIDNameConstNew(const GUID& guid)
|
||||
{
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MAJOR_TYPE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_SUBTYPE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_ALL_SAMPLES_INDEPENDENT);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_FIXED_SIZE_SAMPLES);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_COMPRESSED);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_SAMPLE_SIZE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_WRAPPED_TYPE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_NUM_CHANNELS);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_SAMPLES_PER_SECOND);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_AVG_BYTES_PER_SECOND);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_BLOCK_ALIGNMENT);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_BITS_PER_SAMPLE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_SAMPLES_PER_BLOCK);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_CHANNEL_MASK);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_FOLDDOWN_MATRIX);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_PEAKREF);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_PEAKTARGET);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_AVGREF);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_WMADRC_AVGTARGET);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AUDIO_PREFER_WAVEFORMATEX);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AAC_PAYLOAD_TYPE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_FRAME_SIZE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_FRAME_RATE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_FRAME_RATE_RANGE_MAX);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_FRAME_RATE_RANGE_MIN);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_PIXEL_ASPECT_RATIO);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_DRM_FLAGS);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_PAD_CONTROL_FLAGS);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_SOURCE_CONTENT_HINT);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_CHROMA_SITING);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_INTERLACE_MODE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_TRANSFER_FUNCTION);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_PRIMARIES);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_CUSTOM_VIDEO_PRIMARIES);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_YUV_MATRIX);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_LIGHTING);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_VIDEO_NOMINAL_RANGE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_GEOMETRIC_APERTURE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MINIMUM_DISPLAY_APERTURE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_PAN_SCAN_APERTURE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_PAN_SCAN_ENABLED);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AVG_BITRATE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AVG_BIT_ERROR_RATE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MAX_KEYFRAME_SPACING);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_DEFAULT_STRIDE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_PALETTE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_USER_DATA);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_AM_FORMAT_TYPE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MPEG_START_TIME_CODE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MPEG2_PROFILE);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MPEG2_LEVEL);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MPEG2_FLAGS);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MPEG_SEQUENCE_HEADER);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_SRC_PACK_0);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_CTRL_PACK_0);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_SRC_PACK_1);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_DV_AAUX_CTRL_PACK_1);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_DV_VAUX_SRC_PACK);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_DV_VAUX_CTRL_PACK);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_ARBITRARY_HEADER);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_ARBITRARY_FORMAT);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_IMAGE_LOSS_TOLERANT);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MPEG4_SAMPLE_DESCRIPTION);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_MPEG4_CURRENT_SAMPLE_ENTRY);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_ORIGINAL_4CC);
|
||||
IF_GUID_EQUAL_RETURN(MF_MT_ORIGINAL_WAVE_FORMAT_TAG);
|
||||
// Media types
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_Audio);
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_Video);
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_Protected);
|
||||
#ifdef MFMediaType_Perception
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_Perception);
|
||||
#endif
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_Stream);
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_SAMI);
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_Script);
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_Image);
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_HTML);
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_Binary);
|
||||
IF_GUID_EQUAL_RETURN(MFMediaType_FileTransfer);
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_AI44); // FCC('AI44')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_ARGB32); // D3DFMT_A8R8G8B8
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_AYUV); // FCC('AYUV')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_DV25); // FCC('dv25')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_DV50); // FCC('dv50')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_DVH1); // FCC('dvh1')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_DVC);
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_DVHD);
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_DVSD); // FCC('dvsd')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_DVSL); // FCC('dvsl')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_H264); // FCC('H264')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_I420); // FCC('I420')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_IYUV); // FCC('IYUV')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_M4S2); // FCC('M4S2')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_MJPG);
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_MP43); // FCC('MP43')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_MP4S); // FCC('MP4S')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_MP4V); // FCC('MP4V')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_MPG1); // FCC('MPG1')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_MSS1); // FCC('MSS1')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_MSS2); // FCC('MSS2')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_NV11); // FCC('NV11')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_NV12); // FCC('NV12')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_P010); // FCC('P010')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_P016); // FCC('P016')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_P210); // FCC('P210')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_P216); // FCC('P216')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB24); // D3DFMT_R8G8B8
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB32); // D3DFMT_X8R8G8B8
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB555); // D3DFMT_X1R5G5B5
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB565); // D3DFMT_R5G6B5
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_RGB8);
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_UYVY); // FCC('UYVY')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_v210); // FCC('v210')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_v410); // FCC('v410')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_WMV1); // FCC('WMV1')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_WMV2); // FCC('WMV2')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_WMV3); // FCC('WMV3')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_WVC1); // FCC('WVC1')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_Y210); // FCC('Y210')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_Y216); // FCC('Y216')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_Y410); // FCC('Y410')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_Y416); // FCC('Y416')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_Y41P);
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_Y41T);
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_YUY2); // FCC('YUY2')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_YV12); // FCC('YV12')
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_YVYU);
|
||||
#ifdef MFVideoFormat_H263
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_H263);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_H265
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_H265);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_H264_ES
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_H264_ES);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_HEVC
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_HEVC);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_HEVC_ES
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_HEVC_ES);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_MPEG2
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_MPEG2);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_VP80
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_VP80);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_VP90
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_VP90);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_420O
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_420O);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_Y42T
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_Y42T);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_YVU9
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_YVU9);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_v216
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_v216);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_L8
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_L8);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_L16
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_L16);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_D16
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_D16);
|
||||
#endif
|
||||
#ifdef D3DFMT_X8R8G8B8
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_X8R8G8B8);
|
||||
#endif
|
||||
#ifdef D3DFMT_A8R8G8B8
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_A8R8G8B8);
|
||||
#endif
|
||||
#ifdef D3DFMT_R8G8B8
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_R8G8B8);
|
||||
#endif
|
||||
#ifdef D3DFMT_X1R5G5B5
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_X1R5G5B5);
|
||||
#endif
|
||||
#ifdef D3DFMT_A4R4G4B4
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_A4R4G4B4);
|
||||
#endif
|
||||
#ifdef D3DFMT_R5G6B5
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_R5G6B5);
|
||||
#endif
|
||||
#ifdef D3DFMT_P8
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_P8);
|
||||
#endif
|
||||
#ifdef D3DFMT_A2R10G10B10
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_A2R10G10B10);
|
||||
#endif
|
||||
#ifdef D3DFMT_A2B10G10R10
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_A2B10G10R10);
|
||||
#endif
|
||||
#ifdef D3DFMT_L8
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_L8);
|
||||
#endif
|
||||
#ifdef D3DFMT_L16
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_L16);
|
||||
#endif
|
||||
#ifdef D3DFMT_D16
|
||||
IF_GUID_EQUAL_RETURN(D3DFMT_D16);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_A2R10G10B10
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_A2R10G10B10);
|
||||
#endif
|
||||
#ifdef MFVideoFormat_A16B16G16R16F
|
||||
IF_GUID_EQUAL_RETURN(MFVideoFormat_A16B16G16R16F);
|
||||
#endif
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_PCM); // WAVE_FORMAT_PCM
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_Float); // WAVE_FORMAT_IEEE_FLOAT
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_DTS); // WAVE_FORMAT_DTS
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_Dolby_AC3_SPDIF); // WAVE_FORMAT_DOLBY_AC3_SPDIF
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_DRM); // WAVE_FORMAT_DRM
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_WMAudioV8); // WAVE_FORMAT_WMAUDIO2
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_WMAudioV9); // WAVE_FORMAT_WMAUDIO3
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_WMAudio_Lossless); // WAVE_FORMAT_WMAUDIO_LOSSLESS
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_WMASPDIF); // WAVE_FORMAT_WMASPDIF
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_MSP1); // WAVE_FORMAT_WMAVOICE9
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_MP3); // WAVE_FORMAT_MPEGLAYER3
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_MPEG); // WAVE_FORMAT_MPEG
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_AAC); // WAVE_FORMAT_MPEG_HEAAC
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_ADTS); // WAVE_FORMAT_MPEG_ADTS_AAC
|
||||
#ifdef MFAudioFormat_ALAC
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_ALAC);
|
||||
#endif
|
||||
#ifdef MFAudioFormat_AMR_NB
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_AMR_NB);
|
||||
#endif
|
||||
#ifdef MFAudioFormat_AMR_WB
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_AMR_WB);
|
||||
#endif
|
||||
#ifdef MFAudioFormat_AMR_WP
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_AMR_WP);
|
||||
#endif
|
||||
#ifdef MFAudioFormat_Dolby_AC3
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_Dolby_AC3);
|
||||
#endif
|
||||
#ifdef MFAudioFormat_Dolby_DDPlus
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_Dolby_DDPlus);
|
||||
#endif
|
||||
#ifdef MFAudioFormat_FLAC
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_FLAC);
|
||||
#endif
|
||||
#ifdef MFAudioFormat_Opus
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_Opus);
|
||||
#endif
|
||||
#ifdef MEDIASUBTYPE_RAW_AAC1
|
||||
IF_GUID_EQUAL_RETURN(MEDIASUBTYPE_RAW_AAC1);
|
||||
#endif
|
||||
#ifdef MFAudioFormat_Float_SpatialObjects
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_Float_SpatialObjects);
|
||||
#endif
|
||||
#ifdef MFAudioFormat_QCELP
|
||||
IF_GUID_EQUAL_RETURN(MFAudioFormat_QCELP);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool LogAttributeValueByIndexNew(IMFAttributes *pAttr, DWORD index, MediaType &out)
|
||||
{
|
||||
PROPVARIANT var;
|
||||
PropVariantInit(&var);
|
||||
GUID guid = { 0 };
|
||||
if (SUCCEEDED(pAttr->GetItemByIndex(index, &guid, &var)))
|
||||
{
|
||||
if (guid == MF_MT_DEFAULT_STRIDE && var.vt == VT_INT)
|
||||
out.MF_MT_DEFAULT_STRIDE = var.intVal;
|
||||
else if (guid == MF_MT_FRAME_RATE && var.vt == VT_UI8)
|
||||
Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_FRAME_RATE_NUMERATOR, &out.MF_MT_FRAME_RATE_DENOMINATOR);
|
||||
else if (guid == MF_MT_FRAME_RATE_RANGE_MAX && var.vt == VT_UI8)
|
||||
Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_FRAME_RATE_RANGE_MAX_NUMERATOR, &out.MF_MT_FRAME_RATE_RANGE_MAX_DENOMINATOR);
|
||||
else if (guid == MF_MT_FRAME_RATE_RANGE_MIN && var.vt == VT_UI8)
|
||||
Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_FRAME_RATE_RANGE_MIN_NUMERATOR, &out.MF_MT_FRAME_RATE_RANGE_MIN_DENOMINATOR);
|
||||
else if (guid == MF_MT_PIXEL_ASPECT_RATIO && var.vt == VT_UI8)
|
||||
Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.MF_MT_PIXEL_ASPECT_RATIO_NUMERATOR, &out.MF_MT_PIXEL_ASPECT_RATIO_DENOMINATOR);
|
||||
else if (guid == MF_MT_YUV_MATRIX && var.vt == VT_UI4)
|
||||
out.MF_MT_YUV_MATRIX = var.ulVal;
|
||||
else if (guid == MF_MT_VIDEO_LIGHTING && var.vt == VT_UI4)
|
||||
out.MF_MT_VIDEO_LIGHTING = var.ulVal;
|
||||
else if (guid == MF_MT_DEFAULT_STRIDE && var.vt == VT_UI4)
|
||||
out.MF_MT_DEFAULT_STRIDE = (int)var.ulVal;
|
||||
else if (guid == MF_MT_VIDEO_CHROMA_SITING && var.vt == VT_UI4)
|
||||
out.MF_MT_VIDEO_CHROMA_SITING = var.ulVal;
|
||||
else if (guid == MF_MT_VIDEO_NOMINAL_RANGE && var.vt == VT_UI4)
|
||||
out.MF_MT_VIDEO_NOMINAL_RANGE = var.ulVal;
|
||||
else if (guid == MF_MT_ALL_SAMPLES_INDEPENDENT && var.vt == VT_UI4)
|
||||
out.MF_MT_ALL_SAMPLES_INDEPENDENT = var.ulVal;
|
||||
else if (guid == MF_MT_FIXED_SIZE_SAMPLES && var.vt == VT_UI4)
|
||||
out.MF_MT_FIXED_SIZE_SAMPLES = var.ulVal;
|
||||
else if (guid == MF_MT_SAMPLE_SIZE && var.vt == VT_UI4)
|
||||
out.MF_MT_SAMPLE_SIZE = var.ulVal;
|
||||
else if (guid == MF_MT_VIDEO_PRIMARIES && var.vt == VT_UI4)
|
||||
out.MF_MT_VIDEO_PRIMARIES = var.ulVal;
|
||||
else if (guid == MF_MT_INTERLACE_MODE && var.vt == VT_UI4)
|
||||
out.MF_MT_INTERLACE_MODE = var.ulVal;
|
||||
else if (guid == MF_MT_AM_FORMAT_TYPE && var.vt == VT_CLSID)
|
||||
out.MF_MT_AM_FORMAT_TYPE = *var.puuid;
|
||||
else if (guid == MF_MT_MAJOR_TYPE && var.vt == VT_CLSID)
|
||||
out.pMF_MT_MAJOR_TYPEName = GetGUIDNameConstNew(out.MF_MT_MAJOR_TYPE = *var.puuid);
|
||||
else if (guid == MF_MT_SUBTYPE && var.vt == VT_CLSID)
|
||||
out.pMF_MT_SUBTYPEName = GetGUIDNameConstNew(out.MF_MT_SUBTYPE = *var.puuid);
|
||||
else if (guid == MF_MT_FRAME_SIZE && var.vt == VT_UI8)
|
||||
{
|
||||
Unpack2UINT32AsUINT64(var.uhVal.QuadPart, &out.width, &out.height);
|
||||
out.MF_MT_FRAME_SIZE = out.width * out.height;
|
||||
}
|
||||
PropVariantClear(&var);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MediaType::MediaType()
|
||||
{
|
||||
pMF_MT_MAJOR_TYPEName = NULL;
|
||||
pMF_MT_SUBTYPEName = NULL;
|
||||
Clear();
|
||||
}
|
||||
|
||||
MediaType::MediaType(IMFMediaType *pType)
|
||||
{
|
||||
pMF_MT_MAJOR_TYPEName = NULL;
|
||||
pMF_MT_SUBTYPEName = NULL;
|
||||
Clear();
|
||||
UINT32 count = 0;
|
||||
if (SUCCEEDED(pType->GetCount(&count)) &&
|
||||
SUCCEEDED(pType->LockStore()))
|
||||
{
|
||||
for (UINT32 i = 0; i < count; i++)
|
||||
if (!LogAttributeValueByIndexNew(pType, i, *this))
|
||||
break;
|
||||
pType->UnlockStore();
|
||||
}
|
||||
}
|
||||
|
||||
MediaType::~MediaType()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void MediaType::Clear()
|
||||
{
|
||||
MF_MT_FRAME_SIZE = 0;
|
||||
height = 0;
|
||||
width = 0;
|
||||
MF_MT_YUV_MATRIX = 0;
|
||||
MF_MT_VIDEO_LIGHTING = 0;
|
||||
MF_MT_DEFAULT_STRIDE = 0;
|
||||
MF_MT_VIDEO_CHROMA_SITING = 0;
|
||||
MF_MT_FIXED_SIZE_SAMPLES = 0;
|
||||
MF_MT_VIDEO_NOMINAL_RANGE = 0;
|
||||
MF_MT_FRAME_RATE_NUMERATOR = 0;
|
||||
MF_MT_FRAME_RATE_DENOMINATOR = 0;
|
||||
MF_MT_PIXEL_ASPECT_RATIO_NUMERATOR = 0;
|
||||
MF_MT_PIXEL_ASPECT_RATIO_DENOMINATOR = 0;
|
||||
MF_MT_ALL_SAMPLES_INDEPENDENT = 0;
|
||||
MF_MT_FRAME_RATE_RANGE_MIN_NUMERATOR = 0;
|
||||
MF_MT_FRAME_RATE_RANGE_MIN_DENOMINATOR = 0;
|
||||
MF_MT_SAMPLE_SIZE = 0;
|
||||
MF_MT_VIDEO_PRIMARIES = 0;
|
||||
MF_MT_INTERLACE_MODE = 0;
|
||||
MF_MT_FRAME_RATE_RANGE_MAX_NUMERATOR = 0;
|
||||
MF_MT_FRAME_RATE_RANGE_MAX_DENOMINATOR = 0;
|
||||
memset(&MF_MT_MAJOR_TYPE, 0, sizeof(GUID));
|
||||
memset(&MF_MT_AM_FORMAT_TYPE, 0, sizeof(GUID));
|
||||
memset(&MF_MT_SUBTYPE, 0, sizeof(GUID));
|
||||
}
|
||||
|
||||
}
|
||||
//==================================================================================================
|
||||
|
||||
class SourceReaderCB : public IMFSourceReaderCallback
|
||||
{
|
||||
@@ -655,7 +350,50 @@ public:
|
||||
return uCount;
|
||||
}
|
||||
|
||||
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;
|
||||
cv::AutoLock lock(m_mutex);
|
||||
|
||||
if (SUCCEEDED(hrStatus))
|
||||
{
|
||||
if (pSample)
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): got frame at " << llTimestamp);
|
||||
if (m_lastSample.Get())
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop frame (not processed)");
|
||||
}
|
||||
m_lastSample = pSample;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP OnEvent(DWORD, IMFMediaEvent *) CV_OVERRIDE
|
||||
{
|
||||
return S_OK;
|
||||
@@ -665,8 +403,32 @@ public:
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Wait(DWORD dwMilliseconds, _ComPtr<IMFSample>& videoSample, BOOL& pbEOS);
|
||||
HRESULT Wait(DWORD dwMilliseconds, _ComPtr<IMFSample>& videoSample, BOOL& pbEOS)
|
||||
{
|
||||
pbEOS = FALSE;
|
||||
|
||||
DWORD dwResult = WaitForSingleObject(m_hEvent, dwMilliseconds);
|
||||
if (dwResult == WAIT_TIMEOUT)
|
||||
{
|
||||
return E_PENDING;
|
||||
}
|
||||
else if (dwResult != WAIT_OBJECT_0)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
pbEOS = m_bEOS;
|
||||
if (!pbEOS)
|
||||
{
|
||||
cv::AutoLock lock(m_mutex);
|
||||
videoSample = m_lastSample;
|
||||
CV_Assert(videoSample);
|
||||
m_lastSample.Release();
|
||||
ResetEvent(m_hEvent); // event is auto-reset, but we need this forced reset due time gap between wait() and mutex hold.
|
||||
}
|
||||
|
||||
return m_hrStatus;
|
||||
}
|
||||
private:
|
||||
// Destructor is private. Caller should call Release.
|
||||
virtual ~SourceReaderCB()
|
||||
@@ -686,6 +448,122 @@ public:
|
||||
_ComPtr<IMFSample> m_lastSample;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
// Enumerate and store supported formats and finds format which is most similar to the one requested
|
||||
class FormatStorage
|
||||
{
|
||||
public:
|
||||
struct MediaID
|
||||
{
|
||||
DWORD stream;
|
||||
DWORD media;
|
||||
MediaID() : stream(0), media(0) {}
|
||||
void nextStream()
|
||||
{
|
||||
stream++;
|
||||
media = 0;
|
||||
}
|
||||
void nextMedia()
|
||||
{
|
||||
media++;
|
||||
}
|
||||
bool operator<(const MediaID& other) const
|
||||
{
|
||||
return (stream < other.stream) || (stream == other.stream && media < other.media);
|
||||
}
|
||||
};
|
||||
void read(IMFSourceReader* source)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
MediaID cur;
|
||||
while (SUCCEEDED(hr))
|
||||
{
|
||||
_ComPtr<IMFMediaType> raw_type;
|
||||
hr = source->GetNativeMediaType(cur.stream, cur.media, &raw_type);
|
||||
if (hr == MF_E_NO_MORE_TYPES)
|
||||
{
|
||||
hr = S_OK;
|
||||
cur.nextStream();
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
formats[cur] = MediaType(raw_type.Get());
|
||||
cur.nextMedia();
|
||||
}
|
||||
}
|
||||
}
|
||||
std::pair<MediaID, MediaType> findBest(const MediaType& newType)
|
||||
{
|
||||
std::pair<MediaID, MediaType> best;
|
||||
std::map<MediaID, MediaType>::const_iterator i = formats.begin();
|
||||
for (; i != formats.end(); ++i)
|
||||
{
|
||||
if (newType.isEmpty()) // file input - choose first returned media type
|
||||
{
|
||||
best = *i;
|
||||
break;
|
||||
}
|
||||
if (i->second.isBetterThan(best.second, newType))
|
||||
{
|
||||
best = *i;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
private:
|
||||
std::map<MediaID, MediaType> formats;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
// Enumerates devices and activates one of them
|
||||
class DeviceList
|
||||
{
|
||||
public:
|
||||
DeviceList() : devices(NULL), count(0) {}
|
||||
~DeviceList()
|
||||
{
|
||||
if (devices)
|
||||
{
|
||||
for (UINT32 i = 0; i < count; ++i)
|
||||
if (devices[i])
|
||||
devices[i]->Release();
|
||||
CoTaskMemFree(devices);
|
||||
}
|
||||
}
|
||||
UINT32 read(IID sourceType = MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID)
|
||||
{
|
||||
_ComPtr<IMFAttributes> attr;
|
||||
if (FAILED(MFCreateAttributes(&attr, 1)) ||
|
||||
FAILED(attr->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, sourceType)))
|
||||
{
|
||||
CV_Error(CV_StsError, "Failed to create attributes");
|
||||
}
|
||||
if (FAILED(MFEnumDeviceSources(attr.Get(), &devices, &count)))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Failed to enumerate MSMF devices");
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
_ComPtr<IMFMediaSource> activateSource(UINT32 index)
|
||||
{
|
||||
_ComPtr<IMFMediaSource> result;
|
||||
if (count == 0 || index >= count || FAILED(devices[index]->ActivateObject(__uuidof(IMFMediaSource), (void**)&result)))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Failed to activate media source (device " << index << ")");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
IMFActivate** devices;
|
||||
UINT32 count;
|
||||
};
|
||||
|
||||
} // namespace::
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
/******* Capturing video from camera or file via Microsoft Media Foundation **********/
|
||||
class CvCapture_MSMF : public cv::IVideoCapture
|
||||
@@ -707,11 +585,17 @@ public:
|
||||
virtual bool isOpened() const CV_OVERRIDE { return isOpen; }
|
||||
virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_MSMF; }
|
||||
protected:
|
||||
double getFramerate(MediaType MT) const;
|
||||
bool configureOutput(UINT32 width, UINT32 height, double prefFramerate, UINT32 aspectRatioN, UINT32 aspectRatioD, cv::uint32_t outFormat, bool convertToFormat);
|
||||
bool configureOutput(MediaType newType, cv::uint32_t outFormat, bool convertToFormat);
|
||||
bool setTime(double time, bool rough);
|
||||
bool configureHW(bool enable);
|
||||
|
||||
template <typename CtrlT>
|
||||
bool readComplexPropery(long prop, long& val) const;
|
||||
template <typename CtrlT>
|
||||
bool writeComplexProperty(long prop, double val, long flags);
|
||||
_ComPtr<IMFAttributes> getDefaultSourceConfig(UINT32 num = 10);
|
||||
bool initStream(DWORD streamID, const MediaType& mt);
|
||||
|
||||
Media_Foundation& MF;
|
||||
cv::String filename;
|
||||
int camid;
|
||||
@@ -724,10 +608,8 @@ protected:
|
||||
DWORD dwStreamIndex;
|
||||
MediaType nativeFormat;
|
||||
MediaType captureFormat;
|
||||
cv::uint32_t outputFormat;
|
||||
UINT32 requestedWidth, requestedHeight;
|
||||
int outputFormat;
|
||||
bool convertFormat;
|
||||
UINT32 aspectN, aspectD;
|
||||
MFTIME duration;
|
||||
LONGLONG frameStep;
|
||||
_ComPtr<IMFSample> videoSample;
|
||||
@@ -748,11 +630,7 @@ CvCapture_MSMF::CvCapture_MSMF():
|
||||
videoFileSource(NULL),
|
||||
videoSample(NULL),
|
||||
outputFormat(CV_CAP_MODE_BGR),
|
||||
requestedWidth(0),
|
||||
requestedHeight(0),
|
||||
convertFormat(true),
|
||||
aspectN(1),
|
||||
aspectD(1),
|
||||
sampleTime(0),
|
||||
isOpen(false)
|
||||
{
|
||||
@@ -778,6 +656,65 @@ void CvCapture_MSMF::close()
|
||||
readCallback.Release();
|
||||
}
|
||||
|
||||
bool CvCapture_MSMF::initStream(DWORD streamID, const MediaType& mt)
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Init stream " << streamID << " with MediaType " << mt);
|
||||
_ComPtr<IMFMediaType> mediaTypeOut = mt.createMediaType();
|
||||
if (FAILED(videoFileSource->SetStreamSelection((DWORD)MF_SOURCE_READER_ALL_STREAMS, false)))
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Failed to reset streams");
|
||||
return false;
|
||||
}
|
||||
if (FAILED(videoFileSource->SetStreamSelection(streamID, true)))
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Failed to select stream " << streamID);
|
||||
return false;
|
||||
}
|
||||
HRESULT hr = videoFileSource->SetCurrentMediaType(streamID, NULL, mediaTypeOut.Get());
|
||||
if (hr == MF_E_TOPO_CODEC_NOT_FOUND)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Failed to set mediaType (stream " << streamID << ", " << mt << "(codec not found)");
|
||||
return false;
|
||||
}
|
||||
else if (hr == MF_E_INVALIDMEDIATYPE)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Failed to set mediaType (stream " << streamID << ", " << mt << "(unsupported media type)");
|
||||
return false;
|
||||
}
|
||||
else if (FAILED(hr))
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "Failed to set mediaType (stream " << streamID << ", " << mt << "(HRESULT " << hr << ")");
|
||||
return false;
|
||||
}
|
||||
captureFormat = mt;
|
||||
return true;
|
||||
}
|
||||
|
||||
_ComPtr<IMFAttributes> CvCapture_MSMF::getDefaultSourceConfig(UINT32 num)
|
||||
{
|
||||
CV_Assert(num > 0);
|
||||
_ComPtr<IMFAttributes> res;
|
||||
if (FAILED(MFCreateAttributes(&res, num)) ||
|
||||
FAILED(res->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)) ||
|
||||
FAILED(res->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, false)) ||
|
||||
FAILED(res->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, false)) ||
|
||||
FAILED(res->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, true))
|
||||
)
|
||||
{
|
||||
CV_Error(CV_StsError, "Failed to create attributes");
|
||||
}
|
||||
#ifdef HAVE_MSMF_DXVA
|
||||
if (D3DMgr)
|
||||
{
|
||||
if (FAILED(res->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, D3DMgr.Get())))
|
||||
{
|
||||
CV_Error(CV_StsError, "Failed to create attributes");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CvCapture_MSMF::configureHW(bool enable)
|
||||
{
|
||||
#ifdef HAVE_MSMF_DXVA
|
||||
@@ -835,181 +772,78 @@ bool CvCapture_MSMF::configureHW(bool enable)
|
||||
#endif
|
||||
}
|
||||
|
||||
#define UDIFF(res, ref) (ref == 0 ? 0 : res > ref ? res - ref : ref - res)
|
||||
static UINT32 resolutionDiff(MediaType& mType, UINT32 refWidth, UINT32 refHeight)
|
||||
{ return UDIFF(mType.width, refWidth) + UDIFF(mType.height, refHeight); }
|
||||
#undef UDIFF
|
||||
|
||||
bool CvCapture_MSMF::configureOutput(UINT32 width, UINT32 height, double prefFramerate, UINT32 aspectRatioN, UINT32 aspectRatioD, cv::uint32_t outFormat, bool convertToFormat)
|
||||
bool CvCapture_MSMF::configureOutput(MediaType newType, cv::uint32_t outFormat, bool convertToFormat)
|
||||
{
|
||||
if (width != 0 && height != 0 &&
|
||||
width == captureFormat.width && height == captureFormat.height && prefFramerate == getFramerate(nativeFormat) &&
|
||||
aspectRatioN == aspectN && aspectRatioD == aspectD && outFormat == outputFormat && convertToFormat == convertFormat)
|
||||
return true;
|
||||
|
||||
requestedWidth = width;
|
||||
requestedHeight = height;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
int dwStreamBest = -1;
|
||||
MediaType MTBest;
|
||||
|
||||
DWORD dwMediaTypeTest = 0;
|
||||
DWORD dwStreamTest = 0;
|
||||
while (SUCCEEDED(hr))
|
||||
FormatStorage formats;
|
||||
formats.read(videoFileSource.Get());
|
||||
std::pair<FormatStorage::MediaID, MediaType> bestMatch = formats.findBest(newType);
|
||||
dwStreamIndex = bestMatch.first.stream;
|
||||
nativeFormat = bestMatch.second;
|
||||
MediaType newFormat = nativeFormat;
|
||||
if (convertToFormat)
|
||||
{
|
||||
_ComPtr<IMFMediaType> pType;
|
||||
hr = videoFileSource->GetNativeMediaType(dwStreamTest, dwMediaTypeTest, &pType);
|
||||
if (hr == MF_E_NO_MORE_TYPES)
|
||||
switch (outFormat)
|
||||
{
|
||||
hr = S_OK;
|
||||
++dwStreamTest;
|
||||
dwMediaTypeTest = 0;
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
MediaType MT(pType.Get());
|
||||
if (MT.MF_MT_MAJOR_TYPE == MFMediaType_Video)
|
||||
{
|
||||
if (dwStreamBest < 0 ||
|
||||
resolutionDiff(MT, width, height) < resolutionDiff(MTBest, width, height) ||
|
||||
(resolutionDiff(MT, width, height) == resolutionDiff(MTBest, width, height) && MT.width > MTBest.width) ||
|
||||
(resolutionDiff(MT, width, height) == resolutionDiff(MTBest, width, height) && MT.width == MTBest.width && MT.height > MTBest.height) ||
|
||||
(MT.width == MTBest.width && MT.height == MTBest.height && (getFramerate(MT) > getFramerate(MTBest) && (prefFramerate == 0 || getFramerate(MT) <= prefFramerate)))
|
||||
)
|
||||
{
|
||||
dwStreamBest = (int)dwStreamTest;
|
||||
MTBest = MT;
|
||||
}
|
||||
}
|
||||
++dwMediaTypeTest;
|
||||
case CV_CAP_MODE_BGR:
|
||||
case CV_CAP_MODE_RGB:
|
||||
newFormat.subType = captureMode == MODE_HW ? MFVideoFormat_RGB32 : MFVideoFormat_RGB24;
|
||||
newFormat.stride = (captureMode == MODE_HW ? 4 : 3) * newFormat.width;
|
||||
newFormat.sampleSize = newFormat.stride * newFormat.height;
|
||||
break;
|
||||
case CV_CAP_MODE_GRAY:
|
||||
newFormat.subType = MFVideoFormat_YUY2;
|
||||
newFormat.stride = newFormat.width;
|
||||
newFormat.sampleSize = newFormat.stride * newFormat.height * 3 / 2;
|
||||
break;
|
||||
case CV_CAP_MODE_YUYV:
|
||||
newFormat.subType = MFVideoFormat_YUY2;
|
||||
newFormat.stride = 2 * newFormat.width;
|
||||
newFormat.sampleSize = newFormat.stride * newFormat.height;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
newFormat.interlaceMode = MFVideoInterlace_Progressive;
|
||||
newFormat.isFixedSize = true;
|
||||
if (nativeFormat.subType == MFVideoFormat_MP43) //Unable to estimate FPS for MP43
|
||||
newFormat.frameRateNum = 0;
|
||||
}
|
||||
if (dwStreamBest >= 0)
|
||||
{
|
||||
GUID outSubtype = GUID_NULL;
|
||||
UINT32 outStride = 0;
|
||||
UINT32 outSize = 0;
|
||||
if(convertToFormat)
|
||||
switch (outFormat)
|
||||
{
|
||||
case CV_CAP_MODE_BGR:
|
||||
case CV_CAP_MODE_RGB:
|
||||
outSubtype = captureMode == MODE_HW ? MFVideoFormat_RGB32 : MFVideoFormat_RGB24; // HW accelerated mode support only RGB32
|
||||
outStride = (captureMode == MODE_HW ? 4 : 3) * MTBest.width;
|
||||
outSize = outStride * MTBest.height;
|
||||
break;
|
||||
case CV_CAP_MODE_GRAY:
|
||||
outSubtype = MFVideoFormat_NV12;
|
||||
outStride = MTBest.width;
|
||||
outSize = outStride * MTBest.height * 3 / 2;
|
||||
break;
|
||||
case CV_CAP_MODE_YUYV:
|
||||
outSubtype = MFVideoFormat_YUY2;
|
||||
outStride = 2 * MTBest.width;
|
||||
outSize = outStride * MTBest.height;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
_ComPtr<IMFMediaType> mediaTypeOut;
|
||||
if (// Set the output media type.
|
||||
SUCCEEDED(MFCreateMediaType(&mediaTypeOut)) &&
|
||||
SUCCEEDED(mediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)) &&
|
||||
SUCCEEDED(mediaTypeOut->SetGUID(MF_MT_SUBTYPE, convertToFormat ? outSubtype : MTBest.MF_MT_SUBTYPE)) &&
|
||||
SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, convertToFormat ? MFVideoInterlace_Progressive : MTBest.MF_MT_INTERLACE_MODE)) &&
|
||||
SUCCEEDED(MFSetAttributeRatio(mediaTypeOut.Get(), MF_MT_PIXEL_ASPECT_RATIO, aspectRatioN, aspectRatioD)) &&
|
||||
SUCCEEDED(MFSetAttributeSize(mediaTypeOut.Get(), MF_MT_FRAME_SIZE, MTBest.width, MTBest.height)) &&
|
||||
SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, convertToFormat ? 1 : MTBest.MF_MT_FIXED_SIZE_SAMPLES)) &&
|
||||
SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_SAMPLE_SIZE, convertToFormat ? outSize : MTBest.MF_MT_SAMPLE_SIZE)) &&
|
||||
SUCCEEDED(mediaTypeOut->SetUINT32(MF_MT_DEFAULT_STRIDE, convertToFormat ? outStride : MTBest.MF_MT_DEFAULT_STRIDE)))//Assume BGR24 input
|
||||
{
|
||||
if (SUCCEEDED(videoFileSource->SetStreamSelection((DWORD)MF_SOURCE_READER_ALL_STREAMS, false)) &&
|
||||
SUCCEEDED(videoFileSource->SetStreamSelection((DWORD)dwStreamBest, true)) &&
|
||||
SUCCEEDED(videoFileSource->SetCurrentMediaType((DWORD)dwStreamBest, NULL, mediaTypeOut.Get()))
|
||||
)
|
||||
{
|
||||
dwStreamIndex = (DWORD)dwStreamBest;
|
||||
nativeFormat = MTBest;
|
||||
aspectN = aspectRatioN;
|
||||
aspectD = aspectRatioD;
|
||||
outputFormat = outFormat;
|
||||
convertFormat = convertToFormat;
|
||||
captureFormat = MediaType(mediaTypeOut.Get());
|
||||
return true;
|
||||
}
|
||||
close();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
// we select native format first and then our requested format (related issue #12822)
|
||||
if (!newType.isEmpty()) // camera input
|
||||
initStream(dwStreamIndex, nativeFormat);
|
||||
return initStream(dwStreamIndex, newFormat);
|
||||
}
|
||||
|
||||
// Initialize camera input
|
||||
bool CvCapture_MSMF::open(int _index)
|
||||
bool CvCapture_MSMF::open(int index)
|
||||
{
|
||||
close();
|
||||
if (_index < 0)
|
||||
if (index < 0)
|
||||
return false;
|
||||
_ComPtr<IMFAttributes> msAttr = NULL;
|
||||
if (SUCCEEDED(MFCreateAttributes(&msAttr, 1)) &&
|
||||
SUCCEEDED(msAttr->SetGUID(
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
|
||||
)))
|
||||
DeviceList devices;
|
||||
UINT32 count = devices.read();
|
||||
if (count == 0 || static_cast<UINT32>(index) > count)
|
||||
{
|
||||
IMFActivate **ppDevices = NULL;
|
||||
UINT32 count;
|
||||
if (SUCCEEDED(MFEnumDeviceSources(msAttr.Get(), &ppDevices, &count)))
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
for (int ind = 0; ind < (int)count; ind++)
|
||||
{
|
||||
if (ind == _index && ppDevices[ind])
|
||||
{
|
||||
// Set source reader parameters
|
||||
_ComPtr<IMFMediaSource> mSrc;
|
||||
_ComPtr<IMFAttributes> srAttr;
|
||||
if (SUCCEEDED(ppDevices[ind]->ActivateObject(__uuidof(IMFMediaSource), (void**)&mSrc)) && mSrc &&
|
||||
SUCCEEDED(MFCreateAttributes(&srAttr, 10)) &&
|
||||
SUCCEEDED(srAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE)) &&
|
||||
SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, FALSE)) &&
|
||||
SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, FALSE)) &&
|
||||
SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, TRUE)))
|
||||
{
|
||||
#ifdef HAVE_MSMF_DXVA
|
||||
if (D3DMgr)
|
||||
srAttr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, D3DMgr.Get());
|
||||
#endif
|
||||
readCallback = ComPtr<IMFSourceReaderCallback>(new SourceReaderCB());
|
||||
HRESULT hr = srAttr->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, (IMFSourceReaderCallback*)readCallback.Get());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
readCallback.Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(MFCreateSourceReaderFromMediaSource(mSrc.Get(), srAttr.Get(), &videoFileSource)))
|
||||
{
|
||||
isOpen = true;
|
||||
duration = 0;
|
||||
if (configureOutput(640, 480, 0, aspectN, aspectD, outputFormat, convertFormat))
|
||||
{
|
||||
double fps = getFramerate(nativeFormat);
|
||||
frameStep = (LONGLONG)(fps > 0 ? 1e7 / fps : 0);
|
||||
camid = _index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ppDevices[ind])
|
||||
ppDevices[ind]->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
CoTaskMemFree(ppDevices);
|
||||
CV_LOG_DEBUG(NULL, "Device " << index << " not found (total " << count << " devices)");
|
||||
return false;
|
||||
}
|
||||
_ComPtr<IMFAttributes> attr = getDefaultSourceConfig();
|
||||
_ComPtr<IMFSourceReaderCallback> cb = new SourceReaderCB();
|
||||
attr->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, cb.Get());
|
||||
_ComPtr<IMFMediaSource> src = devices.activateSource(index);
|
||||
if (!src.Get() || FAILED(MFCreateSourceReaderFromMediaSource(src.Get(), attr.Get(), &videoFileSource)))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Failed to create source reader");
|
||||
return false;
|
||||
}
|
||||
|
||||
isOpen = true;
|
||||
camid = index;
|
||||
readCallback = cb;
|
||||
duration = 0;
|
||||
if (configureOutput(MediaType::createDefault(), outputFormat, convertFormat))
|
||||
{
|
||||
frameStep = captureFormat.getFrameStep();
|
||||
}
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
@@ -1020,120 +854,33 @@ bool CvCapture_MSMF::open(const cv::String& _filename)
|
||||
return false;
|
||||
|
||||
// Set source reader parameters
|
||||
_ComPtr<IMFAttributes> srAttr;
|
||||
if (SUCCEEDED(MFCreateAttributes(&srAttr, 10)) &&
|
||||
SUCCEEDED(srAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)) &&
|
||||
SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, false)) &&
|
||||
SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, false)) &&
|
||||
SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, true))
|
||||
)
|
||||
_ComPtr<IMFAttributes> attr = getDefaultSourceConfig();
|
||||
cv::AutoBuffer<wchar_t> unicodeFileName(_filename.length() + 1);
|
||||
MultiByteToWideChar(CP_ACP, 0, _filename.c_str(), -1, unicodeFileName.data(), (int)_filename.length() + 1);
|
||||
if (SUCCEEDED(MFCreateSourceReaderFromURL(unicodeFileName.data(), attr.Get(), &videoFileSource)))
|
||||
{
|
||||
#ifdef HAVE_MSMF_DXVA
|
||||
if(D3DMgr)
|
||||
srAttr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, D3DMgr.Get());
|
||||
#endif
|
||||
cv::AutoBuffer<wchar_t> unicodeFileName(_filename.length() + 1);
|
||||
MultiByteToWideChar(CP_ACP, 0, _filename.c_str(), -1, unicodeFileName.data(), (int)_filename.length() + 1);
|
||||
if (SUCCEEDED(MFCreateSourceReaderFromURL(unicodeFileName.data(), srAttr.Get(), &videoFileSource)))
|
||||
isOpen = true;
|
||||
sampleTime = 0;
|
||||
if (configureOutput(MediaType(), outputFormat, convertFormat))
|
||||
{
|
||||
isOpen = true;
|
||||
sampleTime = 0;
|
||||
if (configureOutput(0, 0, 0, aspectN, aspectD, outputFormat, convertFormat))
|
||||
frameStep = captureFormat.getFrameStep();
|
||||
filename = _filename;
|
||||
PROPVARIANT var;
|
||||
HRESULT hr;
|
||||
if (SUCCEEDED(hr = videoFileSource->GetPresentationAttribute((DWORD)MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &var)) &&
|
||||
var.vt == VT_UI8)
|
||||
{
|
||||
double fps = getFramerate(nativeFormat);
|
||||
frameStep = (LONGLONG)(fps > 0 ? 1e7 / fps : 0);
|
||||
filename = _filename;
|
||||
PROPVARIANT var;
|
||||
HRESULT hr;
|
||||
if (SUCCEEDED(hr = videoFileSource->GetPresentationAttribute((DWORD)MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &var)) &&
|
||||
var.vt == VT_UI8)
|
||||
{
|
||||
duration = var.uhVal.QuadPart;
|
||||
PropVariantClear(&var);
|
||||
}
|
||||
else
|
||||
duration = 0;
|
||||
duration = var.uhVal.QuadPart;
|
||||
PropVariantClear(&var);
|
||||
}
|
||||
else
|
||||
duration = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
|
||||
HRESULT SourceReaderCB::Wait(DWORD dwMilliseconds, _ComPtr<IMFSample>& videoSample, BOOL& bEOS)
|
||||
{
|
||||
bEOS = FALSE;
|
||||
|
||||
DWORD dwResult = WaitForSingleObject(m_hEvent, dwMilliseconds);
|
||||
if (dwResult == WAIT_TIMEOUT)
|
||||
{
|
||||
return E_PENDING;
|
||||
}
|
||||
else if (dwResult != WAIT_OBJECT_0)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
bEOS = m_bEOS;
|
||||
if (!bEOS)
|
||||
{
|
||||
cv::AutoLock lock(m_mutex);
|
||||
videoSample = m_lastSample;
|
||||
CV_Assert(videoSample);
|
||||
m_lastSample.Release();
|
||||
ResetEvent(m_hEvent); // event is auto-reset, but we need this forced reset due time gap between wait() and mutex hold.
|
||||
}
|
||||
|
||||
return m_hrStatus;
|
||||
}
|
||||
|
||||
STDMETHODIMP SourceReaderCB::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex, DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample)
|
||||
{
|
||||
CV_UNUSED(llTimestamp);
|
||||
|
||||
HRESULT hr = 0;
|
||||
cv::AutoLock lock(m_mutex);
|
||||
|
||||
if (SUCCEEDED(hrStatus))
|
||||
{
|
||||
if (pSample)
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): got frame at " << llTimestamp);
|
||||
IMFSample* prev = m_lastSample.Get();
|
||||
if (prev)
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "videoio(MSMF): drop frame (not processed)");
|
||||
}
|
||||
m_lastSample = pSample;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
bool CvCapture_MSMF::grabFrame()
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
@@ -1294,7 +1041,7 @@ bool CvCapture_MSMF::retrieveFrame(int, cv::OutputArray frame)
|
||||
break;
|
||||
if (convertFormat)
|
||||
{
|
||||
if (lock2d || (unsigned int)cursize == captureFormat.MF_MT_SAMPLE_SIZE)
|
||||
if (lock2d || (unsigned int)cursize == captureFormat.sampleSize)
|
||||
{
|
||||
switch (outputFormat)
|
||||
{
|
||||
@@ -1340,13 +1087,6 @@ bool CvCapture_MSMF::retrieveFrame(int, cv::OutputArray frame)
|
||||
return false;
|
||||
}
|
||||
|
||||
double CvCapture_MSMF::getFramerate(MediaType MT) const
|
||||
{
|
||||
if (MT.MF_MT_SUBTYPE == MFVideoFormat_MP43) //Unable to estimate FPS for MP43
|
||||
return 0;
|
||||
return MT.MF_MT_FRAME_RATE_DENOMINATOR != 0 ? ((double)MT.MF_MT_FRAME_RATE_NUMERATOR) / ((double)MT.MF_MT_FRAME_RATE_DENOMINATOR) : 0;
|
||||
}
|
||||
|
||||
bool CvCapture_MSMF::setTime(double time, bool rough)
|
||||
{
|
||||
PROPVARIANT var;
|
||||
@@ -1371,11 +1111,35 @@ bool CvCapture_MSMF::setTime(double time, bool rough)
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename CtrlT>
|
||||
bool CvCapture_MSMF::readComplexPropery(long prop, long & val) const
|
||||
{
|
||||
_ComPtr<CtrlT> ctrl;
|
||||
if (FAILED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&ctrl))))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Failed to get service for stream");
|
||||
return false;
|
||||
}
|
||||
long paramVal, paramFlag;
|
||||
if (FAILED(ctrl->Get(prop, ¶mVal, ¶mFlag)))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Failed to get property " << prop);
|
||||
// we continue
|
||||
}
|
||||
// fallback - get default value
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(ctrl->GetRange(prop, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag)))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Failed to get default value for property " << prop);
|
||||
return false;
|
||||
}
|
||||
val = paramVal;
|
||||
return true;
|
||||
}
|
||||
|
||||
double CvCapture_MSMF::getProperty( int property_id ) const
|
||||
{
|
||||
IAMVideoProcAmp *pProcAmp = NULL;
|
||||
IAMCameraControl *pProcControl = NULL;
|
||||
// image format properties
|
||||
long cVal = 0;
|
||||
if (isOpen)
|
||||
switch (property_id)
|
||||
{
|
||||
@@ -1384,24 +1148,24 @@ double CvCapture_MSMF::getProperty( int property_id ) const
|
||||
case CV_CAP_PROP_CONVERT_RGB:
|
||||
return convertFormat ? 1 : 0;
|
||||
case CV_CAP_PROP_SAR_NUM:
|
||||
return aspectN;
|
||||
return captureFormat.aspectRatioNum;
|
||||
case CV_CAP_PROP_SAR_DEN:
|
||||
return aspectD;
|
||||
return captureFormat.aspectRatioDenom;
|
||||
case CV_CAP_PROP_FRAME_WIDTH:
|
||||
return captureFormat.width;
|
||||
case CV_CAP_PROP_FRAME_HEIGHT:
|
||||
return captureFormat.height;
|
||||
case CV_CAP_PROP_FOURCC:
|
||||
return nativeFormat.MF_MT_SUBTYPE.Data1;
|
||||
return captureFormat.subType.Data1;
|
||||
case CV_CAP_PROP_FPS:
|
||||
return getFramerate(nativeFormat);
|
||||
return captureFormat.getFramerate();
|
||||
case CV_CAP_PROP_FRAME_COUNT:
|
||||
if (duration != 0)
|
||||
return floor(((double)duration / 1e7)*getFramerate(nativeFormat) + 0.5);
|
||||
return floor(((double)duration / 1e7)* captureFormat.getFramerate() + 0.5);
|
||||
else
|
||||
break;
|
||||
case CV_CAP_PROP_POS_FRAMES:
|
||||
return floor(((double)sampleTime / 1e7)*getFramerate(nativeFormat) + 0.5);
|
||||
return floor(((double)sampleTime / 1e7)* captureFormat.getFramerate() + 0.5);
|
||||
case CV_CAP_PROP_POS_MSEC:
|
||||
return (double)sampleTime / 1e4;
|
||||
case CV_CAP_PROP_POS_AVI_RATIO:
|
||||
@@ -1410,253 +1174,87 @@ double CvCapture_MSMF::getProperty( int property_id ) const
|
||||
else
|
||||
break;
|
||||
case CV_CAP_PROP_BRIGHTNESS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_Brightness, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if(FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_Brightness, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_Brightness, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_CONTRAST:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_Contrast, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_Contrast, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_Contrast, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_SATURATION:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_Saturation, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_Saturation, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_Saturation, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_HUE:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_Hue, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_Hue, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_Hue, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_GAIN:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_Gain, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_Gain, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_Gain, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_SHARPNESS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_Sharpness, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_Sharpness, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_Sharpness, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_GAMMA:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_Gamma, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_Gamma, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_Gamma, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_BACKLIGHT:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_BacklightCompensation, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_BacklightCompensation, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_BacklightCompensation, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_MONOCHROME:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_ColorEnable, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_ColorEnable, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal == 0 ? 1 : 0;
|
||||
}
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_ColorEnable, cVal))
|
||||
return cVal == 0 ? 1 : 0;
|
||||
break;
|
||||
case CV_CAP_PROP_TEMPERATURE:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcAmp->Get(VideoProcAmp_WhiteBalance, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcAmp->GetRange(VideoProcAmp_WhiteBalance, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcAmp->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
case CV_CAP_PROP_WHITE_BALANCE_BLUE_U:
|
||||
case CV_CAP_PROP_WHITE_BALANCE_RED_V:
|
||||
if (readComplexPropery<IAMVideoProcAmp>(VideoProcAmp_WhiteBalance, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_PAN:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcControl->Get(CameraControl_Pan, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcControl->GetRange(CameraControl_Pan, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcControl->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMCameraControl>(CameraControl_Pan, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_TILT:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcControl->Get(CameraControl_Tilt, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcControl->GetRange(CameraControl_Tilt, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcControl->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMCameraControl>(CameraControl_Tilt, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_ROLL:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcControl->Get(CameraControl_Roll, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcControl->GetRange(CameraControl_Roll, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcControl->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMCameraControl>(CameraControl_Roll, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_IRIS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcControl->Get(CameraControl_Iris, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcControl->GetRange(CameraControl_Iris, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcControl->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMCameraControl>(CameraControl_Iris, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_EXPOSURE:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcControl->Get(CameraControl_Exposure, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcControl->GetRange(CameraControl_Exposure, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcControl->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
case CV_CAP_PROP_AUTO_EXPOSURE:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
if (readComplexPropery<IAMCameraControl>(CameraControl_Exposure, cVal))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcControl->Get(CameraControl_Exposure, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcControl->GetRange(CameraControl_Exposure, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcControl->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramFlag == VideoProcAmp_Flags_Auto;
|
||||
if (property_id == CV_CAP_PROP_EXPOSURE)
|
||||
return cVal;
|
||||
else
|
||||
return cVal == VideoProcAmp_Flags_Auto;
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_ZOOM:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcControl->Get(CameraControl_Zoom, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcControl->GetRange(CameraControl_Zoom, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcControl->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
if (readComplexPropery<IAMCameraControl>(CameraControl_Zoom, cVal))
|
||||
return cVal;
|
||||
break;
|
||||
case CV_CAP_PROP_FOCUS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcControl->Get(CameraControl_Focus, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcControl->GetRange(CameraControl_Focus, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcControl->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramVal;
|
||||
}
|
||||
case CV_CAP_PROP_AUTOFOCUS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
if (readComplexPropery<IAMCameraControl>(CameraControl_Focus, cVal))
|
||||
{
|
||||
long paramVal, paramFlag;
|
||||
HRESULT hr = pProcControl->Get(CameraControl_Focus, ¶mVal, ¶mFlag);
|
||||
long minVal, maxVal, stepVal;
|
||||
if (FAILED(hr))
|
||||
hr = pProcControl->GetRange(CameraControl_Focus, &minVal, &maxVal, &stepVal, ¶mVal, ¶mFlag);//Unable to get the property, trying to return default value
|
||||
pProcControl->Release();
|
||||
if (SUCCEEDED(hr))
|
||||
return paramFlag == VideoProcAmp_Flags_Auto;
|
||||
if (property_id == CV_CAP_PROP_FOCUS)
|
||||
return cVal;
|
||||
else
|
||||
return cVal == VideoProcAmp_Flags_Auto;
|
||||
}
|
||||
break;
|
||||
|
||||
case CV_CAP_PROP_WHITE_BALANCE_BLUE_U:
|
||||
case CV_CAP_PROP_WHITE_BALANCE_RED_V:
|
||||
case CV_CAP_PROP_RECTIFICATION:
|
||||
case CV_CAP_PROP_TRIGGER:
|
||||
case CV_CAP_PROP_TRIGGER_DELAY:
|
||||
@@ -1667,15 +1265,29 @@ double CvCapture_MSMF::getProperty( int property_id ) const
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename CtrlT>
|
||||
bool CvCapture_MSMF::writeComplexProperty(long prop, double val, long flags)
|
||||
{
|
||||
_ComPtr<CtrlT> ctrl;
|
||||
if (FAILED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&ctrl))))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Failed get service for stream");
|
||||
return false;
|
||||
}
|
||||
if (FAILED(ctrl->Set(prop, (long)val, flags)))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "Failed to set property " << prop);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CvCapture_MSMF::setProperty( int property_id, double value )
|
||||
{
|
||||
IAMVideoProcAmp *pProcAmp = NULL;
|
||||
IAMCameraControl *pProcControl = NULL;
|
||||
// image capture properties
|
||||
MediaType newFormat = captureFormat;
|
||||
if (isOpen)
|
||||
switch (property_id)
|
||||
{
|
||||
@@ -1690,28 +1302,45 @@ bool CvCapture_MSMF::setProperty( int property_id, double value )
|
||||
return false;
|
||||
}
|
||||
case CV_CAP_PROP_FOURCC:
|
||||
return configureOutput(requestedWidth, requestedHeight, getFramerate(nativeFormat), aspectN, aspectD, (int)cvRound(value), convertFormat);
|
||||
return configureOutput(newFormat, (int)cvRound(value), convertFormat);
|
||||
case CV_CAP_PROP_FORMAT:
|
||||
return configureOutput(newFormat, (int)cvRound(value), convertFormat);
|
||||
case CV_CAP_PROP_CONVERT_RGB:
|
||||
return configureOutput(requestedWidth, requestedHeight, getFramerate(nativeFormat), aspectN, aspectD, outputFormat, value != 0);
|
||||
return configureOutput(newFormat, outputFormat, value != 0);
|
||||
case CV_CAP_PROP_SAR_NUM:
|
||||
if (value > 0)
|
||||
return configureOutput(requestedWidth, requestedHeight, getFramerate(nativeFormat), (UINT32)cvRound(value), aspectD, outputFormat, convertFormat);
|
||||
{
|
||||
newFormat.aspectRatioNum = (UINT32)cvRound(value);
|
||||
return configureOutput(newFormat, outputFormat, convertFormat);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_SAR_DEN:
|
||||
if (value > 0)
|
||||
return configureOutput(requestedWidth, requestedHeight, getFramerate(nativeFormat), aspectN, (UINT32)cvRound(value), outputFormat, convertFormat);
|
||||
{
|
||||
newFormat.aspectRatioDenom = (UINT32)cvRound(value);
|
||||
return configureOutput(newFormat, outputFormat, convertFormat);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_FRAME_WIDTH:
|
||||
if (value >= 0)
|
||||
return configureOutput((UINT32)cvRound(value), requestedHeight, getFramerate(nativeFormat), aspectN, aspectD, outputFormat, convertFormat);
|
||||
{
|
||||
newFormat.width = (UINT32)cvRound(value);
|
||||
return configureOutput(newFormat, outputFormat, convertFormat);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_FRAME_HEIGHT:
|
||||
if (value >= 0)
|
||||
return configureOutput(requestedWidth, (UINT32)cvRound(value), getFramerate(nativeFormat), aspectN, aspectD, outputFormat, convertFormat);
|
||||
{
|
||||
newFormat.height = (UINT32)cvRound(value);
|
||||
return configureOutput(newFormat, outputFormat, convertFormat);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_FPS:
|
||||
if (value >= 0)
|
||||
return configureOutput(requestedWidth, requestedHeight, value, aspectN, aspectD, outputFormat, convertFormat);
|
||||
{
|
||||
newFormat.setFramerate(value);
|
||||
return configureOutput(newFormat, outputFormat, convertFormat);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_FRAME_COUNT:
|
||||
break;
|
||||
@@ -1720,183 +1349,51 @@ bool CvCapture_MSMF::setProperty( int property_id, double value )
|
||||
return setTime(duration * value, true);
|
||||
break;
|
||||
case CV_CAP_PROP_POS_FRAMES:
|
||||
if (std::fabs(getFramerate(nativeFormat)) > 0)
|
||||
return setTime(value * 1e7 / getFramerate(nativeFormat), false);
|
||||
if (std::fabs(captureFormat.getFramerate()) > 0)
|
||||
return setTime(value * 1e7 / captureFormat.getFramerate(), false);
|
||||
break;
|
||||
case CV_CAP_PROP_POS_MSEC:
|
||||
return setTime(value * 1e4, false);
|
||||
case CV_CAP_PROP_BRIGHTNESS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_Brightness, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_Brightness, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_CONTRAST:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_Contrast, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_Contrast, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_SATURATION:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_Saturation, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_Saturation, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_HUE:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_Hue, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_Hue, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_GAIN:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_Gain, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_Gain, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_SHARPNESS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_Sharpness, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_Sharpness, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_GAMMA:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_Gamma, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_Gamma, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_BACKLIGHT:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_BacklightCompensation, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_BacklightCompensation, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_MONOCHROME:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = value != 0 ? 0 : 1;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_ColorEnable, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_ColorEnable, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_TEMPERATURE:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcAmp))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcAmp->Set(VideoProcAmp_WhiteBalance, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcAmp->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
return writeComplexProperty<IAMVideoProcAmp>(VideoProcAmp_WhiteBalance, value, VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_PAN:
|
||||
return writeComplexProperty<IAMCameraControl>(CameraControl_Pan, value, CameraControl_Flags_Manual);
|
||||
case CV_CAP_PROP_TILT:
|
||||
return writeComplexProperty<IAMCameraControl>(CameraControl_Tilt, value, CameraControl_Flags_Manual);
|
||||
case CV_CAP_PROP_ROLL:
|
||||
return writeComplexProperty<IAMCameraControl>(CameraControl_Roll, value, CameraControl_Flags_Manual);
|
||||
case CV_CAP_PROP_IRIS:
|
||||
return writeComplexProperty<IAMCameraControl>(CameraControl_Iris, value, CameraControl_Flags_Manual);
|
||||
case CV_CAP_PROP_EXPOSURE:
|
||||
return writeComplexProperty<IAMCameraControl>(CameraControl_Exposure, value, CameraControl_Flags_Manual);
|
||||
case CV_CAP_PROP_AUTO_EXPOSURE:
|
||||
return writeComplexProperty<IAMCameraControl>(CameraControl_Exposure, value, value != 0 ? VideoProcAmp_Flags_Auto : VideoProcAmp_Flags_Manual);
|
||||
case CV_CAP_PROP_ZOOM:
|
||||
return writeComplexProperty<IAMCameraControl>(CameraControl_Zoom, value, CameraControl_Flags_Manual);
|
||||
case CV_CAP_PROP_FOCUS:
|
||||
return writeComplexProperty<IAMCameraControl>(CameraControl_Focus, value, CameraControl_Flags_Manual);
|
||||
case CV_CAP_PROP_AUTOFOCUS:
|
||||
return writeComplexProperty<IAMCameraControl>(CameraControl_Focus, value, value != 0 ? CameraControl_Flags_Auto : CameraControl_Flags_Manual);
|
||||
case CV_CAP_PROP_WHITE_BALANCE_BLUE_U:
|
||||
case CV_CAP_PROP_WHITE_BALANCE_RED_V:
|
||||
break;
|
||||
case CV_CAP_PROP_PAN:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcControl->Set(CameraControl_Pan, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcControl->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_TILT:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcControl->Set(CameraControl_Tilt, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcControl->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_ROLL:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcControl->Set(CameraControl_Roll, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcControl->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_IRIS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcControl->Set(CameraControl_Iris, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcControl->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_EXPOSURE:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcControl->Set(CameraControl_Exposure, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcControl->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
case CV_CAP_PROP_AUTO_EXPOSURE:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal = 0;
|
||||
HRESULT hr = pProcControl->Set(CameraControl_Exposure, paramVal, value != 0 ? VideoProcAmp_Flags_Auto : VideoProcAmp_Flags_Manual);
|
||||
pProcControl->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_ZOOM:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcControl->Set(CameraControl_Zoom, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcControl->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
case CV_CAP_PROP_FOCUS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal = (long)value;
|
||||
HRESULT hr = pProcControl->Set(CameraControl_Focus, paramVal, VideoProcAmp_Flags_Manual);
|
||||
pProcControl->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
case CV_CAP_PROP_AUTOFOCUS:
|
||||
if (SUCCEEDED(videoFileSource->GetServiceForStream((DWORD)MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&pProcControl))))
|
||||
{
|
||||
long paramVal = 0;
|
||||
HRESULT hr = pProcControl->Set(CameraControl_Focus, paramVal, value != 0 ? VideoProcAmp_Flags_Auto : VideoProcAmp_Flags_Manual);
|
||||
pProcControl->Release();
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
break;
|
||||
|
||||
case CV_CAP_PROP_RECTIFICATION:
|
||||
case CV_CAP_PROP_TRIGGER:
|
||||
case CV_CAP_PROP_TRIGGER_DELAY:
|
||||
@@ -1907,7 +1404,6 @@ bool CvCapture_MSMF::setProperty( int property_id, double value )
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,6 +119,8 @@ public:
|
||||
for (int k = 0; k < n_frames; ++k)
|
||||
{
|
||||
checkFrameRead(k, cap);
|
||||
if (::testing::Test::HasFailure() && k % 10 == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool canSeek = false;
|
||||
@@ -138,6 +140,8 @@ public:
|
||||
for (int k = 0; k < n_frames; k += 20)
|
||||
{
|
||||
checkFrameSeek(k, cap);
|
||||
if (::testing::Test::HasFailure() && k % 10 == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +154,8 @@ public:
|
||||
for (int k = 0; k < 10; ++k)
|
||||
{
|
||||
checkFrameSeek(cvtest::TS::ptr()->get_rng().uniform(0, n_frames), cap);
|
||||
if (::testing::Test::HasFailure() && k % 10 == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,6 +223,8 @@ public:
|
||||
EXPECT_EQ(bunny_param.getWidth(), frame.cols);
|
||||
EXPECT_EQ(bunny_param.getHeight(), frame.rows);
|
||||
count_actual += 1;
|
||||
if (::testing::Test::HasFailure() && count_actual % 10 == 0)
|
||||
break;
|
||||
}
|
||||
if (count_prop > 0)
|
||||
{
|
||||
@@ -272,6 +280,8 @@ public:
|
||||
{
|
||||
generateFrame(i, frame_count, img);
|
||||
EXPECT_NO_THROW(writer << img);
|
||||
if (::testing::Test::HasFailure() && i % 10 == 0)
|
||||
break;
|
||||
}
|
||||
EXPECT_NO_THROW(writer.release());
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ if(INSTALL_PYTHON_EXAMPLES)
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
|
||||
ocv_install_example_src("." CMakeLists.txt)
|
||||
ocv_install_example_src("." CMakeLists.txt samples_utils.cmake)
|
||||
if(INSTALL_C_EXAMPLES)
|
||||
install(DIRECTORY data DESTINATION "${OPENCV_SAMPLES_SRC_INSTALL_PATH}" COMPONENT samples_data)
|
||||
endif()
|
||||
|
||||
Reference in New Issue
Block a user