// 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. #ifndef CAP_INTERFACE_HPP #define CAP_INTERFACE_HPP #include "opencv2/core.hpp" #include "opencv2/core/core_c.h" #include "opencv2/videoio.hpp" #include "opencv2/videoio/videoio_c.h" //=================================================== // Legacy structs struct CvCapture { virtual ~CvCapture() {} virtual double getProperty(int) const { return 0; } virtual bool setProperty(int, double) { return 0; } virtual bool grabFrame() { return true; } virtual IplImage* retrieveFrame(int) { return 0; } virtual int getCaptureDomain() { return cv::CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc... }; struct CvVideoWriter { virtual ~CvVideoWriter() {} virtual bool writeFrame(const IplImage*) { return false; } virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc... virtual double getProperty(int) const { return 0; } }; //=================================================== // Modern classes namespace cv { namespace { template inline T castParameterTo(int paramValue) { return static_cast(paramValue); } template <> inline bool castParameterTo(int paramValue) { return paramValue != 0; } } class VideoParameters { public: struct VideoParameter { VideoParameter() = default; VideoParameter(int key_, int value_) : key(key_), value(value_) {} int key{-1}; int value{-1}; mutable bool isConsumed{false}; }; VideoParameters() = default; explicit VideoParameters(const std::vector& params) { const auto count = params.size(); if (count % 2 != 0) { CV_Error_(Error::StsVecLengthErr, ("Vector of VideoWriter parameters should have even length")); } params_.reserve(count / 2); for (std::size_t i = 0; i < count; i += 2) { add(params[i], params[i + 1]); } } VideoParameters(int* params, unsigned n_params) { params_.reserve(n_params); for (unsigned i = 0; i < n_params; ++i) { add(params[2*i], params[2*i + 1]); } } void add(int key, int value) { params_.emplace_back(key, value); } bool has(int key) const { auto it = std::find_if(params_.begin(), params_.end(), [key](const VideoParameter ¶m) { return param.key == key; } ); return it != params_.end(); } template ValueType get(int key) const { auto it = std::find_if(params_.begin(), params_.end(), [key](const VideoParameter ¶m) { return param.key == key; } ); if (it != params_.end()) { it->isConsumed = true; return castParameterTo(it->value); } else { CV_Error_(Error::StsBadArg, ("Missing value for parameter: [%d]", key)); } } template ValueType get(int key, ValueType defaultValue) const { auto it = std::find_if(params_.begin(), params_.end(), [key](const VideoParameter ¶m) { return param.key == key; } ); if (it != params_.end()) { it->isConsumed = true; return castParameterTo(it->value); } else { return defaultValue; } } std::vector getUnused() const { std::vector unusedParams; for (const auto ¶m : params_) { if (!param.isConsumed) { unusedParams.push_back(param.key); } } return unusedParams; } std::vector getIntVector() const { std::vector vint_params; for (const auto& param : params_) { vint_params.push_back(param.key); vint_params.push_back(param.value); } return vint_params; } bool empty() const { return params_.empty(); } bool warnUnusedParameters() const { bool found = false; for (const auto ¶m : params_) { if (!param.isConsumed) { found = true; CV_LOG_INFO(NULL, "VIDEOIO: unused parameter: [" << param.key << "]=" << cv::format("%lld / 0x%016llx", (long long)param.value, (long long)param.value)); } } return found; } private: std::vector params_; }; class VideoWriterParameters : public VideoParameters { public: using VideoParameters::VideoParameters; // reuse constructors }; class VideoCaptureParameters : public VideoParameters { public: using VideoParameters::VideoParameters; // reuse constructors }; class IVideoCapture { public: virtual ~IVideoCapture() {} virtual double getProperty(int) const { return 0; } virtual bool setProperty(int, double) { return false; } virtual bool grabFrame() = 0; virtual bool retrieveFrame(int, OutputArray) = 0; virtual bool isOpened() const = 0; virtual int getCaptureDomain() { return CAP_ANY; } // Return the type of the capture object: CAP_DSHOW, etc... }; class IVideoWriter { public: virtual ~IVideoWriter() {} virtual double getProperty(int) const { return 0; } virtual bool setProperty(int, double) { return false; } virtual bool isOpened() const = 0; virtual void write(InputArray) = 0; virtual int getCaptureDomain() const { return cv::CAP_ANY; } // Return the type of the capture object: CAP_FFMPEG, etc... }; namespace internal { class VideoCapturePrivateAccessor { public: static IVideoCapture* getIVideoCapture(const VideoCapture& cap) { return cap.icap.get(); } }; } // namespace // Advanced base class for VideoCapture backends providing some extra functionality class VideoCaptureBase : public IVideoCapture { public: VideoCaptureBase() : autorotate(false) {} double getProperty(int propId) const CV_OVERRIDE { switch(propId) { case cv::CAP_PROP_ORIENTATION_AUTO: return static_cast(autorotate); case cv::CAP_PROP_FRAME_WIDTH: return shouldSwapWidthHeight() ? getProperty_(cv::CAP_PROP_FRAME_HEIGHT) : getProperty_(cv::CAP_PROP_FRAME_WIDTH); case cv::CAP_PROP_FRAME_HEIGHT: return shouldSwapWidthHeight() ? getProperty_(cv::CAP_PROP_FRAME_WIDTH) : getProperty_(cv::CAP_PROP_FRAME_HEIGHT); default: return getProperty_(propId); } } bool setProperty(int propId, double value) CV_OVERRIDE { switch(propId) { case cv::CAP_PROP_ORIENTATION_AUTO: autorotate = (value != 0); return true; default: return setProperty_(propId, value); } } bool retrieveFrame(int channel, OutputArray image) CV_OVERRIDE { const bool res = retrieveFrame_(channel, image); if (res) applyMetadataRotation(image); return res; } protected: virtual double getProperty_(int) const = 0; virtual bool setProperty_(int, double) = 0; virtual bool retrieveFrame_(int, OutputArray) = 0; protected: bool shouldSwapWidthHeight() const { if (!autorotate) return false; int rotation = static_cast(getProperty(cv::CAP_PROP_ORIENTATION_META)); return std::abs(rotation % 180) == 90; } void applyMetadataRotation(OutputArray mat) const { bool rotation_auto = 0 != getProperty(CAP_PROP_ORIENTATION_AUTO); int rotation_angle = static_cast(getProperty(CAP_PROP_ORIENTATION_META)); if(!rotation_auto || rotation_angle%360 == 0) { return; } cv::RotateFlags flag; if(rotation_angle == 90 || rotation_angle == -270) { // Rotate clockwise 90 degrees flag = cv::ROTATE_90_CLOCKWISE; } else if(rotation_angle == 270 || rotation_angle == -90) { // Rotate clockwise 270 degrees flag = cv::ROTATE_90_COUNTERCLOCKWISE; } else if(rotation_angle == 180 || rotation_angle == -180) { // Rotate clockwise 180 degrees flag = cv::ROTATE_180; } else { // Unsupported rotation return; } cv::rotate(mat, mat, flag); } protected: bool autorotate; }; //================================================================================================== Ptr cvCreateFileCapture_FFMPEG_proxy(const std::string &filename, const VideoCaptureParameters& params); Ptr cvCreateVideoWriter_FFMPEG_proxy(const std::string& filename, int fourcc, double fps, const Size& frameSize, const VideoWriterParameters& params); Ptr createGStreamerCapture_file(const std::string& filename, const cv::VideoCaptureParameters& params); Ptr createGStreamerCapture_cam(int index, const cv::VideoCaptureParameters& params); Ptr create_GStreamer_writer(const std::string& filename, int fourcc, double fps, const Size& frameSize, const VideoWriterParameters& params); Ptr create_MFX_capture(const std::string &filename); Ptr create_MFX_writer(const std::string& filename, int _fourcc, double fps, const Size& frameSize, const VideoWriterParameters& params); Ptr create_AVFoundation_capture_file(const std::string &filename); Ptr create_AVFoundation_capture_cam(int index); Ptr create_AVFoundation_writer(const std::string& filename, int fourcc, double fps, const Size& frameSize, const VideoWriterParameters& params); Ptr create_WRT_capture(int device); Ptr cvCreateCapture_MSMF(int index, const VideoCaptureParameters& params); Ptr cvCreateCapture_MSMF(const std::string& filename, const VideoCaptureParameters& params); Ptr cvCreateVideoWriter_MSMF(const std::string& filename, int fourcc, double fps, const Size& frameSize, const VideoWriterParameters& params); Ptr create_DShow_capture(int index); Ptr create_V4L_capture_cam(int index); Ptr create_V4L_capture_file(const std::string &filename); Ptr create_OpenNI2_capture_cam( int index ); Ptr create_OpenNI2_capture_file( const std::string &filename ); Ptr create_Images_capture(const std::string &filename); Ptr create_Images_writer(const std::string& filename, int fourcc, double fps, const Size& frameSize, const VideoWriterParameters& params); Ptr create_DC1394_capture(int index); Ptr create_RealSense_capture(int index); Ptr create_PvAPI_capture( int index ); Ptr create_XIMEA_capture_cam( int index ); Ptr create_XIMEA_capture_file( const std::string &serialNumber ); Ptr create_ueye_camera(int camera); Ptr create_Aravis_capture( int index ); Ptr createMotionJpegCapture(const std::string& filename); Ptr createMotionJpegWriter(const std::string& filename, int fourcc, double fps, const Size& frameSize, const VideoWriterParameters& params); Ptr createGPhoto2Capture(int index); Ptr createGPhoto2Capture(const std::string& deviceName); Ptr createXINECapture(const std::string &filename); Ptr createAndroidCapture_cam( int index ); Ptr createAndroidCapture_file(const std::string &filename); Ptr createAndroidVideoWriter(const std::string& filename, int fourcc, double fps, const Size& frameSize, const VideoWriterParameters& params); Ptr create_obsensor_capture(int index); bool VideoCapture_V4L_waitAny( const std::vector& streams, CV_OUT std::vector& ready, int64 timeoutNs); static inline std::ostream& operator<<(std::ostream& out, const VideoAccelerationType& va_type) { switch (va_type) { case VIDEO_ACCELERATION_NONE: out << "NONE"; return out; case VIDEO_ACCELERATION_ANY: out << "ANY"; return out; case VIDEO_ACCELERATION_D3D11: out << "D3D11"; return out; case VIDEO_ACCELERATION_VAAPI: out << "VAAPI"; return out; case VIDEO_ACCELERATION_MFX: out << "MFX"; return out; } out << cv::format("UNKNOWN(0x%ux)", static_cast(va_type)); return out; } } // cv:: #endif // CAP_INTERFACE_HPP