Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/videoio/test/test_video_io.cpp
16339 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15
// Third party copyrights are property of their respective owners.
16
//
17
// Redistribution and use in source and binary forms, with or without modification,
18
// are permitted provided that the following conditions are met:
19
//
20
// * Redistribution's of source code must retain the above copyright notice,
21
// this list of conditions and the following disclaimer.
22
//
23
// * Redistribution's in binary form must reproduce the above copyright notice,
24
// this list of conditions and the following disclaimer in the documentation
25
// and/or other materials provided with the distribution.
26
//
27
// * The name of the copyright holders may not be used to endorse or promote products
28
// derived from this software without specific prior written permission.
29
//
30
// This software is provided by the copyright holders and contributors "as is" and
31
// any express or implied warranties, including, but not limited to, the implied
32
// warranties of merchantability and fitness for a particular purpose are disclaimed.
33
// In no event shall the Intel Corporation or contributors be liable for any direct,
34
// indirect, incidental, special, exemplary, or consequential damages
35
// (including, but not limited to, procurement of substitute goods or services;
36
// loss of use, data, or profits; or business interruption) however caused
37
// and on any theory of liability, whether in contract, strict liability,
38
// or tort (including negligence or otherwise) arising in any way out of
39
// the use of this software, even if advised of the possibility of such damage.
40
//
41
//M*/
42
43
#include "test_precomp.hpp"
44
#include "opencv2/videoio/videoio_c.h"
45
46
namespace opencv_test
47
{
48
49
class Videoio_Test_Base
50
{
51
protected:
52
string ext;
53
string video_file;
54
VideoCaptureAPIs apiPref;
55
protected:
56
Videoio_Test_Base() {}
57
virtual ~Videoio_Test_Base() {}
58
virtual void checkFrameContent(Mat &, int) {}
59
virtual void checkFrameCount(int &) {}
60
void checkFrameRead(int idx, VideoCapture & cap)
61
{
62
//int frameID = (int)cap.get(CAP_PROP_POS_FRAMES);
63
Mat img;
64
ASSERT_NO_THROW(cap >> img);
65
//std::cout << "idx=" << idx << " img=" << img.size() << " frameID=" << frameID << std::endl;
66
ASSERT_FALSE(img.empty()) << "idx=" << idx;
67
checkFrameContent(img, idx);
68
}
69
void checkFrameSeek(int idx, VideoCapture & cap)
70
{
71
bool canSeek = false;
72
ASSERT_NO_THROW(canSeek = cap.set(CAP_PROP_POS_FRAMES, idx));
73
if (!canSeek)
74
{
75
std::cout << "Seek to frame '" << idx << "' is not supported. SKIP." << std::endl;
76
return;
77
}
78
EXPECT_EQ(idx, (int)cap.get(CAP_PROP_POS_FRAMES));
79
checkFrameRead(idx, cap);
80
}
81
public:
82
void doTest()
83
{
84
if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
85
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
86
VideoCapture cap;
87
ASSERT_NO_THROW(cap.open(video_file, apiPref));
88
if (!cap.isOpened())
89
{
90
std::cout << "SKIP test: backend " << apiPref << " can't open the video: " << video_file << std::endl;
91
return;
92
}
93
int n_frames = -1;
94
EXPECT_NO_THROW(n_frames = (int)cap.get(CAP_PROP_FRAME_COUNT));
95
if (n_frames > 0)
96
{
97
ASSERT_GT(n_frames, 0);
98
checkFrameCount(n_frames);
99
}
100
else
101
{
102
std::cout << "CAP_PROP_FRAME_COUNT is not supported by backend. Assume 50 frames." << std::endl;
103
n_frames = 50;
104
}
105
106
{
107
SCOPED_TRACE("consecutive read");
108
if (apiPref == CAP_GSTREAMER)
109
{
110
// This workaround is for GStreamer 1.3.1.1 and older.
111
// Old Gstreamer has a bug which handles the total duration 1 frame shorter
112
// Old Gstreamer are used in Ubuntu 14.04, so the following code could be removed after it's EOL
113
n_frames--;
114
}
115
for (int k = 0; k < n_frames; ++k)
116
{
117
checkFrameRead(k, cap);
118
}
119
}
120
bool canSeek = false;
121
EXPECT_NO_THROW(canSeek = cap.set(CAP_PROP_POS_FRAMES, 0));
122
if (!canSeek)
123
{
124
std::cout << "Seek to frame '0' is not supported. SKIP all 'seek' tests." << std::endl;
125
return;
126
}
127
128
if (ext != "wmv" && ext != "h264" && ext != "h265")
129
{
130
SCOPED_TRACE("progressive seek");
131
bool res = false;
132
EXPECT_NO_THROW(res = cap.set(CAP_PROP_POS_FRAMES, 0));
133
ASSERT_TRUE(res);
134
for (int k = 0; k < n_frames; k += 20)
135
{
136
checkFrameSeek(k, cap);
137
}
138
}
139
140
if (ext != "mpg" && ext != "wmv" && ext != "h264" && ext != "h265")
141
{
142
SCOPED_TRACE("random seek");
143
bool res = false;
144
EXPECT_NO_THROW(res = cap.set(CAP_PROP_POS_FRAMES, 0));
145
ASSERT_TRUE(res);
146
for (int k = 0; k < 10; ++k)
147
{
148
checkFrameSeek(cvtest::TS::ptr()->get_rng().uniform(0, n_frames), cap);
149
}
150
}
151
}
152
};
153
154
//==================================================================================================
155
typedef tuple<string, VideoCaptureAPIs> Backend_Type_Params;
156
157
class Videoio_Bunny : public Videoio_Test_Base, public testing::TestWithParam<Backend_Type_Params>
158
{
159
BunnyParameters bunny_param;
160
public:
161
Videoio_Bunny()
162
{
163
ext = get<0>(GetParam());
164
apiPref = get<1>(GetParam());
165
video_file = BunnyParameters::getFilename(String(".") + ext);
166
}
167
void doFrameCountTest()
168
{
169
if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
170
throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
171
VideoCapture cap;
172
EXPECT_NO_THROW(cap.open(video_file, apiPref));
173
if (!cap.isOpened())
174
{
175
std::cout << "SKIP test: backend " << apiPref << " can't open the video: " << video_file << std::endl;
176
return;
177
}
178
179
Size actual;
180
EXPECT_NO_THROW(actual = Size((int)cap.get(CAP_PROP_FRAME_WIDTH),
181
(int)cap.get(CAP_PROP_FRAME_HEIGHT)));
182
EXPECT_EQ(bunny_param.getWidth(), actual.width);
183
EXPECT_EQ(bunny_param.getHeight(), actual.height);
184
185
double fps_prop = 0;
186
EXPECT_NO_THROW(fps_prop = cap.get(CAP_PROP_FPS));
187
if (fps_prop > 0)
188
EXPECT_NEAR(fps_prop, bunny_param.getFps(), 1);
189
else
190
std::cout << "FPS is not available. SKIP check." << std::endl;
191
192
int count_prop = 0;
193
EXPECT_NO_THROW(count_prop = (int)cap.get(CAP_PROP_FRAME_COUNT));
194
// mpg file reports 5.08 sec * 24 fps => property returns 122 frames
195
// but actual number of frames returned is 125
196
if (ext != "mpg")
197
{
198
if (count_prop > 0)
199
{
200
EXPECT_EQ(bunny_param.getCount(), count_prop);
201
}
202
}
203
204
int count_actual = 0;
205
while (cap.isOpened())
206
{
207
Mat frame;
208
EXPECT_NO_THROW(cap >> frame);
209
if (frame.empty())
210
break;
211
EXPECT_EQ(bunny_param.getWidth(), frame.cols);
212
EXPECT_EQ(bunny_param.getHeight(), frame.rows);
213
count_actual += 1;
214
}
215
if (count_prop > 0)
216
{
217
EXPECT_NEAR(bunny_param.getCount(), count_actual, 1);
218
}
219
else
220
std::cout << "Frames counter is not available. Actual frames: " << count_actual << ". SKIP check." << std::endl;
221
}
222
};
223
224
//==================================================================================================
225
226
struct Ext_Fourcc_PSNR
227
{
228
string ext;
229
string fourcc;
230
float PSNR;
231
VideoCaptureAPIs api;
232
};
233
typedef tuple<Size, Ext_Fourcc_PSNR> Size_Ext_Fourcc_PSNR;
234
235
class Videoio_Synthetic : public Videoio_Test_Base, public testing::TestWithParam<Size_Ext_Fourcc_PSNR>
236
{
237
Size frame_size;
238
int fourcc;
239
float PSNR_GT;
240
int frame_count;
241
double fps;
242
public:
243
Videoio_Synthetic()
244
{
245
frame_size = get<0>(GetParam());
246
const Ext_Fourcc_PSNR p = get<1>(GetParam());
247
ext = p.ext;
248
fourcc = fourccFromString(p.fourcc);
249
PSNR_GT = p.PSNR;
250
video_file = cv::tempfile((fourccToString(fourcc) + "." + ext).c_str());
251
frame_count = 100;
252
fps = 25.;
253
apiPref = p.api;
254
}
255
void SetUp()
256
{
257
Mat img(frame_size, CV_8UC3);
258
VideoWriter writer;
259
EXPECT_NO_THROW(writer.open(video_file, apiPref, fourcc, fps, frame_size, true));
260
ASSERT_TRUE(writer.isOpened());
261
for(int i = 0; i < frame_count; ++i )
262
{
263
generateFrame(i, frame_count, img);
264
EXPECT_NO_THROW(writer << img);
265
}
266
EXPECT_NO_THROW(writer.release());
267
}
268
void TearDown()
269
{
270
remove(video_file.c_str());
271
}
272
virtual void checkFrameContent(Mat & img, int idx)
273
{
274
Mat imgGT(frame_size, CV_8UC3);
275
generateFrame(idx, frame_count, imgGT);
276
double psnr = cvtest::PSNR(img, imgGT);
277
ASSERT_GT(psnr, PSNR_GT) << "frame " << idx;
278
}
279
virtual void checkFrameCount(int &actual)
280
{
281
Range expected_frame_count = Range(frame_count, frame_count);
282
283
// Hack! Newer FFmpeg versions in this combination produce a file
284
// whose reported duration is one frame longer than needed, and so
285
// the calculated frame count is also off by one. Ideally, we'd want
286
// to fix both writing (to produce the correct duration) and reading
287
// (to correctly report frame count for such files), but I don't know
288
// how to do either, so this is a workaround for now.
289
if (fourcc == VideoWriter::fourcc('M', 'P', 'E', 'G') && ext == "mkv")
290
expected_frame_count.end += 1;
291
292
// Workaround for some gstreamer pipelines
293
if (apiPref == CAP_GSTREAMER)
294
expected_frame_count.start -= 1;
295
296
ASSERT_LE(expected_frame_count.start, actual);
297
ASSERT_GE(expected_frame_count.end, actual);
298
299
actual = expected_frame_count.start; // adjust actual frame boundary to possible minimum
300
}
301
};
302
303
//==================================================================================================
304
305
static const VideoCaptureAPIs backend_params[] = {
306
#ifdef HAVE_QUICKTIME
307
CAP_QT,
308
#endif
309
310
// TODO: Broken?
311
//#ifdef HAVE_AVFOUNDATION
312
// CAP_AVFOUNDATION,
313
//#endif
314
315
#ifdef HAVE_MSMF
316
CAP_MSMF,
317
#endif
318
319
// TODO: Broken?
320
//#ifdef HAVE_VFW
321
// CAP_VFW,
322
//#endif
323
324
#ifdef HAVE_GSTREAMER
325
CAP_GSTREAMER,
326
#endif
327
328
#ifdef HAVE_FFMPEG
329
CAP_FFMPEG,
330
#endif
331
332
#ifdef HAVE_XINE
333
CAP_XINE,
334
#endif
335
336
CAP_OPENCV_MJPEG
337
// CAP_INTEL_MFX
338
};
339
340
static const string bunny_params[] = {
341
#ifdef HAVE_VIDEO_INPUT
342
string("wmv"),
343
string("mov"),
344
string("mp4"),
345
string("mpg"),
346
string("avi"),
347
string("h264"),
348
string("h265"),
349
#endif
350
string("mjpg.avi")
351
};
352
353
TEST_P(Videoio_Bunny, read_position) { doTest(); }
354
355
TEST_P(Videoio_Bunny, frame_count) { doFrameCountTest(); }
356
357
INSTANTIATE_TEST_CASE_P(videoio, Videoio_Bunny,
358
testing::Combine(
359
testing::ValuesIn(bunny_params),
360
testing::ValuesIn(backend_params)));
361
362
363
//==================================================================================================
364
365
inline Ext_Fourcc_PSNR makeParam(const char * ext, const char * fourcc, float psnr, VideoCaptureAPIs apipref)
366
{
367
Ext_Fourcc_PSNR res;
368
res.ext = ext;
369
res.fourcc = fourcc;
370
res.PSNR = psnr;
371
res.api = apipref;
372
return res;
373
}
374
375
inline static std::ostream &operator<<(std::ostream &out, const Ext_Fourcc_PSNR &p)
376
{
377
out << "FOURCC(" << p.fourcc << "), ." << p.ext << ", " << p.api << ", " << p.PSNR << "dB"; return out;
378
}
379
380
static Ext_Fourcc_PSNR synthetic_params[] = {
381
382
#ifdef HAVE_MSMF
383
#if !defined(_M_ARM)
384
makeParam("wmv", "WMV1", 30.f, CAP_MSMF),
385
makeParam("wmv", "WMV2", 30.f, CAP_MSMF),
386
#endif
387
makeParam("wmv", "WMV3", 30.f, CAP_MSMF),
388
makeParam("wmv", "WVC1", 30.f, CAP_MSMF),
389
makeParam("mov", "H264", 30.f, CAP_MSMF),
390
#endif
391
392
// TODO: Broken?
393
//#ifdef HAVE_VFW
394
//#if !defined(_M_ARM)
395
// makeParam("wmv", "WMV1", 30.f, CAP_VFW),
396
// makeParam("wmv", "WMV2", 30.f, CAP_VFW),
397
//#endif
398
// makeParam("wmv", "WMV3", 30.f, CAP_VFW),
399
// makeParam("wmv", "WVC1", 30.f, CAP_VFW),
400
// makeParam("avi", "H264", 30.f, CAP_VFW),
401
// makeParam("avi", "MJPG", 30.f, CAP_VFW),
402
//#endif
403
404
#ifdef HAVE_QUICKTIME
405
makeParam("mov", "mp4v", 30.f, CAP_QT),
406
makeParam("avi", "XVID", 30.f, CAP_QT),
407
makeParam("avi", "MPEG", 30.f, CAP_QT),
408
makeParam("avi", "IYUV", 30.f, CAP_QT),
409
makeParam("avi", "MJPG", 30.f, CAP_QT),
410
411
makeParam("mkv", "XVID", 30.f, CAP_QT),
412
makeParam("mkv", "MPEG", 30.f, CAP_QT),
413
makeParam("mkv", "MJPG", 30.f, CAP_QT),
414
#endif
415
416
// TODO: Broken?
417
//#ifdef HAVE_AVFOUNDATION
418
// makeParam("mov", "mp4v", 30.f, CAP_AVFOUNDATION),
419
// makeParam("avi", "XVID", 30.f, CAP_AVFOUNDATION),
420
// makeParam("avi", "MPEG", 30.f, CAP_AVFOUNDATION),
421
// makeParam("avi", "IYUV", 30.f, CAP_AVFOUNDATION),
422
// makeParam("avi", "MJPG", 30.f, CAP_AVFOUNDATION),
423
424
// makeParam("mkv", "XVID", 30.f, CAP_AVFOUNDATION),
425
// makeParam("mkv", "MPEG", 30.f, CAP_AVFOUNDATION),
426
// makeParam("mkv", "MJPG", 30.f, CAP_AVFOUNDATION),
427
//#endif
428
429
#ifdef HAVE_FFMPEG
430
makeParam("avi", "XVID", 30.f, CAP_FFMPEG),
431
makeParam("avi", "MPEG", 30.f, CAP_FFMPEG),
432
makeParam("avi", "IYUV", 30.f, CAP_FFMPEG),
433
makeParam("avi", "MJPG", 30.f, CAP_FFMPEG),
434
435
makeParam("mkv", "XVID", 30.f, CAP_FFMPEG),
436
makeParam("mkv", "MPEG", 30.f, CAP_FFMPEG),
437
makeParam("mkv", "MJPG", 30.f, CAP_FFMPEG),
438
#endif
439
440
#ifdef HAVE_GSTREAMER
441
makeParam("avi", "MPEG", 30.f, CAP_GSTREAMER),
442
makeParam("avi", "MJPG", 30.f, CAP_GSTREAMER),
443
makeParam("avi", "H264", 30.f, CAP_GSTREAMER),
444
445
makeParam("mkv", "MPEG", 30.f, CAP_GSTREAMER),
446
makeParam("mkv", "MJPG", 30.f, CAP_GSTREAMER),
447
makeParam("mkv", "H264", 30.f, CAP_GSTREAMER),
448
449
#endif
450
makeParam("avi", "MJPG", 30.f, CAP_OPENCV_MJPEG),
451
};
452
453
454
Size all_sizes[] = {
455
Size(640, 480),
456
Size(976, 768)
457
};
458
459
TEST_P(Videoio_Synthetic, write_read_position) { doTest(); }
460
461
INSTANTIATE_TEST_CASE_P(videoio, Videoio_Synthetic,
462
testing::Combine(
463
testing::ValuesIn(all_sizes),
464
testing::ValuesIn(synthetic_params)));
465
466
} // namespace
467
468