Merge branch 'ParallelVideoStreams' of https://github.com/ilya-lavrenov/opencv into 2.4
This commit is contained in:
commit
c31f106012
@ -424,7 +424,6 @@ CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc,
|
|||||||
|
|
||||||
CV_IMPL int cvWriteFrame( CvVideoWriter* writer, const IplImage* image )
|
CV_IMPL int cvWriteFrame( CvVideoWriter* writer, const IplImage* image )
|
||||||
{
|
{
|
||||||
|
|
||||||
return writer ? writer->writeFrame(image) : 0;
|
return writer ? writer->writeFrame(image) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +57,32 @@ static CvCreateVideoWriter_Plugin icvCreateVideoWriter_FFMPEG_p = 0;
|
|||||||
static CvReleaseVideoWriter_Plugin icvReleaseVideoWriter_FFMPEG_p = 0;
|
static CvReleaseVideoWriter_Plugin icvReleaseVideoWriter_FFMPEG_p = 0;
|
||||||
static CvWriteFrame_Plugin icvWriteFrame_FFMPEG_p = 0;
|
static CvWriteFrame_Plugin icvWriteFrame_FFMPEG_p = 0;
|
||||||
|
|
||||||
static void
|
static cv::Mutex _icvInitFFMPEG_mutex;
|
||||||
icvInitFFMPEG(void)
|
|
||||||
|
class icvInitFFMPEG
|
||||||
{
|
{
|
||||||
static int ffmpegInitialized = 0;
|
public:
|
||||||
if( !ffmpegInitialized )
|
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
|
#if defined WIN32 || defined _WIN32
|
||||||
const char* module_name = "opencv_ffmpeg"
|
const char* module_name = "opencv_ffmpeg"
|
||||||
@ -71,7 +92,7 @@ icvInitFFMPEG(void)
|
|||||||
#endif
|
#endif
|
||||||
".dll";
|
".dll";
|
||||||
|
|
||||||
static HMODULE icvFFOpenCV = LoadLibrary( module_name );
|
icvFFOpenCV = LoadLibrary( module_name );
|
||||||
if( icvFFOpenCV )
|
if( icvFFOpenCV )
|
||||||
{
|
{
|
||||||
icvCreateFileCapture_FFMPEG_p =
|
icvCreateFileCapture_FFMPEG_p =
|
||||||
@ -123,10 +144,8 @@ icvInitFFMPEG(void)
|
|||||||
icvReleaseVideoWriter_FFMPEG_p = (CvReleaseVideoWriter_Plugin)cvReleaseVideoWriter_FFMPEG;
|
icvReleaseVideoWriter_FFMPEG_p = (CvReleaseVideoWriter_Plugin)cvReleaseVideoWriter_FFMPEG;
|
||||||
icvWriteFrame_FFMPEG_p = (CvWriteFrame_Plugin)cvWriteFrame_FFMPEG;
|
icvWriteFrame_FFMPEG_p = (CvWriteFrame_Plugin)cvWriteFrame_FFMPEG;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ffmpegInitialized = 1;
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
class CvCapture_FFMPEG_proxy : public CvCapture
|
class CvCapture_FFMPEG_proxy : public CvCapture
|
||||||
@ -161,9 +180,9 @@ public:
|
|||||||
}
|
}
|
||||||
virtual bool open( const char* filename )
|
virtual bool open( const char* filename )
|
||||||
{
|
{
|
||||||
|
icvInitFFMPEG::Init();
|
||||||
close();
|
close();
|
||||||
|
|
||||||
icvInitFFMPEG();
|
|
||||||
if( !icvCreateFileCapture_FFMPEG_p )
|
if( !icvCreateFileCapture_FFMPEG_p )
|
||||||
return false;
|
return false;
|
||||||
ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename );
|
ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename );
|
||||||
@ -196,7 +215,6 @@ CvCapture* cvCreateFileCapture_FFMPEG_proxy(const char * filename)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class CvVideoWriter_FFMPEG_proxy : public CvVideoWriter
|
class CvVideoWriter_FFMPEG_proxy : public CvVideoWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -214,8 +232,8 @@ public:
|
|||||||
}
|
}
|
||||||
virtual bool open( const char* filename, int fourcc, double fps, CvSize frameSize, bool isColor )
|
virtual bool open( const char* filename, int fourcc, double fps, CvSize frameSize, bool isColor )
|
||||||
{
|
{
|
||||||
|
icvInitFFMPEG::Init();
|
||||||
close();
|
close();
|
||||||
icvInitFFMPEG();
|
|
||||||
if( !icvCreateVideoWriter_FFMPEG_p )
|
if( !icvCreateVideoWriter_FFMPEG_p )
|
||||||
return false;
|
return false;
|
||||||
ffmpegWriter = icvCreateVideoWriter_FFMPEG_p( filename, fourcc, fps, frameSize.width, frameSize.height, isColor );
|
ffmpegWriter = icvCreateVideoWriter_FFMPEG_p( filename, fourcc, fps, frameSize.width, frameSize.height, isColor );
|
||||||
|
@ -328,28 +328,179 @@ void CvCapture_FFMPEG::close()
|
|||||||
#define AVSEEK_FLAG_ANY 1
|
#define AVSEEK_FLAG_ANY 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void icvInitFFMPEG_internal()
|
class ImplMutex
|
||||||
{
|
{
|
||||||
static volatile bool initialized = false;
|
public:
|
||||||
if( !initialized )
|
ImplMutex();
|
||||||
|
~ImplMutex();
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
Impl() { InitializeCriticalSection(&cs); refcount = 1; }
|
||||||
|
~Impl() { 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
|
||||||
|
{
|
||||||
|
Impl() { sl = OS_SPINLOCK_INIT; refcount = 1; }
|
||||||
|
~Impl() {}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
Impl() { pthread_spin_init(&sl, 0); refcount = 1; }
|
||||||
|
~Impl() { 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
|
||||||
|
{
|
||||||
|
Impl() { pthread_mutex_init(&sl, 0); refcount = 1; }
|
||||||
|
~Impl() { 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
|
||||||
|
|
||||||
|
ImplMutex::ImplMutex()
|
||||||
|
{
|
||||||
|
impl = new ImplMutex::Impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImplMutex::~ImplMutex()
|
||||||
|
{
|
||||||
|
delete impl;
|
||||||
|
impl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImplMutex::lock() { impl->lock(); }
|
||||||
|
void ImplMutex::unlock() { impl->unlock(); }
|
||||||
|
bool ImplMutex::trylock() { return impl->trylock(); }
|
||||||
|
|
||||||
|
static int LockCallBack(void **mutex, AVLockOp op)
|
||||||
|
{
|
||||||
|
switch (op)
|
||||||
{
|
{
|
||||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
|
case AV_LOCK_CREATE:
|
||||||
|
*mutex = reinterpret_cast<void*>(new ImplMutex());
|
||||||
|
if (!*mutex)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AV_LOCK_OBTAIN:
|
||||||
|
reinterpret_cast<ImplMutex*>(*mutex)->lock();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AV_LOCK_RELEASE:
|
||||||
|
reinterpret_cast<ImplMutex*>(*mutex)->unlock();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AV_LOCK_DESTROY:
|
||||||
|
ImplMutex* cv_mutex = reinterpret_cast<ImplMutex*>(*mutex);
|
||||||
|
delete cv_mutex;
|
||||||
|
cv_mutex = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ImplMutex _InternalFFMpegRegister_mutex;
|
||||||
|
|
||||||
|
class InternalFFMpegRegister
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Register()
|
||||||
|
{
|
||||||
|
_InternalFFMpegRegister_mutex.lock();
|
||||||
|
static InternalFFMpegRegister init;
|
||||||
|
_InternalFFMpegRegister_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
~InternalFFMpegRegister()
|
||||||
|
{
|
||||||
|
av_lockmgr_register(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
InternalFFMpegRegister()
|
||||||
|
{
|
||||||
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
|
||||||
avformat_network_init();
|
avformat_network_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* register all codecs, demux and protocols */
|
/* register all codecs, demux and protocols */
|
||||||
av_register_all();
|
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);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
bool CvCapture_FFMPEG::open( const char* _filename )
|
bool CvCapture_FFMPEG::open( const char* _filename )
|
||||||
{
|
{
|
||||||
icvInitFFMPEG_internal();
|
InternalFFMpegRegister::Register();
|
||||||
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
||||||
@ -361,7 +512,8 @@ bool CvCapture_FFMPEG::open( const char* _filename )
|
|||||||
int err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
|
int err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0)
|
||||||
|
{
|
||||||
CV_WARN("Error opening file");
|
CV_WARN("Error opening file");
|
||||||
goto exit_func;
|
goto exit_func;
|
||||||
}
|
}
|
||||||
@ -371,7 +523,8 @@ bool CvCapture_FFMPEG::open( const char* _filename )
|
|||||||
#else
|
#else
|
||||||
av_find_stream_info(ic);
|
av_find_stream_info(ic);
|
||||||
#endif
|
#endif
|
||||||
if (err < 0) {
|
if (err < 0)
|
||||||
|
{
|
||||||
CV_WARN("Could not find codec parameters");
|
CV_WARN("Could not find codec parameters");
|
||||||
goto exit_func;
|
goto exit_func;
|
||||||
}
|
}
|
||||||
@ -393,7 +546,8 @@ bool CvCapture_FFMPEG::open( const char* _filename )
|
|||||||
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
|
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
|
||||||
#endif
|
#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);
|
AVCodec *codec = avcodec_find_decoder(enc->codec_id);
|
||||||
if (!codec ||
|
if (!codec ||
|
||||||
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
|
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
|
||||||
@ -401,7 +555,8 @@ bool CvCapture_FFMPEG::open( const char* _filename )
|
|||||||
#else
|
#else
|
||||||
avcodec_open(enc, codec)
|
avcodec_open(enc, codec)
|
||||||
#endif
|
#endif
|
||||||
< 0) goto exit_func;
|
< 0)
|
||||||
|
goto exit_func;
|
||||||
|
|
||||||
video_stream = i;
|
video_stream = i;
|
||||||
video_st = ic->streams[i];
|
video_st = ic->streams[i];
|
||||||
@ -1275,7 +1430,7 @@ void CvVideoWriter_FFMPEG::close()
|
|||||||
bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||||
double fps, int width, int height, bool is_color )
|
double fps, int width, int height, bool is_color )
|
||||||
{
|
{
|
||||||
icvInitFFMPEG_internal();
|
InternalFFMpegRegister::Register();
|
||||||
|
|
||||||
CodecID codec_id = CODEC_ID_NONE;
|
CodecID codec_id = CODEC_ID_NONE;
|
||||||
int err, codec_pix_fmt;
|
int err, codec_pix_fmt;
|
||||||
@ -1495,6 +1650,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
|||||||
frame_width = width;
|
frame_width = width;
|
||||||
frame_height = height;
|
frame_height = height;
|
||||||
ok = true;
|
ok = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1506,6 +1662,7 @@ CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
|
|||||||
capture->init();
|
capture->init();
|
||||||
if( capture->open( filename ))
|
if( capture->open( filename ))
|
||||||
return capture;
|
return capture;
|
||||||
|
|
||||||
capture->close();
|
capture->close();
|
||||||
free(capture);
|
free(capture);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1554,7 +1711,6 @@ CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int four
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )
|
void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )
|
||||||
{
|
{
|
||||||
if( writer && *writer )
|
if( writer && *writer )
|
||||||
@ -1741,15 +1897,12 @@ AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CodecID
|
|||||||
|
|
||||||
bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height, double fps)
|
bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height, double fps)
|
||||||
{
|
{
|
||||||
|
InternalFFMpegRegister::Register();
|
||||||
|
|
||||||
fmt_ = 0;
|
fmt_ = 0;
|
||||||
oc_ = 0;
|
oc_ = 0;
|
||||||
video_st_ = 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
|
// auto detect the output format from the name and fourcc code
|
||||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
|
||||||
fmt_ = av_guess_format(NULL, fileName, NULL);
|
fmt_ = av_guess_format(NULL, fileName, NULL);
|
||||||
@ -1920,6 +2073,8 @@ private:
|
|||||||
|
|
||||||
bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma_format, int* width, int* height)
|
bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma_format, int* width, int* height)
|
||||||
{
|
{
|
||||||
|
InternalFFMpegRegister::Register();
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
ctx_ = 0;
|
ctx_ = 0;
|
||||||
@ -1930,11 +2085,6 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma
|
|||||||
avformat_network_init();
|
avformat_network_init();
|
||||||
#endif
|
#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)
|
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)
|
||||||
err = avformat_open_input(&ctx_, fileName, 0, 0);
|
err = avformat_open_input(&ctx_, fileName, 0, 0);
|
||||||
#else
|
#else
|
||||||
@ -2054,7 +2204,7 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi
|
|||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
if (ret == AVERROR_EOF)
|
if (ret == (int)AVERROR_EOF)
|
||||||
*endOfFile = true;
|
*endOfFile = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,24 @@
|
|||||||
#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
|
#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool isInited = false;
|
static cv::Mutex gst_initializer_mutex;
|
||||||
|
|
||||||
|
class gst_initializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void init()
|
||||||
|
{
|
||||||
|
gst_initializer_mutex.lock();
|
||||||
|
static gst_initializer init;
|
||||||
|
gst_initializer_mutex.unlock();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
gst_initializer()
|
||||||
|
{
|
||||||
|
gst_init(NULL, NULL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class CvCapture_GStreamer : public CvCapture
|
class CvCapture_GStreamer : public CvCapture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -298,16 +315,18 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
|
|||||||
|
|
||||||
__BEGIN__;
|
__BEGIN__;
|
||||||
|
|
||||||
if(!isInited) {
|
gst_initializer::init();
|
||||||
|
|
||||||
|
// if(!isInited) {
|
||||||
// printf("gst_init\n");
|
// printf("gst_init\n");
|
||||||
gst_init (NULL, NULL);
|
// gst_init (NULL, NULL);
|
||||||
|
|
||||||
// gst_debug_set_active(TRUE);
|
// gst_debug_set_active(TRUE);
|
||||||
// gst_debug_set_colored(TRUE);
|
// gst_debug_set_colored(TRUE);
|
||||||
// gst_debug_set_default_threshold(GST_LEVEL_WARNING);
|
// gst_debug_set_default_threshold(GST_LEVEL_WARNING);
|
||||||
|
|
||||||
isInited = true;
|
// isInited = true;
|
||||||
}
|
// }
|
||||||
bool stream = false;
|
bool stream = false;
|
||||||
bool manualpipeline = false;
|
bool manualpipeline = false;
|
||||||
char *uri = NULL;
|
char *uri = NULL;
|
||||||
@ -477,10 +496,11 @@ bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
|
|||||||
encit=encs.find(fourcc);
|
encit=encs.find(fourcc);
|
||||||
if (encit==encs.end())
|
if (encit==encs.end())
|
||||||
CV_ERROR( CV_StsUnsupportedFormat,"Gstreamer Opencv backend doesn't support this codec acutally.");
|
CV_ERROR( CV_StsUnsupportedFormat,"Gstreamer Opencv backend doesn't support this codec acutally.");
|
||||||
if(!isInited) {
|
// if(!isInited) {
|
||||||
gst_init (NULL, NULL);
|
// gst_init (NULL, NULL);
|
||||||
isInited = true;
|
// isInited = true;
|
||||||
}
|
// }
|
||||||
|
gst_initializer::init();
|
||||||
close();
|
close();
|
||||||
source=gst_element_factory_make("appsrc",NULL);
|
source=gst_element_factory_make("appsrc",NULL);
|
||||||
file=gst_element_factory_make("filesink", NULL);
|
file=gst_element_factory_make("filesink", NULL);
|
||||||
|
@ -43,11 +43,12 @@
|
|||||||
#include "test_precomp.hpp"
|
#include "test_precomp.hpp"
|
||||||
#include "opencv2/highgui/highgui.hpp"
|
#include "opencv2/highgui/highgui.hpp"
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
#ifdef HAVE_FFMPEG
|
#ifdef HAVE_FFMPEG
|
||||||
|
|
||||||
#include "ffmpeg_codecs.hpp"
|
#include "ffmpeg_codecs.hpp"
|
||||||
|
|
||||||
using namespace cv;
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class CV_FFmpegWriteBigVideoTest : public cvtest::BaseTest
|
class CV_FFmpegWriteBigVideoTest : public cvtest::BaseTest
|
||||||
@ -118,11 +119,11 @@ public:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Mat img(frame_s, CV_8UC3, Scalar::all(0));
|
Mat img(frame_s, CV_8UC3, Scalar::all(0));
|
||||||
const int coeff = cvRound(cv::min(frame_s.width, frame_s.height)/(fps0 * time_sec));
|
const int coeff = cvRound(min(frame_s.width, frame_s.height)/(fps0 * time_sec));
|
||||||
|
|
||||||
for (int i = 0 ; i < static_cast<int>(fps * time_sec); i++ )
|
for (int i = 0 ; i < static_cast<int>(fps * time_sec); i++ )
|
||||||
{
|
{
|
||||||
//circle(img, Point2i(img_c / 2, img_r / 2), cv::min(img_r, img_c) / 2 * (i + 1), Scalar(255, 0, 0, 0), 2);
|
//circle(img, Point2i(img_c / 2, img_r / 2), min(img_r, img_c) / 2 * (i + 1), Scalar(255, 0, 0, 0), 2);
|
||||||
rectangle(img, Point2i(coeff * i, coeff * i), Point2i(coeff * (i + 1), coeff * (i + 1)),
|
rectangle(img, Point2i(coeff * i, coeff * i), Point2i(coeff * (i + 1), coeff * (i + 1)),
|
||||||
Scalar::all(255 * (1.0 - static_cast<double>(i) / (fps * time_sec * 2) )), -1);
|
Scalar::all(255 * (1.0 - static_cast<double>(i) / (fps * time_sec * 2) )), -1);
|
||||||
writer << img;
|
writer << img;
|
||||||
@ -174,3 +175,221 @@ public:
|
|||||||
TEST(Highgui_Video, ffmpeg_image) { CV_FFmpegReadImageTest test; test.safe_run(); }
|
TEST(Highgui_Video, ffmpeg_image) { CV_FFmpegReadImageTest test; test.safe_run(); }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_FFMPEG) || defined(WIN32) || defined(_WIN32)
|
||||||
|
|
||||||
|
//////////////////////////////// Parallel VideoWriters and VideoCaptures ////////////////////////////////////
|
||||||
|
|
||||||
|
class CreateVideoWriterInvoker :
|
||||||
|
public ParallelLoopBody
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static Size FrameSize;
|
||||||
|
static std::string TmpDirectory;
|
||||||
|
|
||||||
|
CreateVideoWriterInvoker(std::vector<VideoWriter*>& _writers, std::vector<std::string>& _files) :
|
||||||
|
ParallelLoopBody(), writers(&_writers), files(&_files)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator() (const Range& range) const
|
||||||
|
{
|
||||||
|
for (int i = range.start; i != range.end; ++i)
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << i << ".avi";
|
||||||
|
std::string fileName = tempfile(stream.str().c_str());
|
||||||
|
|
||||||
|
files->operator[](i) = fileName;
|
||||||
|
writers->operator[](i) = new VideoWriter(fileName, CV_FOURCC('X','V','I','D'), 25.0f, FrameSize);
|
||||||
|
|
||||||
|
CV_Assert(writers->operator[](i)->isOpened());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<VideoWriter*>* writers;
|
||||||
|
std::vector<std::string>* files;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string CreateVideoWriterInvoker::TmpDirectory;
|
||||||
|
const Size CreateVideoWriterInvoker::FrameSize(1020, 900);
|
||||||
|
|
||||||
|
class WriteVideo_Invoker :
|
||||||
|
public ParallelLoopBody
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { FrameCount = 300 };
|
||||||
|
|
||||||
|
static const Scalar ObjectColor;
|
||||||
|
static const Point Center;
|
||||||
|
|
||||||
|
WriteVideo_Invoker(const std::vector<VideoWriter*>& _writers) :
|
||||||
|
ParallelLoopBody(), writers(&_writers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GenerateFrame(Mat& frame, unsigned int i)
|
||||||
|
{
|
||||||
|
frame = Scalar::all(i % 255);
|
||||||
|
|
||||||
|
std::string text = to_string(i);
|
||||||
|
putText(frame, text, Point(50, Center.y), FONT_HERSHEY_SIMPLEX, 5.0, ObjectColor, 5, CV_AA);
|
||||||
|
circle(frame, Center, i + 2, ObjectColor, 2, CV_AA);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator() (const Range& range) const
|
||||||
|
{
|
||||||
|
CV_Assert((range.start + 1) == range.end);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
GenerateFrame(frame, i);
|
||||||
|
writer->operator<< (frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static std::string to_string(unsigned int i)
|
||||||
|
{
|
||||||
|
std::stringstream stream(std::ios::out);
|
||||||
|
stream << "frame #" << i;
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector<VideoWriter*>* writers;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Scalar WriteVideo_Invoker::ObjectColor(Scalar::all(0));
|
||||||
|
const Point WriteVideo_Invoker::Center(CreateVideoWriterInvoker::FrameSize.height / 2,
|
||||||
|
CreateVideoWriterInvoker::FrameSize.width / 2);
|
||||||
|
|
||||||
|
class CreateVideoCaptureInvoker :
|
||||||
|
public ParallelLoopBody
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreateVideoCaptureInvoker(std::vector<VideoCapture*>& _readers, const std::vector<std::string>& _files) :
|
||||||
|
ParallelLoopBody(), readers(&_readers), files(&_files)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator() (const Range& range) const
|
||||||
|
{
|
||||||
|
for (int i = range.start; i != range.end; ++i)
|
||||||
|
{
|
||||||
|
readers->operator[](i) = new VideoCapture(files->operator[](i));
|
||||||
|
CV_Assert(readers->operator[](i)->isOpened());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::vector<VideoCapture*>* readers;
|
||||||
|
const std::vector<std::string>* files;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ReadImageAndTest :
|
||||||
|
public ParallelLoopBody
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReadImageAndTest(const std::vector<VideoCapture*>& _readers, cvtest::TS* _ts) :
|
||||||
|
ParallelLoopBody(), readers(&_readers), ts(_ts)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void operator() (const Range& range) const
|
||||||
|
{
|
||||||
|
CV_Assert(range.start + 1 == range.end);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Mat actual;
|
||||||
|
(*capture) >> actual;
|
||||||
|
|
||||||
|
WriteVideo_Invoker::GenerateFrame(reference, i);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool next;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::vector<VideoCapture*>* readers;
|
||||||
|
cvtest::TS* ts;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ReadImageAndTest::next;
|
||||||
|
|
||||||
|
TEST(Highgui_Video_parallel_writers_and_readers, accuracy)
|
||||||
|
{
|
||||||
|
const unsigned int threadsCount = 4;
|
||||||
|
cvtest::TS* ts = cvtest::TS::ptr();
|
||||||
|
|
||||||
|
// creating VideoWriters
|
||||||
|
std::vector<VideoWriter*> writers(threadsCount);
|
||||||
|
Range range(0, threadsCount);
|
||||||
|
std::vector<std::string> files(threadsCount);
|
||||||
|
CreateVideoWriterInvoker invoker1(writers, files);
|
||||||
|
parallel_for_(range, invoker1);
|
||||||
|
|
||||||
|
// write a video
|
||||||
|
parallel_for_(range, WriteVideo_Invoker(writers));
|
||||||
|
|
||||||
|
// deleting the writers
|
||||||
|
for (std::vector<VideoWriter*>::iterator i = writers.begin(), end = writers.end(); i != end; ++i)
|
||||||
|
delete *i;
|
||||||
|
writers.clear();
|
||||||
|
|
||||||
|
std::vector<VideoCapture*> readers(threadsCount);
|
||||||
|
CreateVideoCaptureInvoker invoker2(readers, files);
|
||||||
|
parallel_for_(range, invoker2);
|
||||||
|
|
||||||
|
ReadImageAndTest::next = true;
|
||||||
|
|
||||||
|
parallel_for_(range, ReadImageAndTest(readers, ts));
|
||||||
|
|
||||||
|
// deleting tmp video files
|
||||||
|
for (std::vector<std::string>::const_iterator i = files.begin(), end = files.end(); i != end; ++i)
|
||||||
|
{
|
||||||
|
int code = remove(i->c_str());
|
||||||
|
if (code == 1)
|
||||||
|
std::cerr << "Couldn't delete " << *i << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user