Skip to content

Commit

Permalink
videoio(plugins): support VideoCaptureParameters, CAPTURE_API_VERSION=1
Browse files Browse the repository at this point in the history
- example: ffmpeg
  • Loading branch information
alalek committed Jan 28, 2021
1 parent 4678704 commit e705414
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 92 deletions.
90 changes: 54 additions & 36 deletions modules/videoio/src/backend_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,20 +564,40 @@ class PluginCapture : public cv::IVideoCapture
public:
static
Ptr<PluginCapture> create(const OpenCV_VideoIO_Capture_Plugin_API* plugin_api,
const std::string &filename, int camera)
const std::string &filename, int camera, const VideoCaptureParameters& params)
{
CV_Assert(plugin_api);
CV_Assert(plugin_api->v0.Capture_release);

CvPluginCapture capture = NULL;

if (plugin_api->v0.Capture_open)
if (plugin_api->api_header.api_version >= 1 && plugin_api->v1.Capture_open_with_params)
{
CV_Assert(plugin_api->v0.Capture_release);
if (CV_ERROR_OK == plugin_api->v0.Capture_open(filename.empty() ? 0 : filename.c_str(), camera, &capture))
std::vector<int> vint_params = params.getIntVector();
int* c_params = &vint_params[0];
unsigned n_params = (unsigned)(vint_params.size() / 2);

if (CV_ERROR_OK == plugin_api->v1.Capture_open_with_params(
filename.empty() ? 0 : filename.c_str(), camera, c_params, n_params, &capture))
{
CV_Assert(capture);
return makePtr<PluginCapture>(plugin_api, capture);
}
}
else if (plugin_api->v0.Capture_open)
{
if (CV_ERROR_OK == plugin_api->v0.Capture_open(filename.empty() ? 0 : filename.c_str(), camera, &capture))
{
CV_Assert(capture);
Ptr<PluginCapture> cap = makePtr<PluginCapture>(plugin_api, capture);
if (cap && !params.empty())
{
applyParametersFallback(cap, params);
}
return cap;
}
}

return Ptr<PluginCapture>();
}

Expand Down Expand Up @@ -658,11 +678,13 @@ class PluginWriter : public cv::IVideoWriter
const VideoWriterParameters& params)
{
CV_Assert(plugin_api);
CV_Assert(plugin_api->v0.Writer_release);
CV_Assert(!filename.empty());

CvPluginWriter writer = NULL;

if (plugin_api->api_header.api_version >= 1 && plugin_api->v1.Writer_open_with_params)
{
CV_Assert(plugin_api->v0.Writer_release);
CV_Assert(!filename.empty());
std::vector<int> vint_params = params.getIntVector();
int* c_params = &vint_params[0];
unsigned n_params = (unsigned)(vint_params.size() / 2);
Expand All @@ -675,21 +697,25 @@ class PluginWriter : public cv::IVideoWriter
}
else if (plugin_api->v0.Writer_open)
{
CV_Assert(plugin_api->v0.Writer_release);
CV_Assert(!filename.empty());
const bool isColor = params.get(VIDEOWRITER_PROP_IS_COLOR, true);
const int depth = params.get(VIDEOWRITER_PROP_DEPTH, CV_8U);
if (depth != CV_8U)
{
CV_LOG_WARNING(NULL, "Video I/O plugin doesn't support (due to lower API level) creation of VideoWriter with depth != CV_8U");
return Ptr<PluginWriter>();
}
if (params.warnUnusedParameters())
{
CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: unsupported parameters in VideoWriter, see logger INFO channel for details");
return Ptr<PluginWriter>();
}
if (CV_ERROR_OK == plugin_api->v0.Writer_open(filename.c_str(), fourcc, fps, sz.width, sz.height, isColor, &writer))
{
CV_Assert(writer);
return makePtr<PluginWriter>(plugin_api, writer);
}
}

return Ptr<PluginWriter>();
}

Expand Down Expand Up @@ -743,14 +769,21 @@ class PluginWriter : public cv::IVideoWriter
};


