Merge pull request #21337 from mansourmoufid:videocapture-get-property-return

Make cv::VideoCapture::get return cv::CAP_PROP_UNKNOWN (-1) for unsupported properties #21337

The return value indicating an unsupported property is not consistent across backends.

I stumbled on this issue because my code was determining if a property value is valid if it's non-zero (like the documentation says), which worked fine on macOS, but not on Android.

For example, auto-exposure is not supported on macOS, so get() returns 0. But it is supported on Android and 0 means auto-exposure is off.

I think -1 is the better return value to indicate unsupported properties.

I made changes to all the backends. I think I got every case. This breaks API compatibility for some backends, so I based this on branch 3.4.

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
- [x] The PR is proposed to proper branch
- [ ] There is reference to original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Mansour Moufid
2026-06-02 01:27:24 -04:00
committed by GitHub
parent 1d4d81103e
commit a68e8d8289
37 changed files with 142 additions and 114 deletions

View File

@@ -26,6 +26,8 @@ TEST_P(videoio_gstreamer, read_check)
ASSERT_NO_THROW(cap.open(pipeline.str(), CAP_GSTREAMER));
ASSERT_TRUE(cap.isOpened());
EXPECT_EQ(CAP_PROP_UNKNOWN, cap.get(CV__CAP_PROP_LATEST));
Mat buffer, decode_frame, gray_frame, rgb_frame;
for (int i = 0; i < count_frames; ++i)
{

View File

@@ -143,6 +143,7 @@ TEST(videoio_images, write_returns_status)
col.generate(1);
VideoWriter wri(col.getFirstFilename(), CAP_IMAGES, 0, 0, col.getFrame(0).size());
ASSERT_TRUE(wri.isOpened());
EXPECT_EQ(CAP_PROP_UNKNOWN, wri.get(CV__CAP_PROP_LATEST));
const Mat frame = col.getFrame(0);
@@ -345,6 +346,7 @@ TEST_P(videoio_image_seq_start, open)
ASSERT_TRUE(cap.open(pattern, apiPref,
{ CAP_PROP_IMAGE_SEQ_START, start }));
ASSERT_TRUE(cap.isOpened());
EXPECT_EQ(CAP_PROP_UNKNOWN, cap.get(CV__CAP_PROP_LATEST));
for (size_t idx = 0; idx < count; ++idx)
{
Mat img;

View File

@@ -169,6 +169,7 @@ TEST(videoio_ffmpeg, camera_index)
ASSERT_TRUE(cap.open(0, CAP_FFMPEG));
Mat frame;
ASSERT_TRUE(cap.read(frame));
EXPECT_EQ(CAP_PROP_UNKNOWN, cap.get(CV__CAP_PROP_LATEST));
ASSERT_FALSE(frame.empty());
}

View File

@@ -64,6 +64,14 @@ public:
std::cout << "SKIP test: backend " << apiPref << " can't open the video: " << video_file << std::endl;
return;
}
// TODO: Requires FFmpeg wrapper rebuild for Windows
#ifdef _WIN32
if (apiPref != CAP_FFMPEG)
EXPECT_EQ(CAP_PROP_UNKNOWN, cap.get(CV__CAP_PROP_LATEST));
#else
EXPECT_EQ(CAP_PROP_UNKNOWN, cap.get(CV__CAP_PROP_LATEST));
#endif
int n_frames = -1;
EXPECT_NO_THROW(n_frames = (int)cap.get(CAP_PROP_FRAME_COUNT));
if (n_frames > 0)
@@ -528,6 +536,15 @@ TEST_P(Videoio_Writer, write_nothing)
VideoWriter writer;
EXPECT_NO_THROW(writer.open(video_file, apiPref, fourcc, fps, frame_size, true));
ASSERT_TRUE(writer.isOpened());
// TODO: Requires FFmpeg wrapper rebuild for Windows
#ifdef _WIN32
if (apiPref != CAP_FFMPEG)
EXPECT_EQ(CAP_PROP_UNKNOWN, writer.get(CV__CAP_PROP_LATEST));
#else
EXPECT_EQ(cv::VIDEOWRITER_PROP_UNKNOWN, writer.get(CV__CAP_PROP_LATEST));
#endif
#if 0 // no frames
cv::Mat m(frame_size, CV_8UC3, Scalar::all(127));
writer << m;