Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/videoio/src/cap_mfx_reader.cpp
16354 views
1
// This file is part of OpenCV project.
2
// It is subject to the license terms in the LICENSE file found in the top-level directory
3
// of this distribution and at http://opencv.org/license.html
4
5
#include "cap_mfx_reader.hpp"
6
#include "opencv2/core/base.hpp"
7
#include "cap_mfx_common.hpp"
8
#include "opencv2/imgproc/hal/hal.hpp"
9
10
using namespace cv;
11
using namespace std;
12
13
inline bool hasExtension(const String &filename, const String &ext)
14
{
15
if (filename.size() <= ext.size())
16
return false;
17
const size_t diff = filename.size() - ext.size();
18
const size_t found_at = filename.rfind(ext);
19
return found_at == diff;
20
}
21
22
inline mfxU32 determineCodecId(const String &filename)
23
{
24
if (hasExtension(filename, ".h264") || hasExtension(filename, ".264"))
25
return MFX_CODEC_AVC;
26
else if (hasExtension(filename, ".mp2") || hasExtension(filename, ".mpeg2"))
27
return MFX_CODEC_MPEG2;
28
else if (hasExtension(filename, ".265") || hasExtension(filename, ".hevc"))
29
return MFX_CODEC_HEVC;
30
else
31
return (mfxU32)-1;
32
}
33
34
//==========================================================================
35
36
VideoCapture_IntelMFX::VideoCapture_IntelMFX(const cv::String &filename)
37
: session(0), plugin(0), deviceHandler(0), bs(0), decoder(0), pool(0), outSurface(0), good(false)
38
{
39
mfxStatus res = MFX_ERR_NONE;
40
41
// Init device and session
42
deviceHandler = createDeviceHandler();
43
session = new MFXVideoSession();
44
if (!deviceHandler->init(*session))
45
{
46
MSG(cerr << "MFX: Can't initialize session" << endl);
47
return;
48
}
49
50
// Load appropriate plugin
51
52
mfxU32 codecId = determineCodecId(filename);
53
if (codecId == (mfxU32)-1)
54
{
55
MSG(cerr << "MFX: Unsupported extension: " << filename << endl);
56
return;
57
}
58
plugin = Plugin::loadDecoderPlugin(*session, codecId);
59
if (plugin && !plugin->isGood())
60
{
61
MSG(cerr << "MFX: LoadPlugin failed for codec: " << codecId << " (" << filename << ")" << endl);
62
return;
63
}
64
65
// Read some content from file
66
67
bs = new ReadBitstream(filename.c_str());
68
if (!bs->read())
69
{
70
MSG(cerr << "MFX: Failed to read bitstream" << endl);
71
return;
72
}
73
74
// Create decoder and decode stream header
75
76
decoder = new MFXVideoDECODE(*session);
77
mfxVideoParam params;
78
memset(&params, 0, sizeof(params));
79
params.mfx.CodecId = codecId;
80
params.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
81
res = decoder->DecodeHeader(&bs->stream, &params);
82
DBG(cout << "DecodeHeader: " << res << endl << params.mfx << params.mfx.FrameInfo << endl);
83
if (res < MFX_ERR_NONE)
84
{
85
MSG(cerr << "MFX: Failed to decode stream header: " << res << endl);
86
return;
87
}
88
89
// Adjust parameters
90
91
res = decoder->Query(&params, &params);
92
DBG(cout << "MFX Query: " << res << endl << params.mfx << params.mfx.FrameInfo);
93
CV_Assert(res >= MFX_ERR_NONE);
94
95
// Init surface pool
96
97
pool = SurfacePool::create(decoder, params);
98
if (!pool)
99
{
100
MSG(cerr << "MFX: Failed to create surface pool" << endl);
101
return;
102
}
103
104
// Init decoder
105
106
res = decoder->Init(&params);
107
DBG(cout << "MFX Init: " << res << endl << params.mfx.FrameInfo);
108
if (res < MFX_ERR_NONE)
109
{
110
MSG(cerr << "MFX: Failed to init decoder: " << res << endl);
111
return;
112
}
113
114
good = true;
115
}
116
117
118
VideoCapture_IntelMFX::~VideoCapture_IntelMFX()
119
{
120
cleanup(plugin);
121
cleanup(bs);
122
cleanup(decoder);
123
cleanup(pool);
124
session->Close();
125
cleanup(session);
126
cleanup(deviceHandler);
127
}
128
129
double VideoCapture_IntelMFX::getProperty(int) const
130
{
131
MSG(cerr << "MFX: getProperty() is not implemented" << endl);
132
return 0;
133
}
134
135
bool VideoCapture_IntelMFX::setProperty(int, double)
136
{
137
MSG(cerr << "MFX: setProperty() is not implemented" << endl);
138
return false;
139
}
140
141
bool VideoCapture_IntelMFX::grabFrame()
142
{
143
mfxStatus res;
144
mfxFrameSurface1 *workSurface = 0;
145
mfxSyncPoint sync;
146
147
workSurface = pool->getFreeSurface();
148
149
while (true)
150
{
151
if (!workSurface)
152
{
153
// not enough surfaces
154
MSG(cerr << "MFX: Failed to get free surface" << endl);
155
return false;
156
}
157
158
outSurface = 0;
159
res = decoder->DecodeFrameAsync(bs->drain ? 0 : &bs->stream, workSurface, (mfxFrameSurface1**)&outSurface, &sync);
160
if (res == MFX_ERR_NONE)
161
{
162
res = session->SyncOperation(sync, 1000); // 1 sec, TODO: provide interface to modify timeout
163
if (res == MFX_ERR_NONE)
164
{
165
// ready to retrieve
166
DBG(cout << "Frame ready to retrieve" << endl);
167
return true;
168
}
169
else
170
{
171
MSG(cerr << "MFX: Sync error: " << res << endl);
172
return false;
173
}
174
}
175
else if (res == MFX_ERR_MORE_DATA)
176
{
177
if (bs->isDone())
178
{
179
if (bs->drain)
180
{
181
// finish
182
DBG(cout << "Drain finished" << endl);
183
return false;
184
}
185
else
186
{
187
DBG(cout << "Bitstream finished - Drain started" << endl);
188
bs->drain = true;
189
continue;
190
}
191
}
192
else
193
{
194
bool read_res = bs->read();
195
if (!read_res)
196
{
197
// failed to read
198
MSG(cerr << "MFX: Bitstream read failure" << endl);
199
return false;
200
}
201
else
202
{
203
DBG(cout << "Bitstream read success" << endl);
204
continue;
205
}
206
}
207
}
208
else if (res == MFX_ERR_MORE_SURFACE)
209
{
210
DBG(cout << "Getting another surface" << endl);
211
workSurface = pool->getFreeSurface();
212
continue;
213
}
214
else if (res == MFX_WRN_DEVICE_BUSY)
215
{
216
DBG(cout << "Waiting for device" << endl);
217
sleep(1);
218
continue;
219
}
220
else if (res == MFX_WRN_VIDEO_PARAM_CHANGED)
221
{
222
DBG(cout << "Video param changed" << endl);
223
continue;
224
}
225
else
226
{
227
MSG(cerr << "MFX: Bad status: " << res << endl);
228
return false;
229
}
230
}
231
}
232
233
234
bool VideoCapture_IntelMFX::retrieveFrame(int, OutputArray out)
235
{
236
if (!outSurface)
237
{
238
MSG(cerr << "MFX: No frame ready to retrieve" << endl);
239
return false;
240
}
241
mfxFrameSurface1 * s = (mfxFrameSurface1*)outSurface;
242
mfxFrameInfo &info = s->Info;
243
mfxFrameData &data = s->Data;
244
245
const int cols = info.CropW;
246
const int rows = info.CropH;
247
248
out.create(rows, cols, CV_8UC3);
249
Mat res = out.getMat();
250
251
hal::cvtTwoPlaneYUVtoBGR(data.Y, data.UV, data.Pitch, res.data, res.step, cols, rows, 3, false, 0);
252
253
return true;
254
}
255
256
bool VideoCapture_IntelMFX::isOpened() const
257
{
258
return good;
259
}
260
261
int VideoCapture_IntelMFX::getCaptureDomain()
262
{
263
return CAP_INTEL_MFX;
264
}
265
266
//==================================================================================================
267
268