Skip to content

VideoCapture FFMpeg RTSP low fps fixes#22248

Merged
asmorkalov merged 4 commits intoopencv:4.xfrom
cudawarped:ffmpeg_rtsp_low_fps
Sep 12, 2022
Merged

VideoCapture FFMpeg RTSP low fps fixes#22248
asmorkalov merged 4 commits intoopencv:4.xfrom
cudawarped:ffmpeg_rtsp_low_fps

Conversation

@cudawarped
Copy link
Copy Markdown
Contributor

@cudawarped cudawarped commented Jul 14, 2022

When using VideoCapture with the FFMpeg backend to stream from an RTSP source at a low frame rate on a machine with a large number of CPU cores, VideoCapture::read/grab can fail due to the interrupt timer exceeding timeout_after_ms. To try and fix this, this PR adds the CAP_PROP_N_THREADS which can be set on open to reduce the number of threads in this case. This is related to #20002 but I cannot tell if it fixes the issue as I am unable to re-create it on a machine with reading from a file with only 20 CPU cores.

In addition to this VideoCapture::open can get stuck and therefore interupted on the call to err = avformat_find_stream_info(ic, NULL); when streaming from an RTSP source at a low frame rate regardless of the number of CPU cores. The call to open still succeeds and the frame can be read but because the flag interrupt_metadata.timeout has been set in open the call to grab/read fails. To fix this the interrupt_metadata.timeout flag is reset on entry to grab/read.

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

…pture::open().

Reset interupt timer in grab if
err = avformat_find_stream_info(ic, NULL);
is interupted but open is successful.
@cudawarped
Copy link
Copy Markdown
Contributor Author

@asmorkalov I should add that setting the number of threads is not just an RTSP issue/requirement. It seems like a feature that would be useful when streaming fron n camera's and/or when using raw reads (CAP_PROP_FORMAT==-1) as with cv::cudacodec::VideoReader.

For example on a mobile i7-12700H paried with an RTX 3070 Ti I can decode upwards of 60 1080p streams using VideoReader. This currently creates 1200 (20*60) FFMpeg threads but it works just as well with 20 FFMpeg threads.

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.

BTW, FFmpeg emits warning about threads on i7-12700K (20 threads)

//ic->start_time_realtime is in microseconds
return ((double)ic->start_time_realtime);
case CAP_PROP_N_THREADS:
return static_cast<double>(nThreads);
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.

Could we retrive enc->thread_count value here?

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.

BTW, FFmpeg emits warning about threads on i7-12700K (20 threads)

I don't see a warning on a i7-12700H from cv::VideoCapture with FFMpeg backend do you mean the ffmpeg application?

Could we retrive enc->thread_count value here?

Yes, that's a much better idea as the requested value can be overidden in calls to avcodec_open2.

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.

Try OPENCV_FFMPEG_DEBUG=1 env variable.

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.

Cool cheers,

[OPENCV:FFMPEG:24] Application has requested 20 threads. Using a thread count greater than 16 is not recommended.

The comment
https://github.com/FFmpeg/FFmpeg/blob/70f06dd63c9967881c399662646cc593cc5920fb/libavcodec/pthread_internal.h#L24
implies this is h264 only but I get the warning for all file types. Do you think slice threading is refering to time slice threading and performance or actual errors in the encode/decode?

Do you think this should be hardcoded (const int nCpus = min(16,get_number_of_cpus());), it may change and its possible that using more than the default number of threads may have a performance advantage at least for encoding.
https://trac.ffmpeg.org/ticket/8694

};

INSTANTIATE_TEST_CASE_P(/**/, videoio_container, testing::ValuesIn(videoio_container_params));
INSTANTIATE_TEST_CASE_P(/**/, videoio_container, testing::Combine(testing::ValuesIn(videoio_container_params), THREADS));
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.

  • We prefer to keep already existed tests scenarios without changes.
  • Added tests should be reduced (we don't want to increase the test time). Keep them disabled if they doesn't increase code coverage.

I believe it is enough to add one simple test for the new property.

…lude test combining thread change and raw read in the newly added videoio_read test case.
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.

LGTM 👍 Thank you for the contribution!

@asmorkalov asmorkalov merged commit 46d988e into opencv:4.x Sep 12, 2022
@alalek alalek mentioned this pull request Jan 8, 2023
a-sajjad72 pushed a commit to a-sajjad72/opencv that referenced this pull request Mar 30, 2023
* Allow the number of threads FFMpeg uses to be selected during VideoCapture::open().
Reset interupt timer in grab if
err = avformat_find_stream_info(ic, NULL);
is interupted but open is successful.

* Correct the returned number of threads and amend test cases.

* Update container test case.

* Reverse changes added to existing videoio_container test case and include test combining thread change and raw read in the newly added videoio_read test case.
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.

3 participants