Ptr<IVideoCapture> PluginBackend::createCapture(int camera) const
Ptr<IVideoCapture> PluginBackend::createCapture(int camera, const VideoCaptureParameters& params) const
{
try
{
if (capture_api_)
return PluginCapture::create(capture_api_, std::string(), camera); //.staticCast<IVideoCapture>();
return PluginCapture::create(capture_api_, std::string(), camera, params); //.staticCast<IVideoCapture>();
if (plugin_api_)
return legacy::PluginCapture::create(plugin_api_, std::string(), camera); //.staticCast<IVideoCapture>();
{
Ptr<IVideoCapture> cap = legacy::PluginCapture::create(plugin_api_, std::string(), camera); //.staticCast<IVideoCapture>();
if (cap && !params.empty())
{
applyParametersFallback(cap, params);
}
return cap;
}
}
catch (...)
{
Expand All @@ -760,25 +793,21 @@ Ptr<IVideoCapture> PluginBackend::createCapture(int camera) const
return Ptr<IVideoCapture>();
}

Ptr<IVideoCapture> PluginBackend::createCapture(int camera, const VideoCaptureParameters& params) const
{
// TODO Update plugins API to support parameters
Ptr<IVideoCapture> cap = createCapture(camera);
if (cap && !params.empty())
{
applyParametersFallback(cap, params);
}
return cap;
}

Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename) const
Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename, const VideoCaptureParameters& params) const
{
try
{
if (capture_api_)
return PluginCapture::create(capture_api_, filename, 0); //.staticCast<IVideoCapture>();
return PluginCapture::create(capture_api_, filename, 0, params); //.staticCast<IVideoCapture>();
if (plugin_api_)
return legacy::PluginCapture::create(plugin_api_, filename, 0); //.staticCast<IVideoCapture>();
{
Ptr<IVideoCapture> cap = legacy::PluginCapture::create(plugin_api_, filename, 0); //.staticCast<IVideoCapture>();
if (cap && !params.empty())
{
applyParametersFallback(cap, params);
}
return cap;
}
}
catch (...)
{
Expand All @@ -788,17 +817,6 @@ Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename) con
return Ptr<IVideoCapture>();
}

Ptr<IVideoCapture> PluginBackend::createCapture(const std::string &filename, const VideoCaptureParameters& params) const
{
// TODO Update plugins API to support parameters
Ptr<IVideoCapture> cap = createCapture(filename);
if (cap && !params.empty())
{
applyParametersFallback(cap, params);
}
return cap;
}

Ptr<IVideoWriter> PluginBackend::createWriter(const std::string& filename, int fourcc, double fps,
const cv::Size& sz, const VideoWriterParameters& params) const
{
Expand Down
4 changes: 2 additions & 2 deletions modules/videoio/src/cap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ VideoCapture::VideoCapture(const String& filename, int apiPreference) : throwOnF
}

VideoCapture::VideoCapture(const String& filename, int apiPreference, const std::vector<int>& params)
: throwOnFail(true)
: throwOnFail(false)
{
CV_TRACE_FUNCTION();
open(filename, apiPreference, params);
Expand All @@ -89,7 +89,7 @@ VideoCapture::VideoCapture(int index, int apiPreference) : throwOnFail(false)
}

VideoCapture::VideoCapture(int index, int apiPreference, const std::vector<int>& params)
: throwOnFail(true)
: throwOnFail(false)
{
CV_TRACE_FUNCTION();
open(index, apiPreference, params);
Expand Down
66 changes: 40 additions & 26 deletions modules/videoio/src/cap_ffmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@

#include "cap_ffmpeg_impl.hpp"

#define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG
// TODO drop legacy code
//#define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG
#define icvReleaseCapture_FFMPEG_p cvReleaseCapture_FFMPEG
#define icvGrabFrame_FFMPEG_p cvGrabFrame_FFMPEG
#define icvRetrieveFrame_FFMPEG_p cvRetrieveFrame_FFMPEG
Expand Down Expand Up @@ -101,36 +102,14 @@ class CvCapture_FFMPEG_proxy CV_FINAL : public cv::IVideoCapture

return true;
}
virtual bool open( const cv::String& filename )
{
close();

ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename.c_str() );
return ffmpegCapture != 0;
}
bool open(const cv::String& filename, const cv::VideoCaptureParameters& params)
{
close();

ffmpegCapture = icvCreateFileCapture_FFMPEG_p(filename.c_str());
if (ffmpegCapture && !params.empty())
{
if (params.has(CAP_PROP_FORMAT)) // just a sample code
{
int value = params.get<int>(CAP_PROP_FORMAT);
if (!setProperty(CAP_PROP_FORMAT, value))
{
CV_Error_(Error::StsBadArg, ("VIDEOIO/FFMPEG: CAP_PROP_FORMAT parameter value is invalid/unsupported: %d", value));
}
}
if (params.warnUnusedParameters())
{
CV_Error(Error::StsBadArg, "VIDEOIO/FFMPEG: unsupported parameters in .open(), see logger INFO channel for details");
}
}
ffmpegCapture = cvCreateFileCaptureWithParams_FFMPEG(filename.c_str(), params);
return ffmpegCapture != 0;
}
virtual void close()
void close()
{
if (ffmpegCapture)
icvReleaseCapture_FFMPEG_p( &ffmpegCapture );
Expand Down Expand Up @@ -251,7 +230,7 @@ cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& fi
#include "plugin_api.hpp"
#else
#define CAPTURE_ABI_VERSION 1
#define CAPTURE_API_VERSION 0
#define CAPTURE_API_VERSION 1
#include "plugin_capture_api.hpp"
#define WRITER_ABI_VERSION 1
#define WRITER_API_VERSION 0
Expand Down Expand Up @@ -287,6 +266,38 @@ CvResult CV_API_CALL cv_capture_open(const char* filename, int camera_index, CV_
return CV_ERROR_FAIL;
}

static
CvResult CV_API_CALL cv_capture_open_with_params(
const char* filename, int camera_index,
int* params, unsigned n_params,
CV_OUT CvPluginCapture* handle
)
{
if (!handle)
return CV_ERROR_FAIL;
*handle = NULL;
if (!filename)
return CV_ERROR_FAIL;
CV_UNUSED(camera_index);
CvCapture_FFMPEG_proxy *cap = 0;
try
{
cv::VideoCaptureParameters parameters(params, n_params);
cap = new CvCapture_FFMPEG_proxy(filename, parameters);
if (cap->isOpened())
{
*handle = (CvPluginCapture)cap;
return CV_ERROR_OK;
}
}
catch (...)
{
}
if (cap)
delete cap;
return CV_ERROR_FAIL;
}

static
CvResult CV_API_CALL cv_capture_release(CvPluginCapture handle)
{
Expand Down Expand Up @@ -505,6 +516,9 @@ static const OpenCV_VideoIO_Capture_Plugin_API capture_plugin_api =
/* 5*/cv_capture_set_prop,
/* 6*/cv_capture_grab,
/* 7*/cv_capture_retrieve,
},
{
/* 8*/cv_capture_open_with_params,
}
};

