Skip to content

log a debug message if a capture backend is generally available but isn't capabable of a capture mode#22700

Merged
asmorkalov merged 1 commit intoopencv:4.xfrom
kallaballa:capture_backened_debug_msg
May 4, 2023
Merged

log a debug message if a capture backend is generally available but isn't capabable of a capture mode#22700
asmorkalov merged 1 commit intoopencv:4.xfrom
kallaballa:capture_backened_debug_msg

Conversation

@kallaballa
Copy link
Copy Markdown
Contributor

The pertaining issue: #22699

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
  • The PR is proposed to the proper branch
  • There is a reference to the 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


if(!foundFilenameBackend && cv::videoio_registry::hasBackend(static_cast<VideoCaptureAPIs>(apiPreference)))
{
CV_CAPTURE_LOG_DEBUG(NULL,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe CV_LOG_WARNING could be used in this case directly (without preconditions).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright

Comment on lines +123 to +129
//Check if the backend generally is available but can't be used to capture by filename
bool foundFilenameBackend = false;
for (size_t i = 0; i < backends.size(); i++)
{
if((foundFilenameBackend = (apiPreference == backends[i].id)))
break;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of scanning in multiple places we could add internal call:
const VideoBackendInfo& cv::videoio_registry::getBackendInfo(VideoCaptureAPIs api)
(similar to cv::videoio_registry::getBackendName() but non-public).

And then use VideoBackendInfo::mode field directly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a plan

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure what internal in that case means. cv::videoio_registry::internal?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"internal" means that it should not be a part of OpenCV public API.

  • declaration should go to src/videoio_registry.hpp
  • definition/implementation src/videoio_registry.cpp

You could add ::internal nested namespace as your wish.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx!

Copy link
Copy Markdown
Contributor Author

@kallaballa kallaballa Nov 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done a19b5b1

Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for update!

Comment on lines +336 to +338
namespace videoio_registry { namespace internal {
const VideoBackendInfo& getBackendInfo(VideoCaptureAPIs api)
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid indentation in namespaces

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright!

Comment on lines +339 to +340
if (api == CAP_ANY)
CV_Error(Error::StsError, "Wrong backend ID: CAP_ANY");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CV_Assert(api != CAP_ANY); is preferable (this check is an internal assumption)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ic

}

CV_Error(Error::StsError, "Unknown backend ID");
return builtin_backends[0]; // unreachable but necessary to silence warnings
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

silence warnings

Which build configuration provides warning?


builtin_backends[0]

This array may be empty. So even a zero/first element is invalid.

Copy link
Copy Markdown
Contributor Author

@kallaballa kallaballa Nov 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

silence warnings

Which build configuration provides warning?

I can't tell you exactly because it was the CI that was failing with a warning because of returning a temporary. Changing the code to this suppressed the warning.

builtin_backends[0]

This array may be empty. So even a zero/first element is invalid.

Of course, but it's (supposed) to be unreachable. How would you like me to handle that case?

if (api == CAP_ANY)
CV_Error(Error::StsError, "Wrong backend ID: CAP_ANY");

const int N = sizeof(builtin_backends)/sizeof(builtin_backends[0]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

builtin_backends

Not correct.
We should use VideoBackendRegistry::enabledBackends instead.
We need to add getter for this "protected" field:

const std::vector<VideoBackendInfo>& getEnabledBackends() const
{
    return enabledBackends;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright

return info;
}

CV_Error(Error::StsError, "Unknown backend ID");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This exception changes existed behavior of .open() method of VideoCapture for non-existed/disabled backends.

Perhaps we need to return pointer (const VideoBackendInfo*) and check for NULL in caller.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I implement it like that?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is internal API, so it could be adopted later if you have better solution.

Anyway implementation should not raise exception through CV_Error() (as high-level API of VideoCapture doesn't do that in case of failure of opening process).
Changing that behavior would break a lot of existed user code. This is a compatibility question.

@asmorkalov asmorkalov requested a review from opencv-alalek April 6, 2023 16:18
@asmorkalov
Copy link
Copy Markdown
Contributor

@opencv-alalek Could do you have updates?

@opencv-alalek
Copy link
Copy Markdown
Contributor

@asmorkalov There is nothing to add from my side. No idea which updates are expected here.

@kallaballa
Copy link
Copy Markdown
Contributor Author

@asmorkalov There is nothing to add from my side. No idea which updates are expected here.

This exception changes existed behavior of .open() method of VideoCapture for non-existed/disabled backends.

Perhaps we need to return pointer (const VideoBackendInfo*) and check for NULL in caller.

The open question is if it should be implemented like that.

@asmorkalov asmorkalov force-pushed the capture_backened_debug_msg branch from 8a71dda to a2be9e9 Compare May 4, 2023 16:20
@asmorkalov
Copy link
Copy Markdown
Contributor

@kallaballa I simplified your solution a bit and squashed commits. It works as expected now:

$ python3 
Python 3.6.9 (default, Mar 10 2023, 16:46:00) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> c=cv2.VideoCapture(0, cv2.CAP_FFMPEG)
[DEBUG:0@13.436] global videoio_registry.cpp:206 VideoBackendRegistry VIDEOIO: Builtin backends(9): FFMPEG(1000); GSTREAMER(990); INTEL_MFX(980); V4L2(970); CV_IMAGES(960); CV_MJPEG(950); FIREWIRE(940); UEYE(930); OBSENSOR(920)
[DEBUG:0@13.436] global videoio_registry.cpp:230 VideoBackendRegistry VIDEOIO: Available backends(9): FFMPEG(1000); GSTREAMER(990); INTEL_MFX(980); V4L2(970); CV_IMAGES(960); CV_MJPEG(950); FIREWIRE(940); UEYE(930); OBSENSOR(920)
[ INFO:0@13.436] global videoio_registry.cpp:232 VideoBackendRegistry VIDEOIO: Enabled backends(9, sorted by priority): FFMPEG(1000); GSTREAMER(990); INTEL_MFX(980); V4L2(970); CV_IMAGES(960); CV_MJPEG(950); FIREWIRE(940); UEYE(930); OBSENSOR(920)
[ WARN:0@13.436] global cap.cpp:331 open VIDEOIO(FFMPEG): backend is generally available but can't be used to capture by index
>>> quit()

@asmorkalov asmorkalov requested review from asmorkalov and removed request for opencv-alalek May 4, 2023 17:32
@asmorkalov asmorkalov added this to the 4.8.0 milestone May 4, 2023
@asmorkalov asmorkalov merged commit dabf960 into opencv:4.x May 4, 2023
@kallaballa
Copy link
Copy Markdown
Contributor Author

thx!

@asmorkalov asmorkalov mentioned this pull request May 31, 2023
@james-ro-williams
Copy link
Copy Markdown

I'm receiving this warning when attempting to capture from a UDP stream using FFMPEG as a backend in a Docker container: [ WARN:0@30.144] global cap.cpp:204 open VIDEOIO(FFMPEG): backend is generally available but can't be used to capture by name.

I think this warning could do with a bit of an evaluation as it took an awful lot of digging to get to here to figure out what was going on, and I'm still not entirely sure why my VideoCapture is failing - as it works outside the container and fails inside.

This warning implies that FFMPEG is installed correctly and OpenCV is too, unless I'm completely mistaken.

@kallaballa
Copy link
Copy Markdown
Contributor Author

kallaballa commented Jul 27, 2023

I'm receiving this warning when attempting to capture from a UDP stream using FFMPEG as a backend in a Docker container: [ WARN:0@30.144] global cap.cpp:204 open VIDEOIO(FFMPEG): backend is generally available but can't be used to capture by name.

I think this warning could do with a bit of an evaluation as it took an awful lot of digging to get to here to figure out what was going on, and I'm still not entirely sure why my VideoCapture is failing - as it works outside the container and fails inside.

This warning implies that FFMPEG is installed correctly and OpenCV is too, unless I'm completely mistaken.

Hi!
Would you please post the result of opencv_version -v for both environments?
Also could you make a minimal example that fails?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants