Merge pull request #14834 from alalek:videoio_gstreamer_issues

This commit is contained in:
Alexander Alekhin 2019-06-21 13:38:34 +00:00
commit 6b32bd5f15
8 changed files with 934 additions and 586 deletions

View File

@ -1026,6 +1026,40 @@ static inline bool operator>= (const String& lhs, const String& rhs) { return lh
static inline bool operator>= (const char* lhs, const String& rhs) { return rhs.compare(lhs) <= 0; } static inline bool operator>= (const char* lhs, const String& rhs) { return rhs.compare(lhs) <= 0; }
static inline bool operator>= (const String& lhs, const char* rhs) { return lhs.compare(rhs) >= 0; } static inline bool operator>= (const String& lhs, const char* rhs) { return lhs.compare(rhs) >= 0; }
#ifndef OPENCV_DISABLE_STRING_LOWER_UPPER_CONVERSIONS
//! @cond IGNORED
namespace details {
// std::tolower is int->int
static inline char char_tolower(char ch)
{
return (char)std::tolower((int)ch);
}
// std::toupper is int->int
static inline char char_toupper(char ch)
{
return (char)std::toupper((int)ch);
}
} // namespace details
//! @endcond
static inline std::string toLowerCase(const std::string& str)
{
std::string result(str);
std::transform(result.begin(), result.end(), result.begin(), details::char_tolower);
return result;
}
static inline std::string toUpperCase(const std::string& str)
{
std::string result(str);
std::transform(result.begin(), result.end(), result.begin(), details::char_toupper);
return result;
}
#endif // OPENCV_DISABLE_STRING_LOWER_UPPER_CONVERSIONS
//! @} relates cv::String //! @} relates cv::String
} // cv } // cv

File diff suppressed because it is too large Load Diff

View File

@ -154,8 +154,11 @@ CvVideoWriter* cvCreateVideoWriter_AVFoundation( const char* filename, int fourc
CvCapture * cvCreateCameraCapture_Unicap (const int index); CvCapture * cvCreateCameraCapture_Unicap (const int index);
CvCapture * cvCreateCameraCapture_PvAPI (const int index); CvCapture * cvCreateCameraCapture_PvAPI (const int index);
namespace cv {
CvVideoWriter* cvCreateVideoWriter_GStreamer( const char* filename, int fourcc, CvVideoWriter* cvCreateVideoWriter_GStreamer( const char* filename, int fourcc,
double fps, CvSize frameSize, int is_color ); double fps, CvSize frameSize, int is_color );
}
namespace cv namespace cv

View File

@ -227,7 +227,7 @@ public:
const static Size FrameSize; const static Size FrameSize;
static std::string TmpDirectory; static std::string TmpDirectory;
CreateVideoWriterInvoker(std::vector<VideoWriter*>& _writers, std::vector<std::string>& _files) : CreateVideoWriterInvoker(std::vector< cv::Ptr<VideoWriter> >& _writers, std::vector<std::string>& _files) :
writers(_writers), files(_files) writers(_writers), files(_files)
{ {
} }
@ -241,14 +241,14 @@ public:
std::string fileName = tempfile(stream.str().c_str()); std::string fileName = tempfile(stream.str().c_str());
files[i] = fileName; files[i] = fileName;
writers[i] = new VideoWriter(fileName, CAP_FFMPEG, VideoWriter::fourcc('X','V','I','D'), 25.0f, FrameSize); writers[i] = makePtr<VideoWriter>(fileName, CAP_FFMPEG, VideoWriter::fourcc('X','V','I','D'), 25.0f, FrameSize);
CV_Assert(writers[i]->isOpened()); CV_Assert(writers[i]->isOpened());
} }
} }
private: private:
std::vector<VideoWriter*>& writers; std::vector< cv::Ptr<VideoWriter> >& writers;
std::vector<std::string>& files; std::vector<std::string>& files;
}; };
@ -264,7 +264,7 @@ public:
static const Scalar ObjectColor; static const Scalar ObjectColor;
static const Point Center; static const Point Center;
WriteVideo_Invoker(const std::vector<VideoWriter*>& _writers) : WriteVideo_Invoker(const std::vector< cv::Ptr<VideoWriter> >& _writers) :
ParallelLoopBody(), writers(&_writers) ParallelLoopBody(), writers(&_writers)
{ {
} }
@ -304,7 +304,7 @@ protected:
} }
private: private:
const std::vector<VideoWriter*>* writers; const std::vector< cv::Ptr<VideoWriter> >* writers;
}; };
const Scalar WriteVideo_Invoker::ObjectColor(Scalar::all(0)); const Scalar WriteVideo_Invoker::ObjectColor(Scalar::all(0));
@ -315,7 +315,7 @@ class CreateVideoCaptureInvoker :
public ParallelLoopBody public ParallelLoopBody
{ {
public: public:
CreateVideoCaptureInvoker(std::vector<VideoCapture*>& _readers, const std::vector<std::string>& _files) : CreateVideoCaptureInvoker(std::vector< cv::Ptr<VideoCapture> >& _readers, const std::vector<std::string>& _files) :
ParallelLoopBody(), readers(&_readers), files(&_files) ParallelLoopBody(), readers(&_readers), files(&_files)
{ {
} }
@ -324,12 +324,12 @@ public:
{ {
for (int i = range.start; i != range.end; ++i) for (int i = range.start; i != range.end; ++i)
{ {
readers->operator[](i) = new VideoCapture(files->operator[](i), CAP_FFMPEG); readers->operator[](i) = makePtr<VideoCapture>(files->operator[](i), CAP_FFMPEG);
CV_Assert(readers->operator[](i)->isOpened()); CV_Assert(readers->operator[](i)->isOpened());
} }
} }
private: private:
std::vector<VideoCapture*>* readers; std::vector< cv::Ptr<VideoCapture> >* readers;
const std::vector<std::string>* files; const std::vector<std::string>* files;
}; };
@ -337,7 +337,7 @@ class ReadImageAndTest :
public ParallelLoopBody public ParallelLoopBody
{ {
public: public:
ReadImageAndTest(const std::vector<VideoCapture*>& _readers, cvtest::TS* _ts) : ReadImageAndTest(const std::vector< cv::Ptr<VideoCapture> >& _readers, cvtest::TS* _ts) :
ParallelLoopBody(), readers(&_readers), ts(_ts) ParallelLoopBody(), readers(&_readers), ts(_ts)
{ {
} }
@ -346,7 +346,7 @@ public:
{ {
for (int j = range.start; j < range.end; ++j) for (int j = range.start; j < range.end; ++j)
{ {
VideoCapture* capture = readers->operator[](j); VideoCapture* capture = readers->operator[](j).get();
CV_Assert(capture != NULL); CV_Assert(capture != NULL);
CV_Assert(capture->isOpened()); CV_Assert(capture->isOpened());
@ -394,7 +394,7 @@ public:
static bool next; static bool next;
private: private:
const std::vector<VideoCapture*>* readers; const std::vector< cv::Ptr<VideoCapture> >* readers;
cvtest::TS* ts; cvtest::TS* ts;
}; };
@ -406,7 +406,7 @@ TEST(Videoio_Video_parallel_writers_and_readers, accuracy)
cvtest::TS* ts = cvtest::TS::ptr(); cvtest::TS* ts = cvtest::TS::ptr();
// creating VideoWriters // creating VideoWriters
std::vector<VideoWriter*> writers(threadsCount); std::vector< cv::Ptr<VideoWriter> > writers(threadsCount);
Range range(0, threadsCount); Range range(0, threadsCount);
std::vector<std::string> files(threadsCount); std::vector<std::string> files(threadsCount);
CreateVideoWriterInvoker invoker1(writers, files); CreateVideoWriterInvoker invoker1(writers, files);
@ -416,11 +416,9 @@ TEST(Videoio_Video_parallel_writers_and_readers, accuracy)
parallel_for_(range, WriteVideo_Invoker(writers)); parallel_for_(range, WriteVideo_Invoker(writers));
// deleting the writers // deleting the writers
for (std::vector<VideoWriter*>::iterator i = writers.begin(), end = writers.end(); i != end; ++i)
delete *i;
writers.clear(); writers.clear();
std::vector<VideoCapture*> readers(threadsCount); std::vector<cv::Ptr<VideoCapture> > readers(threadsCount);
CreateVideoCaptureInvoker invoker2(readers, files); CreateVideoCaptureInvoker invoker2(readers, files);
parallel_for_(range, invoker2); parallel_for_(range, invoker2);
@ -437,8 +435,7 @@ TEST(Videoio_Video_parallel_writers_and_readers, accuracy)
} }
// delete the readers // delete the readers
for (std::vector<VideoCapture *>::iterator i = readers.begin(), end = readers.end(); i != end; ++i) readers.clear();
delete *i;
} }
#endif #endif

