Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
4abf0b31
Commit
4abf0b31
authored
Nov 19, 2012
by
Ilya Lavrenov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
thread-safe VideoWriter and VideoCapture
parent
6cd70c83
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
457 additions
and
51 deletions
+457
-51
cap.cpp
modules/highgui/src/cap.cpp
+0
-1
cap_ffmpeg.cpp
modules/highgui/src/cap_ffmpeg.cpp
+29
-11
cap_ffmpeg_impl.hpp
modules/highgui/src/cap_ffmpeg_impl.hpp
+177
-27
cap_gstreamer.cpp
modules/highgui/src/cap_gstreamer.cpp
+29
-9
test_ffmpeg.cpp
modules/highgui/test/test_ffmpeg.cpp
+222
-3
No files found.
modules/highgui/src/cap.cpp
View file @
4abf0b31
...
...
@@ -424,7 +424,6 @@ CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc,
CV_IMPL
int
cvWriteFrame
(
CvVideoWriter
*
writer
,
const
IplImage
*
image
)
{
return
writer
?
writer
->
writeFrame
(
image
)
:
0
;
}
...
...
modules/highgui/src/cap_ffmpeg.cpp
View file @
4abf0b31
...
...
@@ -57,11 +57,32 @@ 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"
...
...
@@ -71,7 +92,7 @@ icvInitFFMPEG(void)
#endif
".dll"
;
static
HMODULE
icvFFOpenCV
=
LoadLibrary
(
module_name
);
icvFFOpenCV
=
LoadLibrary
(
module_name
);
if
(
icvFFOpenCV
)
{
icvCreateFileCapture_FFMPEG_p
=
...
...
@@ -123,10 +144,8 @@ 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
...
...
@@ -161,9 +180,9 @@ public:
}
virtual
bool
open
(
const
char
*
filename
)
{
icvInitFFMPEG
::
Init
();
close
();
icvInitFFMPEG
();
if
(
!
icvCreateFileCapture_FFMPEG_p
)
return
false
;
ffmpegCapture
=
icvCreateFileCapture_FFMPEG_p
(
filename
);
...
...
@@ -196,7 +215,6 @@ CvCapture* cvCreateFileCapture_FFMPEG_proxy(const char * filename)
#endif
}
class
CvVideoWriter_FFMPEG_proxy
:
public
CvVideoWriter
{
public
:
...
...
@@ -214,8 +232,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
);
...
...
modules/highgui/src/cap_ffmpeg_impl.hpp
View file @
4abf0b31
...
...
@@ -328,28 +328,179 @@ 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
();
~
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
();
#endif
#endif
/* 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
)
;
}
}
}
;
bool
CvCapture_FFMPEG
::
open
(
const
char
*
_filename
)
{
icvInitFFMPEG_internal
();
InternalFFMpegRegister
::
Register
();
unsigned
i
;
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
);
#endif
if
(
err
<
0
)
{
if
(
err
<
0
)
{
CV_WARN
(
"Error opening file"
);
goto
exit_func
;
}
...
...
@@ -371,7 +523,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
;
}
...
...
@@ -393,7 +546,8 @@ bool CvCapture_FFMPEG::open( const char* _filename )
#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)
...
...
@@ -401,7 +555,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
];
...
...
@@ -1275,7 +1430,7 @@ void CvVideoWriter_FFMPEG::close()
bool
CvVideoWriter_FFMPEG
::
open
(
const
char
*
filename
,
int
fourcc
,
double
fps
,
int
width
,
int
height
,
bool
is_color
)
{
icvInitFFMPEG_internal
();
InternalFFMpegRegister
::
Register
();
CodecID
codec_id
=
CODEC_ID_NONE
;
int
err
,
codec_pix_fmt
;
...
...
@@ -1495,6 +1650,7 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
frame_width
=
width
;
frame_height
=
height
;
ok
=
true
;
return
true
;
}
...
...
@@ -1506,6 +1662,7 @@ CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
capture
->
init
();
if
(
capture
->
open
(
filename
))
return
capture
;
capture
->
close
();
free
(
capture
);
return
0
;
...
...
@@ -1554,7 +1711,6 @@ CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int four
return
0
;
}
void
cvReleaseVideoWriter_FFMPEG
(
CvVideoWriter_FFMPEG
**
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
)
{
InternalFFMpegRegister
::
Register
();
fmt_
=
0
;
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
);
...
...
@@ -1920,6 +2073,8 @@ private:
bool
InputMediaStream_FFMPEG
::
open
(
const
char
*
fileName
,
int
*
codec
,
int
*
chroma_format
,
int
*
width
,
int
*
height
)
{
InternalFFMpegRegister
::
Register
();
int
err
;
ctx_
=
0
;
...
...
@@ -1930,11 +2085,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
...
...
@@ -2054,7 +2204,7 @@ bool InputMediaStream_FFMPEG::read(unsigned char** data, int* size, int* endOfFi
if
(
ret
<
0
)
{
if
(
ret
==
AVERROR_EOF
)
if
(
ret
==
(
int
)
AVERROR_EOF
)
*
endOfFile
=
true
;
return
false
;
}
...
...
modules/highgui/src/cap_gstreamer.cpp
View file @
4abf0b31
...
...
@@ -65,7 +65,24 @@
#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
#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
{
public
:
...
...
@@ -298,16 +315,18 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
__BEGIN__
;
if
(
!
isInited
)
{
gst_initializer
::
init
();
// if(!isInited) {
// printf("gst_init\n");
gst_init
(
NULL
,
NULL
);
//
gst_init (NULL, NULL);
// gst_debug_set_active(TRUE);
// gst_debug_set_colored(TRUE);
// gst_debug_set_default_threshold(GST_LEVEL_WARNING);
isInited
=
true
;
}
//
isInited = true;
//
}
bool
stream
=
false
;
bool
manualpipeline
=
false
;
char
*
uri
=
NULL
;
...
...
@@ -477,10 +496,11 @@ bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
encit
=
encs
.
find
(
fourcc
);
if
(
encit
==
encs
.
end
())
CV_ERROR
(
CV_StsUnsupportedFormat
,
"Gstreamer Opencv backend doesn't support this codec acutally."
);
if
(
!
isInited
)
{
gst_init
(
NULL
,
NULL
);
isInited
=
true
;
}
// if(!isInited) {
// gst_init (NULL, NULL);
// isInited = true;
// }
gst_initializer
::
init
();
close
();
source
=
gst_element_factory_make
(
"appsrc"
,
NULL
);
file
=
gst_element_factory_make
(
"filesink"
,
NULL
);
...
...
modules/highgui/test/test_ffmpeg.cpp
View file @
4abf0b31
...
...
@@ -43,11 +43,12 @@
#include "test_precomp.hpp"
#include "opencv2/highgui/highgui.hpp"
using
namespace
cv
;
#ifdef HAVE_FFMPEG
#include "ffmpeg_codecs.hpp"
using
namespace
cv
;
using
namespace
std
;
class
CV_FFmpegWriteBigVideoTest
:
public
cvtest
::
BaseTest
...
...
@@ -118,11 +119,11 @@ public:
else
{
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
++
)
{
//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
)),
Scalar
::
all
(
255
*
(
1.0
-
static_cast
<
double
>
(
i
)
/
(
fps
*
time_sec
*
2
)
)),
-
1
);
writer
<<
img
;
...
...
@@ -174,3 +175,221 @@ public:
TEST
(
Highgui_Video
,
ffmpeg_image
)
{
CV_FFmpegReadImageTest
test
;
test
.
safe_run
();
}
#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.0
f
,
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
,
"
\n
PSNR: %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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment