mirror of
https://github.com/opencv/opencv.git
synced 2024-12-21 05:28:01 +08:00
7febec49b2
videoio: use oneVPL load mechanism, encoder bitrate estimation * videoio: updated oneVPL support - use mfxLoad * videoio: advanced bitrate estimation for MFX encoder * videoio: improved MediaSDK/oneVPL/libva detection * videoio(ffmpeg): don't try oneVPL * videoio(test): tune checks of videoio_mfx.read_write_raw tests Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
176 lines
6.4 KiB
C++
176 lines
6.4 KiB
C++
// This file is part of OpenCV project.
|
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
|
// of this distribution and at http://opencv.org/license.html
|
|
|
|
#include "test_precomp.hpp"
|
|
|
|
namespace opencv_test { namespace {
|
|
|
|
TEST(videoio_mfx, read_invalid)
|
|
{
|
|
if (!videoio_registry::hasBackend(CAP_INTEL_MFX))
|
|
throw SkipTestException("MediaSDK backend was not found");
|
|
|
|
VideoCapture cap;
|
|
ASSERT_NO_THROW(cap.open("nonexistent-file", CAP_INTEL_MFX));
|
|
ASSERT_FALSE(cap.isOpened());
|
|
Mat img;
|
|
ASSERT_NO_THROW(cap >> img);
|
|
ASSERT_TRUE(img.empty());
|
|
}
|
|
|
|
TEST(videoio_mfx, write_invalid)
|
|
{
|
|
if (!videoio_registry::hasBackend(CAP_INTEL_MFX))
|
|
throw SkipTestException("MediaSDK backend was not found");
|
|
|
|
const string filename = cv::tempfile(".264");
|
|
VideoWriter writer;
|
|
bool res = true;
|
|
ASSERT_NO_THROW(res = writer.open(filename, CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 1, Size(641, 480), true));
|
|
EXPECT_FALSE(res);
|
|
EXPECT_FALSE(writer.isOpened());
|
|
ASSERT_NO_THROW(res = writer.open(filename, CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 1, Size(640, 481), true));
|
|
EXPECT_FALSE(res);
|
|
EXPECT_FALSE(writer.isOpened());
|
|
ASSERT_NO_THROW(res = writer.open(filename, CAP_INTEL_MFX, VideoWriter::fourcc('A', 'B', 'C', 'D'), 1, Size(640, 480), true));
|
|
EXPECT_FALSE(res);
|
|
EXPECT_FALSE(writer.isOpened());
|
|
ASSERT_NO_THROW(res = writer.open(String(), CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 1, Size(640, 480), true));
|
|
EXPECT_FALSE(res);
|
|
EXPECT_FALSE(writer.isOpened());
|
|
ASSERT_NO_THROW(res = writer.open(filename, CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 0, Size(640, 480), true));
|
|
EXPECT_FALSE(res);
|
|
EXPECT_FALSE(writer.isOpened());
|
|
|
|
ASSERT_NO_THROW(res = writer.open(filename, CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 30, Size(640, 480), true));
|
|
ASSERT_TRUE(res);
|
|
ASSERT_TRUE(writer.isOpened());
|
|
Mat t;
|
|
// write some bad frames
|
|
t = Mat(Size(1024, 768), CV_8UC3);
|
|
EXPECT_NO_THROW(writer << t);
|
|
t = Mat(Size(320, 240), CV_8UC3);
|
|
EXPECT_NO_THROW(writer << t);
|
|
t = Mat(Size(640, 480), CV_8UC2);
|
|
EXPECT_NO_THROW(writer << t);
|
|
|
|
// cleanup
|
|
ASSERT_NO_THROW(writer.release());
|
|
remove(filename.c_str());
|
|
}
|
|
|
|
|
|
//==================================================================================================
|
|
|
|
const int FRAME_COUNT = 20;
|
|
|
|
inline void generateFrame(int i, Mat & frame)
|
|
{
|
|
::generateFrame(i, FRAME_COUNT, frame);
|
|
}
|
|
|
|
inline int fourccByExt(const String &ext)
|
|
{
|
|
if (ext == ".mpeg2")
|
|
return VideoWriter::fourcc('M', 'P', 'G', '2');
|
|
else if (ext == ".264")
|
|
return VideoWriter::fourcc('H', '2', '6', '4');
|
|
else if (ext == ".265")
|
|
return VideoWriter::fourcc('H', '2', '6', '5');
|
|
return -1;
|
|
}
|
|
|
|
//==================================================================================================
|
|
|
|
typedef tuple<Size, double, const char *> Size_FPS_Ext;
|
|
typedef testing::TestWithParam< Size_FPS_Ext > videoio_mfx;
|
|
|
|
TEST_P(videoio_mfx, read_write_raw)
|
|
{
|
|
if (!videoio_registry::hasBackend(CAP_INTEL_MFX))
|
|
throw SkipTestException("MediaSDK backend was not found");
|
|
|
|
const Size FRAME_SIZE = get<0>(GetParam());
|
|
const double FPS = get<1>(GetParam());
|
|
const char *ext = get<2>(GetParam());
|
|
const String filename = cv::tempfile(ext);
|
|
const int fourcc = fourccByExt(ext);
|
|
|
|
// For some reason MPEG2 codec does not work well with this particular videostream at 1 FPS
|
|
// even with large bitrate values. Thus skipping this case.
|
|
if (FPS == 1. && fourcc == VideoWriter::fourcc('M', 'P', 'G', '2'))
|
|
throw SkipTestException("This configuration is not supported");
|
|
|
|
bool isColor = true;
|
|
std::queue<Mat> goodFrames;
|
|
|
|
// Write video
|
|
VideoWriter writer;
|
|
writer.open(filename, CAP_INTEL_MFX, fourcc, FPS, FRAME_SIZE, isColor);
|
|
ASSERT_TRUE(writer.isOpened());
|
|
Mat frame(FRAME_SIZE, CV_8UC3);
|
|
for (int i = 0; i < FRAME_COUNT; ++i)
|
|
{
|
|
generateFrame(i, frame);
|
|
goodFrames.push(frame.clone());
|
|
writer << frame;
|
|
}
|
|
writer.release();
|
|
EXPECT_FALSE(writer.isOpened());
|
|
|
|
// Read video
|
|
VideoCapture cap;
|
|
cap.open(filename, CAP_INTEL_MFX);
|
|
ASSERT_TRUE(cap.isOpened());
|
|
EXPECT_EQ(FRAME_SIZE.width, cap.get(CAP_PROP_FRAME_WIDTH));
|
|
EXPECT_EQ(FRAME_SIZE.height, cap.get(CAP_PROP_FRAME_HEIGHT));
|
|
double psnrThreshold = (fourcc == VideoWriter::fourcc('M', 'P', 'G', '2')) ? 27.0 : 29.5; // experimentally chosen value
|
|
for (int i = 0; i < FRAME_COUNT; ++i)
|
|
{
|
|
SCOPED_TRACE(i);
|
|
ASSERT_TRUE(cap.read(frame));
|
|
ASSERT_FALSE(frame.empty());
|
|
ASSERT_EQ(FRAME_SIZE.width, frame.cols);
|
|
ASSERT_EQ(FRAME_SIZE.height, frame.rows);
|
|
// verify
|
|
ASSERT_NE(goodFrames.size(), 0u);
|
|
const Mat goodFrame = goodFrames.front(); goodFrames.pop();
|
|
EXPECT_EQ(goodFrame.depth(), frame.depth());
|
|
EXPECT_EQ(goodFrame.channels(), frame.channels());
|
|
EXPECT_EQ(goodFrame.type(), frame.type());
|
|
double psnr = cvtest::PSNR(goodFrame, frame);
|
|
if ((i == 1 || i == 4) && fourcc == VideoWriter::fourcc('H', '2', '6', '5'))
|
|
{
|
|
// ignore bugs of some HW/SW configurations:
|
|
// - (added 2021-10) i7-11700K, Win10, oneVPL 2021.4.0 / 2021.6.0
|
|
std::cout << "SKIP: bypass frame content check: i=" << i << " psnr=" << psnr << ", expected to be >= " << psnrThreshold << std::endl;
|
|
continue;
|
|
}
|
|
EXPECT_GE(psnr, psnrThreshold);
|
|
}
|
|
EXPECT_FALSE(cap.read(frame));
|
|
EXPECT_TRUE(frame.empty());
|
|
cap.release();
|
|
EXPECT_FALSE(cap.isOpened());
|
|
remove(filename.c_str());
|
|
}
|
|
|
|
inline static std::string videoio_mfx_name_printer(const testing::TestParamInfo<videoio_mfx::ParamType>& info)
|
|
{
|
|
std::ostringstream out;
|
|
const Size sz = get<0>(info.param);
|
|
const std::string ext = get<2>(info.param);
|
|
out << sz.width << "x" << sz.height << "x" << get<1>(info.param) << "x" << ext.substr(1, ext.size() - 1);
|
|
return out.str();
|
|
}
|
|
|
|
INSTANTIATE_TEST_CASE_P(videoio, videoio_mfx,
|
|
testing::Combine(
|
|
testing::Values(Size(640, 480), Size(638, 478), Size(636, 476), Size(1920, 1080)),
|
|
testing::Values(1, 30, 100),
|
|
testing::Values(".mpeg2", ".264", ".265")),
|
|
videoio_mfx_name_printer);
|
|
|
|
}} // namespace
|