From 09fe66e87f87683ab22afee4e43cce9d970dab0c Mon Sep 17 00:00:00 2001 From: Vadim Levin Date: Tue, 10 Mar 2020 16:44:22 +0300 Subject: [PATCH] Merge pull request #16713 from VadimLevin:dev/vlevin/ffmpeg_video_capture_bitrate * feature: Add video capture bitrate read-only property for FFMPEG backend * test: For WIN32 property should be either expected or 0. Added `IsOneOf` helper function, enabled only for _WIN32. --- modules/videoio/include/opencv2/videoio.hpp | 1 + modules/videoio/src/cap_ffmpeg_api.hpp | 3 +- modules/videoio/src/cap_ffmpeg_impl.hpp | 8 ++- modules/videoio/test/test_ffmpeg.cpp | 63 +++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index cf91a0d83d..d09e62c15d 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -176,6 +176,7 @@ enum VideoCaptureProperties { CAP_PROP_AUTO_WB =44, //!< enable/ disable auto white-balance CAP_PROP_WB_TEMPERATURE=45, //!< white-balance color temperature CAP_PROP_CODEC_PIXEL_FORMAT =46, //!< (read-only) codec's pixel format. 4-character code - see VideoWriter::fourcc . Subset of [AV_PIX_FMT_*](https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/raw.c) or -1 if unknown + CAP_PROP_BITRATE =47, //!< (read-only) Video bitrate in kbits/s #ifndef CV_DOXYGEN CV__CAP_PROP_LATEST #endif diff --git a/modules/videoio/src/cap_ffmpeg_api.hpp b/modules/videoio/src/cap_ffmpeg_api.hpp index 2366ee13a3..004758099c 100644 --- a/modules/videoio/src/cap_ffmpeg_api.hpp +++ b/modules/videoio/src/cap_ffmpeg_api.hpp @@ -27,7 +27,8 @@ enum CV_FFMPEG_CAP_PROP_FORMAT=8, CV_FFMPEG_CAP_PROP_SAR_NUM=40, CV_FFMPEG_CAP_PROP_SAR_DEN=41, - CV_FFMPEG_CAP_PROP_CODEC_PIXEL_FORMAT=46 + CV_FFMPEG_CAP_PROP_CODEC_PIXEL_FORMAT=46, + CV_FFMPEG_CAP_PROP_BITRATE=47 }; typedef struct CvCapture_FFMPEG CvCapture_FFMPEG; diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index c69cd74509..fae85425b0 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -492,7 +492,7 @@ struct CvCapture_FFMPEG int64_t get_total_frames() const; double get_duration_sec() const; double get_fps() const; - int get_bitrate() const; + int64_t get_bitrate() const; double r2d(AVRational r) const; int64_t dts_to_frame_number(int64_t dts); @@ -1433,6 +1433,8 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const if (rawMode) return -1; break; + case CV_FFMPEG_CAP_PROP_BITRATE: + return static_cast(get_bitrate()); default: break; } @@ -1457,9 +1459,9 @@ double CvCapture_FFMPEG::get_duration_sec() const return sec; } -int CvCapture_FFMPEG::get_bitrate() const +int64_t CvCapture_FFMPEG::get_bitrate() const { - return ic->bit_rate; + return ic->bit_rate / 1000; } double CvCapture_FFMPEG::get_fps() const diff --git a/modules/videoio/test/test_ffmpeg.cpp b/modules/videoio/test/test_ffmpeg.cpp index 10f41daf7a..0251261b81 100644 --- a/modules/videoio/test/test_ffmpeg.cpp +++ b/modules/videoio/test/test_ffmpeg.cpp @@ -573,5 +573,68 @@ TEST(Videoio_Video_parallel_writers_and_readers, accuracy) readers.clear(); } +typedef std::pair cap_property_t; +typedef std::vector cap_properties_t; +typedef std::pair ffmpeg_cap_properties_param_t; +typedef testing::TestWithParam ffmpeg_cap_properties; + +#ifdef _WIN32 +namespace { +::testing::AssertionResult IsOneOf(double value, double expected1, double expected2) +{ + // internal floating point class is used to perform accurate floating point types comparison + typedef ::testing::internal::FloatingPoint FloatingPoint; + + FloatingPoint val(value); + if (val.AlmostEquals(FloatingPoint(expected1)) || val.AlmostEquals(FloatingPoint(expected2))) + { + return ::testing::AssertionSuccess(); + } + else + { + return ::testing::AssertionFailure() + << value << " is neither equal to " << expected1 << " nor " << expected2; + } +} +} +#endif + +TEST_P(ffmpeg_cap_properties, can_read_property) +{ + ffmpeg_cap_properties_param_t parameters = GetParam(); + const std::string path = parameters.first; + const cap_properties_t properties = parameters.second; + + VideoCapture cap(findDataFile(path), CAP_FFMPEG); + ASSERT_TRUE(cap.isOpened()) << "Can not open " << findDataFile(path); + + for (std::size_t i = 0; i < properties.size(); ++i) + { + const cap_property_t& prop = properties[i]; + const double actualValue = cap.get(static_cast(prop.first)); + #ifndef _WIN32 + EXPECT_DOUBLE_EQ(actualValue, prop.second) + << "Property " << static_cast(prop.first) << " has wrong value"; + #else + EXPECT_TRUE(IsOneOf(actualValue, prop.second, 0.0)) + << "Property " << static_cast(prop.first) << " has wrong value"; + #endif + } +} + +cap_properties_t loadBigBuckBunnyFFProbeResults() { + cap_property_t properties[] = { cap_property_t(CAP_PROP_BITRATE, 5851.), + cap_property_t(CAP_PROP_FPS, 24.), + cap_property_t(CAP_PROP_FRAME_HEIGHT, 384.), + cap_property_t(CAP_PROP_FRAME_WIDTH, 672.) }; + return cap_properties_t(properties, properties + sizeof(properties) / sizeof(cap_property_t)); +} + +const ffmpeg_cap_properties_param_t videoio_ffmpeg_properties[] = { + ffmpeg_cap_properties_param_t("video/big_buck_bunny.avi", loadBigBuckBunnyFFProbeResults()) +}; + +INSTANTIATE_TEST_CASE_P(videoio, ffmpeg_cap_properties, testing::ValuesIn(videoio_ffmpeg_properties)); + #endif }} // namespace