Merge pull request #479 from ilya-lavrenov:TestHighGUI

This commit is contained in:
Andrey Kamaev 2013-02-14 11:21:01 +04:00 committed by OpenCV Buildbot
commit 37e2664cf0
3 changed files with 283 additions and 106 deletions

View File

@ -57,21 +57,42 @@ static CvCreateVideoWriter_Plugin icvCreateVideoWriter_FFMPEG_p = 0;
static CvReleaseVideoWriter_Plugin icvReleaseVideoWriter_FFMPEG_p = 0;
static CvWriteFrame_Plugin icvWriteFrame_FFMPEG_p = 0;
static void
icvInitFFMPEG(void)
static cv::Mutex _icvInitFFMPEG_mutex;
class icvInitFFMPEG
{
static int ffmpegInitialized = 0;
if( !ffmpegInitialized )
public:
static void Init()
{
cv::AutoLock al(_icvInitFFMPEG_mutex);
static icvInitFFMPEG init;
}
private:
#if defined WIN32 || defined _WIN32
HMODULE icvFFOpenCV;
~icvInitFFMPEG()
{
if (icvFFOpenCV)
{
FreeLibrary(icvFFOpenCV);
icvFFOpenCV = 0;
}
}
#endif
icvInitFFMPEG()
{
#if defined WIN32 || defined _WIN32
const char* module_name = "opencv_ffmpeg"
CVAUX_STR(CV_VERSION_EPOCH) CVAUX_STR(CV_VERSION_MAJOR) CVAUX_STR(CV_VERSION_MINOR)
CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
"_64"
#endif
".dll";
static HMODULE icvFFOpenCV = LoadLibrary( module_name );
icvFFOpenCV = LoadLibrary( module_name );
if( icvFFOpenCV )
{
icvCreateFileCapture_FFMPEG_p =
@ -93,18 +114,24 @@ icvInitFFMPEG(void)
icvWriteFrame_FFMPEG_p =
(CvWriteFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvWriteFrame_FFMPEG");
if( icvCreateFileCapture_FFMPEG_p == NULL ||
icvReleaseCapture_FFMPEG_p == NULL ||
icvGrabFrame_FFMPEG_p == NULL ||
icvRetrieveFrame_FFMPEG_p == NULL ||
icvSetCaptureProperty_FFMPEG_p == NULL ||
icvGetCaptureProperty_FFMPEG_p == NULL ||
icvCreateVideoWriter_FFMPEG_p == NULL ||
icvReleaseVideoWriter_FFMPEG_p == NULL ||
icvWriteFrame_FFMPEG_p == NULL )
#if 0
if( icvCreateFileCapture_FFMPEG_p != 0 &&
icvReleaseCapture_FFMPEG_p != 0 &&
icvGrabFrame_FFMPEG_p != 0 &&
icvRetrieveFrame_FFMPEG_p != 0 &&
icvSetCaptureProperty_FFMPEG_p != 0 &&
icvGetCaptureProperty_FFMPEG_p != 0 &&
icvCreateVideoWriter_FFMPEG_p != 0 &&
icvReleaseVideoWriter_FFMPEG_p != 0 &&
icvWriteFrame_FFMPEG_p != 0 )
{
fprintf(stderr, "Failed to load FFMPEG plugin: module handle=%p\n", icvFFOpenCV);
printf("Successfully initialized ffmpeg plugin!\n");
}
else
{
printf("Failed to load FFMPEG plugin: module handle=%p\n", icvFFOpenCV);
}
#endif
}
#elif defined HAVE_FFMPEG
icvCreateFileCapture_FFMPEG_p = (CvCreateFileCapture_Plugin)cvCreateFileCapture_FFMPEG;
@ -117,13 +144,12 @@ icvInitFFMPEG(void)
icvReleaseVideoWriter_FFMPEG_p = (CvReleaseVideoWriter_Plugin)cvReleaseVideoWriter_FFMPEG;
icvWriteFrame_FFMPEG_p = (CvWriteFrame_Plugin)cvWriteFrame_FFMPEG;
#endif
ffmpegInitialized = 1;
}
}
};
class CvCapture_FFMPEG_proxy : public CvCapture
class CvCapture_FFMPEG_proxy :
public CvCapture
{
public:
CvCapture_FFMPEG_proxy() { ffmpegCapture = 0; }
@ -146,18 +172,18 @@ public:
unsigned char* data = 0;
int step=0, width=0, height=0, cn=0;
if(!ffmpegCapture ||
!icvRetrieveFrame_FFMPEG_p(ffmpegCapture,&data,&step,&width,&height,&cn))
return 0;
if (!ffmpegCapture ||
!icvRetrieveFrame_FFMPEG_p(ffmpegCapture, &data, &step, &width, &height, &cn))
return 0;
cvInitImageHeader(&frame, cvSize(width, height), 8, cn);
cvSetData(&frame, data, step);
return &frame;
}
virtual bool open( const char* filename )
{
icvInitFFMPEG::Init();
close();
icvInitFFMPEG();
if( !icvCreateFileCapture_FFMPEG_p )
return false;
ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename );
@ -190,8 +216,8 @@ CvCapture* cvCreateFileCapture_FFMPEG_proxy(const char * filename)
#endif
}
class CvVideoWriter_FFMPEG_proxy : public CvVideoWriter
class CvVideoWriter_FFMPEG_proxy :
public CvVideoWriter
{
public:
CvVideoWriter_FFMPEG_proxy() { ffmpegWriter = 0; }
@ -208,8 +234,8 @@ public:
}
virtual bool open( const char* filename, int fourcc, double fps, CvSize frameSize, bool isColor )
{
icvInitFFMPEG::Init();
close();
icvInitFFMPEG();
if( !icvCreateVideoWriter_FFMPEG_p )
return false;
ffmpegWriter = icvCreateVideoWriter_FFMPEG_p( filename, fourcc, fps, frameSize.width, frameSize.height, isColor );

View File

@ -332,28 +332,187 @@ void CvCapture_FFMPEG::close()
#define AVSEEK_FLAG_ANY 1
#endif
static void icvInitFFMPEG_internal()
class ImplMutex
{
static volatile bool initialized = false;
if( !initialized )
public:
ImplMutex() { init(); }
~ImplMutex() { destroy(); }
void init();
void destroy();
void lock();
bool trylock();
void unlock();
struct Impl;
protected:
Impl* impl;
private:
ImplMutex(const ImplMutex&);
ImplMutex& operator = (const ImplMutex& m);
};
#if defined WIN32 || defined _WIN32 || defined WINCE
struct ImplMutex::Impl
{
void init() { InitializeCriticalSection(&cs); refcount = 1; }
void destroy() { DeleteCriticalSection(&cs); }
void lock() { EnterCriticalSection(&cs); }
bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
void unlock() { LeaveCriticalSection(&cs); }
CRITICAL_SECTION cs;
int refcount;
};
#ifndef __GNUC__
static int _interlockedExchangeAdd(int* addr, int delta)
{
#if defined _MSC_VER && _MSC_VER >= 1500
return (int)_InterlockedExchangeAdd((long volatile*)addr, delta);
#else
return (int)InterlockedExchangeAdd((long volatile*)addr, delta);
#endif
}
#endif // __GNUC__
#elif defined __APPLE__
#include <libkern/OSAtomic.h>
struct ImplMutex::Impl
{
void init() { sl = OS_SPINLOCK_INIT; refcount = 1; }
void destroy() { }
void lock() { OSSpinLockLock(&sl); }
bool trylock() { return OSSpinLockTry(&sl); }
void unlock() { OSSpinLockUnlock(&sl); }
OSSpinLock sl;
int refcount;
};
#elif defined __linux__ && !defined ANDROID
struct ImplMutex::Impl
{
void init() { pthread_spin_init(&sl, 0); refcount = 1; }
void destroy() { pthread_spin_destroy(&sl); }
void lock() { pthread_spin_lock(&sl); }
bool trylock() { return pthread_spin_trylock(&sl) == 0; }
void unlock() { pthread_spin_unlock(&sl); }
pthread_spinlock_t sl;
int refcount;
};
#else
struct ImplMutex::Impl
{
void init() { pthread_mutex_init(&sl, 0); refcount = 1; }
void destroy() { pthread_mutex_destroy(&sl); }
void lock() { pthread_mutex_lock(&sl); }
bool trylock() { return pthread_mutex_trylock(&sl) == 0; }
void unlock() { pthread_mutex_unlock(&sl); }
pthread_mutex_t sl;
int refcount;
};
#endif
void ImplMutex::init()
{
impl = (Impl*)malloc(sizeof(Impl));
impl->init();
}
void ImplMutex::destroy()
{
impl->destroy();
free(impl);
impl = NULL;
}
void ImplMutex::lock() { impl->lock(); }
void ImplMutex::unlock() { impl->unlock(); }
bool ImplMutex::trylock() { return impl->trylock(); }
static int LockCallBack(void **mutex, AVLockOp op)
{
ImplMutex* localMutex = reinterpret_cast<ImplMutex*>(*mutex);
switch (op)
{
case AV_LOCK_CREATE:
localMutex = reinterpret_cast<ImplMutex*>(malloc(sizeof(ImplMutex)));
localMutex->init();
*mutex = localMutex;
if (!*mutex)
return 1;
break;
case AV_LOCK_OBTAIN:
localMutex->lock();
break;
case AV_LOCK_RELEASE:
localMutex->unlock();
break;
case AV_LOCK_DESTROY:
localMutex->destroy();
free(localMutex);
localMutex = NULL;
break;
}
return 0;
}
static ImplMutex _mutex;
static bool _initialized = false;
class InternalFFMpegRegister
{
public:
InternalFFMpegRegister()
{
_mutex.lock();
if (!_initialized)
{
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
avformat_network_init();
avformat_network_init();
#endif
/* register all codecs, demux and protocols */
av_register_all();
/* register all codecs, demux and protocols */
av_register_all();
av_log_set_level(AV_LOG_ERROR);
/* register a callback function for synchronization */
av_lockmgr_register(&LockCallBack);
initialized = true;
av_log_set_level(AV_LOG_ERROR);
_initialized = true;
}
_mutex.unlock();
}
}
~InternalFFMpegRegister()
{
_initialized = false;
av_lockmgr_register(NULL);
}
};
static InternalFFMpegRegister _init;
bool CvCapture_FFMPEG::open( const char* _filename )
{
icvInitFFMPEG_internal();
unsigned i;
bool valid = false;
@ -365,7 +524,8 @@ bool CvCapture_FFMPEG::open( const char* _filename )
int err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
#endif
if (err < 0) {
if (err < 0)
{
CV_WARN("Error opening file");
goto exit_func;
}
@ -375,7 +535,8 @@ bool CvCapture_FFMPEG::open( const char* _filename )
#else
av_find_stream_info(ic);
#endif
if (err < 0) {
if (err < 0)
{
CV_WARN("Could not find codec parameters");
goto exit_func;
}
@ -387,17 +548,18 @@ bool CvCapture_FFMPEG::open( const char* _filename )
AVCodecContext *enc = &ic->streams[i]->codec;
#endif
#ifdef FF_API_THREAD_INIT
avcodec_thread_init(enc, get_number_of_cpus());
#else
//#ifdef FF_API_THREAD_INIT
// avcodec_thread_init(enc, get_number_of_cpus());
//#else
enc->thread_count = get_number_of_cpus();
#endif
//#endif
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
#endif
if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0) {
if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0)
{
AVCodec *codec = avcodec_find_decoder(enc->codec_id);
if (!codec ||
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
@ -405,7 +567,8 @@ bool CvCapture_FFMPEG::open( const char* _filename )
#else
avcodec_open(enc, codec)
#endif
< 0) goto exit_func;
< 0)
goto exit_func;
video_stream = i;
video_st = ic->streams[i];
@ -1279,8 +1442,6 @@ void CvVideoWriter_FFMPEG::close()
bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
double fps, int width, int height, bool is_color )
{
icvInitFFMPEG_internal();
CodecID codec_id = CODEC_ID_NONE;
int err, codec_pix_fmt;
double bitrate_scale = 1;
@ -1499,6 +1660,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
frame_width = width;
frame_height = height;
ok = true;
return true;
}
@ -1510,6 +1672,7 @@ CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
capture->init();
if( capture->open( filename ))
return capture;
capture->close();
free(capture);
return 0;
@ -1558,7 +1721,6 @@ CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int four
return 0;
}
void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )
{
if( writer && *writer )
@ -1749,11 +1911,6 @@ bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height,
oc_ = 0;
video_st_ = 0;
// tell FFMPEG to register codecs
av_register_all();
av_log_set_level(AV_LOG_ERROR);
// auto detect the output format from the name and fourcc code
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
fmt_ = av_guess_format(NULL, fileName, NULL);
@ -1934,11 +2091,6 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma
avformat_network_init();
#endif
// register all codecs, demux and protocols
av_register_all();
av_log_set_level(AV_LOG_ERROR);
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)
err = avformat_open_input(&ctx_, fileName, 0, 0);
#else