View File

@ -71,6 +71,24 @@ Param test_data[] = {
INSTANTIATE_TEST_CASE_P(videoio, Videoio_Gstreamer_Test, testing::ValuesIn(test_data)); INSTANTIATE_TEST_CASE_P(videoio, Videoio_Gstreamer_Test, testing::ValuesIn(test_data));
TEST(Videoio_GStreamer, unsupported_pipeline)
{
VideoCaptureAPIs apiPref = CAP_GSTREAMER;
if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
// could not link videoconvert0 to matroskamux0, matroskamux0 can't handle caps video/x-raw, format=(string)RGBA
std::string pipeline = "appsrc ! videoconvert ! video/x-raw, format=(string)RGBA ! matroskamux ! filesink location=test.mkv";
Size frame_size(640, 480);
VideoWriter writer;
EXPECT_NO_THROW(writer.open(pipeline, apiPref, 0/*fourcc*/, 30/*fps*/, frame_size, true));
EXPECT_FALSE(writer.isOpened());
// no frames
EXPECT_NO_THROW(writer.release());
}
} // namespace } // namespace
#endif #endif

View File

@ -225,8 +225,8 @@ public:
struct Ext_Fourcc_PSNR struct Ext_Fourcc_PSNR
{ {
string ext; const char* ext;
string fourcc; const char* fourcc;
float PSNR; float PSNR;
VideoCaptureAPIs api; VideoCaptureAPIs api;
}; };
@ -359,18 +359,6 @@ INSTANTIATE_TEST_CASE_P(videoio, Videoio_Bunny,
testing::ValuesIn(backend_params))); testing::ValuesIn(backend_params)));
//==================================================================================================
inline Ext_Fourcc_PSNR makeParam(const char * ext, const char * fourcc, float psnr, VideoCaptureAPIs apipref)
{
Ext_Fourcc_PSNR res;
res.ext = ext;
res.fourcc = fourcc;
res.PSNR = psnr;
res.api = apipref;
return res;
}
inline static std::ostream &operator<<(std::ostream &out, const Ext_Fourcc_PSNR &p) inline static std::ostream &operator<<(std::ostream &out, const Ext_Fourcc_PSNR &p)
{ {
out << "FOURCC(" << p.fourcc << "), ." << p.ext << ", " << p.api << ", " << p.PSNR << "dB"; return out; out << "FOURCC(" << p.fourcc << "), ." << p.ext << ", " << p.api << ", " << p.PSNR << "dB"; return out;
@ -380,69 +368,68 @@ static Ext_Fourcc_PSNR synthetic_params[] = {
#ifdef HAVE_MSMF #ifdef HAVE_MSMF
#if !defined(_M_ARM) #if !defined(_M_ARM)
makeParam("wmv", "WMV1", 30.f, CAP_MSMF), {"wmv", "WMV1", 30.f, CAP_MSMF},
makeParam("wmv", "WMV2", 30.f, CAP_MSMF), {"wmv", "WMV2", 30.f, CAP_MSMF},
#endif #endif
makeParam("wmv", "WMV3", 30.f, CAP_MSMF), {"wmv", "WMV3", 30.f, CAP_MSMF},
makeParam("wmv", "WVC1", 30.f, CAP_MSMF), {"wmv", "WVC1", 30.f, CAP_MSMF},
makeParam("mov", "H264", 30.f, CAP_MSMF), {"mov", "H264", 30.f, CAP_MSMF},
#endif #endif
// TODO: Broken? // TODO: Broken?
//#ifdef HAVE_VFW //#ifdef HAVE_VFW
//#if !defined(_M_ARM) //#if !defined(_M_ARM)
// makeParam("wmv", "WMV1", 30.f, CAP_VFW), // {"wmv", "WMV1", 30.f, CAP_VFW},
// makeParam("wmv", "WMV2", 30.f, CAP_VFW), // {"wmv", "WMV2", 30.f, CAP_VFW},
//#endif //#endif
// makeParam("wmv", "WMV3", 30.f, CAP_VFW), // {"wmv", "WMV3", 30.f, CAP_VFW},
// makeParam("wmv", "WVC1", 30.f, CAP_VFW), // {"wmv", "WVC1", 30.f, CAP_VFW},
// makeParam("avi", "H264", 30.f, CAP_VFW), // {"avi", "H264", 30.f, CAP_VFW},
// makeParam("avi", "MJPG", 30.f, CAP_VFW), // {"avi", "MJPG", 30.f, CAP_VFW},
//#endif //#endif
#ifdef HAVE_QUICKTIME #ifdef HAVE_QUICKTIME
makeParam("mov", "mp4v", 30.f, CAP_QT), {"mov", "mp4v", 30.f, CAP_QT},
makeParam("avi", "XVID", 30.f, CAP_QT), {"avi", "XVID", 30.f, CAP_QT},
makeParam("avi", "MPEG", 30.f, CAP_QT), {"avi", "MPEG", 30.f, CAP_QT},
makeParam("avi", "IYUV", 30.f, CAP_QT), {"avi", "IYUV", 30.f, CAP_QT},
makeParam("avi", "MJPG", 30.f, CAP_QT), {"avi", "MJPG", 30.f, CAP_QT},
makeParam("mkv", "XVID", 30.f, CAP_QT), {"mkv", "XVID", 30.f, CAP_QT},
makeParam("mkv", "MPEG", 30.f, CAP_QT), {"mkv", "MPEG", 30.f, CAP_QT},
makeParam("mkv", "MJPG", 30.f, CAP_QT), {"mkv", "MJPG", 30.f, CAP_QT},
#endif #endif
#ifdef HAVE_AVFOUNDATION #ifdef HAVE_AVFOUNDATION
makeParam("mov", "H264", 30.f, CAP_AVFOUNDATION), {"mov", "H264", 30.f, CAP_AVFOUNDATION},
makeParam("mov", "MJPG", 30.f, CAP_AVFOUNDATION), {"mov", "MJPG", 30.f, CAP_AVFOUNDATION},
makeParam("mp4", "H264", 30.f, CAP_AVFOUNDATION), {"mp4", "H264", 30.f, CAP_AVFOUNDATION},
makeParam("mp4", "MJPG", 30.f, CAP_AVFOUNDATION), {"mp4", "MJPG", 30.f, CAP_AVFOUNDATION},
makeParam("m4v", "H264", 30.f, CAP_AVFOUNDATION), {"m4v", "H264", 30.f, CAP_AVFOUNDATION},
makeParam("m4v", "MJPG", 30.f, CAP_AVFOUNDATION), {"m4v", "MJPG", 30.f, CAP_AVFOUNDATION},
#endif #endif
#ifdef HAVE_FFMPEG #ifdef HAVE_FFMPEG
makeParam("avi", "XVID", 30.f, CAP_FFMPEG), {"avi", "XVID", 30.f, CAP_FFMPEG},
makeParam("avi", "MPEG", 30.f, CAP_FFMPEG), {"avi", "MPEG", 30.f, CAP_FFMPEG},
makeParam("avi", "IYUV", 30.f, CAP_FFMPEG), {"avi", "IYUV", 30.f, CAP_FFMPEG},
makeParam("avi", "MJPG", 30.f, CAP_FFMPEG), {"avi", "MJPG", 30.f, CAP_FFMPEG},
makeParam("mkv", "XVID", 30.f, CAP_FFMPEG), {"mkv", "XVID", 30.f, CAP_FFMPEG},
makeParam("mkv", "MPEG", 30.f, CAP_FFMPEG), {"mkv", "MPEG", 30.f, CAP_FFMPEG},
makeParam("mkv", "MJPG", 30.f, CAP_FFMPEG), {"mkv", "MJPG", 30.f, CAP_FFMPEG},
#endif #endif
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
makeParam("avi", "MPEG", 30.f, CAP_GSTREAMER), {"avi", "MPEG", 30.f, CAP_GSTREAMER},
makeParam("avi", "MJPG", 30.f, CAP_GSTREAMER), {"avi", "MJPG", 30.f, CAP_GSTREAMER},
makeParam("avi", "H264", 30.f, CAP_GSTREAMER), {"avi", "H264", 30.f, CAP_GSTREAMER},
makeParam("mkv", "MPEG", 30.f, CAP_GSTREAMER),
makeParam("mkv", "MJPG", 30.f, CAP_GSTREAMER),
makeParam("mkv", "H264", 30.f, CAP_GSTREAMER),
{"mkv", "MPEG", 30.f, CAP_GSTREAMER},
{"mkv", "MJPG", 30.f, CAP_GSTREAMER},
{"mkv", "H264", 30.f, CAP_GSTREAMER},
#endif #endif
makeParam("avi", "MJPG", 30.f, CAP_OPENCV_MJPEG), {"avi", "MJPG", 30.f, CAP_OPENCV_MJPEG},
}; };
@ -458,4 +445,86 @@ INSTANTIATE_TEST_CASE_P(videoio, Videoio_Synthetic,
testing::ValuesIn(all_sizes), testing::ValuesIn(all_sizes),
testing::ValuesIn(synthetic_params))); testing::ValuesIn(synthetic_params)));
struct Ext_Fourcc_API
{
const char* ext;
const char* fourcc;
VideoCaptureAPIs api;
};
inline static std::ostream &operator<<(std::ostream &out, const Ext_Fourcc_API &p)
{
out << "(FOURCC(" << p.fourcc << "), \"" << p.ext << "\", " << p.api << ")"; return out;
}
class Videoio_Writer : public Videoio_Test_Base, public testing::TestWithParam<Ext_Fourcc_API>
{
protected:
Size frame_size;
int fourcc;
double fps;
public:
Videoio_Writer()
{
frame_size = Size(640, 480);
const Ext_Fourcc_API p = GetParam();
ext = p.ext;
fourcc = fourccFromString(p.fourcc);
if (ext.size() == 3)
video_file = cv::tempfile((fourccToString(fourcc) + "." + ext).c_str());
else
video_file = ext;
fps = 25.;
apiPref = p.api;
}
void SetUp()
{
}
void TearDown()
{
if (ext.size() == 3)
(void)remove(video_file.c_str());
}
};
TEST_P(Videoio_Writer, write_nothing)
{
if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
VideoWriter writer;
EXPECT_NO_THROW(writer.open(video_file, apiPref, fourcc, fps, frame_size, true));
ASSERT_TRUE(writer.isOpened());
#if 0 // no frames
cv::Mat m(frame_size, CV_8UC3, Scalar::all(127));
writer << m;
#endif
EXPECT_NO_THROW(writer.release());
}
static vector<Ext_Fourcc_API> generate_Ext_Fourcc_API()
{
const size_t N = sizeof(synthetic_params)/sizeof(synthetic_params[0]);
vector<Ext_Fourcc_API> result; result.reserve(N);
for (size_t i = 0; i < N; i++)
{
const Ext_Fourcc_PSNR& src = synthetic_params[i];
Ext_Fourcc_API e = { src.ext, src.fourcc, src.api };
result.push_back(e);
}
{
Ext_Fourcc_API e = { "appsrc ! videoconvert ! video/x-raw, format=(string)NV12 ! filesink location=test.nv12", "\0\0\0\0", CAP_GSTREAMER };
result.push_back(e);
}
{
Ext_Fourcc_API e = { "appsrc ! videoconvert ! video/x-raw, format=(string)I420 ! matroskamux ! filesink location=test.mkv", "\0\0\0\0", CAP_GSTREAMER };
result.push_back(e);
}
return result;
}
INSTANTIATE_TEST_CASE_P(videoio, Videoio_Writer, testing::ValuesIn(generate_Ext_Fourcc_API()));
} // namespace } // namespace

