videoio: revert registry chages, update cap.cpp
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Mon, 4 Mar 2019 21:37:09 +0000 (21:37 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Mon, 4 Mar 2019 21:37:20 +0000 (21:37 +0000)
1  2 
modules/videoio/include/opencv2/videoio/registry.hpp
modules/videoio/src/cap.cpp
modules/videoio/src/videoio_registry.cpp
modules/videoio/src/videoio_registry.hpp
modules/videoio/test/test_dynamic.cpp
modules/videoio/test/test_video_io.cpp

@@@ -38,6 -38,16 +38,9 @@@ CV_EXPORTS_W std::vector<VideoCaptureAP
  /** @brief Returns list of available backends which works via `cv::VideoWriter()` */
  CV_EXPORTS_W std::vector<VideoCaptureAPIs> getWriterBackends();
  
 -enum Capability
 -{
 -    Read,
 -    Write,
 -    ReadWrite
 -};
 -
+ /** @brief Returns true if backend is available */
 -CV_EXPORTS bool hasBackend(VideoCaptureAPIs api, Capability cap = ReadWrite);
++CV_EXPORTS bool hasBackend(VideoCaptureAPIs api);
  //! @}
  }} // namespace
  
  
  namespace cv {
  
++static bool param_VIDEOIO_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_DEBUG", false);
++static bool param_VIDEOCAPTURE_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOCAPTURE_DEBUG", false);
++static bool param_VIDEOWRITER_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOWRITER_DEBUG", false);
++
++
  void DefaultDeleter<CvCapture>::operator ()(CvCapture* obj) const { cvReleaseCapture(&obj); }
  void DefaultDeleter<CvVideoWriter>::operator ()(CvVideoWriter* obj) const { cvReleaseVideoWriter(&obj); }
  
@@@ -79,25 -77,21 +82,47 @@@ bool VideoCapture::open(const String& f
  
      if (isOpened()) release();
  
 -    const std::vector<VideoCaptureAPIs> backends = cv::videoio_registry::getStreamBackends();
 +    const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByFilename();
      for (size_t i = 0; i < backends.size(); i++)
      {
 -        const VideoCaptureAPIs id = backends[i];
 -        const std::string backendName = cv::videoio_registry::getBackendName(id);
 -        if (apiPreference == CAP_ANY || apiPreference == id)
 +        const VideoBackendInfo& info = backends[i];
 +        if (apiPreference == CAP_ANY || apiPreference == info.id)
          {
-             CvCapture* capture = NULL;
-             VideoCapture_create(capture, icap, info.id, filename);
 -            Ptr<IBackend> factory = VideoBackendRegistry::getInstance().getBackend(id);
 -            if (factory)
 -                icap = factory->tryOpenCapture(backendName, filename, 0);
--            if (!icap.empty())
++            if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
++                CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying capture filename='%s' ...", info.name, filename.c_str()));
++            CV_Assert(!info.backendFactory.empty());
++            const Ptr<IBackend> backend = info.backendFactory->getBackend();
++            if (!backend.empty())
 +            {
-                 if (icap->isOpened())
-                     return true;
-                 icap.release();
++                try
++                {
++                    icap = backend->createCapture(filename);
++                    if (!icap.empty())
++                    {
++                        if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
++                            CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d",
++                                                            info.name, icap->isOpened()));
++                        if (icap->isOpened())
++                            return true;
++                        icap.release();
++                    }
++                    else
++                    {
++                        if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
++                            CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create capture", info.name));
++                    }
++                } catch(const cv::Exception& e) {
++                    CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what()));
++                } catch (const std::exception& e) {
++                    CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what()));
++                } catch(...) {
++                    CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name));
++                }
 +            }
-             if (capture)
++            else
              {
-                 cap.reset(capture);
-                 // assume it is opened
-                 return true;
 -                if (icap->isOpened())
 -                    return true;
 -                icap.release();
++                if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
++                    CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name));
              }
          }
      }
@@@ -121,25 -115,21 +146,47 @@@ bool  VideoCapture::open(int cameraNum
          }
      }
  
 -    const std::vector<VideoCaptureAPIs> backends = cv::videoio_registry::getCameraBackends();
 +    const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_CaptureByIndex();
      for (size_t i = 0; i < backends.size(); i++)
      {
 -        const VideoCaptureAPIs id = backends[i];
 -        const std::string backendName = cv::videoio_registry::getBackendName(id);
 -        if (apiPreference == CAP_ANY || apiPreference == id)
 +        const VideoBackendInfo& info = backends[i];
 +        if (apiPreference == CAP_ANY || apiPreference == info.id)
          {
-             CvCapture* capture = NULL;
-             VideoCapture_create(capture, icap, info.id, cameraNum);
 -            Ptr<IBackend> factory = VideoBackendRegistry::getInstance().getBackend(id);
 -            if (factory)
 -                icap = factory->tryOpenCapture(backendName, std::string(), cameraNum);
--            if (!icap.empty())
++            if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
++                CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying capture cameraNum=%d ...", info.name, cameraNum));
++            CV_Assert(!info.backendFactory.empty());
++            const Ptr<IBackend> backend = info.backendFactory->getBackend();
++            if (!backend.empty())
              {
--                if (icap->isOpened())
--                    return true;
--                icap.release();
++                try
++                {
++                    icap = backend->createCapture(cameraNum);
++                    if (!icap.empty())
++                    {
++                        if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
++                            CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d",
++                                                            info.name, icap->isOpened()));
++                        if (icap->isOpened())
++                            return true;
++                        icap.release();
++                    }
++                    else
++                    {
++                        if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG)
++                            CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create capture", info.name));
++                    }
++                } catch(const cv::Exception& e) {
++                    CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what()));
++                } catch (const std::exception& e) {
++                    CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what()));
++                } catch(...) {
++                    CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name));
++                }
 +            }
-             if (capture)
++            else
 +            {
-                 cap.reset(capture);
-                 // assume it is opened
-                 return true;
++                if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
++                    CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name));
              }
          }
      }
@@@ -318,25 -277,21 +334,48 @@@ bool VideoWriter::open(const String& fi
  
      if (isOpened()) release();
  
 -    const std::vector<VideoCaptureAPIs> backends = cv::videoio_registry::getWriterBackends();
 +    const std::vector<VideoBackendInfo> backends = cv::videoio_registry::getAvailableBackends_Writer();
      for (size_t i = 0; i < backends.size(); i++)
      {
 -        const VideoCaptureAPIs id = backends[i];
 -        const std::string backendName = cv::videoio_registry::getBackendName(id);
 -        if (apiPreference == CAP_ANY || apiPreference == id)
 +        const VideoBackendInfo& info = backends[i];
 +        if (apiPreference == CAP_ANY || apiPreference == info.id)
          {
-             CvVideoWriter* writer_ = NULL;
-             VideoWriter_create(writer_, iwriter, info.id, filename, _fourcc, fps, frameSize, isColor);
 -            Ptr<IBackend> factory = VideoBackendRegistry::getInstance().getBackend(id);
 -            if (factory)
 -                iwriter = factory->tryOpenWriter(backendName, filename, _fourcc, fps, frameSize, isColor);
--            if (!iwriter.empty())
++            if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
++                CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying writer with filename='%s' fourcc=0x%08x fps=%g sz=%dx%d isColor=%d...",
++                                                info.name, filename.c_str(), (unsigned)_fourcc, fps, frameSize.width, frameSize.height, (int)isColor));
++            CV_Assert(!info.backendFactory.empty());
++            const Ptr<IBackend> backend = info.backendFactory->getBackend();
++            if (!backend.empty())
 +            {
-                 if (iwriter->isOpened())
-                     return true;
-                 iwriter.release();
++                try
++                {
++                    iwriter = backend->createWriter(filename, _fourcc, fps, frameSize, isColor);
++                    if (!iwriter.empty())
++                    {
++                        if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
++                            CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): created, isOpened=%d",
++                                                            info.name, iwriter->isOpened()));
++                        if (iwriter->isOpened())
++                            return true;
++                        iwriter.release();
++                    }
++                    else
++                    {
++                        if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG)
++                            CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): can't create writer", info.name));
++                    }
++                } catch(const cv::Exception& e) {
++                    CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", info.name, e.what()));
++                } catch (const std::exception& e) {
++                    CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", info.name, e.what()));
++                } catch(...) {
++                    CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", info.name));
++                }
 +            }
-             if (writer_)
++            else
              {
-                 // assume it is opened
-                 writer.reset(writer_);
-                 return true;
 -                if (iwriter->isOpened())
 -                    return true;
 -                iwriter.release();
++                if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
++                    CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): backend is not available (plugin is missing, or can't be loaded due dependencies or it is not compatible)", info.name));
              }
          }
      }
  #pragma warning(disable: 4748)
  #endif
  
 -//=================================================================
 -// Private interface
 -//=================================================================
 +using namespace cv;
 +
- namespace cv
- {
- static bool param_VIDEOIO_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOIO_DEBUG", false);
- static bool param_VIDEOCAPTURE_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOCAPTURE_DEBUG", false);
- static bool param_VIDEOWRITER_DEBUG = utils::getConfigurationParameterBool("OPENCV_VIDEOWRITER_DEBUG", false);
++namespace cv {
 +
 +namespace {
  
- #define DECLARE_BACKEND(cap, name, mode) { cap, (BackendMode)(mode), 1000, name }
 -namespace cv
 -{
+ #define DECLARE_DYNAMIC_BACKEND(cap, name, mode) \
+ { \
 -    cap, (BackendMode)(mode | MODE_DYNAMIC), 1000, name "_DYNAMIC", 0 \
++    cap, (BackendMode)(mode), 1000, name, createPluginBackendFactory(cap, name) \
+ }
 -#define DECLARE_STATIC_BACKEND(cap, name, mode, f1, f2, f3) \
++#define DECLARE_STATIC_BACKEND(cap, name, mode, createCaptureFile, createCaptureCamera, createWriter) \
+ { \
 -    cap, (BackendMode)(mode), 1000, name, Ptr<StaticBackend>(new StaticBackend(f1, f2, f3)) \
++    cap, (BackendMode)(mode), 1000, name, createBackendFactory(createCaptureFile, createCaptureCamera, createWriter) \
+ }
  
  /** Ordering guidelines:
  - modern optimized, multi-platform libraries: ffmpeg, gstreamer, Media SDK
@@@ -115,12 -128,11 +125,12 @@@ static const struct VideoBackendInfo bu
  #endif
  
  #ifdef HAVE_GPHOTO2
-     DECLARE_BACKEND(CAP_GPHOTO2, "GPHOTO2", MODE_CAPTURE_ALL),
+     DECLARE_STATIC_BACKEND(CAP_GPHOTO2, "GPHOTO2", MODE_CAPTURE_ALL, createGPhoto2Capture, createGPhoto2Capture, 0),
  #endif
  #ifdef HAVE_XINE
-     DECLARE_BACKEND(CAP_XINE, "XINE", MODE_CAPTURE_BY_FILENAME),
+     DECLARE_STATIC_BACKEND(CAP_XINE, "XINE", MODE_CAPTURE_BY_FILENAME, createXINECapture, 0, 0),
  #endif
 +
      // dropped backends: MIL, TYZX, Android
  };
  
@@@ -322,301 -305,26 +332,43 @@@ std::vector<VideoCaptureAPIs> getCamera
      for (size_t i = 0; i < backends.size(); i++)
          result.push_back((VideoCaptureAPIs)backends[i].id);
      return result;
 -}
  
 -std::vector<VideoCaptureAPIs> getBackends()
 -{
 -    return toIDs(VideoBackendRegistry::getInstance().getBackends(MODE_CAPTURE_ALL + MODE_WRITER));
  }
  
 -std::vector<VideoCaptureAPIs> getCameraBackends()
 +std::vector<VideoCaptureAPIs> getStreamBackends()
  {
 -    return toIDs(VideoBackendRegistry::getInstance().getBackends(MODE_CAPTURE_BY_INDEX));
 +    const std::vector<VideoBackendInfo> backends = VideoBackendRegistry::getInstance().getAvailableBackends_CaptureByFilename();
 +    std::vector<VideoCaptureAPIs> result;
 +    for (size_t i = 0; i < backends.size(); i++)
 +        result.push_back((VideoCaptureAPIs)backends[i].id);
 +    return result;
 +
  }
  
 -std::vector<VideoCaptureAPIs> getStreamBackends()
 +std::vector<VideoCaptureAPIs> getWriterBackends()
  {
 -    return toIDs(VideoBackendRegistry::getInstance().getBackends(MODE_CAPTURE_BY_FILENAME));
 +    const std::vector<VideoBackendInfo> backends = VideoBackendRegistry::getInstance().getAvailableBackends_Writer();
 +    std::vector<VideoCaptureAPIs> result;
 +    for (size_t i = 0; i < backends.size(); i++)
 +        result.push_back((VideoCaptureAPIs)backends[i].id);
 +    return result;
  }
  
- } // namespace registry
- #define TRY_OPEN(backend_func) \
- { \
-     try { \
-         if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
-             CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
-         icap = backend_func; \
-         if (param_VIDEOIO_DEBUG ||param_VIDEOCAPTURE_DEBUG) \
-             CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p isOpened=%d ...\n", \
-                 #backend_func, icap.empty() ? NULL : icap.get(), icap.empty() ? -1: icap->isOpened())); \
-     } catch(const cv::Exception& e) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
-     } catch (const std::exception& e) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
-     } catch(...) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
-     } \
-     break; \
- }
- #define TRY_OPEN_LEGACY(backend_func) \
- { \
-     try { \
-         if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
-             CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
-         capture = backend_func; \
-         if (param_VIDEOIO_DEBUG || param_VIDEOCAPTURE_DEBUG) \
-             CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p ...\n", #backend_func, capture)); \
-     } catch(const cv::Exception& e) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
-     } catch (const std::exception& e) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
-     } catch(...) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
-     } \
-     break; \
- }
- void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, int index)
 -std::vector<VideoCaptureAPIs> getWriterBackends()
++bool hasBackend(VideoCaptureAPIs api)
  {
-     CV_UNUSED(capture); CV_UNUSED(icap);
-     switch (api)
-     {
-     default:
-         CV_LOG_WARNING(NULL, "VideoCapture(index=" << index << ") was built without support of requested backendID=" << (int)api);
-         break;
- #ifdef HAVE_GSTREAMER
-     case CAP_GSTREAMER:
-         TRY_OPEN(createGStreamerCapture(index));
-         break;
- #endif
- #ifdef HAVE_MSMF
-     case CAP_MSMF:
-         TRY_OPEN(cvCreateCapture_MSMF(index));
-         break;
- #endif
- #ifdef HAVE_DSHOW
-     case CAP_DSHOW:
-         TRY_OPEN(makePtr<VideoCapture_DShow>(index));
-         break;
- #endif
- #ifdef HAVE_LIBREALSENSE
-     case CAP_REALSENSE:
-         TRY_OPEN(makePtr<VideoCapture_LibRealsense>(index));
-         break;
- #endif
- #ifdef WINRT_VIDEO
-     case CAP_WINRT:
-         TRY_OPEN(makePtr<cv::VideoCapture_WinRT>(index));
-         break;
- #endif
- #ifdef HAVE_GPHOTO2
-     case CAP_GPHOTO2:
-         TRY_OPEN(createGPhoto2Capture(index));
-         break;
- #endif
- #if defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
-     case CAP_V4L:
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_V4L(index))
-         break;
- #endif
-     case CAP_FIREWIRE:
- #ifdef HAVE_DC1394_2
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_DC1394_2(index))
- #endif
-         break; // CAP_FIREWIRE
- #ifdef HAVE_MIL
-     case CAP_MIL:
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_MIL(index))
-         break;
- #endif
- #ifdef HAVE_PVAPI
-     case CAP_PVAPI:
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_PvAPI(index))
-         break;
- #endif
- #ifdef HAVE_OPENNI2
-     case CAP_OPENNI2:
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_OpenNI2(index))
-         break;
- #endif
- #ifdef HAVE_XIMEA
-     case CAP_XIAPI:
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_XIMEA(index))
-         break;
- #endif
- #ifdef HAVE_AVFOUNDATION
-     case CAP_AVFOUNDATION:
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_AVFoundation(index))
-         break;
- #endif
- #ifdef HAVE_ARAVIS_API
-     case CAP_ARAVIS:
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_Aravis(index))
-         break;
- #endif
-     } // switch (api)
- }
- void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, const cv::String& filename)
- {
-     CV_UNUSED(capture);
-     switch (api)
-     {
-     default:
-         CV_LOG_WARNING(NULL, "VideoCapture(filename=" << filename << ") was built without support of requested backendID=" << (int)api);
-         break;
- #if defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO
-     case CAP_V4L:
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_V4L(filename.c_str()))
-         break;
- #endif
- #ifdef HAVE_AVFOUNDATION
-     case CAP_AVFOUNDATION:
-         TRY_OPEN_LEGACY(cvCreateFileCapture_AVFoundation(filename.c_str()))
-         break;
- #endif
- #ifdef HAVE_OPENNI2
-     case CAP_OPENNI2:
-         TRY_OPEN_LEGACY(cvCreateFileCapture_OpenNI2(filename.c_str()))
-         break;
- #endif
- #ifdef HAVE_XIMEA
-     case CAP_XIAPI:
-         TRY_OPEN_LEGACY(cvCreateCameraCapture_XIMEA(filename.c_str()))
-         break;
- #endif
-     case CAP_IMAGES:
-         TRY_OPEN(createFileCapture_Images(filename))
-         break;
- #ifdef HAVE_FFMPEG
-     case CAP_FFMPEG:
-         TRY_OPEN(cvCreateFileCapture_FFMPEG_proxy(filename))
-         break;
- #endif
- #ifdef HAVE_GSTREAMER
-     case CAP_GSTREAMER:
-         TRY_OPEN(createGStreamerCapture(filename))
-         break;
- #endif
- #ifdef HAVE_XINE
-     case CAP_XINE:
-         TRY_OPEN(createXINECapture(filename.c_str()))
-         break;
- #endif
- #ifdef HAVE_MSMF
-     case CAP_MSMF:
-         TRY_OPEN(cvCreateCapture_MSMF(filename))
-         break;
- #endif
- #ifdef HAVE_GPHOTO2
-     case CAP_GPHOTO2:
-         TRY_OPEN(createGPhoto2Capture(filename))
-         break;
- #endif
- #ifdef HAVE_MFX
-     case CAP_INTEL_MFX:
-         TRY_OPEN(makePtr<VideoCapture_IntelMFX>(filename))
-         break;
- #endif
-     case CAP_OPENCV_MJPEG:
-         TRY_OPEN(createMotionJpegCapture(filename))
-         break;
-     } // switch
- }
- void VideoWriter_create(CvVideoWriter*& writer, Ptr<IVideoWriter>& iwriter, VideoCaptureAPIs api,
-         const String& filename, int fourcc, double fps, const Size& frameSize, bool isColor)
- {
- #define CREATE_WRITER(backend_func) \
- { \
-     try { \
-         if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
-             CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
-         iwriter = backend_func; \
-         if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
-             CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p  isOpened=%d...\n", #backend_func, iwriter.empty() ? NULL : iwriter.get(), iwriter.empty() ? iwriter->isOpened() : -1)); \
-     } catch(const cv::Exception& e) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
-     } catch (const std::exception& e) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
-     } catch(...) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
-     } \
-     break; \
- }
- #define CREATE_WRITER_LEGACY(backend_func) \
- { \
-     try { \
-         if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
-             CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): trying ...\n", #backend_func)); \
-         writer = backend_func; \
-         if (param_VIDEOIO_DEBUG || param_VIDEOWRITER_DEBUG) \
-             CV_LOG_WARNING(NULL, cv::format("VIDEOIO(%s): result=%p...\n", #backend_func, writer)); \
-     } catch(const cv::Exception& e) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised OpenCV exception:\n\n%s\n", #backend_func, e.what())); \
-     } catch (const std::exception& e) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised C++ exception:\n\n%s\n", #backend_func, e.what())); \
-     } catch(...) { \
-         CV_LOG_ERROR(NULL, cv::format("VIDEOIO(%s): raised unknown C++ exception!\n\n", #backend_func)); \
-     } \
-     break; \
- }
-     switch (api)
 -    return toIDs(VideoBackendRegistry::getInstance().getBackends(MODE_WRITER));
++    std::vector<VideoBackendInfo> backends = VideoBackendRegistry::getInstance().getEnabledBackends();
++    for (size_t i = 0; i < backends.size(); i++)
 +    {
-     default:
-         CV_LOG_ERROR(NULL, "Unknown VideoWriter backend (check getBuildInformation()): " << (int)api);
-         break;
- #ifdef HAVE_FFMPEG
-     case CAP_FFMPEG:
-         CREATE_WRITER(cvCreateVideoWriter_FFMPEG_proxy(filename, fourcc, fps, frameSize, isColor));
-         break;
- #endif
- #ifdef HAVE_MSMF
-     case CAP_MSMF:
-         CREATE_WRITER(cvCreateVideoWriter_MSMF(filename, fourcc, fps, frameSize, isColor));
-         break;
- #endif
- #ifdef HAVE_MFX
-     case CAP_INTEL_MFX:
-         CREATE_WRITER(VideoWriter_IntelMFX::create(filename, fourcc, fps, frameSize, isColor));
-         break;
- #endif
- #ifdef HAVE_AVFOUNDATION
-     case CAP_AVFOUNDATION:
-         CREATE_WRITER_LEGACY(cvCreateVideoWriter_AVFoundation(filename.c_str(), fourcc, fps, cvSize(frameSize), isColor))
-         break;
- #endif
- #ifdef HAVE_GSTREAMER
- case CAP_GSTREAMER:
-         CREATE_WRITER_LEGACY(cvCreateVideoWriter_GStreamer (filename.c_str(), fourcc, fps, cvSize(frameSize), isColor))
-         break;
- #endif
-     case CAP_OPENCV_MJPEG:
-         CREATE_WRITER(createMotionJpegWriter(filename, fourcc, fps, frameSize, isColor));
-         break;
-     case CAP_IMAGES:
-         if(!fourcc || !fps)
++        const VideoBackendInfo& info = backends[i];
++        if (api == info.id)
 +        {
-             CREATE_WRITER_LEGACY(cvCreateVideoWriter_Images(filename.c_str()));
++            CV_Assert(!info.backendFactory.empty());
++            return !info.backendFactory->getBackend().empty();
 +        }
-         break;
-     } // switch(api)
++    }
++    return false;
  }
  
 -}} // cv::videoio_registry::
++} // namespace registry
 +
 +} // namespace
@@@ -5,6 -5,10 +5,8 @@@
  #ifndef __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
  #define __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
  
 -#include "opencv2/videoio.hpp"
 -#include "opencv2/videoio/registry.hpp"
+ #include "backend.hpp"
  namespace cv
  {
  
@@@ -24,20 -29,26 +26,16 @@@ struct VideoBackendInfo 
                        // 0 - disabled (OPENCV_VIDEOIO_PRIORITY_<name> = 0)
                        // >10000 - prioritized list (OPENCV_VIDEOIO_PRIORITY_LIST)
      const char* name;
 -    Ptr<IBackend> backendFactory;
++    Ptr<IBackendFactory> backendFactory;
  };
  
 -/** @brief Manages list of enabled backends
 - */
 -class VideoBackendRegistry
 -{
 -public:
 -    typedef std::vector<VideoBackendInfo> BackendsVec;
 -protected:
 -    BackendsVec enabledBackends;
 -    VideoBackendRegistry();
 -public:
 -    std::string dumpBackends() const;
 -    Ptr<IBackend> getBackend(VideoCaptureAPIs api) const;
 -    BackendsVec getBackends(int capabilityMask, VideoCaptureAPIs filter = CAP_ANY) const;
 -    bool hasBackend(int mask, VideoCaptureAPIs api) const;
 -
 -    static VideoBackendRegistry& getInstance();
 -};
 +namespace videoio_registry {
 +
 +std::vector<VideoBackendInfo> getAvailableBackends_CaptureByIndex();
 +std::vector<VideoBackendInfo> getAvailableBackends_CaptureByFilename();
 +std::vector<VideoBackendInfo> getAvailableBackends_Writer();
 +
 +} // namespace
  
- void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, int index);
- void VideoCapture_create(CvCapture*& capture, Ptr<IVideoCapture>& icap, VideoCaptureAPIs api, const cv::String& filename);
- void VideoWriter_create(CvVideoWriter*& writer, Ptr<IVideoWriter>& iwriter, VideoCaptureAPIs api,
-         const String& filename, int fourcc, double fps, const Size& frameSize, bool isColor);
  } // namespace
  #endif // __OPENCV_VIDEOIO_VIDEOIO_REGISTRY_HPP__
index 0000000,0e14094..603336a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,83 +1,83 @@@
 -    const int fourcc = VideoWriter::fourcc('H', '2', '6', '4');
+ // This file is part of OpenCV project.
+ // It is subject to the license terms in the LICENSE file found in the top-level directory
+ // of this distribution and at http://opencv.org/license.html.
+ #include "test_precomp.hpp"
+ using namespace std;
+ namespace opencv_test { namespace {
+ const int FRAME_COUNT = 120;
+ inline void generateFrame(int i, Mat & frame)
+ {
+     ::generateFrame(i, FRAME_COUNT, frame);
+ }
+ TEST(videoio_dynamic, basic_write)
+ {
+     const Size FRAME_SIZE(640, 480);
+     const double FPS = 100;
+     const String filename = cv::tempfile(".avi");
++    const int fourcc = VideoWriter::fourcc('M', 'J', 'P', 'G');
+     bool fileExists = false;
+     {
+         vector<VideoCaptureAPIs> backends = videoio_registry::getWriterBackends();
+         for (VideoCaptureAPIs be : backends)
+         {
+             VideoWriter writer;
+             writer.open(filename, be, fourcc, FPS, FRAME_SIZE, true);
+             if (writer.isOpened())
+             {
+                 Mat frame(FRAME_SIZE, CV_8UC3);
+                 for (int j = 0; j < FRAME_COUNT; ++j)
+                 {
+                     generateFrame(j, frame);
+                     writer << frame;
+                 }
+                 writer.release();
+                 fileExists = true;
+             }
+             EXPECT_FALSE(writer.isOpened());
+         }
+     }
+     if (!fileExists)
+     {
+         cout << "None of backends has been able to write video file - SKIP reading part" << endl;
+         return;
+     }
+     {
+         vector<VideoCaptureAPIs> backends = videoio_registry::getStreamBackends();
+         for (VideoCaptureAPIs be : backends)
+         {
+             VideoCapture cap;
+             cap.open(filename, be);
+             if(cap.isOpened())
+             {
+                 int count = 0;
+                 while (true)
+                 {
+                     Mat frame;
+                     if (cap.grab())
+                     {
+                         if (cap.retrieve(frame))
+                         {
+                             ++count;
+                             continue;
+                         }
+                     }
+                     break;
+                 }
+                 EXPECT_EQ(count, FRAME_COUNT);
+                 cap.release();
+             }
+             EXPECT_FALSE(cap.isOpened());
+         }
+     }
+     remove(filename.c_str());
+ }
+ }} // opencv_test::<anonymous>::
@@@ -81,8 -82,9 +82,9 @@@ protected
  public:
      void doTest()
      {
-         if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
 -        if (!videoio_registry::hasBackend(apiPref, videoio_registry::Read))
++        if (!videoio_registry::hasBackend(apiPref))
              throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
+         writeVideo();
          VideoCapture cap;
          ASSERT_NO_THROW(cap.open(video_file, apiPref));
          if (!cap.isOpened())
@@@ -166,7 -168,7 +168,7 @@@ public
      }
      void doFrameCountTest()
      {
-         if (!isBackendAvailable(apiPref, cv::videoio_registry::getStreamBackends()))
 -        if (!videoio_registry::hasBackend(apiPref, videoio_registry::Read))
++        if (!videoio_registry::hasBackend(apiPref))
              throw SkipTestException(cv::String("Backend is not available/disabled: ") + cv::videoio_registry::getBackendName(apiPref));
          VideoCapture cap;
          EXPECT_NO_THROW(cap.open(video_file, apiPref));