Expand Down
34 changes: 29 additions & 5 deletions modules/videoio/src/cap_ffmpeg_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ static AVRational _opencv_ffmpeg_get_sample_aspect_ratio(AVStream *stream)

struct CvCapture_FFMPEG
{
bool open( const char* filename );
bool open(const char* filename, const VideoCaptureParameters& params);
void close();

double getProperty(int) const;
Expand Down Expand Up @@ -857,7 +857,7 @@ class InternalFFMpegRegister
}
};

bool CvCapture_FFMPEG::open( const char* _filename )
bool CvCapture_FFMPEG::open(const char* _filename, const VideoCaptureParameters& params)
{
InternalFFMpegRegister::init();
AutoLock lock(_mutex);
Expand All @@ -866,6 +866,29 @@ bool CvCapture_FFMPEG::open( const char* _filename )

close();

if (!params.empty())
{
if (params.has(CAP_PROP_FORMAT))
{
int value = params.get<int>(CAP_PROP_FORMAT);
if (value == -1)
{
CV_LOG_INFO(NULL, "VIDEOIO/FFMPEG: enabled demuxer only mode: '" << (_filename ? _filename : "<NULL>") << "'");
rawMode = true;
}
else
{
CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: CAP_PROP_FORMAT parameter value is invalid/unsupported: " << value);
return false;
}
}
if (params.warnUnusedParameters())
{
CV_LOG_ERROR(NULL, "VIDEOIO/FFMPEG: unsupported parameters in .open(), see logger INFO channel for details");
return false;
}
}

#if USE_AV_INTERRUPT_CALLBACK
/* interrupt callback */
interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS;
Expand Down Expand Up @@ -2424,21 +2447,22 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,



CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
static
CvCapture_FFMPEG* cvCreateFileCaptureWithParams_FFMPEG(const char* filename, const VideoCaptureParameters& params)
{
// FIXIT: remove unsafe malloc() approach
CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture));
if (!capture)
return 0;
capture->init();
if( capture->open( filename ))
if (capture->open(filename, params))
return capture;

capture->close();
free(capture);
return 0;
}


void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture)
{
if( capture && *capture )
Expand Down
2 changes: 1 addition & 1 deletion modules/videoio/src/cap_ffmpeg_legacy_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extern "C"
typedef struct CvCapture_FFMPEG CvCapture_FFMPEG;
typedef struct CvVideoWriter_FFMPEG CvVideoWriter_FFMPEG;

OPENCV_FFMPEG_API struct CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG(const char* filename);
//OPENCV_FFMPEG_API struct CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG(const char* filename);
OPENCV_FFMPEG_API int cvSetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap,
int prop, double value);
OPENCV_FFMPEG_API double cvGetCaptureProperty_FFMPEG(struct CvCapture_FFMPEG* cap, int prop);
Expand Down
Loading

0 comments on commit e705414

Please sign in to comment.