View File

@ -218,6 +218,14 @@
fun:__itt_*create* fun:__itt_*create*
} }
{
OpenCV-gtk_init
Memcheck:Leak
...
fun:gtk_init
fun:cvInitSystem
}
{ {
OpenCV-FFmpeg-swsscale OpenCV-FFmpeg-swsscale
Memcheck:Addr16 Memcheck:Addr16
@ -227,6 +235,35 @@
fun:cvWriteFrame_FFMPEG fun:cvWriteFrame_FFMPEG
} }
{
OpenCV-GStreamer-gst_init
Memcheck:Leak
...
fun:gst_init
}
{
OpenCV-GStreamer-gst_deinit
Memcheck:Leak
...
fun:gst_deinit
}
{
OpenCV-GStreamer-gst_init_check
Memcheck:Leak
...
fun:gst_init_check
}
{
OpenCV-GStreamer-gst_parse_launch_full-reachable
Memcheck:Leak
match-leak-kinds: reachable
...
fun:gst_parse_launch_full
}
{ {
OpenCV-OpenEXR-ThreadPool OpenCV-OpenEXR-ThreadPool
Memcheck:Leak Memcheck:Leak

View File

@ -18,6 +18,15 @@
fun:_ZN7testing8internal11CmpHelperLEIddEENS_15AssertionResultEPKcS4_RKT_RKT0_ fun:_ZN7testing8internal11CmpHelperLEIddEENS_15AssertionResultEPKcS4_RKT_RKT0_
} }
{
GTest-RegisterTests
Memcheck:Leak
...
fun:RegisterTests
...
fun:_ZN7testing14InitGoogleTestEPiPPc
}
{ {
OpenCL OpenCL
Memcheck:Cond Memcheck:Cond
@ -55,10 +64,10 @@
} }
{ {
glib GTK-css
Memcheck:Leak Memcheck:Leak
fun:*alloc ...
obj:*/libglib* fun:gtk_css_provider*
} }
{ {
@ -120,3 +129,78 @@
... ...
fun:cvWriteFrame_FFMPEG fun:cvWriteFrame_FFMPEG
} }
{
GStreamer-orc_program_compile_full
Memcheck:Leak
match-leak-kinds: reachable
...
fun:orc_program_compile_full
...
fun:clone
}
{
GStreamer-orc_program_new_from_static_bytecode
Memcheck:Leak
match-leak-kinds: reachable
...
fun:orc_program_new_from_static_bytecode
...
fun:clone
}
{
GStreamer-matroska-other
Memcheck:Leak
...
fun:gst*
obj:*gstmatroska*
...
obj:*glib*
fun:start_thread
fun:clone
}
{
GStreamer-matroska-gst_riff_create_video_caps
Memcheck:Leak
...
fun:gst_riff_create_video_caps
obj:*gstmatroska*
...
fun:clone
}
{
GStreamer-tls
Memcheck:Leak
match-leak-kinds: possible
fun:calloc
fun:allocate_dtv
fun:_dl_allocate_tls
}
{
GStreamer-registry
Memcheck:Leak
...
fun:gst_update_registry
}
{
GStreamer-plugin_load
Memcheck:Leak
...
fun:gst_plugin_load_by_name
}
{
GStreamer-separate-threads
Memcheck:Leak
...
obj:*/libglib*
fun:start_thread
fun:clone
}