Repository: opencv/opencv
File: modules/videoio/src/cap_ffmpeg_impl.hpp (C++)

Code before:
            open_timeout = params.get<int>(CAP_PROP_OPEN_TIMEOUT_MSEC);
        }
        if (params.has(CAP_PROP_READ_TIMEOUT_MSEC))
        {
            read_timeout = params.get<int>(CAP_PROP_READ_TIMEOUT_MSEC);
        }
#endif
        if (params.has(CAP_PROP_N_THREADS))
        {
            nThreads = params.get<int>(CAP_PROP_N_THREADS);
        }
        if (params.warnUnusedParameters())
        {
            CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: unsupported parameters in .open(), see logger INFO channel for details. Bailout");
            return false;
        }
    }

    if (params.empty() || !params.has(CAP_PROP_N_THREADS))
    {
        std::string threads_option = utils::getConfigurationParameterString("OPENCV_FFMPEG_THREADS");
        if (!threads_option.empty())
        {
            nThreads = atoi(threads_option.c_str());
        }
    }

#if USE_AV_INTERRUPT_CALLBACK
    /* interrupt callback */
    interrupt_metadata.timeout_after_ms = open_timeout;
    get_monotonic_time(&interrupt_metadata.value);

    ic = avformat_alloc_context();
    ic->interrupt_callback.callback = _opencv_ffmpeg_interrupt_callback;
    ic->interrupt_callback.opaque = &interrupt_metadata;
#endif

    std::string options = utils::getConfigurationParameterString("OPENCV_FFMPEG_CAPTURE_OPTIONS");
    if (options.empty())
    {
#if LIBAVFORMAT_VERSION_MICRO >= 100  && LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 48, 100)
        av_dict_set(&dict, "rtsp_flags", "prefer_tcp", 0);
#else
        av_dict_set(&dict, "rtsp_transport", "tcp", 0);
#endif
    }
    else
    {
        CV_LOG_DEBUG(NULL, "VIDEOIO/FFMPEG: using capture options from environment: " << options);
#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 ? CALC_FFMPEG_VERSION(52, 17, 100) : CALC_FFMPEG_VERSION(52, 7, 0))
        av_dict_parse_string(&dict, options.c_str(), ";", "|", 0);

Review comment (suggestion):
OpenCV initializes threading for encoder in the following way:
```
    if (!enc->thread_count)
    {
        int nCpus = cv::getNumberOfCPUs();
        int requestedThreads = std::min(nCpus, 16);  // [OPENCV:FFMPEG:24] Application has requested XX threads. Using a thread count greater than 16 is not recommended.
        std::string threads_option = utils::getConfigurationParameterString("OPENCV_FFMPEG_THREADS");
        if (!threads_option.empty())
        {
            requestedThreads = atoi(threads_option.c_str());
        }
        enc->thread_count = requestedThreads;
    }
```
I propose to use `nCpus = cv::getNumberOfCPUs()` here too as initial value.

Code after:
        }
#endif
        if (params.has(CAP_PROP_N_THREADS))
        {
            nThreads = requestedThreads = params.get<int>(CAP_PROP_N_THREADS);
        }
        if (params.warnUnusedParameters())
        {
            CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: unsupported parameters in .open(), see logger INFO channel for details. Bailout");
            return false;
        }
    }

    if (params.empty() || !params.has(CAP_PROP_N_THREADS))
    {
        std::string threads_option = utils::getConfigurationParameterString("OPENCV_FFMPEG_THREADS");
        if (!threads_option.empty())
        {
            nThreads = requestedThreads = atoi(threads_option.c_str());
        }
    }

#if USE_AV_INTERRUPT_CALLBACK
    /* interrupt callback */
    interrupt_metadata.timeout_after_ms = open_timeout;
    get_monotonic_time(&interrupt_metadata.value);

    ic = avformat_alloc_context();
    ic->interrupt_callback.callback = _opencv_ffmpeg_interrupt_callback;
    ic->interrupt_callback.opaque = &interrupt_metadata;
#endif

    std::string options = utils::getConfigurationParameterString("OPENCV_FFMPEG_CAPTURE_OPTIONS");
    if (options.empty())
    {
#if LIBAVFORMAT_VERSION_MICRO >= 100  && LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 48, 100)
        av_dict_set(&dict, "rtsp_flags", "prefer_tcp", 0);
#else
        av_dict_set(&dict, "rtsp_transport", "tcp", 0);
#endif
    }
    else
    {
        CV_LOG_DEBUG(NULL, "VIDEOIO/FFMPEG: using capture options from environment: " << options);
#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 ? CALC_FFMPEG_VERSION(52, 17, 100) : CALC_FFMPEG_VERSION(52, 7, 0))
        av_dict_parse_string(&dict, options.c_str(), ";", "|", 0);
#else
        av_dict_set(&dict, "rtsp_transport", "tcp", 0);
#endif
    }
    CV_FFMPEG_FMT_CONST AVInputFormat* input_format = NULL;