mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge pull request #15290 from cudawarped:ffmpeg_raw_retrieve
Add retrieve encoded frame to VideoCapture * Add capacity to retrieve the encoded frame from a VideoCapture object. * Correct raw codec and pixle format output from ffmpeg capture. * Remove warnings from build. * Added VideoCaptureRaw subclass. * Include abstract base class VideoCaptureBase and rename new subclass VideoContainer as suggested by mshabunin. * Remove using. * Change base class name for compatibility with jave bindings generator. * Move grab and retrieve and add override specifier * Add setRaw and readRaw to IVideoCapture interface -setRaw to disable video decoding and enable bitstream filters from mp4 to h254 and h265. -readRaw to return the raw undecoded/filtered bitstream. Add createRawCapture to initiate a backend with setRaw enabled. Remove inheritance and use an independant VideoContainer subclass with IVideoCapture member. * Address unused parameter warings. Remove VideoContainer from python bindings as it no longer returns a Mat. Use opencv type uchar instead of unsigned char. Add missing destructor to VideoContainer class. * Address build warnings and include all params in documentation. * Include deprecated bitstream filtering API. * Update codec_id query to work with older ffmpeg api's. Change api version defines to be consistent - most recent api version first. * Fix typo. * Update test to work with naming of new files in the extra repo * Investigate test failure * Check bytes read by ffmpeg * Removed mp4 video container test * Applied suggested changes. * videoio: rework API for extraction of RAW video streams - FFmpeg only * address review comments
This commit is contained in:
committed by
Alexander Alekhin
parent
af230ec133
commit
0867e3188d
@@ -95,6 +95,90 @@ TEST(videoio_ffmpeg, image)
|
||||
|
||||
//==========================================================================
|
||||
|
||||
typedef tuple<VideoCaptureAPIs, string, string, string, string, string> videoio_container_params_t;
|
||||
typedef testing::TestWithParam< videoio_container_params_t > videoio_container;
|
||||
|
||||
TEST_P(videoio_container, read)
|
||||
{
|
||||
const VideoCaptureAPIs api = get<0>(GetParam());
|
||||
|
||||
if (!videoio_registry::hasBackend(api))
|
||||
throw SkipTestException("Backend was not found");
|
||||
|
||||
const string path = get<1>(GetParam());
|
||||
const string ext = get<2>(GetParam());
|
||||
const string ext_raw = get<3>(GetParam());
|
||||
const string codec = get<4>(GetParam());
|
||||
const string pixelFormat = get<5>(GetParam());
|
||||
const string fileName = path + "." + ext;
|
||||
const string fileNameOut = tempfile(cv::format("test_container_stream.%s", ext_raw.c_str()).c_str());
|
||||
|
||||
// Write encoded video read using VideoContainer to tmp file
|
||||
{
|
||||
VideoCapture container(findDataFile(fileName), api);
|
||||
ASSERT_TRUE(container.isOpened());
|
||||
if (!container.set(CAP_PROP_FORMAT, -1)) // turn off video decoder (extract stream)
|
||||
throw SkipTestException("Fetching of RAW video streams is not supported");
|
||||
ASSERT_EQ(-1.f, container.get(CAP_PROP_FORMAT)); // check
|
||||
EXPECT_EQ(codec, fourccToString((int)container.get(CAP_PROP_FOURCC)));
|
||||
EXPECT_EQ(pixelFormat, fourccToString((int)container.get(CAP_PROP_CODEC_PIXEL_FORMAT)));
|
||||
|
||||
std::ofstream file(fileNameOut, ios::out | ios::trunc | std::ios::binary);
|
||||
size_t totalBytes = 0;
|
||||
Mat raw_data;
|
||||
while (true)
|
||||
{
|
||||
container >> raw_data;
|
||||
size_t size = raw_data.total();
|
||||
if (raw_data.empty())
|
||||
break;
|
||||
ASSERT_EQ(CV_8UC1, raw_data.type());
|
||||
ASSERT_LE(raw_data.dims, 2);
|
||||
ASSERT_EQ(raw_data.rows, 1);
|
||||
ASSERT_EQ((size_t)raw_data.cols, raw_data.total());
|
||||
ASSERT_TRUE(raw_data.isContinuous());
|
||||
totalBytes += size;
|
||||
file.write(reinterpret_cast<char*>(raw_data.data), size);
|
||||
ASSERT_FALSE(file.fail());
|
||||
}
|
||||
ASSERT_GE(totalBytes, (size_t)65536) << "Encoded stream is too small";
|
||||
}
|
||||
|
||||
std::cout << "Checking extracted video stream: " << fileNameOut << std::endl;
|
||||
|
||||
// Check decoded frames read from original media are equal to frames decoded from tmp file
|
||||
{
|
||||
VideoCapture capReference(findDataFile(fileName), api);
|
||||
ASSERT_TRUE(capReference.isOpened());
|
||||
VideoCapture capActual(fileNameOut.c_str(), api);
|
||||
ASSERT_TRUE(capActual.isOpened());
|
||||
Mat reference, actual;
|
||||
int nframes = 0, n_err = 0;
|
||||
while (capReference.read(reference) && n_err < 3)
|
||||
{
|
||||
nframes++;
|
||||
ASSERT_TRUE(capActual.read(actual)) << nframes;
|
||||
EXPECT_EQ(0, cvtest::norm(actual, reference, NORM_INF)) << nframes << " err=" << ++n_err;
|
||||
}
|
||||
ASSERT_GT(nframes, 0);
|
||||
}
|
||||
|
||||
ASSERT_EQ(0, remove(fileNameOut.c_str()));
|
||||
}
|
||||
|
||||
const videoio_container_params_t videoio_container_params[] =
|
||||
{
|
||||
make_tuple(CAP_FFMPEG, "video/big_buck_bunny", "h264", "h264", "h264", "I420"),
|
||||
make_tuple(CAP_FFMPEG, "video/big_buck_bunny", "h265", "h265", "hevc", "I420"),
|
||||
//make_tuple(CAP_FFMPEG, "video/big_buck_bunny", "h264.mkv", "mkv.h264", "h264", "I420"),
|
||||
//make_tuple(CAP_FFMPEG, "video/big_buck_bunny", "h265.mkv", "mkv.h265", "hevc", "I420"),
|
||||
//make_tuple(CAP_FFMPEG, "video/big_buck_bunny", "h264.mp4", "mp4.avc1", "avc1", "I420"),
|
||||
//make_tuple(CAP_FFMPEG, "video/big_buck_bunny", "h265.mp4", "mp4.hev1", "hev1", "I420"),
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/**/, videoio_container, testing::ValuesIn(videoio_container_params));
|
||||
|
||||
//==========================================================================
|
||||
|
||||
static void generateFrame(Mat &frame, unsigned int i, const Point ¢er, const Scalar &color)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user