1 // Copyright (c) 2017-2019 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20
21 #include <mfxvideo.h>
22
23 #include <mfx_session.h>
24 #include <mfx_common.h>
25
26 // sheduling and threading stuff
27 #include <mfx_task.h>
28
29 #include "mfxenc.h"
30 #include "mfx_enc_ext.h"
31
32
33
34 #if defined(MFX_ENABLE_H264_VIDEO_ENCODE_HW) && defined(MFX_ENABLE_LA_H264_VIDEO_HW)
35 #include "mfx_h264_la.h"
36 #endif
37
38 #if defined(MFX_ENABLE_H264_VIDEO_ENCODE_HW) && defined(MFX_ENABLE_H264_VIDEO_FEI_PREENC)
39 #include "mfx_h264_preenc.h"
40 #endif
41
42 #if defined(MFX_ENABLE_H264_VIDEO_ENCODE_HW) && defined(MFX_ENABLE_H264_VIDEO_FEI_ENC)
43 #include "mfx_h264_enc.h"
44 #endif
45
46 template<>
Create(mfxVideoParam & par)47 VideoENC* _mfxSession::Create<VideoENC>(mfxVideoParam& par)
48 {
49 VideoENC* pENC = nullptr;
50 mfxStatus mfxRes = MFX_ERR_MEMORY_ALLOC;
51 mfxU32 codecId = par.mfx.CodecId;
52
53 switch (codecId)
54 {
55 #if ( defined(MFX_ENABLE_LA_H264_VIDEO_HW) || defined(MFX_ENABLE_H264_VIDEO_FEI_PREENC) || defined(MFX_ENABLE_H264_VIDEO_FEI_ENC))
56 case MFX_CODEC_AVC:
57 #if defined(MFX_ENABLE_LA_H264_VIDEO_HW)
58 if (bEnc_LA(&par))
59 pENC = (VideoENC*) new VideoENC_LA(m_pCORE.get(), &mfxRes);
60 #endif
61 #if defined(MFX_ENABLE_H264_VIDEO_FEI_PREENC)
62 if (bEnc_PREENC(&par))
63 pENC = (VideoENC*) new VideoENC_PREENC(m_pCORE.get(), &mfxRes);
64 #endif
65 #if defined(MFX_ENABLE_H264_VIDEO_FEI_ENC) && defined(MFX_ENABLE_H264_VIDEO_ENCODE_HW)
66 if (bEnc_ENC(&par))
67 pENC = (VideoENC*) new VideoENC_ENC(m_pCORE.get(), &mfxRes);
68 #endif
69 break;
70 #endif
71
72 default:
73 break;
74 }
75
76 // check error(s)
77 if (MFX_ERR_NONE != mfxRes)
78 {
79 delete pENC;
80 pENC = nullptr;
81 }
82
83 return pENC;
84 }
85
MFXVideoENC_Query(mfxSession session,mfxVideoParam * in,mfxVideoParam * out)86 mfxStatus MFXVideoENC_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out)
87 {
88 (void)in;
89
90 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
91 MFX_CHECK(out, MFX_ERR_NULL_PTR);
92
93 mfxStatus mfxRes = MFX_ERR_UNSUPPORTED;
94 try
95 {
96
97 #ifdef MFX_ENABLE_USER_ENC
98 mfxRes = MFX_ERR_UNSUPPORTED;
99
100 _mfxSession_1_10 * versionedSession = (_mfxSession_1_10 *)(session);
101 MFXIPtr<MFXISession_1_10> newSession(versionedSession->QueryInterface(MFXISession_1_10_GUID));
102
103 if (newSession && newSession->GetPreEncPlugin().get())
104 {
105 mfxRes = newSession->GetPreEncPlugin()->Query(session->m_pCORE.get(), in, out);
106 }
107 // unsupported reserved to codecid != requested codecid
108 if (MFX_ERR_UNSUPPORTED == mfxRes)
109 #endif
110 switch (out->mfx.CodecId)
111 {
112 #if defined(MFX_ENABLE_LA_H264_VIDEO_HW) || defined(MFX_ENABLE_H264_VIDEO_FEI_PREENC)
113 case MFX_CODEC_AVC:
114 #if defined(MFX_ENABLE_LA_H264_VIDEO_HW)
115 if (bEnc_LA(in))
116 mfxRes = VideoENC_LA::Query(session->m_pCORE.get(), in, out);
117 #endif
118
119 #if defined(MFX_ENABLE_H264_VIDEO_FEI_PREENC)
120 if (bEnc_PREENC(out))
121 mfxRes = VideoENC_PREENC::Query(session->m_pCORE.get(),in, out);
122 #endif
123 break;
124 #endif // MFX_ENABLE_H264_VIDEO_ENC || MFX_ENABLE_H264_VIDEO_ENC_H
125
126
127
128 case 0:
129 default:
130 mfxRes = MFX_ERR_UNSUPPORTED;
131 }
132 }
133 // handle error(s)
134 catch(...)
135 {
136 mfxRes = MFX_ERR_NULL_PTR;
137 }
138 return mfxRes;
139 }
140
MFXVideoENC_QueryIOSurf(mfxSession session,mfxVideoParam * par,mfxFrameAllocRequest * request)141 mfxStatus MFXVideoENC_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request)
142 {
143 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
144 MFX_CHECK(par, MFX_ERR_NULL_PTR);
145 MFX_CHECK(request, MFX_ERR_NULL_PTR);
146
147 mfxStatus mfxRes = MFX_ERR_UNSUPPORTED;
148 try
149 {
150 #ifdef MFX_ENABLE_USER_ENC
151 mfxRes = MFX_ERR_UNSUPPORTED;
152 _mfxSession_1_10 * versionedSession = (_mfxSession_1_10 *)(session);
153 MFXIPtr<MFXISession_1_10> newSession(versionedSession->QueryInterface(MFXISession_1_10_GUID));
154 if (newSession && newSession->GetPreEncPlugin().get())
155 {
156 mfxRes = newSession->GetPreEncPlugin()->QueryIOSurf(session->m_pCORE.get(), par, request, 0);
157 }
158 // unsupported reserved to codecid != requested codecid
159 if (MFX_ERR_UNSUPPORTED == mfxRes)
160 #endif
161 switch (par->mfx.CodecId)
162 {
163
164 #if ( defined(MFX_ENABLE_LA_H264_VIDEO_HW) || defined (MFX_ENABLE_H264_VIDEO_FEI_PREENC) || defined(MFX_ENABLE_H264_VIDEO_FEI_ENC))
165 case MFX_CODEC_AVC:
166
167 #if defined(MFX_ENABLE_LA_H264_VIDEO_HW)
168 if (bEnc_LA(par))
169 mfxRes = VideoENC_LA::QueryIOSurf(session->m_pCORE.get(), par, request);
170 #endif
171 #if defined(MFX_ENABLE_H264_VIDEO_FEI_ENC) && defined(MFX_ENABLE_H264_VIDEO_ENCODE_HW)
172 if (bEnc_ENC(par))
173 mfxRes = VideoENC_ENC::QueryIOSurf(session->m_pCORE.get(), par, request);
174 #endif
175
176 break;
177 #endif // MFX_ENABLE_H264_VIDEO_ENC || MFX_ENABLE_H264_VIDEO_ENC_HW
178
179
180
181 case 0:
182 default:
183 mfxRes = MFX_ERR_UNSUPPORTED;
184 }
185 }
186 // handle error(s)
187 catch(...)
188 {
189 mfxRes = MFX_ERR_NULL_PTR;
190 }
191 return mfxRes;
192 }
193
MFXVideoENC_Init(mfxSession session,mfxVideoParam * par)194 mfxStatus MFXVideoENC_Init(mfxSession session, mfxVideoParam *par)
195 {
196 mfxStatus mfxRes;
197
198 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
199 MFX_CHECK(par, MFX_ERR_NULL_PTR);
200
201 try
202 {
203 // check existence of component
204 if (!session->m_pENC)
205 {
206 // create a new instance
207 session->m_pENC.reset(session->Create<VideoENC>(*par));
208 MFX_CHECK(session->m_pENC.get(), MFX_ERR_INVALID_VIDEO_PARAM);
209 }
210
211 mfxRes = session->m_pENC->Init(par);
212 }
213 // handle error(s)
214 catch(...)
215 {
216 // set the default error value
217 mfxRes = MFX_ERR_UNKNOWN;
218 }
219
220 return mfxRes;
221 }
222
MFXVideoENC_Close(mfxSession session)223 mfxStatus MFXVideoENC_Close(mfxSession session)
224 {
225 mfxStatus mfxRes;
226
227 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
228 MFX_CHECK(session->m_pScheduler, MFX_ERR_NOT_INITIALIZED);
229
230 try
231 {
232 if (!session->m_pENC)
233 {
234 return MFX_ERR_NOT_INITIALIZED;
235 }
236
237 // wait until all tasks are processed
238 session->m_pScheduler->WaitForAllTasksCompletion(session->m_pENC.get());
239
240 mfxRes = session->m_pENC->Close();
241 // delete the codec's instance
242 session->m_pENC.reset(nullptr);
243 }
244 // handle error(s)
245 catch(...)
246 {
247 // set the default error value
248 mfxRes = MFX_ERR_UNKNOWN;
249 }
250
251 return mfxRes;
252 }
253
254 static
MFXVideoENCLegacyRoutineExt(void * pState,void * pParam,mfxU32 threadNumber,mfxU32)255 mfxStatus MFXVideoENCLegacyRoutineExt(void *pState, void *pParam,
256 mfxU32 threadNumber, mfxU32 /* callNumber */)
257 {
258 VideoENC_Ext * pENC = (VideoENC_Ext *) pState;
259 MFX_THREAD_TASK_PARAMETERS *pTaskParam = (MFX_THREAD_TASK_PARAMETERS *) pParam;
260
261 // check error(s)
262 if ((NULL == pState) ||
263 (NULL == pParam) ||
264 (0 != threadNumber))
265 {
266 return MFX_ERR_NULL_PTR;
267 }
268 return pENC->RunFrameVmeENC(pTaskParam->enc.in, pTaskParam->enc.out);
269 }
270
271 enum
272 {
273 MFX_NUM_ENTRY_POINTS = 2
274 };
275
276
MFXVideoENC_ProcessFrameAsync(mfxSession session,mfxENCInput * in,mfxENCOutput * out,mfxSyncPoint * syncp)277 mfxStatus MFXVideoENC_ProcessFrameAsync(mfxSession session, mfxENCInput *in, mfxENCOutput *out, mfxSyncPoint *syncp)
278 {
279 mfxStatus mfxRes;
280
281 MFX_CHECK(session, MFX_ERR_INVALID_HANDLE);
282 MFX_CHECK(session->m_pENC.get(), MFX_ERR_NOT_INITIALIZED);
283 MFX_CHECK(syncp, MFX_ERR_NULL_PTR);
284
285 VideoENC_Ext *pEnc = dynamic_cast<VideoENC_Ext *>(session->m_pENC.get());
286 MFX_CHECK(pEnc, MFX_ERR_INVALID_HANDLE);
287
288 try
289 {
290 mfxSyncPoint syncPoint = NULL;
291 MFX_ENTRY_POINT entryPoints[MFX_NUM_ENTRY_POINTS];
292 mfxU32 numEntryPoints = MFX_NUM_ENTRY_POINTS;
293 memset(&entryPoints, 0, sizeof(entryPoints));
294
295 mfxRes = pEnc->RunFrameVmeENCCheck(in,out,entryPoints,numEntryPoints);
296
297 if ((MFX_ERR_NONE == mfxRes) ||
298 (MFX_WRN_INCOMPATIBLE_VIDEO_PARAM == mfxRes) ||
299 (MFX_WRN_OUT_OF_RANGE == mfxRes) ||
300 (MFX_ERR_MORE_DATA_SUBMIT_TASK == static_cast<int>(mfxRes)) ||
301 (MFX_ERR_MORE_BITSTREAM == mfxRes))
302 {
303 // prepare the absolete kind of task.
304 // it is absolete and must be removed.
305 if (NULL == entryPoints[0].pRoutine)
306 {
307 MFX_TASK task;
308 memset(&task, 0, sizeof(task));
309 // BEGIN OF OBSOLETE PART
310 task.bObsoleteTask = true;
311 // fill task info
312 task.entryPoint.pRoutine = &MFXVideoENCLegacyRoutineExt;
313 task.entryPoint.pState = pEnc;
314 task.entryPoint.requiredNumThreads = 1;
315
316 // fill legacy parameters
317 task.obsolete_params.enc.in = in;
318 task.obsolete_params.enc.out = out;
319
320 task.priority = session->m_priority;
321 task.threadingPolicy = pEnc->GetThreadingPolicy();
322 // fill dependencies
323 task.pSrc[0] = in;
324 task.pDst[0] = out;
325 task.pOwner= pEnc;
326 mfxRes = session->m_pScheduler->AddTask(task, &syncPoint);
327
328 } // END OF OBSOLETE PART
329 else if (1 == numEntryPoints)
330 {
331 MFX_TASK task;
332
333 memset(&task, 0, sizeof(task));
334 task.pOwner = pEnc;
335 task.entryPoint = entryPoints[0];
336 task.priority = session->m_priority;
337 task.threadingPolicy = pEnc->GetThreadingPolicy();
338 // fill dependencies
339
340 task.pSrc[0] = out; // for LA plugin
341 task.pSrc[1] = in->InSurface;
342 task.pDst[0] = out? out->ExtParam : 0;
343
344 // register input and call the task
345 MFX_CHECK_STS(session->m_pScheduler->AddTask(task, &syncPoint));
346 }
347 else
348 {
349 MFX_TASK task;
350
351 memset(&task, 0, sizeof(task));
352 task.pOwner = pEnc;
353 task.entryPoint = entryPoints[0];
354 task.priority = session->m_priority;
355 task.threadingPolicy = pEnc->GetThreadingPolicy();
356 // fill dependencies
357
358 task.pSrc[0] = in->InSurface;
359 task.pDst[0] = entryPoints[0].pParam;
360
361 // register input and call the task
362 MFX_CHECK_STS(session->m_pScheduler->AddTask(task, &syncPoint));
363
364 memset(&task, 0, sizeof(task));
365 task.pOwner = pEnc;
366 task.entryPoint = entryPoints[1];
367 task.priority = session->m_priority;
368 task.threadingPolicy = pEnc->GetThreadingPolicy();
369 // fill dependencies
370 task.pSrc[0] = entryPoints[0].pParam;
371 task.pDst[0] = (MFX_ERR_NONE == mfxRes) ? out:0; // sync point for LA plugin
372 task.pDst[1] = in->InSurface;
373
374
375 // register input and call the task
376 MFX_CHECK_STS(session->m_pScheduler->AddTask(task, &syncPoint));
377 }
378
379 // IT SHOULD BE REMOVED
380 if (MFX_ERR_MORE_DATA_SUBMIT_TASK == static_cast<int>(mfxRes))
381 {
382 mfxRes = MFX_ERR_MORE_DATA;
383 syncPoint = NULL;
384 }
385
386 }
387
388 // return pointer to synchronization point
389 *syncp = syncPoint;
390 }
391 // handle error(s)
392 catch(...)
393 {
394 // set the default error value
395 mfxRes = MFX_ERR_UNKNOWN;
396 }
397
398 return mfxRes;
399
400 } // MFXVideoENC_ProcessFrameAsync
401
402
403 //
404 // THE OTHER ENC FUNCTIONS HAVE IMPLICIT IMPLEMENTATION
405 //
406
407 FUNCTION_RESET_IMPL(ENC, Reset, (mfxSession session, mfxVideoParam *par), (par))
408
409 FUNCTION_IMPL(ENC, GetVideoParam, (mfxSession session, mfxVideoParam *par), (par))
410 FUNCTION_IMPL(ENC, GetFrameParam, (mfxSession session, mfxFrameParam *par), (par))
411