Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/videoio/src/cap_ffmpeg.cpp
16354 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// Intel License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000, Intel Corporation, all rights reserved.
14
// Third party copyrights are property of their respective owners.
15
//
16
// Redistribution and use in source and binary forms, with or without modification,
17
// are permitted provided that the following conditions are met:
18
//
19
// * Redistribution's of source code must retain the above copyright notice,
20
// this list of conditions and the following disclaimer.
21
//
22
// * Redistribution's in binary form must reproduce the above copyright notice,
23
// this list of conditions and the following disclaimer in the documentation
24
// and/or other materials provided with the distribution.
25
//
26
// * The name of Intel Corporation may not be used to endorse or promote products
27
// derived from this software without specific prior written permission.
28
//
29
// This software is provided by the copyright holders and contributors "as is" and
30
// any express or implied warranties, including, but not limited to, the implied
31
// warranties of merchantability and fitness for a particular purpose are disclaimed.
32
// In no event shall the Intel Corporation or contributors be liable for any direct,
33
// indirect, incidental, special, exemplary, or consequential damages
34
// (including, but not limited to, procurement of substitute goods or services;
35
// loss of use, data, or profits; or business interruption) however caused
36
// and on any theory of liability, whether in contract, strict liability,
37
// or tort (including negligence or otherwise) arising in any way out of
38
// the use of this software, even if advised of the possibility of such damage.
39
//
40
//M*/
41
42
#include "precomp.hpp"
43
44
#if defined(HAVE_FFMPEG)
45
46
#include <string>
47
48
#if !defined(HAVE_FFMPEG_WRAPPER)
49
#include "cap_ffmpeg_impl.hpp"
50
51
#define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG
52
#define icvReleaseCapture_FFMPEG_p cvReleaseCapture_FFMPEG
53
#define icvGrabFrame_FFMPEG_p cvGrabFrame_FFMPEG
54
#define icvRetrieveFrame_FFMPEG_p cvRetrieveFrame_FFMPEG
55
#define icvSetCaptureProperty_FFMPEG_p cvSetCaptureProperty_FFMPEG
56
#define icvGetCaptureProperty_FFMPEG_p cvGetCaptureProperty_FFMPEG
57
#define icvCreateVideoWriter_FFMPEG_p cvCreateVideoWriter_FFMPEG
58
#define icvReleaseVideoWriter_FFMPEG_p cvReleaseVideoWriter_FFMPEG
59
#define icvWriteFrame_FFMPEG_p cvWriteFrame_FFMPEG
60
61
#else
62
63
#include "cap_ffmpeg_api.hpp"
64
65
namespace cv { namespace {
66
67
static CvCreateFileCapture_Plugin icvCreateFileCapture_FFMPEG_p = 0;
68
static CvReleaseCapture_Plugin icvReleaseCapture_FFMPEG_p = 0;
69
static CvGrabFrame_Plugin icvGrabFrame_FFMPEG_p = 0;
70
static CvRetrieveFrame_Plugin icvRetrieveFrame_FFMPEG_p = 0;
71
static CvSetCaptureProperty_Plugin icvSetCaptureProperty_FFMPEG_p = 0;
72
static CvGetCaptureProperty_Plugin icvGetCaptureProperty_FFMPEG_p = 0;
73
static CvCreateVideoWriter_Plugin icvCreateVideoWriter_FFMPEG_p = 0;
74
static CvReleaseVideoWriter_Plugin icvReleaseVideoWriter_FFMPEG_p = 0;
75
static CvWriteFrame_Plugin icvWriteFrame_FFMPEG_p = 0;
76
77
static cv::Mutex _icvInitFFMPEG_mutex;
78
79
#if defined _WIN32
80
static const HMODULE cv_GetCurrentModule()
81
{
82
HMODULE h = 0;
83
#if _WIN32_WINNT >= 0x0501
84
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
85
reinterpret_cast<LPCTSTR>(cv_GetCurrentModule),
86
&h);
87
#endif
88
return h;
89
}
90
#endif
91
92
class icvInitFFMPEG
93
{
94
public:
95
static void Init()
96
{
97
cv::AutoLock al(_icvInitFFMPEG_mutex);
98
static icvInitFFMPEG init;
99
}
100
101
private:
102
#if defined _WIN32
103
HMODULE icvFFOpenCV;
104
105
~icvInitFFMPEG()
106
{
107
if (icvFFOpenCV)
108
{
109
FreeLibrary(icvFFOpenCV);
110
icvFFOpenCV = 0;
111
}
112
}
113
#endif
114
115
icvInitFFMPEG()
116
{
117
#if defined _WIN32
118
const wchar_t* module_name_ = L"opencv_ffmpeg"
119
CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION)
120
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
121
L"_64"
122
#endif
123
L".dll";
124
# ifdef WINRT
125
icvFFOpenCV = LoadPackagedLibrary( module_name_, 0 );
126
# else
127
const std::wstring module_name(module_name_);
128
129
const wchar_t* ffmpeg_env_path = _wgetenv(L"OPENCV_FFMPEG_DLL_DIR");
130
std::wstring module_path =
131
ffmpeg_env_path
132
? ((std::wstring(ffmpeg_env_path) + L"\\") + module_name)
133
: module_name;
134
135
icvFFOpenCV = LoadLibraryW(module_path.c_str());
136
if(!icvFFOpenCV && !ffmpeg_env_path)
137
{
138
HMODULE m = cv_GetCurrentModule();
139
if (m)
140
{
141
wchar_t path[MAX_PATH];
142
const size_t path_size = sizeof(path)/sizeof(*path);
143
size_t sz = GetModuleFileNameW(m, path, path_size);
144
/* Don't handle paths longer than MAX_PATH until that becomes a real issue */
145
if (sz > 0 && sz < path_size)
146
{
147
wchar_t* s = wcsrchr(path, L'\\');
148
if (s)
149
{
150
s[0] = 0;
151
module_path = (std::wstring(path) + L"\\") + module_name;
152
icvFFOpenCV = LoadLibraryW(module_path.c_str());
153
}
154
}
155
}
156
}
157
# endif
158
159
if( icvFFOpenCV )
160
{
161
icvCreateFileCapture_FFMPEG_p =
162
(CvCreateFileCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateFileCapture_FFMPEG");
163
icvReleaseCapture_FFMPEG_p =
164
(CvReleaseCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseCapture_FFMPEG");
165
icvGrabFrame_FFMPEG_p =
166
(CvGrabFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvGrabFrame_FFMPEG");
167
icvRetrieveFrame_FFMPEG_p =
168
(CvRetrieveFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvRetrieveFrame_FFMPEG");
169
icvSetCaptureProperty_FFMPEG_p =
170
(CvSetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvSetCaptureProperty_FFMPEG");
171
icvGetCaptureProperty_FFMPEG_p =
172
(CvGetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvGetCaptureProperty_FFMPEG");
173
icvCreateVideoWriter_FFMPEG_p =
174
(CvCreateVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateVideoWriter_FFMPEG");
175
icvReleaseVideoWriter_FFMPEG_p =
176
(CvReleaseVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseVideoWriter_FFMPEG");
177
icvWriteFrame_FFMPEG_p =
178
(CvWriteFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvWriteFrame_FFMPEG");
179
# endif // _WIN32
180
#if 0
181
if( icvCreateFileCapture_FFMPEG_p != 0 &&
182
icvReleaseCapture_FFMPEG_p != 0 &&
183
icvGrabFrame_FFMPEG_p != 0 &&
184
icvRetrieveFrame_FFMPEG_p != 0 &&
185
icvSetCaptureProperty_FFMPEG_p != 0 &&
186
icvGetCaptureProperty_FFMPEG_p != 0 &&
187
icvCreateVideoWriter_FFMPEG_p != 0 &&
188
icvReleaseVideoWriter_FFMPEG_p != 0 &&
189
icvWriteFrame_FFMPEG_p != 0 )
190
{
191
printf("Successfully initialized ffmpeg plugin!\n");
192
}
193
else
194
{
195
printf("Failed to load FFMPEG plugin: module handle=%p\n", icvFFOpenCV);
196
}
197
#endif
198
}
199
}
200
};
201
202
203
}} // namespace
204
#endif // HAVE_FFMPEG_WRAPPER
205
206
207
208
namespace cv {
209
namespace {
210
211
class CvCapture_FFMPEG_proxy CV_FINAL : public cv::IVideoCapture
212
{
213
public:
214
CvCapture_FFMPEG_proxy() { ffmpegCapture = 0; }
215
CvCapture_FFMPEG_proxy(const cv::String& filename) { ffmpegCapture = 0; open(filename); }
216
virtual ~CvCapture_FFMPEG_proxy() { close(); }
217
218
virtual double getProperty(int propId) const CV_OVERRIDE
219
{
220
return ffmpegCapture ? icvGetCaptureProperty_FFMPEG_p(ffmpegCapture, propId) : 0;
221
}
222
virtual bool setProperty(int propId, double value) CV_OVERRIDE
223
{
224
return ffmpegCapture ? icvSetCaptureProperty_FFMPEG_p(ffmpegCapture, propId, value)!=0 : false;
225
}
226
virtual bool grabFrame() CV_OVERRIDE
227
{
228
return ffmpegCapture ? icvGrabFrame_FFMPEG_p(ffmpegCapture)!=0 : false;
229
}
230
virtual bool retrieveFrame(int, cv::OutputArray frame) CV_OVERRIDE
231
{
232
unsigned char* data = 0;
233
int step=0, width=0, height=0, cn=0;
234
235
if (!ffmpegCapture ||
236
!icvRetrieveFrame_FFMPEG_p(ffmpegCapture, &data, &step, &width, &height, &cn))
237
return false;
238
cv::Mat(height, width, CV_MAKETYPE(CV_8U, cn), data, step).copyTo(frame);
239
return true;
240
}
241
virtual bool open( const cv::String& filename )
242
{
243
close();
244
245
ffmpegCapture = icvCreateFileCapture_FFMPEG_p( filename.c_str() );
246
return ffmpegCapture != 0;
247
}
248
virtual void close()
249
{
250
if (ffmpegCapture
251
#if defined(HAVE_FFMPEG_WRAPPER)
252
&& icvReleaseCapture_FFMPEG_p
253
#endif
254
)
255
icvReleaseCapture_FFMPEG_p( &ffmpegCapture );
256
CV_Assert(ffmpegCapture == 0);
257
ffmpegCapture = 0;
258
}
259
260
virtual bool isOpened() const CV_OVERRIDE { return ffmpegCapture != 0; }
261
virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_FFMPEG; }
262
263
protected:
264
CvCapture_FFMPEG* ffmpegCapture;
265
};
266
267
} // namespace
268
269
cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const cv::String& filename)
270
{
271
#if defined(HAVE_FFMPEG_WRAPPER)
272
icvInitFFMPEG::Init();
273
if (!icvCreateFileCapture_FFMPEG_p)
274
return cv::Ptr<cv::IVideoCapture>();
275
#endif
276
cv::Ptr<CvCapture_FFMPEG_proxy> capture = cv::makePtr<CvCapture_FFMPEG_proxy>(filename);
277
if (capture && capture->isOpened())
278
return capture;
279
return cv::Ptr<cv::IVideoCapture>();
280
}
281
282
namespace {
283
284
class CvVideoWriter_FFMPEG_proxy CV_FINAL :
285
public cv::IVideoWriter
286
{
287
public:
288
CvVideoWriter_FFMPEG_proxy() { ffmpegWriter = 0; }
289
CvVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc, double fps, cv::Size frameSize, bool isColor) { ffmpegWriter = 0; open(filename, fourcc, fps, frameSize, isColor); }
290
virtual ~CvVideoWriter_FFMPEG_proxy() { close(); }
291
292
int getCaptureDomain() const CV_OVERRIDE { return cv::CAP_FFMPEG; }
293
294
virtual void write(cv::InputArray image ) CV_OVERRIDE
295
{
296
if(!ffmpegWriter)
297
return;
298
CV_Assert(image.depth() == CV_8U);
299
300
icvWriteFrame_FFMPEG_p(ffmpegWriter, (const uchar*)image.getMat().ptr(), (int)image.step(), image.cols(), image.rows(), image.channels(), 0);
301
}
302
virtual bool open( const cv::String& filename, int fourcc, double fps, cv::Size frameSize, bool isColor )
303
{
304
close();
305
ffmpegWriter = icvCreateVideoWriter_FFMPEG_p( filename.c_str(), fourcc, fps, frameSize.width, frameSize.height, isColor );
306
return ffmpegWriter != 0;
307
}
308
309
virtual void close()
310
{
311
if (ffmpegWriter
312
#if defined(HAVE_FFMPEG_WRAPPER)
313
&& icvReleaseVideoWriter_FFMPEG_p
314
#endif
315
)
316
icvReleaseVideoWriter_FFMPEG_p( &ffmpegWriter );
317
CV_Assert(ffmpegWriter == 0);
318
ffmpegWriter = 0;
319
}
320
321
virtual double getProperty(int) const CV_OVERRIDE { return 0; }
322
virtual bool setProperty(int, double) CV_OVERRIDE { return false; }
323
virtual bool isOpened() const CV_OVERRIDE { return ffmpegWriter != 0; }
324
325
protected:
326
CvVideoWriter_FFMPEG* ffmpegWriter;
327
};
328
329
} // namespace
330
331
cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const cv::String& filename, int fourcc,
332
double fps, cv::Size frameSize, int isColor)
333
{
334
#if defined(HAVE_FFMPEG_WRAPPER)
335
icvInitFFMPEG::Init();
336
if (!icvCreateVideoWriter_FFMPEG_p)
337
return cv::Ptr<cv::IVideoWriter>();
338
#endif
339
cv::Ptr<CvVideoWriter_FFMPEG_proxy> writer = cv::makePtr<CvVideoWriter_FFMPEG_proxy>(filename, fourcc, fps, frameSize, isColor != 0);
340
if (writer && writer->isOpened())
341
return writer;
342
return cv::Ptr<cv::IVideoWriter>();
343
}
344
345
} // namespace
346
347
#endif // defined(HAVE_FFMPEG)
348
349