Path: blob/master/modules/videoio/src/cap_ffmpeg.cpp
16354 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000, Intel Corporation, all rights reserved.13// Third party copyrights are property of their respective owners.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/4041#include "precomp.hpp"4243#if defined(HAVE_FFMPEG)4445#include <string>4647#if !defined(HAVE_FFMPEG_WRAPPER)48#include "cap_ffmpeg_impl.hpp"4950#define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG51#define icvReleaseCapture_FFMPEG_p cvReleaseCapture_FFMPEG52#define icvGrabFrame_FFMPEG_p cvGrabFrame_FFMPEG53#define icvRetrieveFrame_FFMPEG_p cvRetrieveFrame_FFMPEG54#define icvSetCaptureProperty_FFMPEG_p cvSetCaptureProperty_FFMPEG55#define icvGetCaptureProperty_FFMPEG_p cvGetCaptureProperty_FFMPEG56#define icvCreateVideoWriter_FFMPEG_p cvCreateVideoWriter_FFMPEG57#define icvReleaseVideoWriter_FFMPEG_p cvReleaseVideoWriter_FFMPEG58#define icvWriteFrame_FFMPEG_p cvWriteFrame_FFMPEG5960#else6162#include "cap_ffmpeg_api.hpp"6364namespace cv { namespace {6566static CvCreateFileCapture_Plugin icvCreateFileCapture_FFMPEG_p = 0;67static CvReleaseCapture_Plugin icvReleaseCapture_FFMPEG_p = 0;68static CvGrabFrame_Plugin icvGrabFrame_FFMPEG_p = 0;69static CvRetrieveFrame_Plugin icvRetrieveFrame_FFMPEG_p = 0;70static CvSetCaptureProperty_Plugin icvSetCaptureProperty_FFMPEG_p = 0;71static CvGetCaptureProperty_Plugin icvGetCaptureProperty_FFMPEG_p = 0;72static CvCreateVideoWriter_Plugin icvCreateVideoWriter_FFMPEG_p = 0;73static CvReleaseVideoWriter_Plugin icvReleaseVideoWriter_FFMPEG_p = 0;74static CvWriteFrame_Plugin icvWriteFrame_FFMPEG_p = 0;7576static cv::Mutex _icvInitFFMPEG_mutex;7778#if defined _WIN3279static const HMODULE cv_GetCurrentModule()80{81HMODULE h = 0;82#if _WIN32_WINNT >= 0x050183::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,84reinterpret_cast<LPCTSTR>(cv_GetCurrentModule),85&h);86#endif87return h;88}89#endif9091class icvInitFFMPEG92{93public:94static void Init()95{96cv::AutoLock al(_icvInitFFMPEG_mutex);97static icvInitFFMPEG init;98}99100private:101#if defined _WIN32102HMODULE icvFFOpenCV;103104~icvInitFFMPEG()105{106if (icvFFOpenCV)107{108FreeLibrary(icvFFOpenCV);109icvFFOpenCV = 0;110}111}112#endif113114icvInitFFMPEG()115{116#if defined _WIN32117const wchar_t* module_name_ = L"opencv_ffmpeg"118CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION)119#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)120L"_64"121#endif122L".dll";123# ifdef WINRT124icvFFOpenCV = LoadPackagedLibrary( module_name_, 0 );125# else126const std::wstring module_name(module_name_);127128const wchar_t* ffmpeg_env_path = _wgetenv(L"OPENCV_FFMPEG_DLL_DIR");129std::wstring module_path =130ffmpeg_env_path131? ((std::wstring(ffmpeg_env_path) + L"\\") + module_name)132: module_name;133134icvFFOpenCV = LoadLibraryW(module_path.c_str());135if(!icvFFOpenCV && !ffmpeg_env_path)136{137HMODULE m = cv_GetCurrentModule();138if (m)139{140wchar_t path[MAX_PATH];141const size_t path_size = sizeof(path)/sizeof(*path);142size_t sz = GetModuleFileNameW(m, path, path_size);143/* Don't handle paths longer than MAX_PATH until that becomes a real issue */144if (sz > 0 && sz < path_size)145{146wchar_t* s = wcsrchr(path, L'\\');147if (s)148{149s[0] = 0;150module_path = (std::wstring(path) + L"\\") + module_name;151icvFFOpenCV = LoadLibraryW(module_path.c_str());152}153}154}155}156# endif157158if( icvFFOpenCV )159{160icvCreateFileCapture_FFMPEG_p =161(CvCreateFileCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateFileCapture_FFMPEG");162icvReleaseCapture_FFMPEG_p =163(CvReleaseCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseCapture_FFMPEG");164icvGrabFrame_FFMPEG_p =165(CvGrabFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvGrabFrame_FFMPEG");166icvRetrieveFrame_FFMPEG_p =167(CvRetrieveFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvRetrieveFrame_FFMPEG");168icvSetCaptureProperty_FFMPEG_p =169(CvSetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvSetCaptureProperty_FFMPEG");170icvGetCaptureProperty_FFMPEG_p =171(CvGetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvGetCaptureProperty_FFMPEG");172icvCreateVideoWriter_FFMPEG_p =173(CvCreateVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateVideoWriter_FFMPEG");174icvReleaseVideoWriter_FFMPEG_p =175(CvReleaseVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseVideoWriter_FFMPEG");176icvWriteFrame_FFMPEG_p =177(CvWriteFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvWriteFrame_FFMPEG");178# endif // _WIN32179#if 0180if( icvCreateFileCapture_FFMPEG_p != 0 &&181icvReleaseCapture_FFMPEG_p != 0 &&182icvGrabFrame_FFMPEG_p != 0 &&183icvRetrieveFrame_FFMPEG_p != 0 &&184icvSetCaptureProperty_FFMPEG_p != 0 &&185icvGetCaptureProperty_FFMPEG_p != 0 &&186icvCreateVideoWriter_FFMPEG_p != 0 &&187icvReleaseVideoWriter_FFMPEG_p != 0 &&188icvWriteFrame_FFMPEG_p != 0 )189{190printf("Successfully initialized ffmpeg plugin!\n");191}192else193{194printf("Failed to load FFMPEG plugin: module handle=%p\n", icvFFOpenCV);195}196#endif197}198}199};200201202}} // namespace203#endif // HAVE_FFMPEG_WRAPPER204205206207namespace cv {208namespace {209210class CvCapture_FFMPEG_proxy CV_FINAL : public cv::IVideoCapture211{212public:213CvCapture_FFMPEG_proxy() { ffmpegCapture = 0; }214CvCapture_FFMPEG_proxy(const cv::String& filename) { ffmpegCapture = 0; open(filename); }215virtual ~CvCapture_FFMPEG_proxy() { close(); }216217virtual double getProperty(int propId) const CV_OVERRIDE218{219return ffmpegCapture ? icvGetCaptureProperty_FFMPEG_p(ffmpegCapture, propId) : 0;220}221virtual bool setProperty(int propId, double value) CV_OVERRIDE222{223return ffmpegCapture ? icvSetCaptureProperty_FFMPEG_p(ffmpegCapture, propId, value)!=0 : false;224}225virtual bool grabFrame() CV_OVERRIDE226{227return ffmpegCapture ? icvGrabFrame_FFMPEG_p(ffmpegCapture)!=0 : false;228}229virtual bool retrieveFrame(int, cv::OutputArray frame) CV_OVERRIDE230{231unsigned char* data = 0;232int step=0, width=0, height=0, cn=0;233234if (!ffmpegCapture ||235!icvRetrieveFrame_FFMPEG_p(ffmpegCapture, &data, &step, &width, &height, &cn))236return false;237cv::Mat(height, width, CV_MAKETYPE(CV_8U, cn), data, step).copyTo(frame);238return true;239}240virtual bool open( const cv::String& filename )241{242close();243244ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename.c_str() );245return ffmpegCapture != 0;246}247virtual void close()248{249if (ffmpegCapture250#if defined(HAVE_FFMPEG_WRAPPER)251&& icvReleaseCapture_FFMPEG_p252#endif253)254icvReleaseCapture_FFMPEG_p( &ffmpegCapture );255CV_Assert(ffmpegCapture == 0);256ffmpegCapture = 0;257}258259virtual bool isOpened() const CV_OVERRIDE { return ffmpegCapture != 0; }260virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_FFMPEG; }261262protected:263CvCapture_FFMPEG* ffmpegCapture;264};265266} // namespace267268cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const cv::String& filename)269{270#if defined(HAVE_FFMPEG_WRAPPER)271icvInitFFMPEG::Init();272if (!icvCreateFileCapture_FFMPEG_p)273return cv::Ptr<cv::IVideoCapture>();274#endif275cv::Ptr<CvCapture_FFMPEG_proxy> capture = cv::makePtr<CvCapture_FFMPEG_proxy>(filename);276if (capture && capture->isOpened())277return capture;278return cv::Ptr<cv::IVideoCapture>();279}280281namespace {282283class CvVideoWriter_FFMPEG_proxy CV_FINAL :284public cv::IVideoWriter285{286public:287CvVideoWriter_FFMPEG_proxy() { ffmpegWriter = 0; }288CvVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc, double fps, cv::Size frameSize, bool isColor) { ffmpegWriter = 0; open(filename, fourcc, fps, frameSize, isColor); }289virtual ~CvVideoWriter_FFMPEG_proxy() { close(); }290291int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_FFMPEG; }292293virtual void write(cv::InputArray image ) CV_OVERRIDE294{295if(!ffmpegWriter)296return;297CV_Assert(image.depth() == CV_8U);298299icvWriteFrame_FFMPEG_p(ffmpegWriter, (const uchar*)image.getMat().ptr(), (int)image.step(), image.cols(), image.rows(), image.channels(), 0);300}301virtual bool open( const cv::String& filename, int fourcc, double fps, cv::Size frameSize, bool isColor )302{303close();304ffmpegWriter = icvCreateVideoWriter_FFMPEG_p( filename.c_str(), fourcc, fps, frameSize.width, frameSize.height, isColor );305return ffmpegWriter != 0;306}307308virtual void close()309{310if (ffmpegWriter311#if defined(HAVE_FFMPEG_WRAPPER)312&& icvReleaseVideoWriter_FFMPEG_p313#endif314)315icvReleaseVideoWriter_FFMPEG_p( &ffmpegWriter );316CV_Assert(ffmpegWriter == 0);317ffmpegWriter = 0;318}319320virtual double getProperty(int) const CV_OVERRIDE { return 0; }321virtual bool setProperty(int, double) CV_OVERRIDE { return false; }322virtual bool isOpened() const CV_OVERRIDE { return ffmpegWriter != 0; }323324protected:325CvVideoWriter_FFMPEG* ffmpegWriter;326};327328} // namespace329330cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc,331double fps, cv::Size frameSize, int isColor)332{333#if defined(HAVE_FFMPEG_WRAPPER)334icvInitFFMPEG::Init();335if (!icvCreateVideoWriter_FFMPEG_p)336return cv::Ptr<cv::IVideoWriter>();337#endif338cv::Ptr<CvVideoWriter_FFMPEG_proxy> writer = cv::makePtr<CvVideoWriter_FFMPEG_proxy>(filename, fourcc, fps, frameSize, isColor != 0);339if (writer && writer->isOpened())340return writer;341return cv::Ptr<cv::IVideoWriter>();342}343344} // namespace345346#endif // defined(HAVE_FFMPEG)347348349