View File

@ -207,7 +207,6 @@ public:
}
}
private:
std::vector<VideoWriter*>* writers;
std::vector<std::string>* files;
@ -241,18 +240,18 @@ public:
virtual void operator() (const Range& range) const
{
if((range.start + 1) != range.end)
return;
VideoWriter* writer = writers->operator[](range.start);
CV_Assert(writer != NULL);
CV_Assert(writer->isOpened());
Mat frame(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
for (unsigned int i = 0; i < FrameCount; ++i)
for (int j = range.start; j < range.end; ++j)
{
GenerateFrame(frame, i);
writer->operator<< (frame);
VideoWriter* writer = writers->operator[](j);
CV_Assert(writer != NULL);
CV_Assert(writer->isOpened());
Mat frame(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
for (unsigned int i = 0; i < FrameCount; ++i)
{
GenerateFrame(frame, i);
writer->operator<< (frame);
}
}
}
@ -305,47 +304,47 @@ public:
virtual void operator() (const Range& range) const
{
if((range.start + 1) != range.end)
return;
VideoCapture* capture = readers->operator[](range.start);
CV_Assert(capture != NULL);
CV_Assert(capture->isOpened());
const static double eps = 23.0;
unsigned int frameCount = static_cast<unsigned int>(capture->get(CV_CAP_PROP_FRAME_COUNT));
CV_Assert(frameCount == WriteVideo_Invoker::FrameCount);
Mat reference(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
for (unsigned int i = 0; i < frameCount && next; ++i)
for (int j = range.start; j < range.end; ++j)
{
Mat actual;
(*capture) >> actual;
VideoCapture* capture = readers->operator[](j);
CV_Assert(capture != NULL);
CV_Assert(capture->isOpened());
WriteVideo_Invoker::GenerateFrame(reference, i);
const static double eps = 23.0;
unsigned int frameCount = static_cast<unsigned int>(capture->get(CV_CAP_PROP_FRAME_COUNT));
CV_Assert(frameCount == WriteVideo_Invoker::FrameCount);
Mat reference(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
EXPECT_EQ(reference.cols, actual.cols);
EXPECT_EQ(reference.rows, actual.rows);
EXPECT_EQ(reference.depth(), actual.depth());
EXPECT_EQ(reference.channels(), actual.channels());
double psnr = PSNR(actual, reference);
if (psnr < eps)
for (unsigned int i = 0; i < frameCount && next; ++i)
{
#define SUM cvtest::TS::SUMMARY
ts->printf(SUM, "\nPSNR: %lf\n", psnr);
ts->printf(SUM, "Video #: %d\n", range.start);
ts->printf(SUM, "Frame #: %d\n", i);
#undef SUM
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->set_gtest_status();
Mat actual;
(*capture) >> actual;
Mat diff;
absdiff(actual, reference, diff);
WriteVideo_Invoker::GenerateFrame(reference, i);
EXPECT_EQ(countNonZero(diff.reshape(1) > 1), 0);
EXPECT_EQ(reference.cols, actual.cols);
EXPECT_EQ(reference.rows, actual.rows);
EXPECT_EQ(reference.depth(), actual.depth());
EXPECT_EQ(reference.channels(), actual.channels());
next = false;
double psnr = PSNR(actual, reference);
if (psnr < eps)
{
#define SUM cvtest::TS::SUMMARY
ts->printf(SUM, "\nPSNR: %lf\n", psnr);
ts->printf(SUM, "Video #: %d\n", range.start);
ts->printf(SUM, "Frame #: %d\n", i);
#undef SUM
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->set_gtest_status();
Mat diff;
absdiff(actual, reference, diff);
EXPECT_EQ(countNonZero(diff.reshape(1) > 1), 0);
next = false;
}
}
}
}
@ -359,7 +358,7 @@ private:
bool ReadImageAndTest::next;
TEST(Highgui_Video_parallel_writers_and_readers, DISABLED_accuracy)
TEST(Highgui_Video_parallel_writers_and_readers, accuracy)
{
const unsigned int threadsCount = 4;
cvtest::TS* ts = cvtest::TS::ptr();