Merge pull request #11320 from mshabunin:gstreamer-cpp

pull/11385/head
Maksim Shabunin 7 years ago
commit 5ae550c622
  1. 38
      modules/videoio/src/cap.cpp
  2. 589
      modules/videoio/src/cap_gstreamer.cpp
  3. 5
      modules/videoio/src/precomp.hpp
  4. 6
      modules/videoio/test/test_gstreamer.cpp
  5. 243
      modules/videoio/test/test_video_io.cpp

@ -40,6 +40,8 @@
//M*/
#include "precomp.hpp"
#include <iostream>
using namespace std;
#include "cap_intelperc.hpp"
#include "cap_dshow.hpp"
@ -200,12 +202,6 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index)
TRY_OPEN(capture, cvCreateCameraCapture_V4L(index))
#endif
#ifdef HAVE_GSTREAMER
TRY_OPEN(capture, cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L2, reinterpret_cast<char *>(index)))
TRY_OPEN(capture, cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L, reinterpret_cast<char *>(index)))
#endif
if (pref) break; // CAP_VFW or CAP_V4L or CAP_V4L2
case CAP_FIREWIRE:
@ -221,11 +217,6 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index)
TRY_OPEN(capture, cvCreateCameraCapture_CMU(index))
#endif
#if defined(HAVE_GSTREAMER) && 0
// Re-enable again when gstreamer 1394 support will land in the backend code
TRY_OPEN(capture, cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_1394, 0))
#endif
if (pref) break; // CAP_FIREWIRE
#ifdef HAVE_MIL
@ -330,12 +321,6 @@ CV_IMPL CvCapture * cvCreateFileCaptureWithPreference (const char * filename, in
if (apiPreference) break;
#endif
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
TRY_OPEN(result, cvCreateCapture_GStreamer (CV_CAP_GSTREAMER_FILE, filename))
if (apiPreference) break;
#endif
#if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT)
case CAP_QT:
TRY_OPEN(result, cvCreateFileCapture_QT (filename))
@ -463,6 +448,9 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
{
int domains[] =
{
#ifdef HAVE_GSTREAMER
CAP_GSTREAMER,
#endif
#ifdef HAVE_DSHOW
CAP_DSHOW,
#endif
@ -490,7 +478,8 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
// try every possibly installed camera API
for (int i = 0; domains[i] >= 0; i++)
{
#if defined(HAVE_DSHOW) || \
#if defined(HAVE_GSTREAMER) || \
defined(HAVE_DSHOW) || \
defined(HAVE_INTELPERC) || \
defined(WINRT_VIDEO) || \
defined(HAVE_GPHOTO2) || \
@ -499,6 +488,11 @@ static Ptr<IVideoCapture> IVideoCapture_create(int index)
switch (domains[i])
{
#ifdef HAVE_GSTREAMER
case CAP_GSTREAMER:
capture = createGStreamerCapture(index);
break;
#endif
#ifdef HAVE_DSHOW
case CAP_DSHOW:
capture = makePtr<VideoCapture_DShow>(index);
@ -536,6 +530,14 @@ static Ptr<IVideoCapture> IVideoCapture_create(const String& filename, int apiPr
{
bool useAny = (apiPreference == CAP_ANY);
Ptr<IVideoCapture> capture;
#ifdef HAVE_GSTREAMER
if (useAny || apiPreference == CAP_GSTREAMER)
{
capture = createGStreamerCapture(filename);
if (capture && capture->isOpened())
return capture;
}
#endif
#ifdef HAVE_XINE
if (useAny || apiPreference == CAP_XINE)
{

File diff suppressed because it is too large Load Diff

@ -139,7 +139,6 @@ CvVideoWriter* cvCreateVideoWriter_Images(const char* filename);
#define CV_CAP_GSTREAMER_V4L2 2
#define CV_CAP_GSTREAMER_FILE 3
CvCapture* cvCreateCapture_GStreamer(int type, const char *filename);
CvCapture* cvCreateFileCapture_FFMPEG_proxy(const char* filename);
@ -194,7 +193,11 @@ namespace cv
Ptr<IVideoCapture> createGPhoto2Capture(int index);
Ptr<IVideoCapture> createGPhoto2Capture(const String& deviceName);
Ptr<IVideoCapture> createXINECapture(const char* filename);
Ptr<IVideoCapture> createGStreamerCapture(const String& filename);
Ptr<IVideoCapture> createGStreamerCapture(int index);
}
#endif /* __VIDEOIO_H_ */

@ -7,6 +7,7 @@
namespace opencv_test
{
typedef tuple< string, Size, Size, int > Param;
typedef testing::TestWithParam< Param > Videoio_Gstreamer_Test;
@ -19,8 +20,9 @@ TEST_P(Videoio_Gstreamer_Test, test_object_structure)
int count_frames = 10;
std::ostringstream pipeline;
pipeline << "videotestsrc pattern=ball num-buffers=" << count_frames << " ! " << format;
pipeline << ", framerate=1/1, width=" << frame_size.width << ", height=" << frame_size.height << " ! appsink";
VideoCapture cap(pipeline.str(), CAP_GSTREAMER);
pipeline << ", width=" << frame_size.width << ", height=" << frame_size.height << " ! appsink";
VideoCapture cap;
ASSERT_NO_THROW(cap.open(pipeline.str(), CAP_GSTREAMER));
ASSERT_TRUE(cap.isOpened());
Mat buffer, decode_frame, gray_frame, rgb_frame;

@ -46,12 +46,61 @@
namespace opencv_test
{
struct VideoCaptureAPI
{
VideoCaptureAPIs api;
inline const char * toString() const
{
switch (api)
{
case CAP_ANY: return "CAP_ANY";
#ifdef __linux__
case CAP_V4L2: return "CAP_V4L/CAP_V4L2";
#else
case CAP_VFW: return "CAP_VFW";
#endif
case CAP_FIREWIRE: return "CAP_FIREWIRE";
case CAP_QT: return "CAP_QT";
case CAP_UNICAP: return "CAP_UNICAP";
case CAP_DSHOW: return "CAP_DSHOW";
case CAP_PVAPI: return "CAP_PVAPI";
case CAP_OPENNI: return "CAP_OPENNI";
case CAP_OPENNI_ASUS: return "CAP_OPENNI_ASUS";
case CAP_ANDROID: return "CAP_ANDROID";
case CAP_XIAPI: return "CAP_XIAPI";
case CAP_AVFOUNDATION: return "CAP_AVFOUNDATION";
case CAP_GIGANETIX: return "CAP_GIGANETIX";
case CAP_MSMF: return "CAP_MSMF";
case CAP_WINRT: return "CAP_WINRT";
case CAP_INTELPERC: return "CAP_INTELPERC";
case CAP_OPENNI2: return "CAP_OPENNI2";
case CAP_OPENNI2_ASUS: return "CAP_OPENNI2_ASUS";
case CAP_GPHOTO2: return "CAP_GPHOTO2";
case CAP_GSTREAMER: return "CAP_GSTREAMER";
case CAP_FFMPEG: return "CAP_FFMPEG";
case CAP_IMAGES: return "CAP_IMAGES";
case CAP_ARAVIS: return "CAP_ARAVIS";
case CAP_OPENCV_MJPEG: return "CAP_OPENCV_MJPEG";
case CAP_INTEL_MFX: return "CAP_INTEL_MFX";
}
return "unknown";
}
VideoCaptureAPI(int api_ = CAP_ANY) : api((VideoCaptureAPIs)api_) {}
operator int() { return api; }
};
inline std::ostream &operator<<(std::ostream &out, const VideoCaptureAPI & api)
{
out << api.toString(); return out;
}
class Videoio_Test_Base
{
protected:
string ext;
string video_file;
int apiPref;
VideoCaptureAPI apiPref;
protected:
Videoio_Test_Base() {}
virtual ~Videoio_Test_Base() {}
@ -60,14 +109,16 @@ protected:
void checkFrameRead(int idx, VideoCapture & cap)
{
//int frameID = (int)cap.get(CAP_PROP_POS_FRAMES);
Mat img; cap >> img;
Mat img;
ASSERT_NO_THROW(cap >> img);
//std::cout << "idx=" << idx << " img=" << img.size() << " frameID=" << frameID << std::endl;
ASSERT_FALSE(img.empty()) << "idx=" << idx;
checkFrameContent(img, idx);
}
void checkFrameSeek(int idx, VideoCapture & cap)
{
bool canSeek = cap.set(CAP_PROP_POS_FRAMES, idx);
bool canSeek = false;
ASSERT_NO_THROW(canSeek = cap.set(CAP_PROP_POS_FRAMES, idx));
if (!canSeek)
{
std::cout << "Seek to frame '" << idx << "' is not supported. SKIP." << std::endl;
@ -79,26 +130,15 @@ protected:
public:
void doTest()
{
if (apiPref == CAP_AVFOUNDATION)
{
// TODO: fix this backend
std::cout << "SKIP test: AVFoundation backend returns invalid frame count" << std::endl;
return;
}
else if (apiPref == CAP_VFW)
{
// TODO: fix this backend
std::cout << "SKIP test: Video for Windows backend not open files" << std::endl;
return;
}
VideoCapture cap(video_file, apiPref);
VideoCapture cap;
ASSERT_NO_THROW(cap.open(video_file, apiPref));
if (!cap.isOpened())
{
std::cout << "SKIP test: backend " << apiPref << " can't open the video: " << video_file << std::endl;
return;
}
int n_frames = (int)cap.get(CAP_PROP_FRAME_COUNT);
int n_frames = -1;
EXPECT_NO_THROW(n_frames = (int)cap.get(CAP_PROP_FRAME_COUNT));
if (n_frames > 0)
{
ASSERT_GT(n_frames, 0);
@ -124,7 +164,8 @@ public:
checkFrameRead(k, cap);
}
}
bool canSeek = cap.set(CAP_PROP_POS_FRAMES, 0);
bool canSeek = false;
EXPECT_NO_THROW(canSeek = cap.set(CAP_PROP_POS_FRAMES, 0));
if (!canSeek)
{
std::cout << "Seek to frame '0' is not supported. SKIP all 'seek' tests." << std::endl;
@ -134,7 +175,9 @@ public:
if (ext != "wmv" && ext != "h264" && ext != "h265")
{
SCOPED_TRACE("progressive seek");
ASSERT_TRUE(cap.set(CAP_PROP_POS_FRAMES, 0));
bool res = false;
EXPECT_NO_THROW(res = cap.set(CAP_PROP_POS_FRAMES, 0));
ASSERT_TRUE(res);
for (int k = 0; k < n_frames; k += 20)
{
checkFrameSeek(k, cap);
@ -144,7 +187,9 @@ public:
if (ext != "mpg" && ext != "wmv" && ext != "h264" && ext != "h265")
{
SCOPED_TRACE("random seek");
ASSERT_TRUE(cap.set(CAP_PROP_POS_FRAMES, 0));
bool res = false;
EXPECT_NO_THROW(res = cap.set(CAP_PROP_POS_FRAMES, 0));
ASSERT_TRUE(res);
for (int k = 0; k < 10; ++k)
{
checkFrameSeek(cvtest::TS::ptr()->get_rng().uniform(0, n_frames), cap);
@ -154,7 +199,7 @@ public:
};
//==================================================================================================
typedef tuple<string, int> Backend_Type_Params;
typedef tuple<string, VideoCaptureAPI> Backend_Type_Params;
class Videoio_Bunny : public Videoio_Test_Base, public testing::TestWithParam<Backend_Type_Params>
{
@ -168,37 +213,29 @@ public:
}
void doFrameCountTest()
{
if (apiPref == CAP_AVFOUNDATION)
{
// TODO: fix this backend
std::cout << "SKIP test: AVFoundation backend returns invalid frame count" << std::endl;
return;
}
else if (apiPref == CAP_VFW)
{
// TODO: fix this backend
std::cout << "SKIP test: Video for Windows backend not open files" << std::endl;
return;
}
VideoCapture cap(video_file, apiPref);
VideoCapture cap;
EXPECT_NO_THROW(cap.open(video_file, apiPref));
if (!cap.isOpened())
{
std::cout << "SKIP test: backend " << apiPref << " can't open the video: " << video_file << std::endl;
return;
}
EXPECT_EQ(bunny_param.getWidth() , cap.get(CAP_PROP_FRAME_WIDTH));
EXPECT_EQ(bunny_param.getHeight(), cap.get(CAP_PROP_FRAME_HEIGHT));
Size actual;
EXPECT_NO_THROW(actual = Size((int)cap.get(CAP_PROP_FRAME_WIDTH),
(int)cap.get(CAP_PROP_FRAME_HEIGHT)));
EXPECT_EQ(bunny_param.getWidth(), actual.width);
EXPECT_EQ(bunny_param.getHeight(), actual.height);
double fps_prop = cap.get(CAP_PROP_FPS);
double fps_prop = 0;
EXPECT_NO_THROW(fps_prop = cap.get(CAP_PROP_FPS));
if (fps_prop > 0)
EXPECT_NEAR(fps_prop, bunny_param.getFps(), 1);
else
std::cout << "FPS is not available. SKIP check." << std::endl;
int count_prop = 0;
count_prop = (int)cap.get(CAP_PROP_FRAME_COUNT);
EXPECT_NO_THROW(count_prop = (int)cap.get(CAP_PROP_FRAME_COUNT));
// mpg file reports 5.08 sec * 24 fps => property returns 122 frames
// but actual number of frames returned is 125
if (ext != "mpg")
@ -213,7 +250,7 @@ public:
while (cap.isOpened())
{
Mat frame;
cap >> frame;
EXPECT_NO_THROW(cap >> frame);
if (frame.empty())
break;
EXPECT_EQ(bunny_param.getWidth(), frame.cols);
@ -229,7 +266,15 @@ public:
}
};
typedef tuple<string, string, float, int> Ext_Fourcc_PSNR;
//==================================================================================================
struct Ext_Fourcc_PSNR
{
string ext;
string fourcc;
float PSNR;
VideoCaptureAPI api;
};
typedef tuple<Size, Ext_Fourcc_PSNR> Size_Ext_Fourcc_PSNR;
class Videoio_Synthetic : public Videoio_Test_Base, public testing::TestWithParam<Size_Ext_Fourcc_PSNR>
@ -243,39 +288,27 @@ public:
Videoio_Synthetic()
{
frame_size = get<0>(GetParam());
const Ext_Fourcc_PSNR &param = get<1>(GetParam());
ext = get<0>(param);
fourcc = fourccFromString(get<1>(param));
PSNR_GT = get<2>(param);
const Ext_Fourcc_PSNR p = get<1>(GetParam());
ext = p.ext;
fourcc = fourccFromString(p.fourcc);
PSNR_GT = p.PSNR;
video_file = cv::tempfile((fourccToString(fourcc) + "." + ext).c_str());
frame_count = 100;
fps = 25.;
apiPref = get<3>(param);
apiPref = p.api;
}
void SetUp()
{
if (apiPref == CAP_AVFOUNDATION)
{
// TODO: fix this backend
std::cout << "SKIP test: AVFoundation backend can not write video" << std::endl;
return;
}
else if (apiPref == CAP_VFW)
{
// TODO: fix this backend
std::cout << "SKIP test: Video for Windows backend not open files" << std::endl;
return;
}
Mat img(frame_size, CV_8UC3);
VideoWriter writer(video_file, apiPref, fourcc, fps, frame_size, true);
VideoWriter writer;
EXPECT_NO_THROW(writer.open(video_file, apiPref, fourcc, fps, frame_size, true));
ASSERT_TRUE(writer.isOpened());
for(int i = 0; i < frame_count; ++i )
{
generateFrame(i, frame_count, img);
writer << img;
EXPECT_NO_THROW(writer << img);
}
writer.release();
EXPECT_NO_THROW(writer.release());
}
void TearDown()
{
@ -301,6 +334,10 @@ public:
if (fourcc == VideoWriter::fourcc('M', 'P', 'E', 'G') && ext == "mkv")
expected_frame_count.end += 1;
// Workaround for some gstreamer pipelines
if (apiPref == CAP_GSTREAMER)
expected_frame_count.start -= 1;
ASSERT_LE(expected_frame_count.start, actual);
ASSERT_GE(expected_frame_count.end, actual);
@ -310,22 +347,24 @@ public:
//==================================================================================================
int backend_params[] = {
static VideoCaptureAPI backend_params[] = {
#ifdef HAVE_QUICKTIME
CAP_QT,
#endif
#ifdef HAVE_AVFOUNDATION
CAP_AVFOUNDATION,
#endif
// TODO: Broken?
//#ifdef HAVE_AVFOUNDATION
// CAP_AVFOUNDATION,
//#endif
#ifdef HAVE_MSMF
CAP_MSMF,
#endif
#ifdef HAVE_VFW
CAP_VFW,
#endif
// TODO: Broken?
//#ifdef HAVE_VFW
// CAP_VFW,
//#endif
#ifdef HAVE_GSTREAMER
CAP_GSTREAMER,
@ -343,7 +382,7 @@ int backend_params[] = {
// CAP_INTEL_MFX
};
string bunny_params[] = {
static string bunny_params[] = {
#ifdef HAVE_VIDEO_INPUT
string("wmv"),
string("mov"),
@ -368,12 +407,22 @@ INSTANTIATE_TEST_CASE_P(videoio, Videoio_Bunny,
//==================================================================================================
inline Ext_Fourcc_PSNR makeParam(const char * ext, const char * fourcc, float psnr, int apipref)
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)
{
return make_tuple(string(ext), string(fourcc), (float)psnr, (int)apipref);
out << "FOURCC(" << p.fourcc << "), ." << p.ext << ", " << p.api << ", " << p.PSNR << "dB"; return out;
}
Ext_Fourcc_PSNR synthetic_params[] = {
static Ext_Fourcc_PSNR synthetic_params[] = {
#ifdef HAVE_MSMF
#if !defined(_M_ARM)
@ -385,16 +434,17 @@ Ext_Fourcc_PSNR synthetic_params[] = {
makeParam("mov", "H264", 30.f, CAP_MSMF),
#endif
#ifdef HAVE_VFW
#if !defined(_M_ARM)
makeParam("wmv", "WMV1", 30.f, CAP_VFW),
makeParam("wmv", "WMV2", 30.f, CAP_VFW),
#endif
makeParam("wmv", "WMV3", 30.f, CAP_VFW),
makeParam("wmv", "WVC1", 30.f, CAP_VFW),
makeParam("avi", "H264", 30.f, CAP_VFW),
makeParam("avi", "MJPG", 30.f, CAP_VFW),
#endif
// TODO: Broken?
//#ifdef HAVE_VFW
//#if !defined(_M_ARM)
// makeParam("wmv", "WMV1", 30.f, CAP_VFW),
// makeParam("wmv", "WMV2", 30.f, CAP_VFW),
//#endif
// makeParam("wmv", "WMV3", 30.f, CAP_VFW),
// makeParam("wmv", "WVC1", 30.f, CAP_VFW),
// makeParam("avi", "H264", 30.f, CAP_VFW),
// makeParam("avi", "MJPG", 30.f, CAP_VFW),
//#endif
#ifdef HAVE_QUICKTIME
makeParam("mov", "mp4v", 30.f, CAP_QT),
@ -408,17 +458,18 @@ Ext_Fourcc_PSNR synthetic_params[] = {
makeParam("mkv", "MJPG", 30.f, CAP_QT),
#endif
#ifdef HAVE_AVFOUNDATION
makeParam("mov", "mp4v", 30.f, CAP_AVFOUNDATION),
makeParam("avi", "XVID", 30.f, CAP_AVFOUNDATION),
makeParam("avi", "MPEG", 30.f, CAP_AVFOUNDATION),
makeParam("avi", "IYUV", 30.f, CAP_AVFOUNDATION),
makeParam("avi", "MJPG", 30.f, CAP_AVFOUNDATION),
// TODO: Broken?
//#ifdef HAVE_AVFOUNDATION
// makeParam("mov", "mp4v", 30.f, CAP_AVFOUNDATION),
// makeParam("avi", "XVID", 30.f, CAP_AVFOUNDATION),
// makeParam("avi", "MPEG", 30.f, CAP_AVFOUNDATION),
// makeParam("avi", "IYUV", 30.f, CAP_AVFOUNDATION),
// makeParam("avi", "MJPG", 30.f, CAP_AVFOUNDATION),
makeParam("mkv", "XVID", 30.f, CAP_AVFOUNDATION),
makeParam("mkv", "MPEG", 30.f, CAP_AVFOUNDATION),
makeParam("mkv", "MJPG", 30.f, CAP_AVFOUNDATION),
#endif
// makeParam("mkv", "XVID", 30.f, CAP_AVFOUNDATION),
// makeParam("mkv", "MPEG", 30.f, CAP_AVFOUNDATION),
// makeParam("mkv", "MJPG", 30.f, CAP_AVFOUNDATION),
//#endif
#ifdef HAVE_FFMPEG
makeParam("avi", "XVID", 30.f, CAP_FFMPEG),
@ -432,15 +483,13 @@ Ext_Fourcc_PSNR synthetic_params[] = {
#endif
#ifdef HAVE_GSTREAMER
// makeParam("avi", "XVID", 30.f, CAP_GSTREAMER), - corrupted frames, broken indexes
makeParam("avi", "MPEG", 30.f, CAP_GSTREAMER),
makeParam("avi", "IYUV", 30.f, CAP_GSTREAMER),
makeParam("avi", "MJPG", 30.f, CAP_GSTREAMER),
makeParam("avi", "H264", 30.f, CAP_GSTREAMER),
// makeParam("mkv", "XVID", 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),
#endif
makeParam("avi", "MJPG", 30.f, CAP_OPENCV_MJPEG),

Loading…
Cancel
Save